vike

The command line

What vike-cli is, what it deliberately is not, the ten verbs it dispatches, and which of the three surfaces over the platform to reach for.

vike-cli is one binary with ten verbs. It scaffolds a project, discloses what this box's settings resolved to, inspects the credential store, lists what a strategy may call, ships backtests to a data service, drives a running trading daemon from a terminal, and serves the same trading vocabulary to an agent over MCP. Every verb is a sibling module under cmd exposing a run(args) -> ExitCode, and the dispatcher in crates/vike-cli/src/lib.rs never grows command logic — it only routes.

This section is the narrative half. It says what working at the command line is like and which verb answers which question; the CLI reference is the authority for every flag, every exit path and every error string, one page per verb.

The identity is negative

The most useful sentence about this binary is a list of what is not in it. vike-cli links no DataFusion and no venue transport stack — no ureq, no tungstenite, no rustls, no signer. That is not an accident of what has been written so far; it is the test every dependency in crates/vike-cli/Cargo.toml is argued against, edge by edge, on the manifest row itself.

Three of those arguments are worth carrying, because they explain shapes you will meet later:

  • vike-ops and vike-bridge-core are both taken default-features = false. Their default full features carry the venue transport and signing stack, and restoring either would drag it into a laptop binary that never opens a venue socket.
  • the credential store is read through vike-secrets, a crate with zero dependencies, rather than through vike-bridge-core, the reader's historical home. A KEY=VALUE parser is not worth a TLS stack.
  • the client-order-id generator comes from vike-model rather than vike-exec, its historical home. vike-exec would have added a multi-threaded async runtime and core-affinity to a binary whose whole identity is being light.

The consequence is the shape of everything else here: vike-cli asks services, it does not run engines. A backtest is not computed in this process — the profile's TOML text is shipped to a vike-datahub server sitting next to the tape, which runs it and returns a compact report. Live orders are not placed by this process either — they are commands sent to a running vike-tradehub node, whose own control limits and risk gate are what actually enforce anything. The heavy history and the authority both stay where they belong.

The ten verbs, by the job they do

crates/vike-cli/src/lib.rs's COMMANDS is the single source of truth for both the help text and the unknown-command hint, so a new verb appears in --help for free. Grouped by what you are trying to do rather than alphabetically:

jobverbs
set the box upinit scaffolds user_data/; config show discloses every setting and where its value came from; config check judges the same tree and makes the exit code the product; secrets inspects the one credential store, and secrets set upserts one named key into it — the CLI's only credential writer, value from stdin or an environment variable, never argv
do researchindicators prints what a Rhai strategy can actually call; backtest, sweep and walkforward ship a profile to a data service and print what came back
run and watchtrade is the interactive REPL over a live node; strategy-status asks that node what it is running, read-only; mcp serves the same vocabulary to an agent

Ten verbs is the whole surface. There is no clap dependency behind it: the flag grammar is hand-rolled in crates/vike-cli/src/cmd/args.rs and shared by every verb, which is why --flag value and --flag=value work everywhere and why a token beginning -- is a flag and never a value everywhere. Global flags is that grammar's page.

What happens before any verb runs

Typing any subcommand runs the same three steps first — the first two inside crates/vike-cli/src/lib.rs's resolve_policy, the third in run, which calls install_user_indicators only once resolve_policy has returned. The order is load-bearing: a refusal in step 1 returns before an indicator is ever compiled. Together they explain most of what a fresh install does:

  1. A removed environment variable is refused. vike_config::refuse_removed_env fails the process, naming the variable, the file that replaces it and the exact TOML line to write. It fires for every verb, including read-only ones — a stale variable is stale regardless of what you typed, and an operator who still exports VIKE_MAX_ORDER_NOTIONAL believes a ceiling is armed that nothing reads.
  2. <project>/settings is resolved once, through the workspace's one startup sequence (vike_boot::boot). Every project-relative path any verb uses is derived from that single answer, so secrets path, config show and a daemon on the same box cannot disagree about which project they are in.
  3. Your own indicators are installed process-wide. install_user_indicators compiles user_data/indicators/*.rhai before dispatch, so a script run by any verb can call them. A file that fails to load is reported on stderr and never fails the command.

The credential store is the deliberate exception to "resolved once, up front": the dispatcher opens it lazily and only for the three node-facing verbs — trade, mcp and strategy-status — inside their own arms, through node_keyring, because those are the three that authenticate to a node. A backtest has no business opening the file that holds every venue key on the box.

That is a statement about the dispatcher, not about the binary. Two verbs open the store because the file is their subject, and they do it themselves rather than through the deferred boot: secrets reads it directly (vike_secrets::resolve for list, a stat and a permissions check for path, and set writes one key through the workspace's one upsert), and config does too — crates/vike-cli/src/cmd/config.rs's execute loads it before it prints anything, to report the key COUNT, and config check classifies whether it is present, absent or unreadable. So the honest answer to "which invocations touch secrets.env?" is: the three node-facing verbs, plus the two whose job is to tell you about the file.

Diagnostics go to stderr, always

vike-cli mcp's stdout is a JSON-RPC protocol stream, and one stray line on it corrupts the session. So every warning, every settings resolution and every rejected indicator goes to stderr — in every verb, not just that one. It is also why vike-config returns its resolutions as data rather than logging them: a library that writes to its caller's stderr cannot be linked by a binary whose stdout is a protocol.

Which of the three surfaces

The platform has three faces over the same core concepts, and they are not ranked — each is best at something the others are bad at.

Reach for the app when the question is visual — is this fill where I think it is, does this indicator look right on this chart. Reach for the CLI when the answer has to be repeatable, put in a shell script, or reached across an SSH connection to a server with no GUI. Reach for the agent surface when the loop is author, compile, backtest, adjust, and you would rather describe the strategy than write it. All three end up talking to the same daemon over the same authenticated protocol, and The daemon and the app is the page about that.

On this page