M3 · PLAN ITEM · covers X1, N14

Command palette and shortcut help overlay

Today only page jumps have shortcuts (app/static/js/app.js:164-194). Every action, from redeploying one service on one box to testing a proxy, is a mouse trip through a page. The only hint is one footer line (app/templates/base.html:171) and it is partly wrong. One palette, fed by one action registry, makes every action findable by typing, and the same registry prints as cashpilot actions --json for scripts and agents.

Today

  • Redeploy Honeygain on one box: ≈70 keystrokes. g c, /, type the name, about 25 Tabs to the row, Enter opens the detail, Tabs to the right box's Redeploy, Enter, then a browser window.confirm that says nothing about volumes (app.js:3735-3736).
  • The footer says "a page's first letter", but Activity is n (base.html:84) and a opens Setup / Add service (base.html:89, 96).
  • / only works on Catalog and Payouts (app.js:184-186); on Fleet, Dashboard, Settings it does nothing, silently.
  • No list of shortcuts anywhere; r works on the Dashboard only and is mentioned only in a tooltip (dashboard.html:8).

After

  • Same task: ≈12 keystrokes. ⌘K, rede hon, Enter, pick the box, Enter on the plan.
  • Every action is one registry entry, served by GET /api/actions: label, keywords, parameters, the plan it shows, the API call, and its CLI twin. The palette, the ? overlay and cashpilot actions all read it, so they cannot drift apart.
  • Owner-only actions are left out of the registry for viewers, the same way the nav already does (base.html:80-90).
  • Anything that recreates a container shows its plan first; for a stateful node, focus starts on Back.
Before · footer of every page (base.html:171), real copy
CashPilot v2.1.1SourceReport a problem Press g then a page's first letter to jump, / to search
After · same footer
CashPilot v2.1.1Source Press ⌘K to search and run anything, ? for every shortcut

Screen 1 · ⌘K over the Dashboard, query "rede hon"

The palette opens over whatever page you are on. Results are grouped; within a group, what you ran last comes first. The highlighted row is the one Enter runs.

CashPilot
Add service
$184.32

Dashboard

Balance
$184.32
across 9 services
Today
$1.94
+4.1%
This month
$41.07
+12.6%
Containers up
14

Needs attention

Nothing needs you. 2 of 2 boxes reporting.

Services

Click a row with several instances to see each one.
ServiceStatusBalanceCPUMemoryPayout
Honeygain Running 2x$38.100.4%31 MBPayPal
EarnApp Running 2x$27.550.3%44 MBPayPal
Mysterium Running 1x12.4 MYST1.8%120 MBWallet
Storj Running 1x$61.022.2%210 MBWallet
Traffmonetizer Running 2x$9.800.2%28 MBWallet
1 2 3 4 5 6 7
Keys ⌘K / Ctrl K or : opens it from any page ↑↓ moves the highlight ↵ runs, or goes to the next parameter ⌫ on an empty input goes back a step esc closes and returns focus to where you were
  1. 1A visible door. A search button in the top bar with its key printed on it, so mouse users find the palette too. Keyboard: ⌘K, Ctrl K, or : (no modifier, ignored while typing, like g today, app.js:173-175).
  2. 2One combobox. role="combobox" with aria-activedescendant pointing at the highlighted option, so a screen reader announces "Redeploy Honeygain on box-a, keeps its settings, 1 of 5".
  3. 3Recent first. The last thing you ran with these words leads its group, with a recent tag. Kept in localStorage per user; nothing is sent.
  4. 4Fuzzy, word-start match. "rede hon" matches the start of two words; matched letters are underlined in the accent colour. Each row names its scope (box-a) on the right.
  5. 5Parameter rows. "Redeploy Honeygain…" with an ellipsis asks for the box next (Screen 2). Tab on any row fills the input with it, so you can keep typing.
  6. 6Not only actions. Services, boxes, proxies, pages and docs are in the same list, grouped. The registry holds actions; the rest comes from data the page already loaded (/api/services, /api/workers).
  7. 7The CLI twin of the highlighted row, live (wave 3, L5). Click or ⌘C copies it. Same words, same parameters, so what you learn here works in a terminal or in an agent's prompt.

Screen 2 · Enter on "Redeploy Honeygain…": choose the box, then read the plan

Left: the parameter step. Right: the confirm step that replaces today's window.confirm("Redeploy honeygain on this box?") (app.js:3736) with what will actually happen.

CashPilot
Add service
$184.32

Dashboard

Balance
$184.32
Today
$1.94
This month
$41.07
1 2 3 4 5 6 7
Keys ↑↓ pick the box↵ to the plan↵ again runs it (focus starts on Redeploy) ⌫ on empty input goes back one stepesc closes, nothing runs⌘C on the plan copies the CLI line
  1. 1Breadcrumb chips show the steps taken. ⌫ on the empty input pops the last chip, so a wrong choice costs one key, not a restart.
  2. 2Each box says whether it is stateful for this service, the fact that decides whether a recreate is safe. Online state and age of the last heartbeat come from the same data Fleet shows.
  3. 3Unavailable choices stay visible and say why instead of vanishing, so "where is my phone?" has an answer.
  4. 4The plan is the confirm. Today a browser confirm() says "It keeps the settings it was deployed with." and nothing about volumes or downtime (app.js:3736).
  5. 5Facts from the deploy record, the same record that already drives "redeploy notes" (app.js:3739-3742), so the plan and the result use the same words.
  6. 6Copy as CLI on every confirm step (wave 3, L5). --yes skips the prompt in scripts; without it the CLI prints this same plan and asks.
  7. 7Focus starts on the primary button with a visible ring, so Enter is a deliberate second press, never the same keystroke that chose the box.

Screen 3 · Other queries: one list for proxies, isolation, theme, tokens, and the stateful case

Each inset is the palette after typing the query shown. Everything a page button does is reachable here, and owner-only actions are absent for viewers.

query: "proxy"

proxy
Actions
Add egress (proxy or VPN)…↵
Test isp-1socks5last: ok 2 h
Test mobile-2httpfailed
Run a copy through a proxy…3 steps
Docs
Proxies: how it worksdocs

query: "iso"

iso
Actions
Check isolation on box-brecent↵
Check isolation on box-apassed 1 d
Check isolation on every box2 boxes
Docs
LAN isolation by defaultdocs
Starts two short-lived probe containers. Changes no firewall rule.

query: "theme"

theme
Settings · saved to your account
Theme: Dark↵
Theme: Classic night current
Theme: Sunrise
Theme: Warm
Theme: Light
Moving the highlight previews the theme; esc puts the old one back.

query: "token"

token
Actions · owner only
Create API token…for scripts and agents↵
Create a box join token1 h, one useFleet
Revoke API token…2 active
Docs
Driving CashPilot from a script or an agentdocs

query: "redeploy storj", then Enter on box-a: the stateful case

Redeploy Storj›box-a›confirm
Stateful node. Storj keeps its identity and stored pieces on box-a. The volumes are kept, but if the identity volume were lost the node would be disqualified and its held amount forfeited. This plan keeps both volumes. Focus starts on Back, so a stray Enter never recreates the node.
Container recreated
yes · node offline about 30 s, counts against uptime
Volumes kept
2 · storj-identity, storj-data (418 GB)
Focus on Back · Tab to Redeploy, then ↵cashpilot service redeploy storj --box box-a --yes
1 2 3 4 5
  1. 1Proxies and VPNs by words, not by finding the closed <details> on Fleet (fleet.html:89-125). Each proxy row shows its last test result, so "which one is broken" is answered while typing.
  2. 2Per-box actions are expanded per box, plus an "every box" row. The footer line repeats the button's own tooltip (fleet.html:440) so safety text travels with the action.
  3. 3Settings are actions too. The theme lives in the avatar menu today (base.html:124-128); here it previews live while highlighted.
  4. 4Tokens for agents are one query away, with the doc page that explains them. Join tokens are the same ones the Add a box dialog makes (M4).
  5. 5Stateful nodes (Storj, Mysterium) open the plan with focus on Back, and the CLI needs --yes. A stray Enter never recreates anything that could cost a node its reputation. Typing a name is kept for deleting data (M8).

Screen 4 · "?" opens every shortcut, for this page too

Generated from the same registry, so a new action shows up here without anyone editing a help page. Shown over Fleet.

CashPilot
Add service
$184.32

Fleet

Boxes
2
Reporting
2
Containers (online)
14
Running (online)
14
1 2 3 4 5 6
Keys ? (⇧ /) opens it on any pageesc or ? closes⌘K from here goes straight to the palette
  1. 1The real keys, from the registry. Activity is printed as g n because that is what base.html:84 binds; the footer's "first letter" claim goes away.
  2. 2A column for the page you are on, read from body[data-page] (base.html:35). n opens Add a box (M4).
  3. 3/ works on every page that has a list: Fleet filters boxes, Dashboard filters services. Where a page has none, / opens the palette instead of doing nothing.
  4. 4Row navigation for Fleet, Dashboard services, Catalog, Payouts. A focused row is outlined in the focus colour, so i and ⇧ R always say which box they act on.
  5. 5Dialogs keep the existing esc (app.js:156-162) and add focus return: today closing only removes the open class and never sends focus back to the button that opened the dialog.
  6. 6Same list for scripts and agents. cashpilot actions --json prints every action with its parameters and CLI form, so an agent can discover what it may do without reading the UI code.

Screen 5 · The registry in a terminal: cashpilot actions --json

The palette and the CLI share one source. An agent such as Claude Code can list actions, read the plan, and run one with the same safety step.

$ cashpilot actions --json --filter redeploy [ { "id": "service.redeploy", "label": "Redeploy {service} on {box}", "keywords": ["redeploy", "recreate", "update"], "params": [ {"name": "service", "from": "/api/services"}, {"name": "box", "from": "/api/workers", "filter": "runs:{service}"} ], "plan": "POST /api/actions/service.redeploy/plan", "run": "POST /api/actions/service.redeploy", "confirm": "enter | back-focused-if-stateful", "role": "owner", "cli": "cashpilot service redeploy {service} --box {box}", "shortcut": "d (lists)" } ]
$ cashpilot service redeploy honeygain --box box-b Plan: redeploy honeygain on box-b container recreated yes (about 10 s offline) image pulled again from the catalog entry volumes kept 1 honeygain-data settings kept all stateful node no Proceed? [y/N] y ok honeygain on box-b running again after 9 s $ cashpilot service redeploy storj --box box-a < /dev/null refused: storj on box-a is a stateful node and --yes was not given. The plan is printed above it; rerun with --yes to apply. Nothing done. exit 5 $ cashpilot service redeploy honeygain --box box-b --json --yes {"ok": true, "action": "service.redeploy", "box": "box-b", "service": "honeygain", "recreated": true, "volumes_kept": ["honeygain-data"], "seconds_offline": 9}
1 2 3
  1. 1One entry, four surfaces: palette row, ? overlay line, CLI command, API route. The shortcut and the role live in the entry, so the help can never claim a key the code does not bind.
  2. 2The CLI prints the same plan as the palette and asks. Exit codes are stable (0 ok, 2 usage, 3 auth or scope, 5 refused for safety, 7 partial) so an agent can branch on them.
  3. 3--json on every command. A stateful change without --yes prints the plan and exits 5, the CLI form of focus starting on Back in the palette.

Mockup only. Data is fake. Colours, type, buttons, modals, kbd and tables use CashPilot's own stylesheet from origin/main (Classic night, the default theme in app/themes.json), inlined. Yellow numbered dots are annotations, not UI.