Skip to content
/docs

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.ndjson

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 --legacy

Studio-focused flags:

  • --renderer auto|ink|opentui|ansi
  • --directory <path>
  • --include-examples
  • --include-tests
  • --demo-template

Renderer notes:

  • ink is the default interactive renderer on Node.js.
  • opentui is optional and intended for Bun runtimes.
  • ansi is fallback-safe for CI and limited terminals.
  • if ink import/init fails at runtime, Studio falls back to ansi and prints a warning.

Legacy REPL (--legacy) keeps slash commands:

  • /scan for coverage suggestions
  • /test <tool>({args}) for local policy evaluation
  • /test-suite for generated scenario testing
  • /explain <ruleId> for rule explanations
  • /export and /load for 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
FlagRequiredDefaultDescription
--tool <name>YesTool name to generate policy for
--prompt <text>YesNatural-language policy intent
--mode-hint <hint>Noautoauto, deterministic, or llm
--target <target>Nolocallocal or cloud
--save <path>NoAuto path (local target)Save generated YAML
--demo-templateNofalseAllow explicit template fallback generation
--jsonNofalseDeterministic 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
FlagRequiredDefaultDescription
--file <path>YesPolicy YAML file path
--target <target>Nolocallocal or cloud
--project <id>NoCurrent cloud contextCloud project scope override
--jsonNofalseDeterministic 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
FlagRequiredDefaultDescription
--tool <name>YesTool name
--args <json>No{} or stdinTool arguments JSON object
--context <json>No{}Extra context JSON object
--mode <mode>Nolocallocal, cloud, kernel, or custom
--jsonNofalseDeterministic 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 logout

Login flow:

  1. Run veto cloud login in terminal.
  2. Open the verification URL shown by CLI.
  3. Approve the device code in dashboard.
  4. 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/turn for request/response turns
  • POST /v1/cli/charter/stream for 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.body

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.yaml

Quick one-off serve without a config file:

veto mcp serve \
  --upstream http://localhost:3000/mcp \
  --api-key veto_xxx \
  --policy-server http://localhost:3001

Flags:

  • --config <path> for serve/doctor
  • --listen <host:port> for serve
  • --upstream <url> and --transport <mcp-sse|mcp-stdio> for quick serve
  • --api-key <key> and --policy-server <url> for policy checks
  • --timeout-ms <n> for upstream timeout
  • --json for deterministic command output (doctor, init, and startup envelope on serve)

Managed/runtime support notes:

  • managed cloud MCP gateway supports mcp-sse
  • self-hosted CLI gateway supports mcp-sse and mcp-stdio

For managed APIs and architecture details, see MCP Gateway guide.

veto doctor

Diagnostics for runtime, renderer, auth, and connectivity:

veto doctor
veto doctor --json

Runtime 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@latest

For renderer diagnostics:

veto doctor --json

veto 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 \
  --json

Flags:

  • --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 --json

Creates:

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 extension

The 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.ndjson

The 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-agent
  • crypto-trading
  • financial
  • browser-automation
  • data-access
  • communication
  • deployment
  • economic-agent
  • soc2-lite
  • hipaa-lite
  • eu-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
FlagRequiredDefaultDescription
--input <text>One of --input or --filePolicy description as inline text
--file <path>One of --input or --filePath to a text file containing policy descriptions
--output <path>YesOutput file (.yaml) or directory for generated rules
--provider <name>NoopenaiLLM provider: openai, anthropic, gemini, openrouter
--model <name>NoProvider defaultModel identifier (e.g. gpt-4.1, claude-sonnet-4-6)
--quietNofalseSuppress 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
FlagRequiredDefaultDescription
--runs <n>One of --runs or --durationStop after N tool calls
--duration <time>One of --runs or --durationStop after duration (e.g. 30s, 10m, 1h)
--output <path>No./veto/rules/learned.yamlOutput YAML file path
--margin <n>No0.1Numeric range margin as decimal (10% slack around observed values)
--quietNofalseSuppress 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
FlagRequiredDefaultDescription
--policy <path>No./veto/rules/Policy directory to analyze
--output <file>NoWrite JSON report to file
--format <fmt>NotextOutput format: text or json
--quietNofalseSuppress output

Exit codes:

  • 0, No critical gaps found
  • 1, Critical gaps detected (CI-friendly)

Gap severities:

SeverityMeaning
criticalSecurity risk, tools or arguments with no constraints
warningPotential bypass, weak regex, type coercion, missing bounds
infoSuggestion, 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
FlagRequiredDefaultDescription
--fail-uncoveredNofalseExit with code 1 when uncovered tools are found
--suggestNofalseInclude inline YAML rule suggestions for uncovered tools
--format <fmt>NotextOutput 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 successfully
  • 1, Only when --fail-uncovered is 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 json

Invocation modes:

  • Positional mode: veto diff <policy-path> compares working copy vs HEAD for that path.
  • Explicit mode: --old and --new must both be provided, and both must be files or both directories.
FlagRequiredDefaultDescription
<policy-path>Positional mode onlyPolicy 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>NoJSONL tool-call log for deterministic replay impact
--format <fmt>NotextOutput format: text or json

veto version

Prints the current SDK version.

npx veto version
# veto v<installed-version>

python -m veto version --json

veto 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 --json

The 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 --json

Cloud 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