Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

CLI Reference

Note: This is a work in progress. Only simple transfers (send/receive) are currently supported. Some subcommands may be incomplete or have placeholder behavior. Passwords are accepted via --password flag only (no interactive prompt yet).

The paypunk binary is the single entry point for all wallet operations. It auto-launches daemons when needed and tears them down on exit.

Usage

paypunk [OPTIONS] [COMMAND]

Run with no subcommand to auto-launch daemons + TUI.

Global options

FlagShortDefaultDescription
--socket-path-s/tmp/paypunkd.sockpaypunkd IPC socket path
--signerfalseEnable offline signer mode (spawns bridge instead of keypunkd)
--zcash-networkregtestZcash network: regtest, testnet, or mainnet
--lightwalletd-hostNetwork defaultOverride lightwalletd endpoint
--data-dir~/.local/share/paypunk/<network>/Override data directory

Environment variables

All config fields can be overridden via environment variables:

Env varConfig field
PAYPUNK_SOCKET_PATHpaypunkd_socket_path
KEYPUNKD_SOCKET_PATHkeypunkd_socket_path
PAYPUNK_DATA_DIRdata_dir
PAYPUNK_CONFIG_DIRconfig_dir
PAYPUNK_ETHEREUM_RPC_URLethereum_rpc_url
PAYPUNK_LIGHTWALLETD_HOSTlightwalletd_host
PAYPUNK_ZCASH_NETWORKzcash_network
PAYPUNK_BRIDGE_SOCKET_PATHbridge_socket_path
PAYPUNK_OFFLINE_SIGNERoffline_signer ("true" or "1")

Configuration file

Located at ~/.config/paypunk/config.toml. Generated on first run if missing.

paypunkd_socket_path = "/tmp/paypunkd.sock"
keypunkd_socket_path = "/tmp/keypunkd.sock"
bridge_socket_path = "/tmp/paypunk-bridge.sock"
data_dir = "~/.local/share/paypunk/"
config_dir = "~/.config/paypunk/"
ethereum_rpc_url = "http://127.0.0.1:8545"
zcash_network = "regtest"
offline_signer = false

Subcommands

generate-seed

Generate a new wallet seed.

paypunk generate-seed -p <password>
FlagShortTypeRequiredDefault
--password-pStringYes

Prints the 12-word BIP39 mnemonic. Save it offline.

restore-seed

Restore a wallet from an existing seed phrase.

paypunk restore-seed -m "word1 word2 ... word12" -p <password> --birthday-height 1234567
FlagShortTypeRequiredDefault
--mnemonic-mStringYes
--password-pStringYes
--birthday-heightu64NoNone

Birthday height speeds up initial sync by avoiding scanning from genesis. Recommended for mainnet.

On mainnet, if --birthday-height is omitted the wallet auto-fetches the current chain tip as the birthday. This is fine for fresh wallets, but existing funds below that height will not be detected. Always provide a birthday block when restoring a mainnet wallet with prior activity. The stored birthday is consulted by create_account, register_signer, and bulk_derive_accounts before falling back to the tip, and the background sync loop falls back to the minimum account birthday when no blocks have been scanned yet.

unlock

Unlock the wallet and derive accounts from pre-derived viewing keys.

paypunk unlock -p <password>
FlagShortTypeRequiredDefault
--password-pStringYes

On first unlock, bulk-derives 30 viewing keys per protocol from keypunkd, stores them in pre_derived_keys, and creates the first account per protocol.

submit-transfer

Submit a transfer intent for preview (two-phase signing, step 1).

paypunk submit-transfer \
  --to "u1..." --amount "0.001" --from "u1..." \
  --protocol zcash --memo "payment" --account 0
FlagShortTypeRequiredDefault
--to-tStringYes
--amount-aStringYes
--from-fStringYes
--assetStringNoeip155:1/slip44:60
--protocol-pStringNoInferred from asset
--data-dStringNoNone
--memo-mStringNoNone
--accountu32No0

Protocol is inferred from --asset if not provided: eip155 → Ethereum, zcash → Zcash, else defaults to Ethereum.

Saves a pending intent to <data_dir>/pending.intent. Run approve-signature next.

approve-signature

Approve a previously submitted intent (two-phase signing, step 2).

paypunk approve-signature -p <password>
FlagShortTypeRequiredDefault
--password-pStringYes
--accountu32No0

Reads <data_dir>/pending.intent, signs the artifact via keypunkd, broadcasts the transaction, and removes the pending file.

get-balance

Query balance for a protocol and account.

paypunk get-balance --protocol zcash --account 0
paypunk get-balance --protocol ethereum --address 0xf39Fd6...
FlagShortTypeRequiredDefault
--protocol-pStringNozcash
--account-au32No0
--addressStringNoNone (uses account)

If --address is omitted, looks up the account by protocol + derivation path.

list-accounts

List all accounts in the wallet.

paypunk list-accounts

No flags. Prints id | protocol | derivation_path | name | address for each account.

create-account

Create a new account from a pre-derived viewing key.

paypunk create-account --protocol zcash --account-index 1 --name "Savings"
FlagShortTypeRequiredDefault
--protocol-pStringNozcash
--account-indexu32No0
--name-nStringNo"{Protocol} Account {index}"
--birthday-heightu64NoNone

tui

Launch the terminal UI. Does NOT start daemons — they must be running.

paypunk tui
paypunk tui --signer    # connect to bridge instead of keypunkd
FlagShortTypeRequiredDefault
--signerboolNofalse

keypunkd

Launch the key daemon as a foreground process.

paypunk keypunkd --zcash-network regtest
FlagShortTypeRequiredDefault
--socket-path-sStringNo/tmp/keypunkd.sock
--data-dir-dStringNo~/.local/share/paypunk/<network>/
--zcash-network-zStringNoregtest

paypunkd

Launch the app daemon as a foreground process.

paypunk paypunkd --keypunkd-socket /tmp/keypunkd.sock --lightwalletd-host http://127.0.0.1:9067
FlagShortTypeRequiredDefault
--socket-path-sStringNo/tmp/paypunkd.sock
--keypunkd-socket-kStringNo/tmp/keypunkd.sock
--ethereum-rpc-url-eStringNohttp://127.0.0.1:8545
--data-dir-dStringNo~/.local/share/paypunk/<network>/
--lightwalletd-host-lStringNoNetwork default
--zcash-network-zStringNoregtest

bridge

Run the QR bridge web server for air-gapped signing.

paypunk bridge --port 12345 --socket-path /tmp/keypunkd.sock
FlagShortTypeRequiredDefault
--portu16No12345
--socket-pathStringNo/tmp/keypunkd.sock

Serves an HTML page at http://0.0.0.0:{port}/ and a WebSocket at ws://0.0.0.0:{port}/ws.

reset

Remove all wallet data (seed, database, accounts). Resets to clean state.

paypunk reset

No flags. Removes the entire data directory (all networks).

uninstall

Permanently remove all wallet + config data.

paypunk uninstall           # prompts for confirmation
paypunk uninstall --force   # skip confirmation
FlagShortTypeRequiredDefault
--force-fboolNofalse

Removes both data_dir and config_dir.

Auto-launch behavior

When run with no subcommand (or with a client command like generate-seed), paypunk automatically:

  1. Checks if paypunkd is already running on the socket (500ms connect probe)
  2. If not, spawns keypunkd (or bridge in signer mode) + paypunkd as child processes
  3. Waits up to 30 seconds for sockets to appear
  4. Runs the command/TUI
  5. Kills spawned daemons on exit

If daemons are already running, they are reused — no new processes are spawned.

Two-phase signing (CLI)

The CLI uses a two-phase signing flow for transfers:

# Phase 1: build + preview
paypunk submit-transfer --to "u1..." --amount "0.001" --from "u1..." --protocol zcash
# → prints fee, saves pending.intent

# Phase 2: approve + broadcast
paypunk approve-signature -p <password>
# → signs with keypunkd, broadcasts, prints tx hash

The pending intent is stored at <data_dir>/pending.intent (base data dir, not network-specific).