@towns-labs/wallet-cli
v6.0.0
Published
CLI for `tw` account onboarding, session key lifecycle, and relayed transactions.
Readme
towns wallet-cli
CLI for tw account onboarding, session key lifecycle, and relayed transactions.
Built on incur — every command supports --help, --json, --format, and can run as an MCP server via --mcp.
Permissionless
tw is fully permissionless: no signup, no account registration, and no login flow. You can run it immediately with local keys.
Output Modes
incur handles output formatting automatically:
--json— structured JSON output--format table— tabular output- Default: human-readable text
Help and Discovery
# Show all commands
tw --help
# Show help for a specific command
tw account create --help
# Machine-readable command manifest (for LLMs/agents)
tw --llms
# Run as an MCP server
tw --mcp
# Version
tw --versionAccount Create
Create a new account (interactive password prompt):
tw account createCreate a named profile in local dev:
tw account create --env dev --profile agentKeystore layout:
~/.config/towns/tw/profiles/<env>/<profile>/default.keystore.json
~/.config/towns/tw/profiles/<env>/<profile>/sessions/<session-name>.jsonResume a previously created profile:
tw account create --resume --env dev --profile agentNon-interactive mode (stdin password + JSON output):
echo "my-password" | tw account create --password-stdin --jsonUse an explicit keystore path:
tw account create --keystore-path ~/.config/towns/tw/profiles/dev/team/default.keystore.json --env devAccount Export
Export metadata only (safe default):
tw account export --env dev --profile agentExport metadata in JSON:
tw account export --env dev --profile agent --jsonExport decrypted private keys (interactive confirmation required):
tw account export --env dev --profile agent --show-privateAccount Address
Print the main/root account address:
tw account address --env dev --profile agentAddress (Root Alias)
tw address is a root alias for tw account address with optional funding display helpers.
Print address + default funding context (USDC on Base):
tw addressShow a funding payment link:
tw address --link --amount 100Show a QR for the same payment payload:
tw address --qr --amount 100Custom token amount requires explicit decimals:
tw address --token 0x1111111111111111111111111111111111111111 --amount 1 --decimals 18 --linkAccount Balance
Check USDC balance for the main/root account on Base (default):
tw account balance --env dev --profile agentCheck USDC balance on Polygon:
tw account balance --env prod --profile agent --chain polygonFor local dev (--env dev), default chain is Anvil (http://127.0.0.1:8545).
Account Send
Send USDC to an address:
tw account send 1 0x1111111111111111111111111111111111111111Send USDC to ENS on Base:
tw account send 2.5 vitalik.eth --chain baseSend USDC on Polygon with JSON output:
tw account send 10 0x1111111111111111111111111111111111111111 --chain polygon --env prod --jsonLocal dev defaults to Anvil:
tw account send 1 0x1111111111111111111111111111111111111111 --env devContacts
Store aliases in a global contacts file:
~/.config/towns/tw/contacts.jsonAdd contact aliases:
tw contacts add vitalik vitalik.eth
tw contacts add treasury 0x1111111111111111111111111111111111111111List or show contacts:
tw contacts list --json
tw contacts show vitalik --jsonUpdate, rename, and remove:
tw contacts update vitalik 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045
tw contacts rename vitalik vitalik-main
tw contacts remove vitalik-mainExport and import:
tw contacts export --json
tw contacts import ./contacts.json --json
tw contacts import ./contacts.json --force --jsonImport returns deterministic summary fields:
importedCountskippedInvalidCountskippedConflictCountoverwrittenCount
Send via alias:
tw account send 10 vitalikENS safety behavior for ENS-backed contacts:
- If ENS re-resolution fails,
tw account sendfalls back to the stored address. - If ENS re-resolution succeeds but points to a different address than stored, send aborts and requires explicit
tw contacts update.
Send with a portable session file (no root keystore required):
tw account send 1 0x1111111111111111111111111111111111111111 \
--env prod --chain base --session-file ./worker-1.session.jsonAccount Status
Show compact readiness status:
tw account status --env dev --profile agentJSON output for automation:
tw account status --env prod --profile agent --chain polygon --jsonAccount Update Password
Rotate local keystore encryption password (interactive):
tw account update password --env dev --profile agentRotate password non-interactively using stdin lines:
printf "old-password\nnew-password\n" | tw account update password --current-password-stdin --new-password-stdin --jsonSession Create
Create and authorize a scoped session key in one intent:
echo "my-password" | tw session create worker-1 --profile agent --password-stdin --jsonCreate and activate immediately:
echo "my-password" | tw session create worker-2 --profile agent --activate --password-stdinResume a previously interrupted create flow:
echo "my-password" | tw session create worker-1 --profile agent --resume --password-stdin --jsonGrant full wildcard access (explicit opt-in):
echo "my-password" | tw session create worker-admin --profile agent --full-access --password-stdinSession List
List local sessions:
tw session list --profile agent --jsonInclude on-chain key status:
tw session list --profile agent --on-chain --jsonSession Export
Export a session key as a portable file:
TW_PASSWORD="my-password" TW_EXPORT_PASSWORD="export-password" \
tw session export worker-1 --profile agent --output ./worker-1.session.jsonOr provide the export password via stdin:
echo "export-password" | tw session export worker-1 --profile agent \
--output ./worker-1.session.json --export-password-stdinSession Import
Import a portable session as a session-only profile:
tw session import ./worker-1.session.json --profile worker-1This creates:
~/.config/towns/tw/profiles/worker-1/session.jsonSession-only profiles can execute account send but cannot run manager commands that require a root keystore.
Session Rotate
Rotate the active session (auto-generates new name):
echo "my-password" | tw session rotate --profile agent --password-stdin --jsonRotate to an explicit new session name:
echo "my-password" | tw session rotate --profile agent --new-name worker-3 --password-stdinResume interrupted rotation:
echo "my-password" | tw session rotate --profile agent --resume --password-stdin --jsonSession Revoke
Revoke a non-active session on-chain, verify, then delete local file:
echo "my-password" | tw session revoke worker-1 --profile agent --password-stdin --jsonForce revoke active session:
echo "my-password" | tw session revoke worker-2 --profile agent --force --password-stdinIdempotent retry/cleanup when already revoked on-chain:
echo "my-password" | tw session revoke worker-2 --profile agent --resume --password-stdin --jsonPermissions List
List all on-chain keys with summarized call/spend permissions:
tw permissions list --profile agent --jsonPermissions Show
Show full permission rules for a key using positional <key-ref>:
tw permissions show agent-key --profile agent --jsonExplicit selectors are also supported:
tw permissions show --key-hash 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa --profile agent --jsonPermissions Grant
Grant wildcard call permission:
echo "my-password" | tw permissions grant agent-key --type call --target any --selector any --profile agent --password-stdin --jsonGrant spend permission for daily USDC limit:
echo "my-password" | tw permissions grant agent-key --type spend --token USDC --spend-limit 100 --period day --profile agent --password-stdin --jsonPermissions Revoke
Revoke one rule by stable rule id:
echo "my-password" | tw permissions revoke agent-key --rule call:0x2222222222222222222222222222222222222222:0xa9059cbb --profile agent --password-stdin --jsonRevoke all call/spend rules for a key:
echo "my-password" | tw permissions revoke agent-key --all --profile agent --password-stdin --jsonPassword Automation
Use TW_PASSWORD for non-interactive flows:
TW_PASSWORD="my-password" tw session list --profile agent --jsonStdin is supported for commands requiring keystore decryption/signing:
echo "my-password" | tw session rotate --profile agent --password-stdin --json