CASHPILOT_ADMIN_API_KEY resolves to role owner (app/auth.py:177-179), so a Home Assistant widget or an agent gets full control, including stored credentials and volume deletion. No scopes, no expiry, no box limit, no last-used..env or the compose file, docker compose up -d, update every client. Nothing in the UI. Revoking one client means rotating everyone./docs are switched off (app/main.py:2315-2317). An agent reads app.js to learn the routes: api() is a bare fetch wrapper (app/static/js/app.js:14-38) with nothing to record or copy.CASHPILOT_API_KEY). People paste it into scripts; it is the worker key, role fleet (app/auth.py:180-182).A token lets a script, a dashboard widget or an AI agent act as you, limited to the scopes and boxes you pick. Each one is shown once, stored hashed, and can be revoked here without a restart.
| Name | Scopes | Boxes | Expires | Last used | |
|---|---|---|---|---|---|
| home-assistant cp_hA2x_…f9 | read | all | 4 min ago · GET /api/earnings | Revoke | |
| claude-code cp_Qm7d_…k2 | readoperateproxies | box-abox-b | just now · POST /api/services/honeygain/restart | Revoke | |
| old-grafana cp_Zt0p_…a1 | read | all | 19 days ago | Extend Revoke | |
| Admin key legacy, set in .env CASHPILOT_ADMIN_API_KEY | admin (everything) | all | 12 days ago | How to retire it |
The cashpilot CLI talks to this dashboard over the same API. Every command takes --json, --dry-run on anything that changes a box, and exits non-zero on refusal.
The URL above is this dashboard's own address, filled in for you. CLI reference
Claude Code and other agents work best with a token scoped to what you want them to touch, plus the guide below. Destructive calls return a plan first; the agent must send confirm to carry it out.
Do it once with clicks, then copy it to a script. Values from credential fields are replaced with $VARIABLE names.
cashpilot service restart honeygain --box box-aCopy CLI Copy curlcashpilot egress test res-pool-1 --box box-bCopy CLI Copy curlcashpilot egress add res-pool-1 --url-stdin <<< $PROXY_URLCopy CLI Copy curlcashpilot service deploy earnapp --box box-b --env-file earnapp.envCopy CLI Copy curlcashpilot service stop storj --box box-b --yesCopy CLI Copy curlapi_tokens table (hash, scopes, worker_ids, expires_at, last_used_at), checked in get_current_user next to the env keys (app/auth.py:153-183).cli/ package published as cashpilot and also baked into the UI image, so docker exec works with no install. --token-stdin keeps the token out of shell history. Today: no CLI exists./api/docs and /openapi.json come back, but behind sign-in, which keeps the reason they were removed (app/main.py:2311-2317). docs/agents.md and a generated llms.txt list scopes, the plan then plan_id contract and exit codes. MCP server = the same CLI in mcp mode.CP.api() (app.js:14-38) appends method, path and body to a ring of 10 in sessionStorage; a route→command map turns it into CLI text. Bodies are masked by field name (password, token, *_KEY, url credentials) before storing. 2 clicks to a working command.cashpilot service logs honeygain --box box-a$PROXY_PASS.POST /api/proxies (fleet.html:1101).CASHPILOT_API_KEY for compatibility; the label says what it is.box_not_allowed).$ pbpaste | cashpilot login --url http://cashpilot.local:8080 --token-stdin Signed in as token claude-code (read, operate, proxies · boxes box-a, box-b · expires 2027-02-06) Saved to ~/.config/cashpilot/config.toml (mode 600) $ cashpilot status --json { "version": "2.2.0", "boxes": [ { "name": "box-a", "online": true, "running": 6, "isolation": "on" }, { "name": "box-b", "online": true, "running": 4, "isolation": "off" } ], "findings": [ { "id": "down/earnapp@box-b", "severity": "fail" } ], "balance_usd": 41.87 } $ cashpilot service restart honeygain --box box-a ✓ honeygain restarting on box-a $ cashpilot service rm storj --box box-b ✗ refused: token claude-code lacks scope "deploy" Ask the owner to add it in Settings › API & CLI. $ echo $? 3 # exit codes: 0 ok · 1 error · 2 usage · 3 auth or scope · 4 not found # 5 refused for safety (incl. no --yes) · 6 box offline · 7 partial · 8 conflict
Ask the owner for a token with the smallest scopes that do the job. Never ask for admin to restart a service.
| Scope | Lets you | CLI |
|---|---|---|
| read | status, earnings, logs, fleet | status · service ls|logs · finding ls |
| operate | start, stop, restart | service start|stop|restart |
| deploy | deploy, redeploy, remove | service deploy|redeploy|rm |
| proxies | proxies and proxied copies | egress add|import|test · copy apply |
| admin | settings, credentials, tokens | token ls|create|revoke · box add |
Storj, Mysterium and other nodes with an identity volume never lose data by default. Every remove, stop or redeploy returns a plan first:
The volume flag must repeat the slug, the same check as the dialog in M8. Over HTTP, add dry_run=1 to the same request: it returns {"plan": …, "plan_id": "…"}; send plan_id back within 5 minutes.
docs_url=None, redoc_url=None, openapi_url=None: no schema at all, by design, because it was public.api() is the single choke point for every UI call: the right place to record and translate./api/proxies, /copies, /test.