CLI Preview
Target Veto command-line grammar for the CLI elevation work.
CLI elevation preview: this page records the target command grammar for SDK work in review. Receipt, MCP import/restore, and Python entrypoint commands must not be treated as generally available until the claims manifest marks them implemented.
Installation
Target package (Node.js):
npx veto-cli@latest <command>
pnpm dlx veto-cli@latest <command>
bunx veto-cli@latest <command>Compatibility wrapper (kept for existing users):
npx veto-sdk@latest <command>Planned Python entrypoint:
# Installed globally with pip
veto <command>The planned Python entrypoint covers the bootstrap, validation, MCP import/restore, and receipt commands used by Python-native agents:
python -m veto version --json
python -m veto init --json
python -m veto validate issue_refund --arguments '{"amount_usd":900}' --json
python -m veto receipts verify .veto/receipts.ndjsonCommands
veto / veto studio / veto repl / veto --repl
Starts Veto Studio (full-screen, keyboard-first TUI) by default.
# No command defaults to Studio
veto
# Explicit Studio command
veto studio
# Compatibility entrypoints
veto repl
veto --repl
# Legacy line REPL
veto repl --legacyStudio-focused flags:
--renderer auto|ink|opentui|ansi--directory <path>--include-examples--include-tests--demo-template
Renderer notes:
inkis the default interactive renderer on Node.js.opentuiis optional and intended for Bun runtimes.ansiis fallback-safe for CI and limited terminals.- if
inkimport/init fails at runtime, Studio falls back toansiand prints a warning.
Legacy REPL (--legacy) keeps slash commands:
/scanfor coverage suggestions/test <tool>({args})for local policy evaluation/test-suitefor generated scenario testing/explain <ruleId>for rule explanations/exportand/loadfor YAML workflows
For full workflows and a copy-paste demo script, see Interactive REPL.
veto policy generate
Generate policy YAML from natural language (local or cloud target).
# Local generation, save file
veto policy generate \
--tool approve_invoice \
--prompt "do not approve invoices above 50 dollars" \
--save ./veto/rules/approve-invoice.yaml
# Cloud generation with machine-readable output
veto policy generate \
--tool approve_invoice \
--prompt "do not approve invoices above 50 dollars" \
--target cloud \
--json| Flag | Required | Default | Description |
|---|---|---|---|
--tool <name> | Yes | Tool name to generate policy for | |
--prompt <text> | Yes | Natural-language policy intent | |
--mode-hint <hint> | No | auto | auto, deterministic, or llm |
--target <target> | No | local | local or cloud |
--save <path> | No | Auto path (local target) | Save generated YAML |
--demo-template | No | false | Allow explicit template fallback generation |
--json | No | false | Deterministic JSON response envelope |
veto policy apply
Apply an existing policy YAML file locally or submit it to cloud drafts.
veto policy apply --file ./veto/rules/approve-invoice.yaml
veto policy apply --file ./veto/rules/approve-invoice.yaml --target cloud --json| Flag | Required | Default | Description |
|---|---|---|---|
--file <path> | Yes | Policy YAML file path | |
--target <target> | No | local | local or cloud |
--project <id> | No | Current cloud context | Cloud project scope override |
--json | No | false | Deterministic JSON response envelope |
veto guard check
Run a non-interactive guard evaluation for a tool call.
# Explicit args JSON
veto guard check --tool approve_invoice --args '{"amount":120}' --mode local --json
# Pipe args from stdin
echo '{"amount":120}' | veto guard check --tool approve_invoice --mode local --json| Flag | Required | Default | Description |
|---|---|---|---|
--tool <name> | Yes | Tool name | |
--args <json> | No | {} or stdin | Tool arguments JSON object |
--context <json> | No | {} | Extra context JSON object |
--mode <mode> | No | local | local, cloud, kernel, or custom |
--json | No | false | Deterministic JSON response envelope |
veto cloud login and context commands
Device flow for human users and context management for CLI sessions.
veto cloud login
veto cloud whoami
veto cloud org use <org-id>
veto cloud project use <project-id>
veto cloud logoutLogin flow:
- Run
veto cloud loginin terminal. - Open the verification URL shown by CLI.
- Approve the device code in dashboard.
- Return to terminal; CLI stores scoped session tokens.
Charter for CLI agents
After login, terminal-native agents can run Charter over the CLI transport. The server endpoints are:
POST /v1/cli/charter/turnfor request/response turnsPOST /v1/cli/charter/streamfor SSE status, tool progress, result/error, and done events
Both endpoints use the CLI access token as Authorization: Bearer <token>. Use the streaming endpoint for custom terminals, Claude Code bridges, or agent runners that need progress updates and stale-response guards:
curl -N https://api.veto.so/v1/cli/charter/stream \
-H 'Authorization: Bearer vcl_at_xxx' \
-H 'content-type: application/json' \
-d '{
"message": "Refunds over $200 require support lead approval.",
"mode": "compile",
"surface": "cli"
}'Every streamed event includes requestId. Policy-changing results include verification.linkUrl; the draft is not live until that link is approved.
Use fetch or any SSE library to consume the stream:
const res = await fetch("https://api.veto.so/v1/cli/charter/stream", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.VETO_CLI_ACCESS_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
message: "Refunds over $200 require support lead approval.",
mode: "compile",
surface: "cli",
}),
});
// parse SSE chunks from res.bodyveto mcp serve / veto mcp doctor / veto mcp init
Run Veto as an MCP gateway in self-hosted environments.
# Scaffold config
veto mcp init
# Validate connectivity and config
veto mcp doctor
veto mcp doctor --json
# Start gateway
veto mcp serve --config ./veto/mcp.config.yamlQuick one-off serve without a config file:
veto mcp serve \
--upstream http://localhost:3000/mcp \
--api-key veto_xxx \
--policy-server http://localhost:3001Flags:
--config <path>forserve/doctor--listen <host:port>forserve--upstream <url>and--transport <mcp-sse|mcp-stdio>for quickserve--api-key <key>and--policy-server <url>for policy checks--timeout-ms <n>for upstream timeout--jsonfor deterministic command output (doctor,init, and startup envelope onserve)
Managed/runtime support notes:
- managed cloud MCP gateway supports
mcp-sse - self-hosted CLI gateway supports
mcp-sseandmcp-stdio
For managed APIs and architecture details, see MCP Gateway guide.
veto doctor
Diagnostics for runtime, renderer, auth, and connectivity:
veto doctor
veto doctor --jsonRuntime troubleshooting
If npx veto-cli@latest fails with module-resolution errors from ~/.npm/_npx, it is usually a corrupted transient npx install cache, not a policy/runtime bug.
Use either approach:
# One-off isolated cache
npm_config_cache=/tmp/veto-npx-cache npx -y veto-cli@latest
# Then retry normal invocation
npx -y veto-cli@latestFor renderer diagnostics:
veto doctor --jsonveto validate
Validate one tool call from the Python CLI and append a local decision receipt.
veto validate issue_refund \
--arguments '{"amount_usd":900}' \
--config-dir ./veto \
--receipt-store ./.veto/receipts.ndjson \
--jsonFlags:
--tool-name <name>when you prefer a flag over the positional tool name--arguments <json>or--args <json>for tool arguments--validation-mode cloud|local|kernel|custom|api--receipt-store <path>for the local NDJSON chain--session-id <id>and--agent-id <id>for receipt context--api-key <key>and--base-url <url>for cloud validation
veto init
Scaffolds a Veto configuration in the current directory. For brand-new TypeScript apps, prefer create-veto-app. Use veto init when adding Veto to an existing project.
npx veto init
npx veto init --force
npx veto init --pack coding-agent
npx veto init --pack soc2-lite
npx veto init --pack @veto/soc2-lite
npx veto init --cloud
python -m veto init --agent codex --jsonCreates:
veto/
├── veto.config.yaml # Main configuration file
├── mcp.config.yaml # MCP upstream and policy-server config
├── .env.example # Example environment variables
└── rules/
└── defaults.yaml # Default rule template or pack extensionThe Python initializer also writes a denied smoke-test receipt to .veto/receipts.ndjson unless --no-receipt-smoke is set. Verify it with:
veto receipts verify .veto/receipts.ndjsonThe generated veto.config.yaml is a policy workspace scaffold. Use --cloud or set VETO_API_KEY when you want the current TypeScript SDK, Charter, approvals, and dashboard logging to use Veto Cloud:
version: "1.0"
mode: "strict"
validation:
mode: "cloud"--api-key <key> writes the key into veto/veto.config.yaml; if you use it, do not commit that file.
If the veto/ directory already exists, the command does not overwrite existing files unless --force is set.
To restore an MCP client file from a backup, use veto mcp import --restore in the Node CLI or veto mcp restore --backup <path> in the Python CLI. veto init --restore intentionally reports the explicit restore action instead of mutating client config implicitly.
--pack pre-fills veto/rules/defaults.yaml with:
version: "1.0"
extends: "@veto/<pack>"Supported built-in packs:
coding-agentcrypto-tradingfinancialbrowser-automationdata-accesscommunicationdeploymenteconomic-agentsoc2-litehipaa-liteeu-ai-act-starter
You can pass either short names such as soc2-lite or scoped names such as @veto/soc2-lite. Starter compliance packs are guardrails to review and tune; they do not make an app compliant or certified.
veto compile
Compiles natural language policy descriptions into deterministic YAML rules using an LLM at build time.
# From inline text
veto compile --input "Block emails to domains outside company.com" --output ./veto/rules/email.yaml
# From a text file
veto compile --file policies.txt --output ./veto/rules/
# With a specific provider
veto compile --input "Cap transfers at $5000" --output ./veto/rules/limits.yaml --provider anthropic| Flag | Required | Default | Description |
|---|---|---|---|
--input <text> | One of --input or --file | Policy description as inline text | |
--file <path> | One of --input or --file | Path to a text file containing policy descriptions | |
--output <path> | Yes | Output file (.yaml) or directory for generated rules | |
--provider <name> | No | openai | LLM provider: openai, anthropic, gemini, openrouter |
--model <name> | No | Provider default | Model identifier (e.g. gpt-4.1, claude-sonnet-4-6) |
--quiet | No | false | Suppress output |
The compile command uses the LLM only at build time. The generated YAML rules run locally with zero network calls at runtime.
Requires the corresponding provider API key as an environment variable (OPENAI_API_KEY, ANTHROPIC_API_KEY, GEMINI_API_KEY, or OPENROUTER_API_KEY).
veto learn
Observe tool calls and auto-generate tight allowlist policies from real usage patterns.
# Stop after 10 tool calls
veto learn --runs 10
# Stop after 30 minutes
veto learn --duration 30m
# Custom output path
veto learn --output ./veto/rules/learned.yaml| Flag | Required | Default | Description |
|---|---|---|---|
--runs <n> | One of --runs or --duration | Stop after N tool calls | |
--duration <time> | One of --runs or --duration | Stop after duration (e.g. 30s, 10m, 1h) | |
--output <path> | No | ./veto/rules/learned.yaml | Output YAML file path |
--margin <n> | No | 0.1 | Numeric range margin as decimal (10% slack around observed values) |
--quiet | No | false | Suppress output |
The learn command reads tool calls from stdin as JSON objects, one per line:
{"tool": "send_email", "args": {"to": "alice@company.com", "subject": "Hello"}}
{"tool": "transfer_funds", "args": {"amount": 500, "currency": "USD"}}After observing enough calls, it generates deterministic constraints:
- Number ranges with configurable margin
- String enum allowlists (when fewer than 10 unique values observed)
- Required field detection
- Array length bounds
veto test
Adversarial policy gap finder. Analyzes your YAML rules for coverage gaps, regex bypasses, type coercion issues, and uncovered tools.
# Analyze default policy directory
veto test
# Analyze specific directory
veto test --policy ./veto/rules
# Save JSON report
veto test --output report.json
# JSON output format
veto test --format json| Flag | Required | Default | Description |
|---|---|---|---|
--policy <path> | No | ./veto/rules/ | Policy directory to analyze |
--output <file> | No | Write JSON report to file | |
--format <fmt> | No | text | Output format: text or json |
--quiet | No | false | Suppress output |
Exit codes:
0, No critical gaps found1, Critical gaps detected (CI-friendly)
Gap severities:
| Severity | Meaning |
|---|---|
critical | Security risk, tools or arguments with no constraints |
warning | Potential bypass, weak regex, type coercion, missing bounds |
info | Suggestion, coverage improvements, best practices |
veto scan
Audits discovered tools in your project against loaded rule coverage.
# Audit current project
veto scan
# Include inline YAML starter snippets for uncovered tools
veto scan --suggest
# Fail CI if uncovered tools exist
veto scan --fail-uncovered
# Machine-readable output
veto scan --format json| Flag | Required | Default | Description |
|---|---|---|---|
--fail-uncovered | No | false | Exit with code 1 when uncovered tools are found |
--suggest | No | false | Include inline YAML rule suggestions for uncovered tools |
--format <fmt> | No | text | Output format: text or json |
Coverage behavior:
- A tool is covered if at least one matching tool rule exists, or at least one global rule is present.
Exit codes:
0, Scan executed successfully1, Only when--fail-uncoveredis set and uncovered tools were found
veto diff
Compares policy snapshots and can replay deterministic impact against historical tool-call logs.
# Compare working file vs HEAD snapshot (git-aware mode)
veto diff financial.yaml
# Compare explicit file or directory snapshots
veto diff --old ./rules-v1 --new ./rules-v2
# Add deterministic impact replay from JSONL tool-call log
veto diff financial.yaml --log calls.jsonl
# JSON output
veto diff --old ./rules-v1 --new ./rules-v2 --log calls.jsonl --format jsonInvocation modes:
- Positional mode:
veto diff <policy-path>compares working copy vsHEADfor that path. - Explicit mode:
--oldand--newmust both be provided, and both must be files or both directories.
| Flag | Required | Default | Description |
|---|---|---|---|
<policy-path> | Positional mode only | Policy file path; compares working copy vs HEAD | |
--old <path> | Explicit mode (with --new) | Old policy file or directory | |
--new <path> | Explicit mode (with --old) | New policy file or directory | |
--log <path> | No | JSONL tool-call log for deterministic replay impact | |
--format <fmt> | No | text | Output format: text or json |
veto version
Prints the current SDK version.
npx veto version
# veto v<installed-version>
python -m veto version --jsonveto mcp import and restore
Install or restore an MCP client entry that routes tools through Veto.
# Node CLI
veto mcp import --output mcp.json --config veto/mcp.config.yaml --json
veto import mcp --output mcp.json --json
veto mcp import --restore --output mcp.json --json
# Python CLI
veto mcp import --cloud --output mcp.json --json
veto mcp restore --backup mcp.json.veto-backup-20260604T120000Z --jsonThe local import path creates a backup before replacing an existing server entry. Managed cloud import points the client at https://api.veto.so/v1/mcp/default.
veto receipts
Export, verify, and inspect decision receipts.
# Verify a local NDJSON chain
veto receipts verify .veto/receipts.ndjson
# Copy a normalized local export
veto receipts export --file .veto/receipts.ndjson --output receipts.ndjson --json
# Export from Veto Cloud
veto receipts export --cloud \
--project-id proj_123 \
--start-date 2026-06-01T00:00:00Z \
--limit 1000 \
--output receipts.ndjson \
--json
# Show one receipt from a local chain
veto receipts show rcp_000000000000000000000001 --file receipts.ndjson --jsonCloud export follows X-Veto-Next-Cursor until the server stops returning a cursor. --limit must be between 1 and 10000.
veto help
Shows all commands and flags.
npx veto help
