@cryptocadet/cli

中文文档
0.3.0发布于 2026/11/01UNLICENSEDES Module构建来源已验证

CryptoCadet v4 client package: agent hot-wallet signer + local policy engine (Base/USDC).

原始使用文档
文档目录8 节
  1. Install
  2. The load-bearing guarantee
  3. Trust model & blast radius
  4. Locked decisions
  5. Surfaces
  6. Two secrets, two keychain entries
  7. On-disk layout — ~/.cryptocadet/
  8. Build / test

@cryptocadet/cli — Local Signer + Policy Engine (v4 Instruction 01)

The buyer-side spending component of CryptoCadet v4. Holds a dedicated agent hot wallet with a bounded float, enforces a local policy as the sole spending control (no smart account, no on-chain caveat enforcer), and signs ERC-20 payments on Base. The user's main wallet key never enters this package in any code path.

This is the CLIENT package. The cryptocadet server holds no keys and must never import this module.

Install

macOS:      brew install thetechjd/cryptocadet-cli/cryptocadet
Linux:      curl -fsSL https://cryptocadet.app/install.sh | sh
Node (any): npm i -g @cryptocadet/cli

Then:       cryptocadet init

The brew and curl artifacts are self-contained binaries (Node 24 embedded) — no node, npm, or node_modules on the user's machine. The npm channel needs Node ≥ 22.5 (built-in node:sqlite). Windows: use the npm channel for v4.0. The curl installer is install.sh at the repo root (served from https://cryptocadet.app/install.sh); the build script, Homebrew formula, and release checklist live in packaging/.

The load-bearing guarantee

Every signing decision passes through evaluate() — pure, synchronous, fail-closed (any error/missing field/unparseable amount ⇒ DENY). There is exactly one signing call site for the agent payment path, and it is gated on gate.allow === true:

  • The gate + single broadcast live in PaymentSigner.pay().
  • The real key-signing primitive (sendTransfer) is wired in exactly one place, liveBroadcaster, which is the production tail of that single gated path.
  • test/single-gate.test.ts proves this by source inspection — add a second payment-signing path and it fails.

The only other transaction-signing path is sweep — the human-only revocation drain, never registered on the agent transport.

Trust model & blast radius

The detached signer unlocks the agent key from the OS keychain (one OS authorization) and holds the plaintext only in process memory for the session — never on disk. Anything that can read this process's memory while it runs can obtain the agent key. This is why the float is bounded: the blast radius is the float, never the main wallet. Top-up from the main wallet is always a human action; nothing auto-drains it.

Locked decisions

  • Network: Base only (8453 mainnet / 84532 Sepolia). Asset: USDC default, other ERC-20s per the local allowlist. No native-token spending, ever.
  • Fee-on-transfer tokens: rejected at allowlist time (edit_allowlist refuses them; evaluate() refuses them as a backstop). Settlement would otherwise under-deliver.
  • Subscription floor: spendable = balance − subscriptionReserve. Per-call payments may never cross the reserve (evaluate() step 6).
  • pay takes a server-issued quoteId only — never a raw recipient/amount. A poisoned "pay 0xattacker" instruction has no quote to ride on, and a forged quote fails the recipient allowlist.
  • Revoke = rotate + sweep. Sweep is balance-discovery-driven (inbound Transfer-log scan), so a forgotten long-tail token is drained too; native gas is drained last.

Surfaces

The client is one binary (cryptocadet, alias ccx) serving both roles — an account can be both buyer and seller. Commands are grouped on two axes: local-vs-remote state, and agent-exposed-vs-human-only.

Agent-facing MCP (exactly four verbs — AGENT_TOOL_NAMES): check_balance, quote_payment, pay, dry_run. Wired in runtime.ts via buildAgentTools only; test/command-surface.test.ts proves the two surfaces are disjoint.

LOCAL state — human-only (keys + policy, never leave the machine): init, wallet:show, policy:show, policy:set (caps/reserve/escalation), allowlist:add/ allowlist:remove (tokens + recipients), topup:request (human-approved, no auto-drain), checkout (pay a merchant-supplied signed quote — see below), rotate (--and-sweep --to), sweep --to <addr>, reserve:check.

checkout --quote-json <json> | --quote-file <path> [--allowlist-recipient] [--approve|--yes] — the human one-shot pay verb, for merchant checkout flows (e.g. a host tool topping up a credit balance). The merchant issues a quote from its own server account, so the buyer cannot re-fetch it by id (GET /v4/quotes/:id is account-scoped); instead the merchant hands over the full SignedQuote and this verb pays it through the same gated PaymentSigner.pay() the agent transport uses — the serverSig is re-verified against the pinned pubkey and every field re-checked against local policy before the single broadcast, so the quote's transport need not be trusted. --allowlist-recipient adds the quote's payout to the recipient allowlist first (the fail-closed policy ships with none); --approve confirms an above-threshold (ESCALATE) quote out-of-band. Reads the quote from --quote-json, --quote-file, or piped stdin.

REMOTE state — server postgres via authenticated API (seller/buyer, no key risk): login/logout, product:list|create|update|disable, payout:set, subs:list|create|cancel, history.

mcp:serve [--detach|--stop|--status] — RDK detach pattern: PID file under ~/.cryptocadet, keychain unlock on detached start, clean stop/status.

Two secrets, two keychain entries

The agent wallet key (keychainRef) and the server credential (serverAuthRef, API key or JWT) are different secrets with different blast radii and live in separate OS-keychain entries. The server credential is never written to a plaintext dotfile. Heavy/native/optional deps (e.g. keytar) install on first use via requireDep, never at package-install time.

On-disk layout — ~/.cryptocadet/

agent.key.enc (AES-256-GCM, data key in OS keychain) · policy.json (sole enforcement) · ledger.sqlite (idempotency + pending-tx) · config.json (non-secret).

Build / test

pnpm install
pnpm typecheck     # tsc --noEmit, strict
pnpm test          # vitest — adversarial diagnostics 1–14
pnpm build         # emits dist/, bin: cryptocadet

Requires Node ≥ 22.5 (built-in node:sqlite). No native modules; the OS keychain is reached via keytar if present, else the platform CLI (secret-tool/security).

版本与发布记录

@cryptocadet/cli 共发布 8 个版本,首次发布于 2026/07/08;过去 12 个月发布了 8 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.3.0latest2026/11/012 天前
0.2.12026/07/233 个月前
0.2.02026/07/223 个月前
0.1.42026/07/213 个月前
0.1.32026/07/103 个月前
0.1.22026/07/093 个月前

关于 @cryptocadet/cli 的常见问题

@cryptocadet/cli 是什么?

CryptoCadet v4客户端包:代理热钱包签名者+本地策略引擎(Base/USDC)。

如何安装 @cryptocadet/cli?

在项目目录运行 npm install @cryptocadet/cli,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 ccx、cryptocadet,可以用 npx ccx 直接运行。

@cryptocadet/cli 支持 TypeScript 吗?

该包的 package.json 没有声明类型入口。需要类型提示时,可以在 npm 上查找社区维护的 @types/cryptocadet__cli 是否存在。

@cryptocadet/cli 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@cryptocadet/cli 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=22.5.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@cryptocadet/cli 可以商用吗?

@cryptocadet/cli 使用 UNLICENSED 许可。作者声明为 UNLICENSED,即不授予公开使用许可(与公共领域的 Unlicense 不同)。使用前需获得作者授权。以上为概括,不构成法律意见,请以许可原文为准。

@cryptocadet/cli 还在维护吗?

最新版本 0.3.0 发布于 2026/11/01(2 天前);至今共发布 8 个版本,其中过去 12 个月发布了 8 个;首次发布于 2026/07/08。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。