Skip to content

ov run

ov run is the CLI equivalent of vault_run. It fetches secrets for the active app, injects them as env vars, runs a command, and exits. Use it in scripts, CI, deploy pipelines, or anywhere you need secrets without the MCP layer.

If an ov agent is already running and unlocked, ov run uses it — no password prompt, no --machine-key needed, even on a workstation. The prompt-on-every-invocation flow described below only fires as a fallback when no usable agent is reachable.


Terminal window
ov run [flags] -- <command>

Run database migrations with all secrets for the default app:

Terminal window
ov run -- go run ./cmd/migrate

Run with a specific app:

Terminal window
ov run --app my-saas -- npm test

Inject only specific secrets:

Terminal window
ov run --app my-saas --secrets DATABASE_URL,STRIPE_SECRET_KEY -- go test ./...

Run non-interactively in CI or a systemd service (no password prompt):

Terminal window
ov run --machine-key /etc/ov/machine.kek --app my-saas -- ./server

Force the in-process path, bypassing any running agent:

Terminal window
ov run --no-agent --app my-saas -- ./server

ov run tries the local ov agent socket before it ever prompts for a password. It reuses the same socket discovery, key handling, and peer-UID verification as the MCP bridge, then sends the resolved (app, env) as a request the daemon honors per-invocation. This means:

  • One ov agent start, many terminal tabs, zero prompts. Every ov run in every tab uses the already-unlocked agent.
  • The context line shows which path served the run — an (agent) segment appears at the end of the line when the agent handled it:
    ov run: using app=my-saas env=production (.ov.yaml at /home/dev/repo) (agent)
    No (agent) segment means the local (password-prompt / --machine-key) path ran, exactly as before this feature shipped.
  • Fallback is automatic and safe. ov run falls back to the local path only when no usable agent is reachable: no socket, an unreadable/undecodable socket key, an agent whose session is locked, or an agent older than the CLI’s minimum supported version (see ov agent for the version-gate note). A static notice prints to stderr immediately before the fallback’s context line so you always know why the agent wasn’t used, e.g.:
    ov run: agent is locked; falling back to master-password prompt (run 'ov agent stop' then 'ov agent start' to restart it)
    ov run: using app=my-saas env=production (.ov.yaml at /home/dev/repo)
    Fallback never happens once a command may have started executing. If the agent accepted the request and something goes wrong afterward (a lost connection, an unrecognized daemon reply), ov run reports the error and exits — it does not silently re-run the command locally, which would risk running it twice.
  • --no-agent skips the probe entirely and always uses the local path (prompts for the master password unless --machine-key is set). Use it when you specifically want the terminal-native environment described below, or to sidestep the agent for any of the divergences in the table.

Because the daemon executes the command, not your shell, a handful of things differ from running ov run without an agent. None of these weaken the zero-knowledge guarantee — secret values still never cross the agent socket in either direction; the daemon runs the subprocess itself and returns only the exit code plus interceptor-filtered output.

AxisLocal ov runVia the agent
Subprocess environmentYour full shell environmentThe daemon’s sanitized, allowlist-only environment (HOME, USER, PATH, SHELL, TERM, TZ, LANG, LC_*, XDG_*, OV_*, LOGNAME, TMPDIR — see below) and the daemon’s PATH, frozen from when ov agent start launched
Subprocess cwdYour terminal’s cwdAlso your terminal’s cwd (sent per-request) — no divergence here
Ctrl-CKills the subprocess along with your shell’s process groupDetaches the client only — the daemon-side command keeps running. See the warning below
Accidental-exfiltration heuristicNot runThe daemon’s CheckInbound heuristic applies (same one vault_run uses) — bulk-env dumps and unquoted single-secret redirects are rejected
Output redactionSanitizeOutput + full-match secret redactionSame, plus a second pass through the agent’s own interceptor
Legacy v1-HMAC-only secretsVisible via the env-agnostic fallbackNot visible for any (app, env) pair other than the agent’s startup pair (see ADR-019) — re-store the secret under the current scheme, or use --no-agent
--secrets countUnlimitedCapped at 100 per run
Output sizeUnlimitedCapped at 64 MB
Audit accessor identitycli/<version>The daemon’s own accessor identity (mcp-agent/<version> or machine-key/<version>)

If a command isn’t on the daemon’s PATH, the agent path now surfaces a clear error (command could not be started — check that the binary exists on the agent's PATH) with a --no-agent hint appended, instead of a silent exit 255. This is a fix shared with vault_run: an unstartable binary used to come back as a success-shaped exit_code: -1; it’s now an honest error on both paths.

PATH hygiene note: the agent’s sanitized environment is actually more hygienic than your shell in one respect — it strips things your shell leaks into every local ov run today, like LD_PRELOAD, DYLD_*, and ambient credential variables (tokens picked up from direnv/nvm/etc.) that aren’t on the allowlist above. The trade-off is that the PATH is global to the daemon and frozen at ov agent start time, not scoped per-project — restart the agent after changing what needs to be on its PATH.


Without a running agent, ov run prompts for your master password on every invocation. For automated deployments — CI pipelines, Docker containers, systemd services — use a machine key file instead:

Terminal window
# One-time setup (as a human, interactive)
ov auth derive-machine-key --out /etc/ov/machine.kek
# Every subsequent run (no prompt)
ov run --machine-key /etc/ov/machine.kek --app my-saas -- ./server

--machine-key also participates in the agent-first path: if the agent was started with --machine-key and no interactive socket key file is available, passing the same --machine-key to ov run lets it derive the socket key and use the agent. See ov agent for the socket-key precedence details.

See the Machine Keys guide for full setup instructions, Docker and systemd examples, key rotation, and security properties.


FlagDescription
--app NAMETarget app (overrides config default)
--env NAMETarget environment (overrides config default)
--secrets NAME1,NAME2Explicit list of secrets to inject
--machine-key PATHPath to a machine key file — skips password prompt, and lets ov run derive the agent socket key if no key file is available (see Machine Keys)
--no-agentSkip the agent daemon and resolve secrets in-process (prompts for the master password unless --machine-key is set)
--no-context-line, -qSuppress the resolved-context line printed to stderr (also: OV_QUIET=1)