The daemon and the app
Three clients of one trading node — the desktop app in observe mode, the CLI's REPL and read verb, and the MCP server — what each is best at, and what strategy-status actually reads.
The thing that trades is vike-tradehub: a headless
daemon on a server, run as a systemd unit, holding the live core, the venue mounts and the risk
gate. It survives an SSH disconnect because it is not attached to your login session. Everything on
this page is a client of that daemon, and none of them holds any authority the daemon does not
grant.
That is the frame worth carrying into the rest of the platform: the node is the trading process; the app, the CLI and the agent surface are three ways of looking at it and asking it for things.
One node, three clients
| client | how it attaches | best at |
|---|---|---|
vike-desktop --observe <addr> | the node's observe server, plus local keyless venue feeds | watching. Charts, the DOM ladder, positions and the trade panel over a remote daemon's account plane |
vike-cli trade --node <addr> | observe and control, from a terminal | acting, over SSH, on a box with no display — and being able to paste exactly what you did into an incident write-up |
vike-cli strategy-status --node <addr> | observe only, one short-lived connection | answering what is that daemon actually running? in one line of shell |
vike-cli mcp --node <addr> | observe and control, exposed as MCP tools | handing the same vocabulary to an agent, behind a preview gate |
The desktop app's remote mode is worth a sentence of its own, because it is not simply "the app,
read-only". vike-desktop's split-plane model divides its data in two: the account plane — orders,
positions, equity, bar history — belongs to the backend and arrives as wire snapshots over the
observe bridge, while the market-data plane — books, the trade tape, order-flow series — belongs
to the venue and is subscribed directly and keylessly. In --observe mode on a full build you get a
remote daemon's account plane beside local feeds, with no local core and no execution engines at
all. Observe mode is that page.
Two scopes, two keys
Every one of those attachments authenticates, and the protocol has exactly two scopes.
VIKE_TRADEHUB_OBSERVE_KEY opens a read connection; VIKE_TRADEHUB_CONTROL_KEY opens a write one.
The node verifies each scope against its own key, so a control key cannot stand in for an
observe key — which is why strategy-status, a read verb, asks specifically for the observe half
and reports the observe-specific absent-key message rather than a vaguer "no key" line.
Both keys are resolved once, by the dispatcher, for the three node-facing verbs only:
process environment → <project>/settings/secrets.env → nothingThe second rung is the same store the daemon itself loads them from, which is the whole point:
before it existed, a box configured exactly as the daemon documents answered nothing to do. The
first rung wins because an export is ephemeral, narrow and deliberate — it is what makes "point at
a different node for one command" possible — while the store is the box's standing configuration.
crates/vike-cli/src/cmd/nodekeys.rs carries that argument, including why this is not the
policy.toml case: a node key is a credential, not a risk limit, and presenting a different key
cannot widen what an authenticated peer may do. The worst an exported key achieves is failing the
handshake.
Which keys this box holds is answered by vike-cli secrets, by
name and never by value.
What strategy-status reads
strategy-status is the shell-level answer to what is that daemon running? It opens one
short-lived observe connection, sends one request, and prints what came back
(crates/vike-cli/src/cmd/trade_status.rs). Three things:
node hub-a — paper — build vike-tradehub 0.1.0 (abc1234, clean)
params: spread=0.01 size=20
STRATEGY MODE PARAMS
spread_maker paper venue=polymarket symbol=TOK-A spread=0.01
np LIVE venue=polymarket symbol=TOK-B edge=0.02The identity line names the node and the build it is running, down to the commit and whether
that tree was dirty — the same provenance every --version in the workspace answers, asked
remotely. The effective-params line is what the daemon resolved, not what a file says. And then
one row per mounted strategy, with its mode and its parameters.
The mode cell is uppercase exactly when it matters: LIVE shouts, paper is the quiet default.
Column widths come from the data, headers included, so a long strategy name cannot shear the params
column. --json prints the wire payload verbatim instead — a machine consumer gets the protocol's
own schema rather than a second hand-maintained shape that could drift from it.
Until this verb existed the only way to ask that question from a shell was to compile a throwaway probe, which is a thing people did.
A node too old to answer is refused on this side
The verb is feature-negotiated: against a node whose handshake advertises no strategy-verbs capability, the client sends nothing after the handshake and refuses locally. That is deliberate — an older node's deserializer cannot decode the frame, so sending it would produce an opaque decode error at the node instead of a diagnosis here. The message names the missing capability and the one action that fixes it: upgrade that node.
Choosing between them
They overlap on purpose, and the useful question is not which is most powerful but what does this moment need.
Take the app when the question is visual and the answer is a shape — is this fill where the chart says it is, is the book thinning out, does this indicator behave the way it did in the backtest. Nothing at a terminal replaces looking at a chart.
Take the CLI when the answer has to survive being written down. A strategy-status --json in a
cron job, a trade session pasted into an incident review with the --reason you typed on each
line, a deploy script that refuses to start a unit — none of those have a GUI shape. It is also the
only one of the three that works over an SSH connection to a box with no display, which describes
most trading servers.
Take the agent surface when the loop is author, compile, backtest, adjust and you would rather describe the change than type it. It speaks the same write vocabulary as the REPL — the same construction site, the same client-order-id mint, the same guardrail — so a verb added to one is visibly missing from the other rather than silently absent.
Whichever you take, the node's own control limits and risk gate are the enforcing backstop, and the
per-venue arming ceiling in policy.toml sits above even the
credential read. A client can only ever ask. See
the control boundary,
risk and arming and
the node protocol for what the daemon does with what it is asked.
The trade REPL
What driving a live node from a terminal is actually like — the two connections, the preview before every write, what the local guardrail is and is not, and why each command reports its own outcome.
The agent door
What vike-cli mcp is as a CLI verb — a local stdio server, one vocabulary shared with the REPL, a preview gate that fails closed, a profile that can withhold the write tools outright — and where the tool-by-tool reference lives.