Skip to content

CLI Reference

This is the command surface for @ckb-firewall/cli.

  • Node 20+ required
  • ESM only
  • Defaults point to the canonical testnet registry cell and contracts
  • Registry-touching commands fetch live cell data through the CKB RPC before building anything
  • inspect, check, and execute auto-discover the current registry cell outpoint via the CKB indexer (get_cells) when using testnet defaults, so they keep working after governance updates without requiring --registry-tx overrides. Falls back silently to the configured outpoint if the indexer is unavailable.

Show the current registry entries with their expiry status.

Terminal window
ckb-firewall inspect
ckb-firewall inspect --rpc-url https://testnet.ckb.dev

Options: --rpc-url, --registry-tx, --registry-index


Test whether a specific lock args is currently blacklisted.

Terminal window
ckb-firewall check --lock-args 0xabc123...

Options: --lock-args (required), --rpc-url, --registry-tx, --registry-index


Create a governance proposal. All fields are hashed together into a canonical proposalIdHash — every field is immutable after creation.

Terminal window
ckb-firewall propose \
--action add \
--lock-args 0xabc123... \
--evidence https://evidence.example/... \
--classification theft \
--severity high \
--rationale "Drained 50k CKB from multiple wallets in a single transaction." \
--proposer alice

To activate or rotate the registry treasury metadata, create a metadata proposal:

Terminal window
ckb-firewall propose \
--action set-treasury \
--treasury-lock-code-hash 0x... \
--treasury-lock-hash-type type \
--treasury-lock-args 0x... \
--evidence https://evidence.example/treasury \
--classification other \
--severity high \
--rationale "Activate the public registry treasury for proposal anchors and growth." \
--proposer alice

Options: --action, --lock-args, --expires-at, --evidence, --classification, --severity, --rationale, --proposer, --treasury-lock-code-hash, --treasury-lock-hash-type, --treasury-lock-args, --review-delay-ms (override the on-chain review delay in ms; testnet/drill use only)

Classifications: theft, scam, hack, sanctions, other
Severities: critical, high, medium, low

Proposal actions: add, remove, set-treasury. set-treasury creates a PBLK v2 proposal cell that binds the target treasury lock hash. It keeps the blacklist entries unchanged and updates only the governance header treasury metadata.

After creation the CLI prints an export command. Share the exported JSON with other governance participants via export / import.


List proposals and their current status.

Terminal window
ckb-firewall proposals
ckb-firewall proposals --status voting

Options: --status (pending-review, voting, approved, executed, rejected)


Record a cryptographically signed validator vote on a proposal.

Terminal window
ckb-firewall vote --proposal abc123 --vote yes
# prompts for private key

Options: --proposal, --vote (yes, no, abstain), --rpc-url, --registry-tx, --registry-index

The CLI prompts for the validator private key with masked input. Pass --private-key <hex> to provide it non-interactively (scripted use only — do not use in shared environments).

What this command does:

  1. Derives the compressed public key from the provided private key
  2. Checks the pubkey is in the authorized validator set (Merkle membership proof against the on-chain validatorMerkleRoot in the BLKL governance header)
  3. Rejects the vote if the key is not an authorized validator
  4. Signs the vote: blake2b({domain:"ckb-firewall:vote", proposalIdHash, vote, timestamp, pubkey})
  5. Stores the vote locally with signature and Merkle proof
  6. Updates the voteDigestHash — a commitment to the full set of votes cast so far

Votes are local until execute. Export and share the updated proposal so other participants can import your vote.


Build or submit the on-chain PBLK proposal cell used by GOV1 v4 execution.

Terminal window
ckb-firewall anchor --proposal abc123 --to-address ckt1...
ckb-firewall anchor \
--proposal abc123 \
--to-address ckt1... \
--from-account ckt1... \
--submit
ckb-firewall anchor \
--proposal abc123 \
--proposal-tx 0x... \
--proposal-index 0

Options: --proposal (required), --rpc-url, --registry-tx, --registry-index, --to-address, --from-account, --capacity, --fee-rate, --privkey-path, --output-index, --proposal-tx, --proposal-index, --proposal-anchor-code-tx, --proposal-anchor-code-index, --treasury-cell, --treasury-lock-dep, --tx-out, --submit

For non-treasury registries, without --submit, the command prints the exact ckb-cli wallet transfer --to-data ... command. With --submit, it runs ckb-cli, submits the proposal cell transfer, and stores the resulting proposal-cell outpoint on the proposal JSON.

For treasury-backed registries, anchor builds a keyless proposal-anchor transaction funded by the autonomous treasury pool — no private key required:

Terminal window
# Build the TX (keyless — treasury-lock validates without a signature)
ckb-firewall anchor \
--proposal abc123 \
--tx-out gov_anchor_tx.json
# Build and submit in one step (still keyless)
ckb-firewall anchor \
--proposal abc123 \
--submit

The CLI auto-discovers treasury cells from the registry’s governance header. To select specific treasury cells manually, add --treasury-cell <tx-hash>:<index> one or more times. For private deployments, override the proposal-anchor code outpoint with --proposal-anchor-code-tx and --proposal-anchor-code-index, and add --treasury-lock-dep <tx-hash>:<index>[:code|dep_group] for any extra cell deps required by a custom treasury lock.

If you create the cell separately, run anchor again with --proposal-tx and --proposal-index to record the outpoint.

After the outpoint is stored, execute can infer it:

Terminal window
ckb-firewall execute --proposal abc123

Build the registry update transaction from an approved validator-voted proposal. Verifies vote signatures and Merkle proofs before building a witness that the on-chain governance lock verifies again.

Terminal window
ckb-firewall execute \
--proposal abc123 \
--tx-out ./gov_tx.json

Options: --proposal, --rpc-url, --registry-tx, --registry-index, --proposal-tx, --proposal-index, --proposal-anchor-code-tx, --proposal-anchor-code-index, --treasury-cell, --treasury-lock-dep, --tx-out, --sign, --from-account, --privkey-path (non-interactive key file for signing), --ready (find and execute all proposals whose review window has passed and vote threshold is met)

--proposal-tx and --proposal-index override the stored live PBLK proposal-cell outpoint when needed. The generated transaction spends that proposal cell with a relative timestamp since delay and returns its remaining capacity as change.

For treasury-backed registries, execute is also fully keyless — the autonomous treasury-lock funds any registry capacity growth:

Terminal window
# Default: keyless — treasury cells auto-discovered, no private key required
ckb-firewall execute --proposal abc123
# Override: specify treasury cells manually (still keyless)
ckb-firewall execute \
--proposal abc123 \
--treasury-cell 0x...:0 \
--treasury-cell 0x...:1

The treasury-lock contract validates the TX by detecting the proposal-anchor input being consumed, so no signature is needed. Proposal cell capacity is returned to the treasury pool automatically.

For private deployments, override the proposal-anchor code outpoint with --proposal-anchor-code-tx/--proposal-anchor-code-index, and add --treasury-lock-dep <tx-hash>:<index>[:code|dep_group] for extra treasury cell deps.


Build a transaction that reclaims a rejected or abandoned treasury-funded proposal anchor without changing the registry.

Terminal window
ckb-firewall reclaim \
--proposal abc123 \
--tx-out ./gov_reclaim_tx.json

Options: --proposal, --rpc-url, --registry-tx, --registry-index, --proposal-tx, --proposal-index, --proposal-anchor-code-tx, --proposal-anchor-code-index, --treasury-lock-dep, --tx-out, --sign, --from-account, --force

reclaim verifies the live PBLK cell data against the local proposal and current registry type ID, checks that the anchor is locked to the registry treasury, checks that the anchor carries the proposal-anchor type args, sets the same relative timestamp since delay used by execution, and returns the remaining capacity to the treasury lock. On canonical testnet, the deployed proposal-anchor code outpoint is used by default. Use --treasury-lock-dep for any extra cell deps required by a custom treasury lock.

By default, reclaim refuses proposals that are still in their review window or that appear executable. Use --force only after governance has decided not to execute the proposal.


Launch the browser-based governance dashboard.

Terminal window
ckb-firewall gui
ckb-firewall gui --port 8080
ckb-firewall gui --no-open

Options:

OptionDefaultDescription
--port7979Port for the local app server
--no-openStart the server without opening a browser tab

The command attempts to bind port 80 and serve the dashboard at http://ckb-firewall.localhost (no port in the URL). If port 80 is unavailable it falls back to http://ckb-firewall.localhost:<port>. To get the portless URL without sudo, grant Node the capability to bind low ports:

Terminal window
# Linux
sudo setcap cap_net_bind_service+eip $(which node)
# macOS
sudo ckb-firewall gui
# Windows (run terminal as Administrator)
ckb-firewall gui

Press Ctrl+C to stop the server. The server uses the same --rpc-url and registry defaults as inspect.

For a walkthrough of the GUI interface see GUI mode.


Export a proposal to a shareable JSON file for multi-party governance coordination.

Terminal window
ckb-firewall export --proposal abc123 --out proposal-abc123.json
ckb-firewall export --proposal abc123 # prints to stdout

Options: --proposal, --out


Import a proposal shared by another governance participant. Validates proposalIdHash and voteDigestHash integrity before saving. If the proposal already exists locally, votes are merged rather than overwritten.

Terminal window
ckb-firewall import proposal-abc123.json
ckb-firewall import proposal-abc123.json --force

Arguments: <file> (required)
Options: --force (skip overwrite confirmation)


All registry changes go through governance. The proposal is a local JSON file until execute submits it on-chain. No private key is required for anchor or execute — the autonomous treasury-lock funds both operations.

propose → anchor → export → [share] → import → vote → export → [share] → import → execute
  1. Any participant runs propose to create the proposal file, then anchor to lock it on-chain (funded by the treasury pool — no key needed). Anchoring first starts the review window clock.
  2. The JSON is exported and shared out-of-band (email, Signal, IPFS, etc.)
  3. Each validator runs import to receive it, then vote with their validator key, then export again to share their vote
  4. After the review window and vote threshold are met, any participant runs execute — also funded by the treasury pool, no key needed

There is no sign command. Validator vote signatures are collected during vote and embedded in the execute witness by execute itself.

The minimum timeline is approximately 96 hours (72h review window + time for validators to vote). The CLI warns if a temporary entry’s expiresAt falls within this window.