CLI
Veto command-line interface reference.
Installation
Canonical 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>Python:
# Installed globally with pip
veto <command>Commands
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.
veto 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 init
Scaffolds a new Veto configuration in the current directory.
npx veto init
npx veto init --force # Overwrite existing files
npx veto init --pack coding-agentCreates:
veto/
├── veto.config.yaml # Main configuration file
└── rules/
└── defaults.yaml # Default rule templateThe generated veto.config.yaml defaults to local mode:
version: "1.0"
mode: "strict"No API key or account needed to start. Add VETO_API_KEY to switch to cloud mode later.
If the veto/ directory already exists, the command does not overwrite existing files unless --force is set.
--pack pre-fills veto/rules/defaults.yaml with:
version: "1.0"
extends: "@veto/<pack>"Supported built-in packs:
coding-agentfinancialbrowser-automationdata-access
You can pass either coding-agent or @veto/coding-agent.
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-4o, claude-sonnet-4-5-20250929) |
--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).
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>veto help
Shows all commands and flags.
npx veto help