For v0.1.5+, based on the kohaku-cli README. Flags may still evolve — when in doubt, run kohaku help or kohaku <command> --help.
# Commands Summary
| Command | What it does |
|---|---|
help |
Show CLI help / list commands |
create-wallet |
Create or --import an encrypted seed wallet (--stealth-start-block on import) |
list-wallets |
List wallets on disk |
next-fresh-address |
Derive the next public address (--peek to preview only) |
init-profile |
Publish EIP-5564 stealth keys (and optionally a name); fully interactive with no args |
export-private-key |
Print one account’s private key to stdout |
reveal-seed-phrase |
Decrypt and print the wallet BIP-39 mnemonic |
balances |
Public + private balances; recent private checks may be reused (--refresh to sync now); stealth announcement scan (--skip-stealth-scan) |
activity |
View encrypted local history of CLI transaction submissions |
transfer |
Send from a public account or use --from tornado|privacy-pools|railgun for a private transfer |
transact-raw |
Submit raw calldata (multi-call → EIP-7702 UserOp) |
shield |
Deposit from a public account into a privacy protocol |
unshield |
Withdraw private balance (--next, --to s0, --tail-calls on Tornado + Privacy Pools + Railgun) |
private-transfer |
Pay an exact or maximum amount to a public recipient or privately to a Railgun 0zk address |
ragequit |
Exit one unapproved Privacy Pools note to its original depositor |
import-tornado-note |
Import legacy Tornado note string(s) |
export-tornado-note |
Export unspent Tornado note secret(s) |
register-name |
Register a .eth / .gwei / .wei name |
renew-name |
Renew / extend a name |
transfer-name |
Transfer name ownership (and ENS manager) |
set-name-text-record |
Set a text record on a name |
set-name-website |
Set contenthash / website (ipfs:// / bzz://) |
set-name-reverse-record |
Set primary reverse record for an account |
fetch-sync-cache |
Prefetch verified mainnet Railgun, Tornado, and Privacy Pools history |
view-network-traffic |
Review what the CLI contacted (Tor vs clearnet) |
clear-tor-cache |
Delete tor-js Arti cache (--public-sync also wipes sync cache) |
see-stealth-meta-address |
Print this wallet’s stealth meta-address URI |
see-decrypted-storage |
Debug: decrypt and print wallet storage JSON |
Most mutating commands dry-run by default. Add --broadcast only when you intend to send.
# Commands Reference
Global behavior:
| Topic | Detail |
|---|---|
| RPC | --rpc-url <url> or env RPC_URL (required for most commands except create-wallet without --import, and list-wallets). |
| Default privacy protocol | Env DEFAULT_PRIVACY_PROTOCOL (tornado | railgun | privacy-pools). When set, shield / unshield / private-transfer may omit --protocol, and balances includes that protocol by default. Examples below still pass --protocol / --include explicitly. |
| Data directory | --dataDir <path> (default ~/.kohaku-cli). |
| Networks | Wallets created with --testnet expect Sepolia (11155111); otherwise mainnet (1). RPC chain ID must match the wallet. |
--non-interactive |
Available on every command below. Skips prompts and spinners; prints JSON where applicable. Requires flags documented per command (--password-file or --password, --wallet, amounts, --from, --to / --next, etc.). Use for CI, agents, and piping output. |
--password-file <path> |
Preferred for automation on POSIX. Reads the wallet password from a regular, non-symlink file owned by the current user with mode 0400 or 0600. Mutually exclusive with --password. |
--password <password> |
Legacy wallet unlock input. A literal string or existing file path is accepted for compatibility; prefer --password-file in scripts. |
--without-tor |
Disable Tor for non-RPC HTTP (default: Tor on for private-protocol and Pimlico-backed commands, including transfer / transact-raw / names). Or set KOHAKU_WITHOUT_TOR=1. Ethereum RPC stays clearnet. Review contacts with view-network-traffic. |
| Proving artifacts | Railgun, Tornado, and Privacy Pools circuits install with the CLI through kohaku-artifacts. No separate fetch is needed; fetch-artifacts was removed in 0.0.10. |
| Public-sync cache | fetch-sync-cache installs a verified mainnet snapshot under <dataDir>/sync-cache-v2 for Railgun, historical PPOI leaves, Tornado, and Privacy Pools. Complete PPOI leaf pages and confirmed historical indexer responses fetched after that snapshot are reused across wallets from sync-cache-v2/live (up to 256 MiB). Heads, recent indexer state, incomplete PPOI pages and PPOI checks remain live. Sepolia keeps its existing sync path. Old <dataDir>/public-sync-cache data is not read. clear-tor-cache --public-sync removes both directories. |
# create-wallet <name>
Create a BIP-39 seed wallet encrypted on disk. The <name> argument is a single token (no spaces) and cannot be proving-artifacts, public-sync-cache, or sync-cache-v2 (reserved data directory names).
New seed: records the current chain tip in .stealth-start-block so later balances stealth scans do not walk announcement history from before the wallet existed. Uses --rpc-url / RPC_URL when set; otherwise a public RPC for mainnet or Sepolia (--testnet).
Import (--import): scans used public HD indexes via RPC. Writes the current chain tip to .stealth-start-block (same as a new seed) so the first balances stealth scan does not walk historical announcements. Pass --stealth-start-block with no value to opt into the Kohaku-schema floor (mainnet 25700000, Sepolia 11455454), or --stealth-start-block <block> for an explicit floor (values below the ERC-5564 announcer deploy are rounded up to that block). Later, balances --stealth-start-block can still back-date below whatever was written at import.
| Option | Description |
|---|---|
--testnet |
Tag wallet for Sepolia instead of mainnet. |
--import |
Restore from mnemonic instead of generating a new one. |
--long-seed |
Generate a 24-word (256-bit) mnemonic instead of the default 12-word (128-bit). Ignored with --import. |
--rpc-url <url> |
Required with --import (or RPC_URL) to scan used addresses. Optional for new wallets when writing .stealth-start-block. |
--stealth-start-block [block] |
With --import: write .stealth-start-block. Omit the flag to record the current tip (same as a new wallet). Bare flag: Kohaku floor (mainnet 25700000, Sepolia 11455454). With a number: that block, rounded up to the ERC-5564 announcer deploy if lower. |
--mnemonic <phrase> |
Mnemonic (required with --non-interactive --import). |
--password <password> |
Encryption password (required with --non-interactive). |
--non-interactive |
No prompts; no mnemonic box on create. |
--dataDir <path> |
Data root. |
Interactive: encryption password (twice); for --import, masked mnemonic entry. New wallets display the mnemonic once in a warning box.
Examples:
kohaku create-wallet myWallet --testnet
kohaku create-wallet myWallet24 --testnet --long-seed
kohaku create-wallet restored --testnet --import --rpc-url "$RPC_URL"
kohaku create-wallet restored --testnet --import --rpc-url "$RPC_URL" --stealth-start-block
kohaku create-wallet restored --testnet --import --rpc-url "$RPC_URL" --stealth-start-block 10000000
# list-wallets
List wallet names and network kind (mainnet / testnet).
| Option | Description |
|---|---|
--non-interactive |
Output `{“wallets”:{“name”:{“mainnet”:true |
--dataDir <path> |
Data root. |
# next-fresh-address
Derive the next HD public account and print its address. By default the account is also persisted; use --peek to inspect it without writing.
| Option | Description |
|---|---|
--wallet <name> |
Wallet (prompt if omitted). |
--password <password> |
Unlock password. |
--peek |
Print the next fresh address without persisting it (e.g. to craft --tail-calls before unshield --next). |
--non-interactive |
Requires --wallet and --password; prints address only. |
--dataDir <path> |
Data root. |
Interactive: wallet picker (if needed), wallet password.
Examples:
kohaku next-fresh-address --wallet testWallet
kohaku next-fresh-address --wallet testWallet --peek
kohaku next-fresh-address --wallet testWallet --password "$WALLET_PW" --non-interactive
# init-profile
Publish EIP-5564 stealth viewing/spending keys on the ERC-6538 registry for an HD account. Optionally register (or reuse) a .eth / .gwei / .wei name and set stealth-address-scheme-1 on it. With a name: commit → wait 60s → one EIP-7702 UserOp for reveal/register + reverse + text + registerKeys. With --no-name: a single EOA registerKeys transaction (no 7702). Creates public account index 0 if missing.
Interactive: can run with no args (kohaku init-profile) — prompts for name vs no-name (and protocol when needed). With --non-interactive, provide exactly one of --name or --no-name.
| Option | Description |
|---|---|
--name <label-or-name> |
Bare label or full name (alice / alice.gwei). Existing owned names are reused. Optional in interactive mode. |
--no-name |
Skip name registration; only register stealth keys for --index on ERC-6538. Optional in interactive mode. |
--protocol <ens|gns|wns> |
Required when --name is a bare label (no TLD); interactive mode can pick a protocol instead. |
--index <n> |
HD account that owns/registers the name and registry entry (default: 0). |
--years <n> |
Registration duration when registering a new ENS name (default: 1). GNS/WNS are always 1 year. |
--wallet <name> |
Wallet. |
--password <password> |
Unlock password. |
--rpc-url <url> |
RPC endpoint. |
--broadcast |
Sign and submit on-chain. Omit to simulate / print payloads. |
--owner-priv |
Derive --index from the seed when that account is not yet in public accounts. |
--without-tor |
Disable Tor for non-RPC HTTP (Pimlico when using EIP-7702, etc.). RPC stays clearnet. Or set KOHAKU_WITHOUT_TOR=1. |
--non-interactive |
JSON where applicable; requires --wallet, --password, and --name or --no-name. |
--dataDir <path> |
Data root. |
Examples:
kohaku init-profile
kohaku init-profile --broadcast
kohaku init-profile --wallet testWallet --name alice --protocol ens --broadcast
kohaku init-profile --wallet testWallet --name alice.gwei --broadcast
kohaku init-profile --wallet testWallet --no-name --broadcast
# export-private-key
Export the private key for one public account. The key is printed directly to stdout; handle it as sensitive material.
| Option | Description |
|---|---|
--wallet <name> |
Wallet (prompt if omitted). |
--password <password> |
Unlock password. |
--address <address> |
Export a persisted public account by address. |
--index <index> |
Export by non-negative HD derivation index, even if the account has not been persisted yet. |
--non-interactive |
Skip the reveal confirmation; requires --wallet and --password. |
--dataDir <path> |
Data root. |
Provide exactly one of --address or --index. Interactive mode confirms before revealing the key.
Examples:
kohaku export-private-key --wallet testWallet --index 0
kohaku export-private-key --wallet testWallet --address 0xYourAddress
# reveal-seed-phrase
Decrypt and print the wallet’s BIP-39 seed phrase. Interactive mode asks you to confirm twice before printing (both default to No).
| Option | Description |
|---|---|
--wallet <name> |
Wallet (prompt if omitted). |
--password <password> |
Unlock password. |
--non-interactive |
Skip both reveal confirmations; requires --wallet and --password. Prints the phrase only (no box). |
--dataDir <path> |
Data root. |
Examples:
kohaku reveal-seed-phrase --wallet testWallet
# balances
Show aggregated public balances (ETH + default ERC-20s for the chain, plus any private tokens discovered), and private balances for the protocols you select. Also prints the wallet profile name (reverse-resolved for HD index 0, if any; JSON: wallet_profile_name). Use see-stealth-meta-address for the stealth meta URI.
By default, private balances are included only for DEFAULT_PRIVACY_PROTOCOL (if set). Otherwise only public balances are shown, with a short warning. Pass --include to sync one or more protocols explicitly (required for multiple protocols at once, or for any private balance when the env is unset).
Successful private balance checks can be reused for up to one minute from an encrypted wallet-local display cache. Cached sections show their age; JSON includes private_balance_freshness. Use --refresh to sync now. Changes to wallet identity, protocol storage, or operation activity invalidate cached views. Spending flows use their normal sync path. When every requested private view is recent, balances skips private wallet initialization and Tor bootstrap; public balances are still fetched. Independent private protocols sync concurrently when fresh checks are needed.
balances always loads already-imported stealth accounts into public totals. It also scans ERC-5564 announcements for new payments (same spinner progress as protocol first-sync). A line of the form Stealth scan from block {start} · {latest - start} blocks prints before that progress bar. --stealth-start-block sets the history floor (and can back-date below the wallet file, down to the announcer deploy block); use --skip-stealth-scan to skip discovery for a faster run.
| Option | Description |
|---|---|
--wallet <name> |
Wallet (optional in interactive mode). |
--password <password> |
Unlock password. |
--rpc-url <url> |
RPC endpoint. |
--include <protocols> |
Comma-separated private protocols to sync (railgun, privacy-pools, tornado). Default: DEFAULT_PRIVACY_PROTOCOL only, or none if unset. |
--verbose |
Human: per-address public breakdown + private note list for included protocols. JSON: adds public_account_indexes_by_address and private_notes. |
--refresh |
Bypass recent private balance checks and sync now. |
--tokensList <addrs> |
Extra ERC-20 addresses (comma- or space-separated), merged with chain defaults. |
--without-tor |
Disable Tor for privacy HTTP when syncing private protocols (default: Tor on). Covers Railgun Subsquid/PPOI, Tornado saga, Privacy Pools ASP, Pimlico, etc. RPC stays clearnet. Or set KOHAKU_WITHOUT_TOR=1. |
--stealth-start-block <block> |
Floor for the ERC-5564 announcement scan (decimal or 0x-hex); skips older history on first/full scan. Can back-date below the wallet .stealth-start-block (often the creation/import tip; as far as the announcer deploy block). When omitted, uses that file if present, otherwise the Kohaku import default (mainnet 25700000, Sepolia 11455454). Not a way to skip scanning. |
--skip-stealth-scan |
Skip announcement discovery for this run. Already-imported stealth accounts still appear in public balances. |
--non-interactive |
JSON only; requires --wallet and --password. |
--dataDir <path> |
Data root. |
Interactive: wallet picker, password, loading spinner, formatted tables.
Default Sepolia ERC-20s include USDC, DAI, and WETH; mainnet adds USDC, USDT, DAI, WETH.
Examples:
kohaku balances --wallet testWallet --include tornado
kohaku balances --wallet testWallet --include railgun,tornado --verbose
kohaku balances --wallet testWallet --verbose --include privacy-pools --tokensList 0xYourToken
kohaku balances --wallet testWallet --include tornado --without-tor
kohaku balances --wallet testWallet --include railgun,privacy-pools,tornado --refresh
kohaku balances --wallet testWallet --skip-stealth-scan
# activity
Show this wallet’s encrypted local CLI transaction history, newest first. Requires the wallet password but no RPC or protocol sync. Records start with v0.0.12; dry runs and transactions from other tools are absent. A timed-out receipt stays submitted; this command does not poll or refresh its status.
| Option | Description |
|---|---|
--wallet <name> |
Wallet (interactive picker if omitted). |
--password <password> / --password-file <path> |
Unlock password. |
--non-interactive |
Print versioned JSON with wallet and activity. |
--dataDir <path> |
Data root. |
kohaku activity --wallet testWallet
kohaku activity --wallet testWallet --password-file ./wallet-password --non-interactive
# transfer
Transfer ETH or ERC-20 tokens from one wallet public account to any public address. For a public source, the command simulates the transfer and prints its transaction payload unless --broadcast is set. Set --from to railgun, tornado, or privacy-pools to run the same private transfer as private-transfer --protocol <protocol>. A Railgun --to 0zk… recipient receives an internal private transfer without unshielding; public recipients receive an exact amount through a fresh account.
| Option | Description |
|---|---|
--wallet <name> |
Wallet. |
--password <password> |
Unlock password. |
--from <address-or-index|protocol> |
Public account address, HD index, stealth selector (s0), or private protocol (railgun, tornado, privacy-pools). |
--sender-priv <key> |
Public transfer only: sign for an external sender. The key must match --from and is not saved. Interactive broadcasts prompt with hidden input if needed; non-interactive broadcasts require this option. Unsaved HD indexes are derived automatically. |
--to <address> |
Recipient address, Railgun 0zk address, name, or stealth meta-address. |
--stealth |
Public transfer only: resolve a scheme-1 stealth meta-address from --to and send via EIP-5564. |
--token <address|symbol|eth> |
Token address or symbol (default: eth). |
--amount-wei <n> |
Amount in base units. |
--amount-formatted <decimal> |
Human-readable amount using token decimals. |
--amount-max |
Send the maximum recipient amount after estimated fees. Public ERC-20 transfers send the full token balance; public ETH transfers reserve gas. Private protocol transfers reserve protocol and gas fees. |
--exclude-new-pools |
With --from tornado only, use classic Tornado pools. |
--rpc-url <url> |
RPC endpoint. |
--broadcast |
Sign and submit. Omit to print a public transaction payload or prepared private operation. |
--without-tor |
Disable Tor for non-RPC HTTP (Pimlico UserOps, etc.). RPC stays clearnet. Or set KOHAKU_WITHOUT_TOR=1. |
--non-interactive |
JSON output; requires --wallet, --password, --from, --to, and one amount flag. |
--dataDir <path> |
Data root. |
Provide at most one of --amount-wei, --amount-formatted, or --amount-max. In interactive mode, omitted sender, recipient, and amount values are prompted; max works with public and private sources. Private protocol sources accept the same options as private-transfer; --sender-priv <key> and --stealth are public-transfer-only.
Examples:
kohaku transfer --wallet testWallet --from 0 --to 0xRecipient --amount-formatted 0.01
kohaku transfer --wallet testWallet --from 0 --to 0xRecipient --token USDC --amount-max --broadcast
kohaku transfer --wallet testWallet --from tornado --to 0xRecipient --amount-formatted 0.1 --broadcast
kohaku transfer --wallet testWallet --from railgun --to 0xRecipient --amount-formatted 0.1 --broadcast
# transact-raw
Simulate or submit one or more raw contract calls from a public account.
- One call: processed as a normal EOA transaction.
- Two or more calls: batched into a single EIP-7702 UserOperation (Simple7702Account
executeBatch) and submitted via Pimlico. If the sender is not already delegated to0xe6Cae83BdE06E4c305530e199D7217f42808555B, the EIP-7702 authorization is included in that same UserOp.
| Option | Description |
|---|---|
--targets <addresses> |
Required. Comma- or space-separated contract addresses. |
--payloads <hex> |
Required. Comma- or space-separated calldata values matching --targets by position. |
--values <wei> |
ETH value in wei for each call (default: 0 for every call). The count must match --targets. |
--wallet <name> |
Wallet. |
--password <password> |
Unlock password. |
--from <address-or-index> |
Sender public account address or HD index. |
--sender-priv <key> |
Sign for an external sender. The key must match --from and is not saved. Interactive broadcasts prompt with hidden input if needed; non-interactive broadcasts require this option. Unsaved HD indexes are derived automatically. |
--rpc-url <url> |
RPC endpoint. |
--broadcast |
Sign and submit on-chain (single EOA tx, or one batched UserOp for 2+ calls). Omit to simulate and print payloads. |
--without-tor |
Disable Tor for non-RPC HTTP (Pimlico UserOps, etc.). RPC stays clearnet. Or set KOHAKU_WITHOUT_TOR=1. |
--non-interactive |
JSON output; requires --wallet, --password, and --from. |
--dataDir <path> |
Data root. |
Each target must have one payload and, when provided, one value. Every call is simulated before any transaction is broadcast.
Examples:
kohaku transact-raw --wallet testWallet --from 0 --targets 0xContract --payloads 0xCalldata
kohaku transact-raw --wallet testWallet --from 0 --targets 0xContractA,0xContractB --payloads 0xDataA,0xDataB --values 0,1000000000000000 --broadcast
# shield
Move funds from a public account into a private protocol.
| Option | Description |
|---|---|
--protocol <railgun|privacy-pools|tornado> |
Required unless DEFAULT_PRIVACY_PROTOCOL is set to one of those values. |
--wallet <name> |
Wallet. |
--password <password> |
Unlock password. |
--from <address-or-index> |
Sender public account address, HD index, or stealth selector (s0). |
--sender-priv <key> |
Sign for an external sender. The key must match --from and is not saved. Interactive broadcasts prompt with hidden input if needed; non-interactive broadcasts require this option. Unsaved HD indexes are derived automatically. |
--token <address|symbol|eth> |
Token (default: eth). |
--amount-wei <n> |
Amount in base units. |
--amount-formatted <decimal> |
Human amount (uses token decimals). |
--amount-max |
Shield the maximum spendable amount. ETH: balance minus estimated gas. ERC-20: full token balance (ETH must still cover gas). Tornado: floored to a multiple of the smallest pool denomination; if gas then knocks the amount below a step, the CLI drops one step and rebuilds. Provide at most one of --amount-wei, --amount-formatted, or --amount-max. |
--exclude-new-pools |
Tornado only: use classic pools, whose smallest ETH denomination is 0.1. Full pool sync and balances are unchanged. |
--exclude-denomination <amount> |
Tornado only: exclude a pool size in token units (repeatable; can combine with --exclude-new-pools). |
--disallow-multiple-userops |
Tornado only: reject a shield plan that needs more than five deposit notes and thus multiple transactions. |
--rpc-url <url> |
RPC endpoint. |
--broadcast |
Sign and send on-chain. Omit for dry-run (transaction JSON only). |
--skip-sim |
Dry-run only: skip eth_call / UserOp simulation and fee estimates. fees stay in --non-interactive JSON but are zeroed. Cannot be combined with --broadcast. Use this for counterfactual senders (no balance) so you can still print payloads for later --tail-calls. |
--base-fee-gwei, --priority-fee-gwei |
Optional fee overrides (reserved; auto fees used today). |
--without-tor |
Disable Tor for privacy HTTP (Subsquid / PPOI / saga / ASP / etc.). RPC stays clearnet. Or set KOHAKU_WITHOUT_TOR=1. |
--non-interactive |
JSON output; requires --wallet, --password, --from, and an amount flag (--amount-wei, --amount-formatted, or --amount-max). |
--dataDir <path> |
Data root. |
Interactive (no amount / from flags): shows the selected sender and balance before the amount prompt (or max) → dry-run JSON or confirmations with --broadcast. --amount-max picks the sender before calculating the maximum.
Protocols:
- privacy-pools — Any asset the entrypoint has a pool for (mainnet: ETH, USDC, USDT; Sepolia: ETH). Any amount at or above that pool’s minimum deposit. The vetting fee is deducted from the deposit and shown in the fee preview.
- railgun — ETH and ERC-20; non-ETH may need an approval. Approval + shield (2+ calls) are submitted as one EIP-7702 UserOp via Pimlico.
- tornado — ETH and ERC-20 tokens in the installed SDK’s static
TornadoInstancescatalog that also have SDK paymaster support (src/utils/tornado-pools.tsadapts it for the CLI; mainnet and Sepolia differ). Amount must be an exact multiple of the smallest pool denomination for that asset. Multi-denomination deposits (and any ERC-20 approvals) use EIP-7702 UserOps with up to five deposit notes each. Approvals are aggregated per pool (e.g. 2×1000 + 5×100 → approve 2000 and 500, not seven separate approves).
Interactive Tornado shields always offer a note-packing choice. The first option uses the fewest notes; alternatives explicitly exclude denominations, prioritizing individual 3-style sizes before pairs and broader groups (for example exclude only 0.3, only 0.03, then both). Only distinct exact packings are offered, up to four choices, with the option to enter another amount. Each choice shows the note count, denominations used, and transaction count. Confirmation shows a multiline count-by-denomination breakdown, sender, and transaction/fee details without a pool contract address list. It rounds displayed ETH fee estimates upward to six decimal places; JSON retains exact values. Non-interactive shields use the fewest-note exact packing. Repeat --exclude-denomination <amount> to exclude specific sizes in the selected token’s normal units, for example --exclude-denomination 3 for the 3 ETH pool. This combines with --exclude-new-pools and does not narrow sync or balances.
Tornado signature nonces and Privacy Pools deposit indexes each span all pools and assets on the selected chain, with separate sequences for the two protocols. Shield preparation refreshes complete protocol history and checks proposed indexes against deposits and spent nullifiers, including notes submitted outside the CLI. Every note in a Tornado packing gets a distinct nonce, across denominations and batches. If history cannot be verified through the sampled chain head, preparation stops. Pending external deposits can still race with a separately prepared shield.
Tornado shields allow five deposit notes per transaction, automatically splitting larger plans into sequential EIP-7702 UserOps. Approvals do not count as notes and are included independently in each token batch. A single native-note shield still uses an EOA transaction. --disallow-multiple-userops errors before preparing commitments unless the entire packing fits in five notes. Five is a conservative CLI policy, not a protocol limit or a guarantee of simulation success. The CLI estimates every batch before confirming the full plan and combined fee; each send is prepared against current state after the previous transaction has been included successfully with one confirmation. Later estimation/submission/inclusion failures stop the sequence. A shield can complete partially: earlier deposits remain shielded, and the CLI reports their hashes, confirmed amount, and unconfirmed remainder with a nonzero exit status. Non-interactive output includes per-batch status and hashes. An unresolved receipt is labelled unknown; reconcile its saved hash before retrying and never repeat the original full amount blindly. Prepared commitments/calls and progress are saved encrypted in <wallet>/shield-runs/<runId>.json; no automatic replay or resume is performed. --amount-max must also cover the combined estimated batch fees; if its initial reserve is insufficient, the CLI stops before submitting and asks for a smaller explicit amount.
Successful Tornado shields finish with Etherscan links for every submitted transaction and ✔ Shield flow completed.; Sepolia links point to Sepolia Etherscan.
When a shield needs more than one on-chain call, the CLI uses EIP-7702 Simple7702Account (0xe6Cae83B…855B) the same way as transact-raw.
Examples:
kohaku shield --protocol tornado --wallet testWallet --from 0 --amount-formatted 0.1 --broadcast
kohaku shield --protocol tornado --wallet testWallet --from s0 --amount-formatted 0.1 --broadcast
kohaku shield --protocol tornado --wallet testWallet --from 0 --amount-max --broadcast
kohaku shield --protocol railgun --wallet testWallet --from 0 --token 0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238 --amount-formatted 10 --broadcast
kohaku shield --protocol tornado --wallet testWallet --from 0 --amount-formatted 0.1 --without-tor
# Counterfactual sender: print payloads without simulating (e.g. to compose unshield --tail-calls)
kohaku shield --protocol tornado --wallet testWallet --from 1 --amount-formatted 0.1 --skip-sim --non-interactive
# unshield
Withdraw private balance to a public address. Railgun, Tornado Cash, and Privacy Pools all submit an ERC-4337 user operation.
| Option | Description |
|---|---|
--protocol <railgun|privacy-pools|tornado> |
Required unless DEFAULT_PRIVACY_PROTOCOL is set to one of those values. |
--wallet <name> |
Wallet. |
--password <password> |
Unlock password. |
--to <address> |
Recipient: public address, HD index address, stealth selector (s0), or name (.eth / .gwei / .wei). |
--next |
Create and use the next fresh public account (mutually exclusive with --to). An index that already has a nonce, balance, or code is saved and skipped. |
--token <address|symbol|eth> |
Token (default: eth). |
--amount-wei <n> |
Amount in base units. |
--amount-formatted <decimal> |
Human amount. |
--amount-max |
Maximum spendable amount from one derivation scheme (Railgun: after estimated fees; Privacy Pools: one scheme after its own estimated fees; Tornado: one scheme’s unspent notes). |
--exclude-new-pools |
Tornado only: use classic pools for this withdrawal. |
--tail-calls <target:calldata[:value],...> |
Ordered calls appended after the payout. Optional third field is msg.value (hex or decimal wei) — ETH unshields only; ERC-20 tails cannot include msg.value. Tornado ERC-20 tails work for paymaster-supported tokens (Sepolia: DAI; mainnet: DAI, USDC, USDT, WBTC). Railgun ERC-20 tails work for any shielded token; bundler gas is paid from a separate shielded WETH balance, not from the unshielded asset. Tornado and Privacy Pools tails require --next, a stored public HD --to, or a stored stealth --to (sN). Peeked/custom addresses are not allowed. That account is the EIP-7702 delegator: tail calls run there and leftover funds stay there. Railgun tails require a wallet-controlled recipient (--next / HD --to / stealth). |
--rpc-url <url> |
RPC endpoint. |
--broadcast |
Submit via the protocol bundler or paymaster. Omit to print prepared private operation JSON only. |
--without-tor |
Disable Tor for non-RPC HTTP (default: Tor on for all private-protocol network calls). Covers Pimlico (via local reverse proxy), Railgun Subsquid/PPOI, Tornado saga CDN, Privacy Pools ASP, and other fetch traffic. Ethereum RPC stays on clearnet. First Tor bootstrap may take several seconds. Or set KOHAKU_WITHOUT_TOR=1. |
--non-interactive |
JSON; requires --wallet, --password, --to or --next, and an amount flag. |
--dataDir <path> |
Data root. |
Interactive: recipient menu (next fresh / custom address / existing public or stealth account) → amount (shows max: the larger single-scheme amount; Railgun and Privacy Pools after estimated fees; Tornado by that scheme’s unspent notes) → a warning only when the withdrawal spends legacy notes → prepared op or broadcast confirmation.
Tornado amounts: shields can combine denominations, including 0.01 and 0.03 ETH notes; the amount must be an exact multiple of the smallest denomination for that asset (ETH: 0.01 by default, 0.1 with --exclude-new-pools; DAI Sepolia: 100; etc.). New shields use signature-derived secrets. Existing BIP-32 notes and imported note strings stay spendable as legacy notes. A withdrawal spends one derivation scheme. The balance line names the legacy portion only when it is non-zero, and a warning is printed only when that withdrawal spends legacy notes. Wallets with no legacy notes do not mention derivation schemes. --amount-max is the larger single-scheme amount, not the sum of both. Unshield can combine multiple notes of that one scheme in one paymaster UserOp (including ERC-20: fee taken from the first note via quoteWeiInToken, remaining notes withdrawn in the execution phase) only when the recipient is --next, a stored public HD --to, or a stored stealth --to (sN) — otherwise extra notes would land on a note-derived EIP-7702 account this wallet does not store. --tail-calls have the same requirement. A custom / peeked --to is allowed only for a single-note unshield with no --tail-calls (the SDK withdraws to a recoverable note-derived EIP-7702 sender, which forwards the proceeds minus the fee to that address). Every Tornado unshield uses an EIP-7702 executor, including a single note. Confirmation shows that executor; unused-gas refunds stay there. ERC-20 tails cannot include msg.value.
Railgun amounts: treasury BPS is added on top of the requested amount so the recipient receives that amount exactly. Bundler / privacy-paymaster gas is always paid from shielded WETH (you need a WETH note even when unshielding USDC). --tail-calls works for ETH and ERC-20; funds already land at to via the privacy paymaster (no leftover-forward baking). ERC-20 tails cannot include msg.value.
Privacy Pools amounts: New shields use signature-derived secrets. Existing BIP-32 notes stay spendable as legacy notes. A withdrawal spends one derivation scheme, preferring legacy when those notes cover the net plus that scheme’s paymaster fee. The balance line names the legacy portion only when it is non-zero, and a warning is printed only when that withdrawal spends legacy notes. Wallets with no legacy notes do not mention derivation schemes. --amount is the net the recipient receives. The paymaster fee comes out of the private balance on top of that net. Unused gas can refund to the same recipient, so they may receive a little more than the typed amount. Approved notes are spent largest first; further notes are execution-phase withdrawals in the same user operation. --tail-calls and multi-note withdrawals require --next, a stored public HD --to, or a stored stealth --to (sN). That account signs the EIP-7702 delegation, runs the tail calls, and keeps any change, so custom tails do not have to transfer leftovers out of a hidden account. A custom / peeked --to is allowed only for a single-note unshield with no --tail-calls (the pool pays that address during validation). Sepolia has no paymaster adapter, so unshield fails there until one is configured; shield and balances still work. Withdrawals are not sent through fastrelay.
Stealth recipients: --to s0 (or another stored stealth selector) works for Tornado, Railgun, and Privacy Pools when the stealth private key is in this wallet, including Tornado and Privacy Pools --tail-calls and multi-note amounts (the CLI uses the stored key as the EIP-7702 account). Railgun ERC-20 without --tail-calls can also go to a custom (non-wallet) address. Railgun native ETH unshield and --tail-calls still need a recipient whose key is in this wallet (--next, stored public/stealth address, or sN), because unwrap / tails run on that EIP-7702 account.
Examples:
kohaku unshield --protocol tornado --wallet testWallet --next --amount-max
kohaku unshield --protocol tornado --wallet testWallet --next --amount-formatted 0.1 --broadcast
kohaku unshield --protocol tornado --wallet testWallet --to s0 --amount-formatted 0.1 --broadcast
kohaku unshield --protocol tornado --wallet testWallet --to s0 --amount-formatted 1 --tail-calls 0x1111111111111111111111111111111111111111:0x1234 --broadcast
kohaku unshield --protocol tornado --wallet testWallet --next --amount-formatted 1 --tail-calls 0x1111111111111111111111111111111111111111:0x1234,0x2222222222222222222222222222222222222222:0xabcd:0x2386f26fc10000 --broadcast
kohaku unshield --protocol tornado --wallet testWallet --next --token DAI --amount-formatted 100 --broadcast
kohaku unshield --protocol tornado --wallet testWallet --next --token DAI --amount-formatted 100 --tail-calls 0x1111111111111111111111111111111111111111:0x1234 --broadcast
kohaku unshield --protocol railgun --wallet testWallet --to 0xStoredWalletAddress --token USDC --amount-formatted 25 --broadcast
kohaku unshield --protocol railgun --wallet testWallet --next --token USDC --amount-formatted 3 --tail-calls 0x1111111111111111111111111111111111111111:0x1234 --broadcast
kohaku unshield --protocol tornado --wallet testWallet --next --amount-formatted 0.1 --without-tor
# private-transfer
Send an exact private amount to someone else. For a public recipient, this unshields through a fresh public account and forwards the amount with a tail call. For a Railgun 0zk recipient, the transfer stays inside Railgun and does not unshield. The 4337 paymaster gas is paid from private WETH.
| Option | Description |
|---|---|
--protocol <railgun|privacy-pools|tornado> |
Required unless DEFAULT_PRIVACY_PROTOCOL is set. |
--wallet <name> |
Wallet. |
--password <password> / --password-file <path> |
Unlock password. |
--to <address> |
Final recipient: public address, Railgun 0zk address, stealth selector (s0), or name (.eth / .gwei / .wei). A stealth selector is paid by the tail call; its key is not the delegator. |
--token <address|symbol|eth> |
Token (default: eth). |
--exclude-new-pools |
Tornado only: use classic pools. |
--amount-wei <n> |
Exact amount the recipient receives, in base units. |
--amount-formatted <decimal> |
Exact amount the recipient receives. |
--amount-max |
Maximum recipient amount after estimated protocol and gas fees. |
--rpc-url <url> |
RPC endpoint. |
--broadcast |
Submit via the protocol bundler or paymaster. Omit to print the prepared private operation. |
--without-tor |
Disable Tor for non-RPC HTTP. |
--non-interactive |
JSON; requires --wallet, --password or --password-file, --to, and one of --amount-wei, --amount-formatted, or --amount-max. |
--dataDir <path> |
Data root. |
Use --amount-max (or enter max interactively) to send the available amount after estimated fees. Legacy and signature-derived notes stay separate; Railgun also reserves private WETH for gas. There is no --next or --tail-calls. For public recipients, the fresh account is persisted only after a successful --broadcast. Railgun internal transfers use a fresh wallet-owned 4337 executor, persisted after broadcast, but do not create a fresh receiving account or unshield funds to it.
transfer --from railgun, transfer --from tornado, and transfer --from privacy-pools are aliases for this command with the corresponding --protocol value.
Tornado: the paymaster fee is taken from the unshielded notes, so the command unshields the smallest note sum that covers the transfer plus that fee. A 0.1 ETH payment can require more than 0.1 ETH in notes to cover the fee. The tail pays exactly 0.1 ETH and the remainder stays on the fresh account. The same rule applies to tokens (--token DAI and the other paymaster fee-adapter tokens).
Railgun and Privacy Pools: the unshield net equals the transfer amount, so the tail can drain the fresh account to zero. Railgun’s treasury fee is added on top of that amount. Railgun bundler gas is paid from shielded WETH. The Privacy Pools paymaster fee is paid from the private balance on top of the net. On Privacy Pools the fresh account is the delegate and the refund recipient — --to is not. Unused-gas change stays on the fresh account and is not forwarded.
Railgun 0zk recipient: private-transfer --protocol railgun and transfer --from railgun prepare a direct Railgun transfer with no unshield or tail call. The amount is the exact private token amount delivered; eth selects private WETH. The signed operation still uses the ERC-4337 paymaster, which charges private WETH for gas. The CLI activity log records the sending 0zk address, receiving 0zk address, UserOp hash, and mined transaction hash when available.
Examples:
kohaku private-transfer --protocol tornado --wallet testWallet --to 0xFriend --amount-formatted 0.1 --broadcast
kohaku private-transfer --protocol railgun --wallet testWallet --to 0xFriend --amount-formatted 0.1 --broadcast
kohaku private-transfer --protocol railgun --wallet testWallet --to 0zk1... --amount-formatted 0.1 --broadcast
kohaku private-transfer --protocol privacy-pools --wallet testWallet --to 0xFriend --amount-formatted 0.1 --broadcast
kohaku private-transfer --protocol tornado --wallet testWallet --to 0xFriend --token DAI --amount-formatted 50 --broadcast
# ragequit
Return the full remaining balance of one unapproved Privacy Pools note to its original depositor. The depositor must sign and hold ETH for gas. This reveals the deposit link; use unshield for approved notes. Get the label from balances --include privacy-pools --verbose.
| Option | Description |
|---|---|
--label <label> |
Required note label, decimal or hex. |
--scheme <signature|legacy> |
Note derivation scheme (default: signature). |
--from <address-or-index> |
Original depositor; defaults to the note depositor. Supports saved address, HD index, or stealth selector. |
--sender-priv <key> |
Sign for an external original depositor. The key must match --from and is not saved. Interactive broadcasts prompt with hidden input if needed; non-interactive broadcasts require this option. Unsaved HD indexes are derived automatically. |
--wallet <name> |
Wallet. |
--password <password> / --password-file <path> |
Unlock password. |
--rpc-url <url> |
RPC endpoint. |
--broadcast |
Sign and submit; omit to simulate and print payloads. |
--without-tor |
Disable Tor for non-RPC HTTP. |
--non-interactive |
No prompts; supply wallet and password. |
--dataDir <path> |
Data root. |
kohaku ragequit --wallet testWallet --label 123
kohaku ragequit --wallet testWallet --label 123 --scheme legacy --broadcast
# import-tornado-note
Import legacy Tornado Cash note string(s) into this wallet (deposits that were not made from this mnemonic). Notes are synced against chain state and stored for later unshield / export-tornado-note.
| Argument | Description |
|---|---|
<notes...> |
One or more legacy note strings: tornado-<currency>-<denom>-<chainId>-0x… |
| Option | Description |
|---|---|
--wallet <name> |
Wallet. |
--password <password> |
Unlock password. |
--rpc-url <url> |
RPC endpoint. |
--without-tor |
Disable Tor for privacy HTTP (default: Tor on). |
--non-interactive |
No prompts; requires --wallet and --password. |
--dataDir <path> |
Data root. |
Examples:
kohaku import-tornado-note --wallet testWallet 'tornado-eth-0.1-11155111-0x…'
# export-tornado-note
Export unspent Tornado Cash note secret(s) for an exact pool denomination (legacy note strings compatible with import-tornado-note). Interactive mode confirms before printing secrets; --non-interactive skips the confirmation.
| Option | Description |
|---|---|
--wallet <name> |
Wallet. |
--password <password> |
Unlock password. |
--rpc-url <url> |
RPC endpoint. |
--token <address|symbol|eth> |
Token (default: eth). |
--amount-wei <n> |
Exact pool denomination in base units. |
--amount-formatted <decimal> |
Exact pool denomination as a decimal. |
--without-tor |
Disable Tor for privacy HTTP (default: Tor on). |
--non-interactive |
No prompts; requires --wallet and --password. |
--dataDir <path> |
Data root. |
Provide exactly one of --amount-wei or --amount-formatted.
Examples:
kohaku export-tornado-note --wallet testWallet --amount-formatted 0.1
kohaku export-tornado-note --wallet testWallet --token DAI --amount-formatted 100 --non-interactive
# Names (.eth / .gwei / .wei)
Commands below manage top-level ENS (.eth), GNS (.gwei), and WNS (.wei) names. Shared options:
| Option | Description |
|---|---|
--wallet <name> |
Wallet. |
--password <password> |
Unlock password. |
--rpc-url <url> |
RPC endpoint. |
--broadcast |
Sign and submit on-chain. Omit to simulate / print payloads. |
--owner-priv |
Derive --index from the seed when that account is not yet in public accounts. |
--without-tor |
Disable Tor for non-RPC HTTP (Pimlico when broadcasting UserOps, etc.). RPC stays clearnet. Or set KOHAKU_WITHOUT_TOR=1. |
--non-interactive |
JSON where applicable; requires --wallet and --password. |
--dataDir <path> |
Data root. |
--index on most name commands is only needed when the required HD account is not stored in the public accounts list yet (the controller is still a specific seed index). register-name is different: --index selects which account will own the new name (default 0).
ENS has separate owner (NFT / registrant) and manager (registry owner for records). GNS/WNS have a single NFT owner only.
# register-name
Register a top-level name: commit → 60s wait → reveal/register.
| Option | Description |
|---|---|
--protocol <ens|gns|wns> |
Required. Naming system. |
--name <label-or-name> |
Bare label (alice) or full name (alice.gwei). TLD must match --protocol when present. |
--index <n> |
HD account that will own the name (default: 0). |
--years <n> |
Duration in whole years (ENS only; GNS/WNS always 1 year). Default: 1. |
--set-reverse |
Also set this name as the account’s primary reverse record. |
Plus shared name wallet options above.
Examples:
kohaku register-name --wallet testWallet --protocol ens --name alice --years 1 --broadcast
kohaku register-name --wallet testWallet --protocol gns --name bob.gwei --index 2 --set-reverse --broadcast
# renew-name
Extend / renew a top-level name. Anyone may pay on-chain; the CLI prefers the name owner when present in the wallet. Interactive mode prompts for --years on ENS (Enter → 1); GNS/WNS always add 1 year.
| Option | Description |
|---|---|
--name <name> |
Required. Full name including TLD. |
--years <n> |
Extension in whole years (ENS only). Interactive default: 1. |
--index <n> |
Only needed when the payer HD index is not stored in public accounts yet (defaults to name owner when present). |
Examples:
kohaku renew-name --wallet testWallet --name alice.eth --years 1 --broadcast
kohaku renew-name --wallet testWallet --name alice.gwei --broadcast
# transfer-name
Transfer name ownership and/or ENS manager. GNS/WNS only support NFT owner transfer. Interactive mode prompts for --to and (ENS) --role when omitted; role default is both.
| Option | Description |
|---|---|
--name <name> |
Required. Full name including TLD. |
--to <address-or-name> |
Recipient address or .eth / .gwei / .wei name; prompted if omitted. |
--role <owner|manager|both> |
What to transfer (default: both). manager / both are ENS-only; prompted if omitted. |
--index <n> |
Only needed when the required HD index is not stored in public accounts yet. |
Examples:
kohaku transfer-name --wallet testWallet --name alice.eth --to 0xRecipient --role both --broadcast
kohaku transfer-name --wallet testWallet --name alice.gwei --to bob.gwei --broadcast
# set-name-text-record
Set a text record on a top-level name. Interactive mode prompts for --key / --value when omitted.
| Option | Description |
|---|---|
--name <name> |
Required. Full name including TLD. |
--key <key> |
Text record key (e.g. url, avatar, com.twitter); prompted if omitted. |
--value <value> |
Text record value (empty string clears); prompted if omitted. |
--index <n> |
Only needed when the required HD index is not stored in public accounts yet. |
Examples:
kohaku set-name-text-record --wallet testWallet --name alice.eth --key url --value https://example.com --broadcast
# set-name-website
Set the contenthash / website for a top-level name (ipfs:// or bzz://). Interactive mode prompts for --content-hash when omitted.
| Option | Description |
|---|---|
--name <name> |
Required. Full name including TLD. |
--content-hash <uri> |
Must start with ipfs:// or bzz://; prompted if omitted. |
--index <n> |
Only needed when the required HD index is not stored in public accounts yet. |
Examples:
kohaku set-name-website --wallet testWallet --name alice.eth --content-hash ipfs://bafy… --broadcast
# set-name-reverse-record
Set a name as the primary reverse record for the signing account.
| Option | Description |
|---|---|
--name <name> |
Required. Full name including TLD. |
--index <n> |
Only needed when the required HD index is not stored in public accounts yet. |
Examples:
kohaku set-name-reverse-record --wallet testWallet --name alice.eth --broadcast
# fetch-sync-cache
Download the mainnet public sync snapshot into <dataDir>/sync-cache-v2. It contains bounded Railgun Subsquid records, complete historical PPOI leaf pages, and frozen Tornado and Privacy Pools Saga history. A fresh wallet reads that history locally. Live Subsquid or RPC covers blocks after the snapshot; live PPOI handles Merkle-root validation, TXID status, proof submission, and the growing list tip. Sepolia keeps its existing sync path and does not use this snapshot.
Each file is checked against its size and SHA-256 in the snapshot manifest. Public files live directly under sync-cache/v2/saga/, sync-cache/v2/railgun/, and sync-cache/v2/ppoi/; verified downloads are stored by hash under <dataDir>/sync-cache-v2/objects/. An interrupted download can be resumed; the CLI activates a snapshot only when every file is present and verified. The previous active v2 snapshot remains usable while a new one downloads. Older <dataDir>/public-sync-cache files are not read by this version.
Live mainnet sync also retains complete PPOI leaf pages and confirmed historical indexer ranges in sync-cache-v2/live, shared across wallets and capped at 256 MiB. Heads, recent indexer state, incomplete PPOI pages, PPOI root validation, status, and submissions remain live. Existing v2 snapshots remain compatible; there is no need to fetch a new one just for this cache change.
| Option | Description |
|---|---|
| (none) | Fetch the snapshot manifest, then install files not already verified on disk. |
--force |
Re-download files even when they already verify locally. |
--without-tor |
Download over clearnet. Much faster, and reveals only that this IP fetched public pool data. Or set KOHAKU_WITHOUT_TOR=1. |
--dataDir <path> |
Data root (cache lives at <dataDir>/sync-cache-v2). |
--non-interactive |
JSON summary only. |
Snapshot base URL: KOHAKU_SYNC_CACHE_BASE_URL (default https://artifacts.0000000000.org/sync-cache/v2). Each file has a five-minute download budget and three attempts.
The command exits nonzero if a file fails. Re-run it to resume; partial snapshots are not used for sync.
Examples:
# Consumers
kohaku fetch-sync-cache
kohaku fetch-sync-cache --without-tor
# Publisher: build a new mainnet snapshot from the live public sources
npx tsx scripts/build-sync-cache-v2-saga.ts ./sync-cache-v2-publish 2026-11-01-ppoi
npx tsx scripts/build-sync-cache-v2-railgun.ts ./sync-cache-v2-publish 2026-11-01-ppoi
npx tsx scripts/build-sync-cache-v2-ppoi.ts ./sync-cache-v2-publish 2026-11-01-ppoi
The Railgun builder reads GraphQL queries from a clean local ../kohaku-rs checkout at commit 357104d3be2e06d91f532563f09c5a9804be088e, matching the pinned WASM package. It can take a while; completed segment files are reused on rerun. The Saga builder verifies the source digest of every sealed and hot chunk before freezing it. The PPOI builder uses the same pinned Rust configuration and freezes only complete historical leaf pages; its source-root checks still happen live in every wallet sync. For a full new snapshot, build on a trusted connection and run both npx tsx scripts/verify-sync-cache-v2.ts ./sync-cache-v2-publish and npx tsx scripts/verify-sync-cache-v2-ppoi.ts ./sync-cache-v2-publish. To extend an already published v2 snapshot, place its current manifest.json in a directory, run only the PPOI builder there, and verify the new files with npx tsx scripts/verify-sync-cache-v2-ppoi.ts <directory>. Upload the new ppoi/ directory to the R2 sync-cache/v2/ prefix, then upload the updated manifest.json last. Existing Saga and Railgun objects stay in place. During an update, a download that encounters an old manifest with newly replaced public files will fail verification and can be retried after the new manifest is live. For staging, point KOHAKU_SYNC_CACHE_BASE_URL at a host serving the release and run kohaku fetch-sync-cache --without-tor --dataDir <scratch-dir> before updating the public manifest.
# view-network-traffic
Browse the per-wallet network traffic log (what the CLI contacted, when, and whether the request went over Tor). Useful for reviewing anonymity risk.
Traffic is appended to <dataDir>/<wallet>/network-traffic.ndjson while you use the wallet (balances / shield / unshield / transfer / …). API keys in URLs are redacted before write. Ethereum RPC is always logged as clearnet.
| Option | Description |
|---|---|
--wallet <name> |
Wallet (optional interactive picker). |
--tor-only / --clearnet-only |
Filter by path. |
--category <name> |
pimlico | subsquid | ppoi | saga | asp | fastrelay | rpc | other. |
--limit <n> |
Last N events only. |
--json |
Print JSON (summary + entries). |
--non-interactive |
Dump the log to stdout (no scroll UI). |
--clear |
Delete this wallet’s traffic log. |
--dataDir <path> |
Data root. |
Interactive (TTY): scrollable viewer — j/k or arrows, space/PgDn, g/G top/bottom, q quit. Tor rows are green; clearnet yellow; errors red.
Examples:
kohaku view-network-traffic --wallet testWallet
kohaku view-network-traffic --wallet testWallet --clearnet-only
kohaku view-network-traffic --wallet testWallet --category rpc --json
kohaku view-network-traffic --wallet testWallet --clear
# clear-tor-cache
Delete the on-disk tor-js Arti cache (~/.local/share/tor-js). Use after Tor bootstrap failures such as corrupted cache / “Unable to bootstrap a working directory”. The next Tor start re-downloads consensus (slower first bootstrap).
| Option | Description |
|---|---|
--public-sync |
Also delete <dataDir>/sync-cache-v2 and old <dataDir>/public-sync-cache files. |
--non-interactive |
Print JSON { cleared, path } instead of a human message. |
Examples:
kohaku clear-tor-cache
kohaku clear-tor-cache --public-sync
kohaku clear-tor-cache --non-interactive
# see-stealth-meta-address
Print this wallet’s scheme-1 stealth meta-address URI (st:<network>:0x…). Derived from the seed; no RPC required.
| Option | Description |
|---|---|
--wallet <name> |
Wallet (prompt if omitted). Required with --non-interactive. |
--password <password> |
Unlock password. |
--non-interactive |
Requires --wallet and --password; prints the URI only. |
--dataDir <path> |
Data root. |
Examples:
kohaku see-stealth-meta-address --wallet testWallet
kohaku see-stealth-meta-address --wallet testWallet --password "$WALLET_PW" --non-interactive
# see-decrypted-storage <type>
Debug helper: decrypt and print wallet storage JSON.
| Argument | public | stealth | railgun | privacy-pools | tornado |
|---|---|
| Options | Same wallet / password / --non-interactive / --dataDir as other commands. |
Files include public-accounts.json, stealth storage, rg-storage.json, ppv1-storage.json, and Tornado note storage.
# Tips
- Dry run vs broadcast:
transfer,transact-raw,shield,unshield,private-transfer,ragequit,init-profile, and the name commands default to prepare or simulate only. Always read the printed transaction data before adding--broadcast. - Tor (all-but-RPC): Non-RPC HTTP (Pimlico, Railgun Subsquid/PPOI, Tornado saga, Privacy Pools ASP, …) goes through tor-js by default on
balances(when syncing private protocols),shield,unshield,private-transfer, Tornado note import/export,transfer,transact-raw, and name commands. Ethereum RPC stays clearnet. Use--without-tororKOHAKU_WITHOUT_TOR=1to skip. Saga CDN requests are Tor-or-fail (no clearnet fallback; large GETs time out afterKOHAKU_TOR_CDN_TIMEOUT_MS, default 45s). Sync progress shows saga and RPC work where totals are available. Proving circuits come from thekohaku-artifactsdependency installed with the CLI and are not fetched at prove time. Prefetch verified mainnet protocol history withkohaku fetch-sync-cache. After Tor bootstrap corruption, runkohaku clear-tor-cache. On mainnet, verified Railgun, historical PPOI, Tornado, and Privacy Pools data come from<dataDir>/sync-cache-v2; live sources handle newer state and PPOI checks. Wipe v2 and old v1 cache files withkohaku clear-tor-cache --public-sync. SetKOHAKU_TOR_DEBUG=1for per-request Tor logs. Review withview-network-traffic --wallet <name>. - Fresh addresses: Use
next-fresh-addressbefore funding, andunshield --next/private-transferwhen you want withdrawals to land on a new public key that was not your shield source. Usenext-fresh-address --peekto see the next address without persisting it (e.g. when building--tail-callsfor a laterunshield --next). Do not pass a peeked address as Tornado / Privacy Pools--totogether with--tail-calls— peeked addresses are not stored, so the CLI will refuse rather than 7702 a note-derived key. - Profile / stealth: Prefer
init-profile(fully interactive with no args) to publish ERC-6538 keys (and optionally a name). Unshield to stored stealth accounts with--to s0. Print the meta URI withsee-stealth-meta-address. New wallets and imports store.stealth-start-blockat the current chain tip so firstbalancesstealth scans skip pre-wallet announcer history. Passcreate-wallet --import --stealth-start-block(bare) for the Kohaku-schema floor (mainnet25700000/ Sepolia11455454), or an explicit block. Laterbalances --stealth-start-blockcan still back-date below the file. - Exact pays from private balance: Prefer
private-transferover manually crafting a transfer--tail-calls. - Tornado notes: Use
export-tornado-note/import-tornado-noteto move legacy note secrets between wallets for testing or recovery. - Private key / seed exports:
export-private-key,reveal-seed-phrase, andexport-tornado-noteprint raw secrets to stdout. Avoid terminal logs, shell history, and shared environments. - Agents: Pass
--non-interactive --password-file … --wallet …and parse JSON stdout; setRPC_URLin the environment to avoid repeating--rpc-url.