The sb CLI
@safebank/cli is the sb command-line interface — programmable banking from
your terminal, built on @safebank/sdk. Use it for
scripting, CI, and exploring the API by hand.
Build and run
From the monorepo:
pnpm --filter @safebank/cli build
node packages/cli/bin/sb.js --help
Every command accepts these global flags:
| Flag | Purpose |
|---|---|
--api-key <key> | Key for this invocation (overrides profile / env). |
--base-url <url> | Override the API base URL. |
-p, --profile <name> | Config profile to use. |
--json | Machine-readable JSON output. |
Try the demo (no API key needed)
The fastest way to see the whole choreography — create wallet → on-ramp →
issue a card → claim a handle → pay @volt-components (signed locally) →
delegate to an agent → stand up a treasury and fire a sweep → off-ramp — is
the dry run against an in-memory stub:
node packages/cli/bin/sb.js demo --dry-run
--dry-run makes no network calls and needs no key; it's also the CI gate
that keeps the demo from rotting. Drop --dry-run to run it for real against a
sandbox profile:
sb demo # real end-to-end run
sb demo --fast # skip the narration pauses
Log in
Save an API key as a local profile (written to ~/.safebank/config.json).
login validates the key by resolving your tenant:
sb login sb_test_... # saves under the `sandbox` profile by default
sb whoami # show the active profile + tenant
Credentials resolve in order: --api-key flag → SAFEBANK_API_KEY /
SAFEBANK_API_URL env → the active profile. On first use a sandbox demo
signer is generated and stored (mode 0600) at
~/.safebank/demo-signer.json.
Command tree
- Overview
- wallets
- pay
- cards
- treasury
- ramp
sb
├── login [apiKey] Save an API key as a profile
├── whoami Show the active profile + tenant
├── wallets
│ ├── create Create a multisig wallet
│ ├── list List your wallets
│ ├── get <id> Show a wallet with balances
│ └── fund <id> Fund a wallet from the sandbox faucet
├── pay
│ ├── send Send USDC to a @handle or 0x address
│ └── list List payments
├── cards
│ ├── issue Issue a Safe-funded card from a wallet
│ ├── limits show|set View / set spend limits
│ └── freeze | unfreeze Toggle a card
├── agents
│ ├── create | key | limits Agent principals + scoped keys + caps
│ └── suspend | reactivate The agent kill-switch
├── treasury
│ ├── setup | list | status Bucketed treasury accounts
│ ├── rules add|list|toggle|rm Standing sweep rules
│ └── sweep | sign | sweeps Propose / sign / list sweeps
├── ramp
│ ├── on <walletId> On-ramp USDC (fiat simulated)
│ ├── off <walletId> Off-ramp toward fiat (owners sign)
│ └── list List ramps
├── policies
│ ├── create | list | versions Versioned policy documents
│ ├── add-version | attach|detach Commit versions / bind to a subject
│ └── evaluate Deterministic dry-run + rule trace
└── demo Run the scripted end-to-end flow
sb wallets create --name "Acme Treasury" --threshold 1 --wait
sb wallets create --owner 0xYourSigner # default owner is your demo signer
sb wallets list
sb wallets get <walletId> # includes balances
sb wallets fund <walletId> --usdc 250
sb wallets fund <walletId> --eth # drip ETH for gas
--wait on create polls until the Safe is DEPLOYED on-chain.
# Proposes, signs locally (raw secp256k1), and executes in one command.
sb pay send --from <walletId> --to @volt-components --amount 25.00
sb pay send --from <walletId> --to 0xRecipient --amount 10 --memo "invoice"
sb pay list
--to accepts a @handle, a 0x address, or an email.
sb cards issue --wallet <walletId> --daily 500 --monthly 5000
sb cards limits set <cardId> --per-txn 250 --block-mcc 7995
sb cards freeze <cardId>
# name:kind:targetBps[:apyBps] — one Safe per bucket
sb treasury setup --name "Acme Treasury" \
--bucket Operating:operating:6000 \
--bucket Reserve:reserve:3000 \
--bucket Yield:yield:1000:450
sb treasury status <accountId>
sb treasury rules add <accountId> --type sweep_excess \
--source <ops> --dest <reserve> --threshold 1000
sb treasury sweep <accountId> --from <ops> --to <reserve> --amount 250 --sign
sb ramp on <walletId> --amount 100 # credit USDC (fiat simulated)
sb ramp off <walletId> --amount 50 --sign # debit toward fiat (owners sign)
sb ramp list
Scripting with --json
Every command supports --json for piping into jq or other tooling:
WALLET=$(sb wallets create --name CI --json | jq -r .id)
sb wallets fund "$WALLET" --usdc 250 --json
sb pay send --from "$WALLET" --to @volt-components --amount 5 --json | jq .status
See also
- Quickstart — the same flow, with response shapes.
- TypeScript SDK — the library the CLI is built on.