Skip to main content

VoiceRun command-line interface

Project description

VoiceRun CLI

A command-line interface for building and deploying voice agents on the VoiceRun platform.

Table of Contents

Installation

Prerequisites

  • Python 3.10 or higher

Install from PyPI

pip install voicerun-cli

Install from Source

git clone https://github.com/VoiceRun/voicerun-cli.git
cd voicerun-cli
pip install -e .

Install a Specific Version

uv tool install voicerun-cli==1.0.0 --force

Install Local Version

To install a local checkout as a CLI tool (useful for testing changes):

uv tool install --force -e .

Quick Start

# 1. Set up the CLI
vr setup

# 2. Create a new voice agent project
vr init my-agent

# 3. Navigate to the project directory
cd my-agent

# 4. Sign in to VoiceRun
vr signin

# 5. Edit handler.py to customize your agent logic

# 6. Validate your project
vr validate

# 7. Deploy to VoiceRun
vr push

# 8. Debug visually or open the web UI
vr debug      # Launch Pipeline Debugger
vr open       # Open web UI

Authentication

VoiceRun CLI supports three authentication methods:

Browser Authentication (Recommended)

vr signin

Opens your default browser for secure OAuth-style authentication.

Email/Password

vr signin
# Then select option 2 when prompted

API Key

vr signin
# Then select option 3 when prompted

Sign Out

vr signout

Credentials are stored in ~/.voicerun/:

  • Cookie: ~/.voicerun/cookie
  • API Key: ~/.voicerun/apikey
  • Config: ~/.voicerun/config.json

Global Options

vr --version

Show the installed CLI version and exit.

vr --version
vr -V

vr --update

Update the VoiceRun CLI to the latest version from PyPI and refresh all installed skills and MCP server configurations.

vr --update
vr -U

What it does:

  1. Upgrades the voicerun-cli package to the latest version via pip
  2. Reinstalls skills to the targets selected during vr setup (e.g., Claude Code, Codex, OpenClaw)
  3. Refreshes MCP server configuration for the targets selected during vr setup (e.g., Claude Code, Cursor, Windsurf)

Only targets that were explicitly chosen during vr setup are updated — no interactive prompts are shown. If vr setup has not been run, the update will skip skills and MCP configuration.

Example:

# Update everything
vr --update

# Short form
vr -U

vr --context

Run a single command against a named context without switching the active context. This is the one-off equivalent of vr context switch — it changes the API/frontend URLs and per-context credentials/organization used for this invocation only, and leaves current_context in ~/.voicerun/config.json untouched.

# Run against 'staging' for this command only; active context is unchanged afterwards
vr --context staging get agents

# The long --context form may appear anywhere on the line
vr get agents --context staging
Flag Description
--context, -c Name of an existing context (see vr context list) to use for this command only.

Behavior:

  • The override is applied via the VOICERUN_CONTEXT environment variable, so an explicit VOICERUN_API_URL (if exported) still wins for the API URL — the context still selects the credentials and effective organization.
  • An unknown context name aborts with exit code 2 before the command runs.
  • The long --context form is recognized in any position. The short -c form is only recognized before the subcommand (vr -c staging get agents), because several subcommands already use -c for their own options (e.g. vr create phonenumber -c US--country-code). After a subcommand, use the long form.

Example:

# Push to staging once without leaving your shell switched to it
vr --context staging push

# Equivalent persistent form (changes the active context until switched back):
#   vr context switch staging && vr push && vr context switch <previous>

Commands

Agent auto-resolution: Many commands that take an AGENT argument can infer it automatically when run inside a voicerun project directory (i.e., one with .voicerun/agent.lock). In those cases, the AGENT argument is optional. These commands are marked with [AGENT] in their usage.

Tenants

A project is laid out like a Helm chart: one .voicerun/ directory on disk, many releases. Tenant-specific overlays and release state live under .voicerun/tenants/<name>/.

my-agent/
  handler.py, tools.py, …                shared function code
  .voicerun/                              the chart (shared)
    agent.yaml
    values.yaml                           shared base values
    templates/
      deployment.yaml
      simulation.yaml
    tenants/                              per-release overlays + state
      millers/
        values.yaml                       tenant base overlay
        values.development.yaml           per-env overlay (optional)
        values.production.yaml
        agent.lock                        per-tenant release state
      counter-service/
        values.yaml
        agent.lock

Project-mutating commands (vr push, vr deploy, vr release, vr render, vr simulate, vr pull, vr test, vr debug, vr open, vr validate) accept:

Option Description
--tenant, -t Tenant name (a directory under .voicerun/tenants/).

VOICERUN_TENANT provides the same override when the flag is omitted.

Precedence: --tenant flag > VOICERUN_TENANT > none (legacy single-agent mode at .voicerun/agent.lock).

Values overlay order when rendering: chart values.yaml → tenant values.yaml → either --values <file> or the env-specific values.<env>.yaml (from the tenant dir when a tenant is set, else from the chart) → --set entries.

Examples:

# Push code and write per-tenant agent.lock under .voicerun/tenants/millers/
vr push --tenant millers
vr release production --tenant millers

# Short form
vr push -t counter-service

# Persist across commands in a shell session
export VOICERUN_TENANT=daves-hot-chicken
vr validate
vr push
vr release production

vr setup

Set up the VoiceRun CLI environment by installing required dependencies.

vr setup

Example:

vr setup

vr signin

Sign in to the VoiceRun API.

vr signin

Prompts for authentication method:

  1. Web browser (default) - Opens browser for OAuth authentication
  2. Email/Password - Enter credentials directly
  3. API Key - Use an API key for authentication

Example:

vr signin
# Select authentication method when prompted

Error behavior: commands distinguish authentication from authorization failures. A 401 prints Unauthorized. Please sign in with 'vr signin'. (missing/invalid credential). A 403 prints the server's actual error — e.g. which permission the credential is missing — since re-authenticating cannot fix a permission gap. Automation that matches on the old blanket Unauthorized message for 403s should match the server error text instead.


vr signout

Sign out and clear stored credentials.

vr signout

vr init

Create a new voice agent project from templates.

vr init [PROJECT_NAME]

Options:

Option Description
--yes, -y Skip prompts and use defaults
--force, -f Overwrite existing files
--template, -t Initialize from a remote template (name or ID)
--var Template variable as key=value (can be repeated)

Example:

# Interactive mode
vr init

# Non-interactive with project name
vr init my-agent --yes

# Initialize from a remote template
vr init my-agent --template customer-support

# Initialize from template with variables
vr init my-agent -t customer-support --var greeting="Hello" --var language="en"

vr validate

Validate project structure and configuration.

vr validate

Options:

Option Description
--environment, -e Environment to render templates for
--quiet, -q Only output errors
--tenant, -t Tenant name under .voicerun/tenants/ (see Tenants). Defaults to none or $VOICERUN_TENANT.

Validation Checks:

  • handler.py exists and contains async def handler()
  • .voicerun/ directory structure is correct
  • agent.yaml is valid with required fields
  • YAML syntax in all template files
  • Deployment spec contains only allowed fields

Example:

# Validate with specific environment
vr validate -e production

# Quiet mode (errors only)
vr validate -q

vr pull

Pull agent code from the VoiceRun server to your local machine.

vr pull [AGENT_ID]

Arguments:

Argument Description
AGENT_ID Agent ID to pull (not required if inside a voicerun project)

Options:

Option Description
--output, -o Output directory (defaults to agent name)
--yes, -y Skip confirmation prompt
--tenant, -t Tenant name under .voicerun/tenants/ (see Tenants). Defaults to none or $VOICERUN_TENANT.

Behavior:

  • Inside a voicerun project: Pulls code using the agent ID from agent.lock and overwrites local files
  • Outside a voicerun project: Requires an agent ID, creates a new directory with the pulled code and initializes .voicerun/agent.lock

Example:

# Pull inside an existing project
vr pull

# Pull a specific agent into a new directory
vr pull 550e8400-e29b-41d4-a716-446655440000

# Pull into a custom directory
vr pull 550e8400-e29b-41d4-a716-446655440000 -o ./my-agent

# Skip confirmation
vr pull --yes

vr push

Deploy your agent code to the VoiceRun server.

vr push

Options:

Option Description
--name Name for the function version
--new, -n Create a new function version instead of updating
--yes, -y Skip confirmation prompts
--tenant, -t Tenant name under .voicerun/tenants/ (see Tenants). Defaults to none or $VOICERUN_TENANT.

Behavior:

  • Validates the project before pushing
  • Packages code as a zip archive (excludes .venv, __pycache__, .git, etc. and files matching .vrignore)
  • Creates or updates agent.lock with agent and function IDs
  • First push creates a new agent; subsequent pushes update the existing version

Example:

# Push with confirmation
vr push

# Push without confirmation
vr push --yes

# Create a new version
vr push --new --name "v2.0"

vr deploy

Deploy the latest pushed function version to an environment.

Legacy. vr deploy targets agent-scoped environments from before the IaC migration. It prints a deprecation warning on every run. New agents should use vr release <ENVIRONMENT> (org-scoped environment + release + entrypoint model) instead.

vr deploy <ENVIRONMENT>

Arguments:

Argument Description
ENVIRONMENT Target environment name or ID (e.g., development, production). If not specified, you'll be prompted to select.

Options:

Option Description
--yes, -y Skip confirmation prompt
--tenant, -t Tenant name under .voicerun/tenants/ (see Tenants). Defaults to none or $VOICERUN_TENANT.

Prerequisites:

  • Run vr push first to create an agent and generate agent.lock

What it does:

  1. Validates the project structure
  2. Loads the agent ID and function ID from agent.lock
  3. Resolves the target environment
  4. Deploys the function version to the environment

Example:

# Deploy interactively (select environment from list)
vr deploy

# Deploy to development environment
vr deploy development

# Deploy to production without confirmation
vr deploy production --yes

vr release

Create a release tying an agent to an org-scoped environment at a point in time. The latest release for a given (agent, environment) pair is implicitly the active one — no isActive flag or manual version bump required.

vr release [AGENT] <ENVIRONMENT>

Arguments:

Argument Description
AGENT Agent name or ID (defaults to agent.lock)
ENVIRONMENT Org-scoped environment name or ID

Options:

Option Description
--function, -f Function ID to release (defaults to agent.lock's functionId)
--values, -v Values file to overlay (e.g. prod.yaml). Resolved relative to the tenant overlay dir when --tenant is set, otherwise relative to .voicerun/. Without this flag, only the chart base + (tenant base, if any) are loaded.
--entrypoint, -e Entrypoint name or ID. After the release is created, point this entrypoint at the new release in the same command.
--weight Partial-rollout weight (1–100) for the new release on --entrypoint. Without it, the entrypoint's release list is replaced with the new release at weight 100 (full cutover). With it, the new release is appended at the given weight, leaving existing entries unchanged for canary / staged rollouts.
--yes, -y Skip the confirmation prompt when the project has unpushed local changes.
--tenant, -t Tenant name under .voicerun/tenants/ (see Tenants). Defaults to none or $VOICERUN_TENANT.

Prerequisites:

  • Run vr push first to generate agent.lock, or pass --function explicitly
  • The target environment must already exist (see vr create environment)
  • If .voicerun/templates/ exists, Helm must be installed — vr release renders the full manifest at release time so the runtime has an immutable snapshot. No templates directory means no manifest is attached. If templates exist but Helm isn't on PATH, the command fails loudly rather than creating a silent release.

Unpushed-changes check:

Before creating the release, the CLI compares the project's current checksum against the one stored in agent.lock at last vr push. On mismatch, it warns that the release will run the previously-pushed function (not what's on disk) and prompts to confirm. Pass --yes for scripted/CI use. The check is silent for projects whose agent.lock predates this feature (no checksum field).

Secret resolution:

Rendered manifests may contain $VR_SECRET:<name> placeholders (e.g. in values files or template output). These are not embedded in the release payload — they're resolved against organization/environment secrets at session start, so secrets never round-trip through the release record.

Example:

# Inside a voicerun project (agent + function from agent.lock)
vr release production

# Explicit agent
vr release my-agent production

# Pin a specific function version
vr release my-agent production --function 550e8400-e29b-41d4-a716-446655440000

# Overlay a specific values file
vr release my-agent production --values prod.yaml

# Full cutover: route the entrypoint at the new release
vr release my-agent production --entrypoint support-line

# Staged 25% canary on the entrypoint, leaving prior releases in place
vr release my-agent production --entrypoint support-line --weight 25

# Skip the unpushed-changes prompt (CI)
vr release my-agent production --yes

vr debug

Launch the Pipeline Debugger — a visual Electron app for real-time agent testing. Can also place outbound phone calls directly from the CLI.

vr debug behaves differently depending on how the agent is deployed:

  • Legacy (v1) agents — pushes your local code (unless --skip-push) and debugs the per-agent debug environment.
  • Declarative (v2) agents (deployed with vr release into org-level environments) — does not push or release. It starts a debug session against an existing release. Choose the release with --release, narrow the interactive picker with -e <environment>, or pick from the list. Non-interactive runs (--yes, piped stdin, or --script) require --release.
vr debug

Options:

Option Description
--skip-push, -s (v1) Skip pushing code, use the existing deployment. Implied for v2 agents.
--environment, -e (v1) Environment name (default: debug). (v2) Filter the release picker to this org environment.
--release (v2 only) Release ID to debug. When omitted you pick from existing releases; required in non-interactive runs.
--yes, -y Non-interactive: never prompt. For v2 agents this requires --release.
--headless Run without GUI (for CI / coding agents). Streams JSONL events to stdout, reads text input from stdin, and exports session JSON on exit
--output, -o Output file path for headless session JSON (auto-generated if omitted)
--script Path to a JSON file with scripted messages (array of strings). Each message is sent one-per-turn automatically
--outbound Place an outbound phone call instead of launching the debugger (v1 agents only)
--to-phone-number Destination phone number in E.164 format (required with --outbound)
--from-phone-number Caller ID / originating phone number in E.164 format (optional)
--tenant, -t Tenant name under .voicerun/tenants/ (see Tenants). Defaults to none or $VOICERUN_TENANT.

Prerequisites:

  • Node.js must be installed for the debugger (not required for --outbound mode)
  • For v2 agents: at least one release must exist (vr release <environment>)

What it does:

  • Legacy (v1) agent in a project: Pushes your local code to the VoiceRun server (unless --skip-push), installs debugger dependencies if needed, and launches the Pipeline Debugger connected to your agent's debug environment.
  • Declarative (v2) agent in a project: Resolves an existing release (via --release, the -e environment filter, or an interactive picker), starts an authenticated debug session against it, and connects the debugger to that release. No code is pushed or released.
  • Outside a project: Opens the Pipeline Debugger with no prefilled agent info, so you can connect manually.
  • Headless mode: Runs a lightweight Node client (no Electron / browser) instead of the GUI — connects to the agent, streams JSONL events to stdout, and accepts text input on stdin (one message per line). It self-terminates when the session ends, on a scripted run's completion, or on stdin close / idle, and writes the session JSON on SIGINT/SIGTERM. Useful for CI pipelines and coding agents. For v2 agents, pass --release (headless is non-interactive when stdin is piped).
  • Outbound mode: Pushes your code and places an outbound phone call to the specified number. Returns a telephonyCallId for tracking. Does not launch the debugger GUI. (v1 agents only.)

Example:

# Legacy (v1): push and debug (inside a project)
vr debug

# Legacy (v1): debug without pushing (use existing deployment)
vr debug --skip-push
vr debug -s

# Legacy (v1): debug a specific environment
vr debug -e staging

# Declarative (v2): pick a release interactively
vr debug

# Declarative (v2): narrow the picker to one environment
vr debug -e staging

# Declarative (v2): debug a specific release (works non-interactively / in CI)
vr debug --release rel_abc123

# Open the debugger standalone (from any directory)
vr debug

# Headless mode (CI / coding agents)
vr debug --headless                              # v1
vr debug --headless --release rel_abc123         # v2
vr debug --headless --output session.json

# Run a scripted conversation
vr debug --script test-messages.json
vr debug --headless --script test-messages.json -o results.json
vr debug --headless --release rel_abc123 --script test-messages.json -o results.json   # v2

# Place an outbound phone call (v1 agents)
vr debug --outbound --to-phone-number "+15551234567"

# Outbound call with caller ID and custom environment
vr debug --outbound --to-phone-number "+15551234567" --from-phone-number "+15559876543" -e production

# Outbound call without pushing (use existing deployment)
vr debug --outbound --to-phone-number "+15551234567" --skip-push

vr open

Open the web interface to your deployed agent.

vr open

Options:

Option Description
--tenant, -t Tenant name under .voicerun/tenants/ (see Tenants). Defaults to none or $VOICERUN_TENANT.

Requires agent.lock to exist (created after vr push; per-tenant when --tenant is set). Opens your default browser to the agent's function page.


vr render

Render VoiceRun templates and display the output.

vr render

Options:

Option Description
--values, -f Custom values file path
--set, -s Override values (can be used multiple times)
--output, -o Output format: yaml (default) or json
--quiet, -q Only output templates, no validation messages
--tenant, -t Tenant name under .voicerun/tenants/ (see Tenants). Defaults to none or $VOICERUN_TENANT.

Example:

# Render with default values
vr render

# Render with specific values file
vr render -f .voicerun/values.yaml

# Override specific values
vr render --set stt.model=deepgram-flux --set environment=production

# Output as JSON
vr render -o json

vr test

Run tests for the voice agent project.

vr test

Options:

Option Description
--environment, -e Environment to fetch secrets from (e.g., development, production)
--verbose, -v Run pytest in verbose mode
--coverage, -c Run with coverage reporting
--skip-install Skip dependency installation
--tenant, -t Tenant name under .voicerun/tenants/ (see Tenants). Defaults to none or $VOICERUN_TENANT.

What it does:

  1. Validates project structure
  2. Installs project dependencies (unless --skip-install)
  3. Optionally fetches secrets from the specified environment
  4. Runs pytest with the specified options

Example:

# Run all tests
vr test

# Run specific test file
vr test tests/test_handler.py

# Run tests with development secrets
vr test -e development

# Run with verbose output and coverage
vr test -v -c

# Skip dependency installation
vr test --skip-install

# Pass extra arguments to pytest
vr test -- -k "test_name" -x

vr simulate

Run a Simulation resource defined in .voicerun/templates/ against an agent in an environment. The API pre-creates N agent sessions (origin: simulation) and the voicerun-simulations service drives each one as a Gemini-Live caller against the active release for (agent, environment).

vr simulate [AGENT] <ENVIRONMENT> --name <SIMULATION_NAME>

Arguments:

Argument Description
AGENT Agent name or ID (defaults to agent.lock)
ENVIRONMENT Org-scoped environment name or ID

Options:

Option Description
--name Simulation resource name to run. If omitted, lists available simulations from .voicerun/templates/ and exits.
--release, -r Pin the run to a specific release ID. Defaults to the latest release for (agent, environment).
--values, -v Values file to overlay for local listing/preview (e.g. prod.yaml). Resolved relative to the tenant overlay dir when --tenant is set, otherwise relative to .voicerun/. The server uses the release's manifest regardless.
--wait Block until every spawned session reaches a terminal status (completed or failed), printing aggregate progress. Default: return immediately with the run ID.
--yes, -y Skip the cost-guardrail confirmation prompt that appears when spec.numberOfSimulations exceeds 10.
--tenant, -t Tenant name under .voicerun/tenants/ (see Tenants). Defaults to none or $VOICERUN_TENANT.

Prerequisites:

  • .voicerun/templates/ must exist and contain at least one kind: Simulation document with a spec.systemPrompt.
  • Helm must be installed — vr simulate renders the templates locally before submitting (run vr setup if missing).
  • The target environment must already have an active release for the agent (created via vr release) — simulations call into the live /ws/entrypoint route. The active release's manifest is authoritative for spec.systemPrompt and spec.numberOfSimulations; local edits not yet released are previewed but not used at run time.

Simulation resource shape:

kind: Simulation
metadata:
  name: happy-path
spec:
  systemPrompt: |
    You are a customer calling support. Ask to reset your password.
  numberOfSimulations: 5

PSTN mode (real phone calls): set mode: pstn to place a REAL outbound phone call to the agent's entrypoint number instead of a direct WebSocket — exercising the full carrier path (codec transcoding, jitter, DTMF-over-PSTN, the agent's actual telephony ingress). The number dialed defaults to the phone number assigned to the agent + environment; set spec.toNumber (E.164) to override. Each run is a real, billable call, so the CLI always confirms before submitting (skip with --yes). Not compatible with direction: outbound, and --wait is not yet supported (the agent answers a genuine call, so the run's session records track the simulated caller only).

kind: Simulation
metadata:
  name: pstn-smoke
spec:
  systemPrompt: |
    You are a customer calling support. Ask to reset your password.
  mode: pstn
  numberOfSimulations: 1

Example:

# List available simulations in the project
vr simulate production

# Run a single simulation against an environment
vr simulate production --name happy-path

# Explicit agent + pin to a specific release
vr simulate my-agent production --name happy-path --release 550e8400-e29b-41d4-a716-446655440000

# Overlay a values file (for local preview) and block until done
vr simulate my-agent production --name happy-path --values prod.yaml --wait

# Bulk run, skipping the cost-guardrail prompt
vr simulate production --name stress-test --yes

Output:

Prints the run ID and the spawned session IDs. Inspect individual runs with:

  • vr describe session <id> — full session detail
  • vr metrics session <id> — custom metrics recorded during the run
  • vr experiments funnel <experiment> — when simulations are tied to an experiment

vr evaluation

View evaluations produced by Evaluator resources defined in .voicerun/templates/. Evaluators are scored or extracted server-side after each session completes; the CLI is read-only — define new evaluators by adding a kind: Evaluator document and shipping it via vr release.

vr evaluation list

List evaluations for an agent, or for a specific session.

vr evaluation list [AGENT]

Arguments:

Argument Description
AGENT Agent name or ID (defaults to agent.lock)

Options:

Option Description
--session, -S Limit to a single session ID. Pulls from /v1/sessions/:id/evaluations instead of the agent-scoped endpoint.
--status, -s Filter by status (pending, complete, error, skipped). skipped rows are evaluations whose precondition predicate didn't match the session — no LLM call was made.
--type, -T Filter by eval type (judge, extraction, deterministic, script). deterministic rows assert on the derived session view without an LLM.
--limit, -l Page size.
--page, -p Page number.
--json, -j Output as JSON.
--table, -t Output as table (default for interactive terminals).

Example:

# List evaluations for the current project agent
vr evaluation list

# Limit to a single session
vr evaluation list --session 550e8400-e29b-41d4-a716-446655440000

# Filter to failed judge runs
vr evaluation list --status error --type judge

# Audit which sessions were skipped (precondition not met)
vr evaluation list --status skipped

# Audit cheap deterministic evals (no LLM cost)
vr evaluation list --type deterministic

vr evaluation info

Show full detail for a single evaluation, including ruling/extraction payload, success criteria, and token usage.

vr evaluation info <EVALUATION_ID>

Arguments:

Argument Description
EVALUATION_ID Evaluation UUID

Options:

Option Description
--json, -j Output as JSON.
--table, -t Output as rich panels (default for interactive terminals).

Example:

vr evaluation info 550e8400-e29b-41d4-a716-446655440000

Output includes:

  • Status, eval type, trigger, evaluator ID, session ID, model
  • For judge evaluations: success flag, ruling, success criteria
  • For extraction evaluations: the extracted payload
  • For deterministic evaluations: success flag, assertion predicate, and structured details ({ matched: true } on success, or { matched: false, failedPath, reason } on failure)
  • For skipped evaluations: a "Skipped" panel showing the precondition reason — no per-type result panel is rendered, since the eval never ran
  • Prompt and completion token usage (zero for deterministic and skipped rows)
  • Timestamps

vr get

List resources by type.

kubectl-style filter: every vr get <resource> command takes an optional positional argument that filters the same table down to a single matching row — vr get agents my-agent is the one-row form of vr get agents. Most resources match by name or ID; phonenumbers and assignments also match by phone number or friendly name; releases match by ID only (no name field). When the filter doesn't match anything, the command exits non-zero with a clear "not found" message.

Output format: every vr get <resource> command accepts -j/--json (emit {"data": [...]} with full, untruncated field values — the machine-parseable source of truth) and -t/--table (force the human-readable table). With neither flag, the format is auto-detected: table on an interactive terminal, JSON when output is piped, redirected, or consumed by a coding agent. One exception: on vr get entrypoints, -t is taken by --type, so use the long form --table there. vr get variables --json returns {"data": {"organizationVariables": [...], "environmentVariables": [...]}}, where environmentVariables is null when the agent-environment scope was not queried. In JSON mode the legacy-deprecation warning on agentenvironments is suppressed so stdout stays parseable.

vr get agents

List agents (or describe one as a single-row list when name or ID is given).

vr get agents [NAME_OR_ID]

Arguments:

Argument Description
NAME_OR_ID Optional: filter to a single agent by name or ID

Displays a table with agent name, ID, description, voice, and transport.

vr get functions

List all functions for a specific agent.

vr get functions [AGENT]

Arguments:

Argument Description
AGENT Agent name or ID (defaults to agent.lock)

Example:

# Inside a voicerun project (uses agent.lock)
vr get functions

# Explicit agent
vr get functions my-agent
vr get functions 550e8400-e29b-41d4-a716-446655440000

vr get environments

List all org-scoped environments.

vr get environments

Example:

vr get environments

vr get agentenvironments

List legacy per-agent environments. For org-scoped environments, use vr get environments.

Legacy. Per-agent environments are deprecated in favor of org-scoped environments + releases. This command prints a deprecation warning but otherwise runs normally (reads are never blocked).

vr get agentenvironments [AGENT]

Arguments:

Argument Description
AGENT Agent name or ID (defaults to agent.lock)

Example:

# Inside a voicerun project (uses agent.lock)
vr get agentenvironments

# Explicit agent
vr get agentenvironments my-agent

vr get releases

List releases, optionally filtered by agent and/or environment. The latest release for a given (agent, environment) pair is implicitly the active one.

vr get releases

Options:

Option Description
--agent, -a Filter by agent name or ID
--environment, -e Filter by environment name or ID

Example:

# List all releases
vr get releases

# Filter by agent
vr get releases --agent my-agent

# Filter by agent and environment
vr get releases --agent my-agent --environment production

The table resolves AGENT, ENVIRONMENT, and FUNCTION columns to their human-readable names; rows whose underlying entity has been deleted fall back to the bare ID.

vr get entrypoints

List all org-scoped entrypoints (phone, web, native).

vr get entrypoints

Options:

Option Description
--type, -t Filter by entrypoint type (phone, web, or native)

Example:

# List all entrypoints
vr get entrypoints

# Only phone entrypoints
vr get entrypoints --type phone

vr get variables

List variables that agents can read via context.variables.get(NAME) at runtime. Always lists organization-level variables. If an agent and environment are both resolvable (via --agent/agent.lock and --environment), also lists that environment's variables.

vr get variables

Options:

Option Description
--agent, -a Agent name or ID (defaults to agent.lock)
--environment, -e Environment name or ID (required to list agent variables)
--org Only list organization-level variables

Example:

# List organization variables
vr get variables --org

# Inside a voicerun project, list both org + environment variables
vr get variables --environment production

# Explicit agent
vr get variables --agent my-agent --environment production

Masked values render as •••••••• in the output.

vr get secrets

List organization-level secrets used by evaluators. Agent-scoped secrets are not yet supported for runtime injection — use vr create variable with --masked when you need a value readable via context.variables.get().

vr get secrets

Options:

Option Description
--agent, -a Agent name or ID (for listing existing legacy agent-scoped secret records)

Example:

# List organization secrets
vr get secrets

vr get phonenumbers

List organization phone numbers.

vr get phonenumbers

Displays a table with phone number, friendly name, ID, area code, and country code.

vr get telephony

List organization telephony providers.

vr get telephony

Displays a table with provider name, ID, and provider type.

vr get assignments

List all phone number assignments for an agent.

vr get assignments [AGENT]

Arguments:

Argument Description
AGENT Agent name or ID (defaults to agent.lock)

Example:

# Inside a voicerun project (uses agent.lock)
vr get assignments

# Explicit agent
vr get assignments my-agent

Displays a table with phone number ID, environment ID, assignment ID, and created at timestamp.

vr get templates

List available agent templates.

vr get templates

Displays a table with template name, ID, category, description, and public/private status.

vr get organizations

List the organizations you belong to (or describe one as a single-row list when name or ID is given). Aliases: vr get organization, vr get orgs.

vr get organizations [NAME_OR_ID]

Arguments:

Argument Description
NAME_OR_ID Optional: filter to a single organization by name or ID

Example:

# List every org you belong to
vr get organizations

# Describe one by name or ID
vr get organizations "Prim Voices"
vr get organizations 8e77d4bd-2b70-4e10-8e60-18ea552eb117

Displays a table with organization name, ID, your role, and a in the DEFAULT column for your current org context. Backed by the user-scoped /v1/me/organizations endpoint, so it works for any signed-in user (not just admins).


vr describe

Show detailed information about a specific resource.

Output format: every vr describe <resource> command accepts -j/--json (emit {"data": {...}} with full, untruncated field values — panels width-truncate long values like UUIDs, JSON never does) and -t/--table (force the human-readable panels). With neither flag, the format is auto-detected: panels on an interactive terminal, JSON when output is piped, redirected, or consumed by a coding agent. In JSON mode the legacy-deprecation warning on agentenvironment is suppressed so stdout stays parseable.

vr describe assignment

Show detailed information about a phone number assignment.

vr describe assignment [AGENT] <ASSIGNMENT_ID>

Arguments:

Argument Description
AGENT Agent name or ID (defaults to agent.lock)
ASSIGNMENT_ID Assignment UUID

Example:

# Inside a voicerun project (uses agent.lock)
vr describe assignment 550e8400-e29b-41d4-a716-446655440000

# Explicit agent
vr describe assignment my-agent 550e8400-e29b-41d4-a716-446655440000

Output includes:

  • Assignment details (ID, environment ID, phone number ID)
  • Timestamps

vr describe agent

Show detailed information about an agent.

vr describe agent [NAME_OR_ID]

Arguments:

Argument Description
NAME_OR_ID Agent name or UUID (defaults to agent.lock)

Example:

# Inside a voicerun project (uses agent.lock)
vr describe agent

# Explicit agent
vr describe agent my-agent

Output includes:

  • Basic information (ID, name, description)
  • Voice & transport configuration
  • Organization details and creator attribution (user ID or service account ID for agents created by an organization service account)
  • Debug & tracing settings
  • Timestamps

vr describe function

Show detailed information about a function.

vr describe function [AGENT] <NAME_OR_ID>

Arguments:

Argument Description
AGENT Agent name or ID (defaults to agent.lock)
NAME_OR_ID Function name, display name, or UUID

Example:

# Inside a voicerun project (uses agent.lock)
vr describe function main-handler

# Explicit agent
vr describe function my-agent main-handler

Output includes:

  • Basic information (ID, name, display name)
  • Code configuration (language, strategy, multifile)
  • Code preview (if available)
  • Test data (if configured)
  • Timestamps

vr describe environment

Show detailed information about an org-scoped environment.

vr describe environment <NAME_OR_ID>

Arguments:

Argument Description
NAME_OR_ID Environment name or UUID

Example:

vr describe environment production

Output includes:

  • Basic information (ID, name, description)
  • Organization ID
  • Timestamps

vr describe agentenvironment

Show detailed information about a legacy per-agent environment. For org-scoped environments, use vr describe environment.

Legacy. Per-agent environments are deprecated in favor of org-scoped environments + releases. This command prints a deprecation warning but otherwise runs normally (reads are never blocked).

vr describe agentenvironment [AGENT] <NAME_OR_ID>

Arguments:

Argument Description
AGENT Agent name or ID (defaults to agent.lock)
NAME_OR_ID Environment name or UUID

Example:

# Inside a voicerun project (uses agent.lock)
vr describe agentenvironment production

# Explicit agent
vr describe agentenvironment my-agent production

Output includes:

  • Basic information (ID, name, phone number, debug flag)
  • Speech-to-text (STT) configuration
  • Recording settings
  • Error handling, audio processing, VAD, and advanced settings
  • Timestamps

vr describe release

Show detailed information about a release.

vr describe release <RELEASE_ID>

Arguments:

Argument Description
RELEASE_ID Release UUID

Example:

vr describe release 550e8400-e29b-41d4-a716-446655440000

Output includes:

  • Release ID, status, and timestamps
  • Agent, environment, and function rendered as Name (id) (or just the ID when the entity has been deleted)
  • Created-by user ID or service account ID (releases pushed by an organization service account, e.g. from CI, are attributed to the service account), and organization ID

vr describe entrypoint

Show detailed information about an entrypoint.

vr describe entrypoint <NAME_OR_ID>

Arguments:

Argument Description
NAME_OR_ID Entrypoint name or UUID

Example:

vr describe entrypoint support-line

Output includes:

  • Basic information (ID, name, type, status, organization ID)
  • Weighted release list — each releaseId with its weight and percentage share of traffic. An entrypoint with no releases configured is flagged as a misconfiguration.
  • Per-type config block (e.g., phone number details, allowed origins, client ID)

vr describe variable

Show detailed information about a variable. Searches organization-level variables by default, and agent environment variables when --agent and --environment are provided.

vr describe variable <NAME_OR_ID>

Arguments:

Argument Description
NAME_OR_ID Variable name or UUID

Options:

Option Description
--agent, -a Agent name or ID (defaults to agent.lock)
--environment, -e Environment name or ID (required to search agent variables)
--org Only search organization-level variables

Example:

vr describe variable ANTHROPIC_API_KEY
vr describe variable ANTHROPIC_API_KEY --agent my-agent --environment production

Masked values render as •••••••• in the output.

vr describe secret

Show detailed information about an organization-level secret (evaluator-only).

vr describe secret <NAME_OR_ID>

Arguments:

Argument Description
NAME_OR_ID Secret name or UUID

Options:

Option Description
--agent, -a Agent name or ID (searches organization secrets first, then agent secrets)

Example:

vr describe secret MY_API_KEY

vr describe phonenumber

Show detailed information about a phone number. Looks up by ID, the E.164 phone number itself, or the friendly name.

vr describe phonenumber <PHONE_NUMBER_OR_ID>

Arguments:

Argument Description
PHONE_NUMBER_OR_ID Phone number ID, the E.164 phone number, or the friendly name

Example:

# By UUID
vr describe phonenumber 550e8400-e29b-41d4-a716-446655440000

# By the phone number itself
vr describe phonenumber +15551234567

# By friendly name
vr describe phonenumber "Support Line"

Output includes:

  • Phone number, friendly name, area code, country code
  • Telephony provider ID
  • Timestamps

vr describe telephony

Show detailed information about a telephony provider.

vr describe telephony <NAME_OR_ID>

Arguments:

Argument Description
NAME_OR_ID Telephony provider name or UUID

Example:

vr describe telephony my-twilio

Output includes:

  • Provider name, type, and ID
  • Organization ID
  • Timestamps

vr describe organization

Show detailed information about an organization you belong to. Aliases: vr describe org, vr describe orgs, vr describe organizations.

vr describe organization <NAME_OR_ID>

Arguments:

Argument Description
NAME_OR_ID Organization name or UUID

Example:

vr describe organization "Prim Voices"
vr describe organization 8e77d4bd-2b70-4e10-8e60-18ea552eb117

Output includes:

  • Organization name and ID
  • Your role in the org (owner, admin, member)
  • Whether this org is your current context
  • Your membership ID

Backed by the user-scoped /v1/me/organizations endpoint, so it only resolves orgs you're a member of.


vr create

Create resources.

vr create assignment

Assign a phone number to an agent environment.

vr create assignment [AGENT] <ENVIRONMENT> <PHONE_NUMBER_ID>

Arguments:

Argument Description
AGENT Agent name or ID (defaults to agent.lock)
ENVIRONMENT Environment name or ID
PHONE_NUMBER_ID Organization phone number ID

Options:

Option Description
--configure Configure the phone number with the telephony provider after assignment

Example:

# Inside a voicerun project (uses agent.lock)
vr create assignment production 550e8400-e29b-41d4-a716-446655440000

# Explicit agent
vr create assignment my-agent production 550e8400-e29b-41d4-a716-446655440000
vr create assignment my-agent production 550e8400-e29b-41d4-a716-446655440000 --configure

vr create environment

Create an org-scoped environment. Agents are released into it via vr release.

vr create environment <NAME>

Arguments:

Argument Description
NAME Environment name (unique within the organization)

Options:

Option Description
--description, -d Description of the environment

Example:

vr create environment production
vr create environment staging --description "Pre-production testing"

vr create agentenvironment

Create a legacy per-agent environment. For org-scoped environments, use vr create environment.

Legacy. Per-agent environments are deprecated in favor of org-scoped environments + releases. This command prints a deprecation warning and requires an interactive y/N confirmation before creating. Pass --yes/-y to skip it (required in non-interactive shells, which otherwise abort).

vr create agentenvironment [AGENT] <NAME>

Arguments:

Argument Description
AGENT Agent name or ID (defaults to agent.lock)
NAME Environment name

Options:

Option Description
--stt-model Speech-to-text model (e.g. nova-3)
--stt-language STT language code (e.g. en)
--stt-endpointing STT endpointing timeout in ms
--recording/--no-recording Enable or disable call recording
--yes, -y Skip the legacy-deprecation confirmation

Example:

# Inside a voicerun project (uses agent.lock)
vr create agentenvironment production

# Explicit agent
vr create agentenvironment my-agent production

# With STT and recording options
vr create agentenvironment my-agent staging --stt-model nova-3 --stt-language en --recording

# Skip the confirmation (e.g. in CI)
vr create agentenvironment production --yes

vr create entrypoint

Create or update an entrypoint that routes traffic to one or more releases. Entrypoints are org-scoped and polymorphic — pick the subcommand matching the channel (phone, web, or native).

Entrypoints are not tied to a specific agent or environment. Instead, each entrypoint carries a weighted list of releases and the API picks one per call via weighted random selection. That list can mix releases across agents and environments — only the release IDs need to be valid.

vr create entrypoint {phone|web|native} <NAME> [OPTIONS]

Common options (phone, web, native):

Option Description
--release, -r Release routing target as <releaseId>[:<weight>] (optional, repeatable). Weight defaults to 1 when omitted. Duplicate release IDs are rejected. Omit entirely to create a release-less entrypoint and wire releases up later via vr update entrypoint.

To split traffic, pass --release multiple times with explicit weights (e.g. --release rel-a:70 --release rel-b:30). The weights don't need to sum to any particular number — shares are computed relative to the total. A release-less entrypoint is allowed at create time but will return a 404 ("no release found") when called until releases are attached.

vr create entrypoint phone
vr create entrypoint phone <NAME> [--release <ID>[:<WEIGHT>]] --phone-number <E164>

Options:

Option Description
--phone-number, -p E.164 phone number (e.g. +15551234567) (required)
--telephony, -t Telephony provider ID
--friendly-name Friendly name for the number
--area-code Area code
--country-code Country code
--direction inbound, outbound, or both

Example:

# Single release
vr create entrypoint phone support-line \
  --release 550e8400-e29b-41d4-a716-446655440000 \
  --phone-number "+15551234567" --friendly-name "Support" --direction inbound

# 70/30 A/B split across two releases
vr create entrypoint phone support-line \
  --release rel-a:70 --release rel-b:30 \
  --phone-number "+15551234567"

# Release-less — wire the release in later with `vr update entrypoint`
vr create entrypoint phone support-line --phone-number "+15551234567"
vr create entrypoint web
vr create entrypoint web <NAME> [--release <ID>[:<WEIGHT>]] --allowed-origin <ORIGIN>

Options:

Option Description
--allowed-origin, -o Allowed origin (repeat for multiple) (required)

Example:

vr create entrypoint web widget \
  --release rel-latest \
  -o https://acme.com -o https://app.acme.com
vr create entrypoint native
vr create entrypoint native <NAME> [--release <ID>[:<WEIGHT>]] --client-id <ID>

Options:

Option Description
--client-id, -c Client ID for the native SDK (required)
--client-secret-secret-id Secret ID holding the client secret
--allowed-api-key-id Allowed API key ID (repeat for multiple)

Example:

vr create entrypoint native mobile-app \
  --release rel-latest \
  --client-id mobile-ios --client-secret-secret-id 550e8400-e29b-41d4-a716-446655440000

vr update

Use vr update for resource mutations that don't fit create/delete flows, plus the existing global vr --update flag for upgrading the CLI itself.

vr update entrypoint

Update an existing entrypoint's routing or metadata in place. Passing --release replaces the entire routing list (it is not an append).

vr update entrypoint <ENTRYPOINT_ID> [--release ... ] [--name ...] [--status ...]

Options:

Option Description
--release, -r Replace the routing list with these <releaseId>[:<weight>] entries (repeatable).
--name Rename the entrypoint.
--status active or disabled.

At least one of --release, --name, or --status must be provided.

Example:

# Shift a 50/50 split to 100% on the new release
vr update entrypoint 550e8400-e29b-41d4-a716-446655440000 \
  --release rel-new:100

# Disable an entrypoint without deleting it
vr update entrypoint 550e8400-e29b-41d4-a716-446655440000 --status disabled

vr create entrypoint update still works as a deprecated alias and prints a warning directing you to vr update entrypoint.

vr create variable

Create a variable that an agent handler can read via context.variables.get(NAME). By default creates a variable scoped to a specific agent environment; pass --org to create an organization-level variable visible to every agent in the org.

Use --masked for sensitive values like API keys — the value is still delivered to the agent at runtime, but hidden from CLI listings and UI reads.

vr create variable <NAME> <VALUE>

Arguments:

Argument Description
NAME Variable name (use the same key in context.variables.get(NAME))
VALUE Variable value

Options:

Option Description
--agent, -a Agent name or ID (defaults to agent.lock)
--environment, -e Environment name or ID (required unless --org)
--org Create an organization-level variable instead of an agent environment variable
--masked Mask the value in listings and describe output

Examples:

# Create an environment variable inside a voicerun project
vr create variable ANTHROPIC_API_KEY sk-ant-... --environment production --masked

# Explicit agent
vr create variable ANTHROPIC_API_KEY sk-ant-... --agent my-agent --environment production --masked

# Organization-level variable available to every agent
vr create variable SUPPORT_EMAIL help@acme.com --org

In the Python handler:

def handler(context):
    api_key = context.variables.get("ANTHROPIC_API_KEY")
    ...

vr create secret

Create an organization-level secret for use by evaluators. Agent-scoped secrets are not yet supported for runtime injection — if you need a value readable via context.variables.get() at runtime, use vr create variable with --masked instead.

vr create secret <NAME> <VALUE>

Arguments:

Argument Description
NAME Secret name
VALUE Secret value

Options:

Option Description
--agent, -a (Unsupported) Rejects with a redirect to vr create variable --masked

Example:

# Create an organization secret for evaluator usage
vr create secret MY_API_KEY sk-1234567890

vr create phonenumber

Create or purchase a phone number for the organization.

vr create phonenumber <TELEPHONY_ID>

Arguments:

Argument Description
TELEPHONY_ID Telephony provider ID

Options:

Option Description
--purchase Purchase a new number from the telephony provider
--area-code, -a Area code for the phone number
--country-code, -c Country code (defaults to US)
--friendly-name, -n Friendly name for the phone number
--phone-number, -p Phone number to register (without --purchase)

Example:

# Purchase a new phone number
vr create phonenumber <telephony-id> --purchase --area-code 415

# Register an existing phone number
vr create phonenumber <telephony-id> --phone-number "+15551234567" --friendly-name "Support Line"

vr create template

Create a reusable template from the current project files. All text files in the project directory are collected and uploaded. Binary files are skipped automatically. Files matching patterns in .vrignore are excluded.

vr create template <NAME>

Arguments:

Argument Description
NAME Template name

Options:

Option Description
--description, -d Template description
--category, -c Template category
--public/--private Make template public or private to org (default: public)

Example:

# Create a public template
vr create template my-agent-template

# Create a private template with metadata
vr create template my-agent-template --private -d "Customer support agent" -c "support"

vr create telephony

Create a telephony provider for the organization. Missing options will be prompted interactively.

vr create telephony

Options:

Option Description
--name, -n Name for the telephony provider
--provider-type, -p Provider type (e.g., twilio, telnyx)
--account-sid Twilio Account SID
--api-key-sid Twilio API Key SID
--api-key-secret Twilio API Key Secret
--api-key Telnyx API Key

Example:

# Interactive mode
vr create telephony

# Non-interactive with all options
vr create telephony --name "My Twilio" --provider-type twilio \
  --account-sid AC123 --api-key-sid SK123 --api-key-secret secret123

vr delete

Delete resources.

vr delete assignment

Delete a phone number assignment from an agent.

vr delete assignment [AGENT] <ASSIGNMENT_ID>

Arguments:

Argument Description
AGENT Agent name or ID (defaults to agent.lock)
ASSIGNMENT_ID Assignment ID

Example:

# Inside a voicerun project (uses agent.lock)
vr delete assignment 550e8400-e29b-41d4-a716-446655440000

# Explicit agent
vr delete assignment my-agent 550e8400-e29b-41d4-a716-446655440000

vr delete agent

Delete an agent.

vr delete agent <NAME_OR_ID>

Arguments:

Argument Description
NAME_OR_ID Agent name or ID

Example:

vr delete agent my-agent

vr delete function

Delete a function from an agent.

vr delete function [AGENT] <NAME_OR_ID>

Arguments:

Argument Description
AGENT Agent name or ID (defaults to agent.lock)
NAME_OR_ID Function name, display name, or ID

Example:

# Inside a voicerun project (uses agent.lock)
vr delete function main-handler

# Explicit agent
vr delete function my-agent main-handler

vr delete environment

Delete an org-scoped environment.

vr delete environment <NAME_OR_ID>

Arguments:

Argument Description
NAME_OR_ID Environment name or ID

Example:

vr delete environment staging

vr delete agentenvironment

Delete a legacy per-agent environment. For org-scoped environments, use vr delete environment.

Legacy. Per-agent environments are deprecated in favor of org-scoped environments + releases. This command prints a deprecation warning and requires an interactive y/N confirmation before deleting. Pass --yes/-y to skip it (required in non-interactive shells, which otherwise abort).

vr delete agentenvironment [AGENT] <NAME_OR_ID>

Arguments:

Argument Description
AGENT Agent name or ID (defaults to agent.lock)
NAME_OR_ID Environment name or ID

Options:

Option Description
--yes, -y Skip the legacy-deprecation confirmation

Example:

# Inside a voicerun project (uses agent.lock)
vr delete agentenvironment staging

# Explicit agent
vr delete agentenvironment my-agent staging

# Skip the confirmation (e.g. in CI)
vr delete agentenvironment staging --yes

vr delete release

Delete a release by ID.

vr delete release <RELEASE_ID>

Arguments:

Argument Description
RELEASE_ID Release UUID

Example:

vr delete release 550e8400-e29b-41d4-a716-446655440000

vr delete entrypoint

Delete an entrypoint by name or ID.

vr delete entrypoint <NAME_OR_ID>

Arguments:

Argument Description
NAME_OR_ID Entrypoint name or ID

Example:

vr delete entrypoint support-line

vr delete variable

Delete a variable. Searches organization-level variables first, then agent environment variables when --agent and --environment are both provided.

vr delete variable <NAME_OR_ID>

Arguments:

Argument Description
NAME_OR_ID Variable name or ID

Options:

Option Description
--agent, -a Agent name or ID (defaults to agent.lock)
--environment, -e Environment name or ID (required to delete agent variables)
--org Only search organization-level variables

Example:

vr delete variable SUPPORT_EMAIL --org
vr delete variable ANTHROPIC_API_KEY --agent my-agent --environment production

vr delete secret

Delete an organization-level secret (evaluator usage). Searches organization secrets first, then legacy agent-scoped secret records.

vr delete secret <NAME_OR_ID>

Arguments:

Argument Description
NAME_OR_ID Secret name or ID

Options:

Option Description
--agent, -a Agent name or ID

Example:

vr delete secret MY_API_KEY

vr delete phonenumber

Delete or release an organization phone number.

vr delete phonenumber <NAME_OR_ID>

Arguments:

Argument Description
NAME_OR_ID Phone number ID, phone number, or friendly name

Options:

Option Description
--release Release the number back to the telephony provider

Example:

# Delete from VoiceRun only
vr delete phonenumber "+15551234567"

# Release back to the telephony provider
vr delete phonenumber "+15551234567" --release

vr delete telephony

Delete an organization telephony provider.

vr delete telephony <NAME_OR_ID>

Arguments:

Argument Description
NAME_OR_ID Telephony provider name or ID

Example:

vr delete telephony my-twilio

vr context

Manage API contexts for different environments (development, staging, production). A context bundles an API URL, a frontend URL, and an optional pinned organization — all stored on the context definition in ~/.voicerun/config.json. Pinning an organization is how you work across multiple orgs in the same environment: create one context per org with the same URLs.

To run a single command against another context without switching, use the global vr --context flag instead of vr context switch.

Session-scoped switching. When the environment identifies a terminal tab or coding-agent session — the first of VOICERUN_SESSION_KEY, CLAUDE_CODE_SESSION_ID, ITERM_SESSION_ID, TERM_SESSION_ID, WT_SESSIONvr context switch applies only to that session, so concurrent sessions on the same machine (e.g. several Claude Code sessions) never clobber each other's context. Resolution order for every command:

  1. --context flag / VOICERUN_CONTEXT env var (this invocation only)
  2. The session's own switch, if it made one
  3. The machine-wide current_context in ~/.voicerun/config.json

Session entries live in ~/.voicerun/sessions/ (one small JSON file per session, created only by an explicit switch) and clean themselves up: entries idle for more than 7 days are pruned on the next switch, with a 100-entry cap as a backstop. A pruned entry is harmless — the session simply resolves the machine-wide context again (or, if that is unset, gets the guidance error and re-switches). vr context current shows how the context was resolved: local (session), staging (override), or default (global).

Coding-agent subagents share the top-level session. Claude Code exposes the same CLAUDE_CODE_SESSION_ID to subagents as to the main session, so subagents share the session's pin — a vr context switch inside one subagent changes the context for the parent and all sibling subagents. Subagents that need their own context should pass --context <name> on every command instead of switching.

vr context list

List all available contexts and show the current one. Columns include each context's API/frontend URLs and its pinned organization (blank when unpinned).

vr context list

vr context current

Show the current context with API and frontend URLs, including how it was resolved — (session), (override), or (global). When the context has been unset, prints Context: not set with guidance instead.

vr context current

vr context switch

Switch to a different context. Plain vr context switch <NAME> picks the narrowest scope available: inside an identifiable session (see Session-scoped switching) it pins the context for that session only and leaves the machine-wide context untouched; outside one (no session env var — e.g. a bare SSH shell or CI) it sets the machine-wide context, exactly as it always has.

--global always sets the machine-wide context — the default resolved by every session without its own pin, including future ones — and clears the running session's own pin, so the global choice takes effect where you ran it instead of being shadowed.

vr context switch <NAME>
vr context switch <NAME> --global

Options:

Option Description
--global, -g Set the machine-wide current context even when running inside an identifiable session. Also clears the session's own pin so the global choice takes effect immediately in that session.

Examples:

# Terminal tab A — pins 'local' for this tab only
vr context switch local

# Terminal tab B, concurrently — pins 'staging'; tab A is unaffected
vr context switch staging

# Either tab — sets the machine-wide default for everything un-pinned
# (new tabs, scripts, cron) and re-points this tab at it too
vr context switch development --global

# Check which scope your context came from
vr context current        # e.g. "Context: local (session)" or "development (global)"

Rule of thumb: day-to-day, just use vr context switch — the session scoping makes it safe. Reach for --global when you mean "change the default for this machine," not "change it for me right now."

vr context unset

Unset the current context so that every command must pick one explicitly — the opt-in fail-closed mode for machines where multiple sessions (or coding agents) share the CLI and none of them should inherit an ambient context.

vr context unset

Behavior:

  • Writes "current_context": null to ~/.voicerun/config.json and clears any custom_api_url from vr context set-url. Also removes the enclosing session's own pin (other sessions' explicit pins are left alone).

  • While unset, any command that reaches the API (or builds a frontend/API URL) exits with code 1 and prints guidance:

    No context is set.
    Pass --context <name>, run 'vr context switch <name>', or set VOICERUN_CONTEXT
    Available contexts: local, development, default
    
  • Nothing falls back to default (production) implicitly. A context resolved via vr --context, a new vr context switch, the VOICERUN_CONTEXT environment variable, or a VOICERUN_API_URL override still works — only the stored fallback is disabled.

  • vr context delete of the context you are currently on also puts the CLI into this no-context-selected state, instead of automatically switching you to default.

  • Configs that have simply never set a context (fresh installs) keep resolving to default; the fail-closed behavior only applies after an explicit vr context unset.

  • Local read-only commands (vr context list, vr context switch, vr render, vr --version, …) work as usual.

vr context create

Create a new user-defined context.

vr context create <NAME> <API_URL> <FRONTEND_URL> [--org <NAME_OR_ID>]

Options:

Option Description
--org, -o Organization name or ID to pin on the context. A name is resolved against your memberships (/v1/me/organizations); a UUID is stored as-is. Omit to leave the context unpinned — requests then use your account's default organization.

Examples:

vr context create staging https://api.staging.voicerun.com https://app.staging.voicerun.com

# Two contexts for the same environment, one per organization
vr context create acme https://api.voicerun.com https://app.voicerun.com --org "Acme Inc"
vr context create globex https://api.voicerun.com https://app.voicerun.com --org 8e77d4bd-2b70-4e10-8e60-18ea552eb117

vr context delete

Delete a user-defined context. If the context you delete is the one you are currently on, the CLI no longer switches you to default (production) automatically — instead you are left with no context selected, the same state as after vr context unset. API commands will error with guidance until you pick a new context with vr context switch <name>. Any session entries pinned to the deleted context are removed as well, so no session keeps resolving to a name that no longer exists.

vr context delete <NAME>

vr context set-url

Set a custom API URL for the current session.

vr context set-url <API_URL>

vr context set-org

Pin the organization for the current context. Useful when your account belongs to multiple organizations. The pin is stored on the context definition in ~/.voicerun/config.json (next to api_url/frontend_url) and is sent as the organization-id header on every request made under that context.

vr context set-org <NAME_OR_ID>

Arguments:

Argument Description
NAME_OR_ID Organization name or ID (pass empty string to clear the pin)

Behavior:

  • A name is resolved against your memberships via /v1/me/organizations; a UUID is stored as-is (super-admins can target orgs they aren't members of this way).
  • An unpinned context sends no organization header — the API resolves your account's default organization server-side.
  • The pin is part of the context definition, so it survives vr signout (like the context URLs do).
  • Service-account tokens are bound to their organization server-side and cannot be re-pinned; set-org rejects them.

Example:

# Pin by name or ID
vr context set-org "Acme Inc"
vr context set-org 8e77d4bd-2b70-4e10-8e60-18ea552eb117

# Clear the pin (fall back to your default organization)
vr context set-org ""

vr metrics

Query custom metrics for agents. Supports listing metric names, discovering tags, fetching time-series data, and viewing per-session metrics. Commands that accept an agent filter will resolve from --agent (or positional argument) first, falling back to agent.lock if run inside a voicerun project.

vr metrics names

List available custom metric names.

vr metrics names [AGENT]

Arguments:

Argument Description
AGENT Agent name or ID (optional, filters by agent; uses agent.lock if omitted)

Options:

Option Description
--json, -j Output as JSON
--table, -t Output as table (default for interactive terminals)

Example:

# List all metric names
vr metrics names

# List metric names for a specific agent
vr metrics names my-agent

vr metrics tags

Discover available tag keys and their values for filtering.

vr metrics tags

Options:

Option Description
--metric, -m Filter tags by metric name
--agent, -a Agent name or ID (uses agent.lock if omitted)
--json, -j Output as JSON
--table, -t Output as table (default for interactive terminals)

Example:

# List all tags
vr metrics tags

# List tags for a specific metric
vr metrics tags --metric my_custom_metric

# List tags for a specific agent
vr metrics tags --agent my-agent

vr metrics timeseries

Fetch time-series data for a custom metric with type-appropriate aggregation.

vr metrics timeseries <METRIC_NAME> --start <START> --end <END>

Arguments:

Argument Description
METRIC_NAME The metric name to query

Options:

Option Description
--start, -s Start date (ISO 8601, e.g. 2026-03-15T00:00:00Z) (required)
--end, -e End date (ISO 8601, e.g. 2026-03-16T00:00:00Z) (required)
--step Time interval for aggregation (e.g. 30m, 1h, 1d). Default: 1h
--agent, -a Agent name or ID (uses agent.lock if omitted)
--environment, -E Environment ID
--tags Tag filters as JSON (e.g. '{"channel":"phone"}')
--json, -j Output as JSON
--table, -t Output as table (default for interactive terminals)

Example:

# Fetch timeseries for a metric over a day
vr metrics timeseries call_duration --start 2026-03-15T00:00:00Z --end 2026-03-16T00:00:00Z

# With hourly aggregation for a specific agent
vr metrics timeseries call_duration -s 2026-03-15T00:00:00Z -e 2026-03-16T00:00:00Z --step 1h --agent my-agent

# Filter by tags
vr metrics timeseries call_duration -s 2026-03-15T00:00:00Z -e 2026-03-16T00:00:00Z --tags '{"channel":"phone"}'

vr metrics session

Fetch all custom metrics for a specific session.

vr metrics session <SESSION_ID>

Arguments:

Argument Description
SESSION_ID Session ID

Options:

Option Description
--json, -j Output as JSON
--table, -t Output as table (default for interactive terminals)

Example:

vr metrics session 550e8400-e29b-41d4-a716-446655440000

Output includes:

  • Metric name, type, value, and timestamp for each metric recorded in the session

vr experiments

View experiments and A/B test results for agents. All subcommands resolve the agent from --agent or from agent.lock if run inside a voicerun project.

vr experiments list

List all experiments for an agent.

vr experiments list

Options:

Option Description
--agent, -a Agent name or ID (uses agent.lock if omitted)
--json, -j Output as JSON
--table, -t Output as table (default for interactive terminals)

Example:

# List experiments for the current project
vr experiments list

# List experiments for a specific agent
vr experiments list --agent my-agent

vr experiments describe

Show detailed results for a specific experiment, including variant performance, conversion rates, and statistical significance.

vr experiments describe <EXPERIMENT_NAME>

Arguments:

Argument Description
EXPERIMENT_NAME Experiment name

Options:

Option Description
--agent, -a Agent name or ID (uses agent.lock if omitted)
--json, -j Output as JSON
--table, -t Output as table (default for interactive terminals)

Example:

# Describe an experiment in the current project
vr experiments describe greeting_style

# Describe an experiment for a specific agent
vr experiments describe greeting_style --agent my-agent

Output includes:

  • Session count and completion status
  • Conversion metrics being tracked
  • Stop conditions (iterations and confidence thresholds)
  • Variant breakdown with per-metric conversion rates
  • Statistical significance results (confidence, p-value)

vr experiments timeseries

Fetch time-series data for an experiment metric, broken down by variant.

vr experiments timeseries <EXPERIMENT_NAME> --metric <METRIC> --start <START> --end <END>

Arguments:

Argument Description
EXPERIMENT_NAME Experiment name

Options:

Option Description
--metric, -m Metric/outcome name to query (required)
--start, -s Start date (ISO 8601, e.g. 2026-03-15T00:00:00Z) (required)
--end, -e End date (ISO 8601, e.g. 2026-03-16T00:00:00Z) (required)
--step Time interval for aggregation (e.g. 30m, 1h, 1d). Default: 1h
--agent, -a Agent name or ID (uses agent.lock if omitted)
--json, -j Output as JSON
--table, -t Output as table (default for interactive terminals)

Example:

# Fetch daily timeseries for a conversion metric
vr experiments timeseries greeting_style --metric booking_completed \
  --start 2026-03-01T00:00:00Z --end 2026-03-15T00:00:00Z --step 1d

# Hourly breakdown for a specific agent
vr experiments timeseries greeting_style -m call_duration \
  -s 2026-03-15T00:00:00Z -e 2026-03-16T00:00:00Z --agent my-agent

vr experiments funnel

Show the conversion funnel for an experiment, comparing variant performance across each conversion metric with lift calculations.

vr experiments funnel <EXPERIMENT_NAME>

Arguments:

Argument Description
EXPERIMENT_NAME Experiment name

Options:

Option Description
--agent, -a Agent name or ID (uses agent.lock if omitted)
--json, -j Output as JSON
--table, -t Output as table (default for interactive terminals)

Example:

# View conversion funnel for the current project
vr experiments funnel greeting_style

# View funnel for a specific agent
vr experiments funnel greeting_style --agent my-agent

Output includes:

  • Total sessions and conversion metrics
  • Per-variant breakdown: sessions, conversions, conversion rate, and lift vs baseline

vr ft

Fine-tune small open models (Qwen LoRA) and manage fine-tuning jobs. vr ft talks to the VoiceRun fine-tuning API, which proxies to the internal fine-tuning control plane. Admin-only in v1.

The full lifecycle: files upload (data) → create (train) → deploy (serve on vLLM) → eval (score against a held-out test set) → release (publish under a stable name agents call as voicerun/<name>). Instead of uploading files by hand, datasets create can build the train/val/test files straight from production traffic.

Training data is conversational JSONL — one object per line of the form {"messages": [{"role": "user", "content": "..."}, {"role": "assistant", "content": "..."}]}.

Every upload is an immutable file with its own id (ftfile-…) and a recorded sha256 — re-uploading the same filename creates a new file, never overwrites. Jobs pin an exact training_file (and validation_file) id, so runs stay reproducible no matter how many times you upload. Files are partitioned per organization on the server.

vr ft files upload

Upload a JSONL data file — training (default), validation, or a held-out test set for evals.

vr ft files upload data/train.jsonl
vr ft files upload data/val.jsonl --purpose validation
vr ft files upload data/test.jsonl --purpose test

The bytes go directly to object storage via a one-time resumable upload URL, not through the VoiceRun API — so large files aren't limited by the API/WAF. The flow is: validate locally → init (get the upload URL) → PUT the bytes → complete (the server reads them back, re-validates, and finalizes). An invalid file fails locally before anything is uploaded.

Arguments:

Argument Description
PATH Path to a JSONL file (required)

Options:

Option Description
--purpose training (default), validation, or test
--json, -j Output as JSON
--table, -t Output as table (default for interactive terminals)

vr ft files check

Validate a JSONL file locally, without uploading (no network call). Same invariants the server enforces on complete, so a clean check means the upload will validate.

vr ft files check data/train.jsonl

Arguments:

Argument Description
PATH Path to a JSONL file (required)

Options:

Option Description
--json, -j Output as JSON
--table, -t Output as table (default for interactive terminals)

vr ft files list

List uploaded training files.

vr ft files list

Options:

Option Description
--json, -j Output as JSON
--table, -t Output as table (default for interactive terminals)

vr ft create

Create a fine-tuning job.

vr ft create --model Qwen/Qwen3-1.7B --training-file ftfile-abc123 --suffix inline-v4

# Block until the job finishes, streaming events (exit 0 only if it succeeded)
vr ft create --model Qwen/Qwen3-0.6B --training-file ftfile-abc123 --wait

# Auto-chain: on success, deploy to an ephemeral T4, eval against the test file, then tear down
vr ft create --model Qwen/Qwen3-1.7B --training-file ftfile-abc123 \
  --test-file ftfile-test123 --auto-eval --eval-scorer slot_intent

When --auto-eval is set, a successful job auto-chains: the trained model is deployed to an ephemeral T4 in the home cluster, evaluated against --test-file with the chosen scorer/post-processor, and the deployment is torn down once the eval reaches a terminal state. --auto-eval requires both --test-file and --eval-scorer (there is no platform default scorer).

Options:

Option Description
--model, -m Base model, e.g. Qwen/Qwen3-1.7B (required)
--training-file Training file id from vr ft files upload (required)
--validation-file Validation file id
--method lora (default), qlora, or full
--n-epochs Number of epochs (default 5)
--n-checkpoints Checkpoints to keep (default 5)
--learning-rate, --lr Learning rate (default 2e-5)
--batch-size, -b Effective batch size (default 32)
--gradient-accumulation-steps, --grad-accum Gradient accumulation steps (default 2)
--max-seq-len Max sequence length (default 2048)
--warmup-ratio LR warmup ratio (default 0.03)
--lora-r LoRA rank (default 64)
--lora-alpha LoRA alpha (default 128)
--lora-dropout LoRA dropout (default 0.0)
--lora-trainable-modules LoRA target modules (default all-linear)
--train-on-inputs / --no-train-on-inputs Train on prompt tokens too (default off)
--suffix Suffix for the output model name
--seed Random seed (default 42)
--accelerator GPU to train on: A100:1, L4:1, or T4:1 (default: platform default)
--test-file Test file id (purpose=test) to auto-evaluate against; required with --auto-eval
--auto-eval On success, deploy to an ephemeral T4, eval against --test-file, then tear down; requires --test-file and --eval-scorer
--eval-scorer Scorer for the auto-eval — see vr ft scorers (required with --auto-eval)
--eval-postprocessor Output transform applied before the auto-eval scores — see vr ft postprocessors (default none)
--eval-max-tokens Generation cap per example for the auto-eval (default 64)
--wait Wait for the job to finish, printing events; exit 0 only if it succeeded
--json, -j Output as JSON
--table, -t Output as table (default for interactive terminals)

vr ft list

List fine-tuning jobs.

vr ft list

Options:

Option Description
--limit, -l Max jobs to return (default 50)
--json, -j Output as JSON
--table, -t Output as table (default for interactive terminals)

vr ft get

Show a fine-tuning job.

vr ft get ftjob-abc123

Arguments:

Argument Description
JOB_ID Fine-tuning job id (required)

Options:

Option Description
--json, -j Output as JSON
--table, -t Output as table (default for interactive terminals)

vr ft cancel

Cancel a running or queued fine-tuning job.

vr ft cancel ftjob-abc123

Arguments:

Argument Description
JOB_ID Fine-tuning job id (required)

Options:

Option Description
--json, -j Output as JSON
--table, -t Output as table (default for interactive terminals)

vr ft events

List a job's events (status transitions, logs).

vr ft events ftjob-abc123

Arguments:

Argument Description
JOB_ID Fine-tuning job id (required)

Options:

Option Description
--json, -j Output as JSON
--table, -t Output as table (default for interactive terminals)

vr ft logs

Print the training pod's logs (plain text). 404s if the job has no training pod yet (still queued) or the pod is gone.

vr ft logs ftjob-abc123
vr ft logs ftjob-abc123 -f --tail 500   # follow until the job finishes

Arguments:

Argument Description
JOB_ID Fine-tuning job id (required)

Options:

Option Description
--follow, -f Keep polling for new lines until the job finishes
--tail Trailing lines to fetch (default 200, max 2000)

vr ft deploy

Deploy a model to a dedicated vLLM endpoint (low-latency, one model per endpoint) — from a fine-tuning job or a merged model URI. Provide --job or --model-uri as the source (one is required); --base-model is required with --model-uri.

# Deploy a finished fine-tune (its adapter is merged, then served)
vr ft deploy --job ftjob-abc123 --served-model-name my-qwen

# Or serve an already-merged model straight from GCS
vr ft deploy --model-uri gs://prim-ai-development-models/my-merged-model \
  --base-model Qwen/Qwen3-0.6B --served-model-name my-qwen --accelerator T4:1

Options:

Option Description
--served-model-name, --name Model id clients send, e.g. my-qwen (required)
--job Fine-tuning job id to deploy (its adapter is merged, then served)
--model-uri OR a gs:// URI of an already-merged model to serve
--base-model Base model (required with --model-uri), e.g. Qwen/Qwen3-0.6B
--accelerator GPU: T4:1 (default), L4:1, or A100:1
--replicas Number of vLLM replicas (default 1)
--wait Wait until the deployment reaches a terminal status, printing events; exit 0 only if running
--json, -j Output as JSON
--table, -t Output as table (default for interactive terminals)

vr ft deployments

List serving deployments.

vr ft deployments

Options:

Option Description
--limit, -l Max deployments to return (default 50)
--json, -j Output as JSON
--table, -t Output as table (default for interactive terminals)

vr ft deployment

Show a serving deployment.

vr ft deployment ftdeploy-abc123

Arguments:

Argument Description
DEPLOYMENT_ID Deployment id (required)

Options:

Option Description
--json, -j Output as JSON
--table, -t Output as table (default for interactive terminals)

vr ft terminate

Terminate (tear down) a serving deployment.

vr ft terminate ftdeploy-abc123

Arguments:

Argument Description
DEPLOYMENT_ID Deployment id (required)

Options:

Option Description
--json, -j Output as JSON
--table, -t Output as table (default for interactive terminals)

vr ft scorers

List the evaluation scorers (use one with vr ft eval --scorer). Current scorers: exact_match, contains:<text>, regex:<pattern>, json_field:<path>, classification:<field>, set_f1:<field>, slot_intent.

vr ft scorers

Options:

Option Description
--json, -j Output as JSON
--table, -t Output as table (default for interactive terminals)

vr ft eval

Run a test set against a deployed model and score it.

vr ft eval --deployment ftdeploy-abc123 --test-file ftfile-test123 \
  --scorer classification:intent --wait

Options:

Option Description
--deployment, -d Deployment id to test — must be running (required)
--test-file Test-set file id, upload with vr ft files upload --purpose test (required)
--scorer Scorer spec — see vr ft scorers (default exact_match)
--max-tokens Generation cap per example (default 64)
--wait Poll until the eval finishes, then print metrics
--json, -j Output as JSON
--table, -t Output as table (default for interactive terminals)

vr ft evals

List evaluation runs.

vr ft evals --deployment ftdeploy-abc123

Options:

Option Description
--deployment, -d Filter to one deployment
--limit, -l Max evals to return (default 50)
--json, -j Output as JSON
--table, -t Output as table (default for interactive terminals)

vr ft evaluation

Show an evaluation run and its metrics.

vr ft evaluation fteval-abc123

Arguments:

Argument Description
EVAL_ID Eval id (required)

Options:

Option Description
--json, -j Output as JSON
--table, -t Output as table (default for interactive terminals)

vr ft results

Show an eval's per-example results (the drill-down behind the metrics): each row's input, expected vs actual (or gold vs pred for classification scorers), pass/fail, and latency.

vr ft results fteval-abc123 --failures-only

Arguments:

Argument Description
EVAL_ID Eval id (required)

Options:

Option Description
--failures-only Only show rows that failed
--limit, -l Max rows to fetch (default 50)
--json, -j Output as JSON
--table, -t Output as table (default for interactive terminals)

vr ft evals-compare

Compare two evaluation runs: metric deltas (A → B) and per-example pass/fail flips — regressions (passed in A, failed in B) and fixes (failed in A, passed in B). Warns when the two evals used different test files or scorers.

vr ft evals-compare fteval-baseline fteval-candidate

Arguments:

Argument Description
EVAL_A Baseline eval id (A) (required)
EVAL_B Candidate eval id (B) (required)

Options:

Option Description
--json, -j Output as JSON
--table, -t Output as table (default for interactive terminals)

vr ft release

Release a model under a stable name so agents call voicerun/<name>. Provide exactly one source: --deployment (adopt a running, evaluated one), --job (merge + serve a finished fine-tune), or --model-uri (serve an already-merged model). --cluster serves it in another cluster.

If the name already has an active model and both have comparable evals (same test file + scorer), a release whose headline metrics regress is blocked with a per-metric incumbent-vs-candidate table — pass --force to release anyway.

# Adopt a running, evaluated deployment
vr ft release --deployment ftdeploy-abc123 --name inline-agent

# Or release a finished fine-tune directly (merged, then served)
vr ft release --job ftjob-abc123 --name inline-agent

Options:

Option Description
--deployment, -d Release a running, evaluated deployment
--job Release a succeeded fine-tune job (its adapter is merged, then served)
--model-uri Release an already-merged model in GCS (gs://...)
--base-model Base model, e.g. Qwen/Qwen3-0.6B (required with --model-uri)
--name Public model id agents call (required with --job/--model-uri)
--cluster Serving cluster name, e.g. enterprise-development-sg (default: the home cluster)
--accelerator GPU for a serving deployment created from --job/--model-uri (default T4:1)
--eval Eval id for provenance (default: the deployment's latest succeeded eval)
--description Notes shown in the registry
--force Release even if the candidate's eval regresses vs the active incumbent's
--json, -j Output as JSON
--table, -t Output as table (default for interactive terminals)

vr ft models

List released models.

vr ft models --status active

Options:

Option Description
--status Filter by status (e.g. active)
--cluster Only models served in this cluster
--limit, -l Max models to return (default 100)
--json, -j Output as JSON
--table, -t Output as table (default for interactive terminals)

vr ft model

Show a released model and where it's served.

vr ft model inline-agent

Arguments:

Argument Description
NAME Model name (required)

Options:

Option Description
--json, -j Output as JSON
--table, -t Output as table (default for interactive terminals)

vr ft retire

Retire a released model (agents can no longer call it by name).

vr ft retire inline-agent

Arguments:

Argument Description
NAME Model name (required)

Options:

Option Description
--json, -j Output as JSON
--table, -t Output as table (default for interactive terminals)

vr ft datasets create

Build a training dataset with a recipe: pull sessions from the source (agents + time window), run the recipe's transform (optionally calling an LLM), split into train/val/test, and register the splits as immutable files (ftfile-…) ready for vr ft create. The flags come in four layers — generic build controls, the source block, the LLM block, and recipe params.

# Default recipe (inline_slot_v1) over June production traffic
vr ft datasets create --name june-prod \
  --agent-id agent-abc123 \
  --from 2026-06-01 --to 2026-07-01

# Relabel through an LLM, tune recipe params, and block until the build finishes
vr ft datasets create --name june-prod-llm \
  --agent-id agent-abc123 \
  --from 2026-06-01 --to 2026-07-01 \
  --llm-model gpt-5.4 \
  --param target_model=Qwen/Qwen3-1.7B --param split.val=0.15 \
  --wait

# Estimate first: sessions, cache hits, LLM calls, and projected splits — no files written
vr ft datasets create --name june-prod --dry-run --wait \
  --agent-id agent-abc123 \
  --from 2026-06-01 --to 2026-07-01

The source flags (--agent-id, --from, --to) go together and are only sent when given — recipes that declare needs_source require them. The LLM block is sent only with --llm-model; --llm-base-url (default https://api.openai.com/v1) and --llm-key-env (default OPENAI_API_KEY, read on the control plane) refine it. Recipe params come from --params-file (a JSON object) overlaid with repeatable --param key=value — values parse as JSON when valid (60 → int, true → bool, [1,2] → list; bare text stays a string) and dotted keys nest (split.val=0.1). Each recipe validates its own params — vr ft datasets recipes shows what it accepts.

Options:

Option Description
--name Dataset name (required)
--recipe Dataset recipe (default inline_slot_v1) — see vr ft datasets recipes
--seed Deterministic build seed (default 42)
--dry-run Estimate the build (sessions, LLM calls, projected splits) without writing files
--max-sessions Cap on sessions read from the source
--max-examples Cap on examples in the built dataset
--parent-dataset Derive from this dataset id instead of a fresh extraction
--agent-id Source agent id — repeat for multiple
--from Source window start (ISO 8601, e.g. 2026-06-01)
--to Source window end (ISO 8601, exclusive)
--llm-model LLM the recipe may call, e.g. gpt-5.4 (required/optional per recipe)
--llm-base-url LLM API base URL (default https://api.openai.com/v1; requires --llm-model)
--llm-key-env Env var on the control plane holding the LLM API key (default OPENAI_API_KEY; requires --llm-model)
--param Recipe param as key=value (repeatable; value parsed as JSON when valid, dots nest)
--params-file JSON file of recipe params (--param overrides its keys)
--wait Wait for the build to finish, printing events; exit 0 only if it becomes ready
--json, -j Output as JSON
--table, -t Output as table (default for interactive terminals)

vr ft datasets recipes

List the dataset recipes the control plane can build. For each recipe: description, whether it needs the source block, whether it needs the LLM block (required, optional, or none), the transform version, and a field table of its params (name, type, default, description).

vr ft datasets recipes

Options:

Option Description
--json, -j Output as JSON
--table, -t Output as table (default for interactive terminals)

vr ft datasets list

List datasets.

vr ft datasets list
vr ft datasets list --status ready

Options:

Option Description
--status Filter by status: queued, building, ready, failed, or cancelled
--limit, -l Max datasets to return (default 50)
--json, -j Output as JSON
--table, -t Output as table (default for interactive terminals)

vr ft datasets get

Show a dataset: status, train/val/test counts, relabel stats (cached/called/failed), the parent dataset id (for derived builds), and the three produced file ids. A finished --dry-run build renders its estimate instead — sessions, direct pairs, cache hits, LLM calls needed, and the projected splits. Once a real build is ready, the file ids are printed ready to paste into vr ft create --training-file … --validation-file … (and vr ft eval --test-file …).

vr ft datasets get ftdataset-abc123

Arguments:

Argument Description
DATASET_ID Dataset id (required)

Options:

Option Description
--json, -j Output as JSON
--table, -t Output as table (default for interactive terminals)

vr ft datasets events

List a dataset build's events (status transitions, progress).

vr ft datasets events ftdataset-abc123

Arguments:

Argument Description
DATASET_ID Dataset id (required)

Options:

Option Description
--json, -j Output as JSON
--table, -t Output as table (default for interactive terminals)

vr ft datasets cancel

Cancel a dataset build (while it is queued or building).

vr ft datasets cancel ftdataset-abc123

Arguments:

Argument Description
DATASET_ID Dataset id (required)

Options:

Option Description
--json, -j Output as JSON
--table, -t Output as table (default for interactive terminals)

.vrignore

You can create a .vrignore file in your project root to exclude files and directories from uploads. It works like .gitignore and applies to both vr push and vr create template.

Example .vrignore:

# Ignore log files
*.log

# Ignore data directory
data/

# Ignore build artifacts
build/**

# Ignore a specific file at root only
/config.local.yaml

# Ignore all .csv files
*.csv

Supported syntax:

Pattern Description
*.log Glob pattern — matches any .log file at any depth
secret.txt Exact name — matches secret.txt in any directory
data/ Trailing / — matches directories only
/config.yaml Leading / — anchored to project root only
build/** Globstar — matches everything under build/
**/test.py Globstar prefix — matches test.py at any depth
# comment Lines starting with # are ignored

vr report

Report issues to VoiceRun and track the tickets you've filed — see their status, read replies from the VoiceRun team, and respond.

vr report bug
vr report list
vr report show <ticket-id>
vr report reply <ticket-id> "message"

Subcommands:

Subcommand Description
bug Submit a bug report
list List your submitted bug reports
show Show a bug report with its conversation (replies and status changes)
reply Reply on one of your bug reports

Options (bug):

Option Description
--title, -t Bug title/summary
--description, -d Bug description
--include-system-info Include CLI version and OS info (default: true)
--no-system-info Exclude system information
--dry-run Show what would be submitted without sending

Options (list):

Option Description
--status, -s Filter by status: open, in_progress, resolved, closed
--limit, -l Limit number of results
--page, -p Page number
--json, -j Output as JSON
--table, -t Output as table (default for interactive terminals)

Options (show / reply):

Option Description
--json, -j Output as JSON
--table, -t Output as table (default for interactive terminals)

Behavior:

  • show includes the full conversation: replies (yours and VoiceRun Support's) interleaved with status-change entries.
  • reply prompts for the message when it isn't passed as an argument.
  • Replying to a resolved or closed ticket re-opens it — the command tells you when that happens, and JSON output carries a reopened flag plus the current ticketStatus.
  • You are notified in the web app (and by email, per your notification preferences) when VoiceRun replies to your ticket or changes its status.

Examples:

# Interactive mode - prompts for title and description
vr report bug

# Provide title and description inline
vr report bug --title "Login error" --description "Can't log in with SSO"

# Exclude system information
vr report bug --no-system-info

# Dry run - preview what would be submitted
vr report bug --title "Test bug" --dry-run

# List your bug reports (open ones only)
vr report list --status open

# Show one ticket with its conversation
vr report show 58eb775a-577c-44cf-86bd-abac21b25d78

# Reply (re-opens the ticket if it was resolved/closed)
vr report reply 58eb775a-577c-44cf-86bd-abac21b25d78 "Still happening on 1.7.2"

Project Structure

After running vr init, your project will have this structure:

my-agent/
├── handler.py                      # Main agent code (entry point)
├── README.md                       # Project documentation
├── requirements.txt                # Python dependencies
└── .voicerun/                      # Configuration directory
    ├── agent.yaml                  # Agent metadata and configuration
    ├── agent.lock                  # Created after vr push (tracks agent/function IDs)
    ├── values.yaml                 # Base values for template rendering
    ├── values.<env>.yaml           # Per-environment value overlays (e.g. values.production.yaml)
    └── templates/                  # Declarative resources (see below)
        ├── deployment.yaml         # Runtime config: STT/TTS, recording, redaction, tracing
        ├── simulation.yaml         # Simulated caller for regression testing
        ├── webhook.yaml            # Session-end webhook delivery
        └── evaluator.yaml          # Post-session scoring / extraction

Declarative Resources

Files under .voicerun/templates/ are rendered with Helm at vr release time and snapshotted onto the release manifest. Each file contains one or more YAML documents with an apiVersion: voicerun/v1 header and a kind: of Deployment, Simulation, Webhook, or Evaluator. Preview the rendered output with vr render; validate spec keys with vr validate.

Deployment

Runtime configuration for the agent in an environment — region, runtime mode, variables, STT/TTS, recording, redaction, tracing, and the optional relay endpoint.

apiVersion: voicerun/v1
kind: Deployment
metadata:
  name: my-agent-deployment
spec:
  mode: coderunner            # 'coderunner' (handler.py sandbox) or 'relay'
  region: us-central1-a
  variables:
    LOG_LEVEL: info
  stt:
    model: flux-general-en
    language: en
    failover:
      model: nova-3
  tts:
    provider: cartesia
    model: sonic-2
    voice: lyric
    language: en
    speed: 1.0
  relay:                      # only when mode: relay
    url: wss://my-relay.example.com/ws/agent
  recording:
    enabled: false
    location: gs://my-bucket/recordings/
  redaction:
    enabled: false
  tracing:
    enabled: true

In relay mode the agent runs in voicerun-relay and handler.py is not required at the project root — vr validate skips the handler check automatically.

Simulation

A simulated caller used by vr simulate. The CLI submits the simulation's metadata.name and the server resolves spec.systemPrompt and spec.numberOfSimulations from the active release's manifest.

apiVersion: voicerun/v1
kind: Simulation
metadata:
  name: happy-path
spec:
  systemPrompt: |
    You are a customer calling support. Ask to reset your password.
  numberOfSimulations: 5
  voice: Aoede               # optional Gemini-Live prebuilt voice

Webhook

Session-end webhook delivery configuration. The URL must be HTTPS. Leave secret unset to have the platform generate one.

apiVersion: voicerun/v1
kind: Webhook
metadata:
  name: my-agent-webhook
spec:
  url: https://example.com/voicerun/session-webhook
  secret: shhh

Evaluator

Scores or extracts data from a session after it completes. View results with vr evaluation list and vr evaluation info.

Common fields (every evalType):

Field Description
title Human-readable title shown in evaluation listings.
evalType judge, extraction, or deterministic.
targetFormat events or transcript. Deterministic always reads the session view — this field is ignored for that type.
precondition (optional) JSON predicate evaluated against the derived session view. Sessions that don't satisfy it are recorded as status="skipped" with no LLM call. See Preconditions.

Judge — LLM scores the session against successCriteria:

apiVersion: voicerun/v1
kind: Evaluator
metadata:
  name: resolution-judge
spec:
  title: Resolution Judge
  evalType: judge
  targetFormat: transcript
  systemPrompt: |
    Score the session 1-5 on whether the agent resolved the caller's
    request. Respond with a JSON object matching the response schema.
  responseSchema: {}
  successCriteria:
    score: { $gte: 4 }
  apiProvider: openai
  model: gpt-4o
  organizationSecretName: OPENAI_API_KEY

Extraction — LLM pulls structured data; no pass/fail:

apiVersion: voicerun/v1
kind: Evaluator
metadata:
  name: call-summary
spec:
  title: Call Summary
  evalType: extraction
  targetFormat: transcript
  systemPrompt: "Extract the intent, whether the issue was resolved, and a one-sentence summary."
  responseSchema:
    type: object
    properties:
      intent: { type: string }
      resolved: { type: boolean }
      summary: { type: string }
  apiProvider: openai
  model: gpt-4o

Deterministic — asserts on the derived session view without an LLM. Zero token cost, fully repeatable. Use for purely factual checks (did the caller say a word, did the call run long enough, was it routed through a specific environment):

apiVersion: voicerun/v1
kind: Evaluator
metadata:
  name: inbound-cancellation-request
spec:
  title: Inbound caller mentioned cancellation
  evalType: deterministic
  assertion:
    direction: "inbound"
    events:
      $any:
        name: "transcript_part"
        data.role: "user"
        data.content: { $icontains: "cancel" }

The assertion is a JSON predicate over the session view:

Field Description
turn_count Number of completed turns (count of turn_end events). A mid-turn hangup doesn't count.
duration_seconds Seconds between startedAt and endedAt. Returns 0 when the session hasn't ended.
direction inbound or outbound
origin Where the session came from (e.g. phone, web, simulation, native)
tags Session tags as a string array. Matchable by bare primitive (tags: "billing") or by $inc / $ninc.
environment [id, name] for the session's environment — prefers the org-scoped environmentId, falls back to legacy agentEnvironmentId. Matchable by bare primitive against either value: environment: "production" or environment: "<uuid>" both work.
events Raw event list in arrival order — each element is { name, data, timestamp }. Use with $any to assert on event names or payloads (see below).

Operators:

Operator Meaning
$eq / $ne Equals / not equals (deep equality)
$gt / $gte / $lt / $lte Numeric comparison
$in / $nin Value is / is not in a literal array
$inc / $ninc Input array does / does not contain this value
$contains String input contains this substring (case-sensitive)
$icontains String input contains this substring (case-insensitive)
$any Input array has at least one element matching the sub-predicate

Dotted field paths walk nested objects. On match → success: true with details: { matched: true }; on mismatch → success: false with details: { matched: false, failedPath, reason } so the failing clause is captured.

Bare primitive vs array input. When a predicate's value is a primitive ("production", 42, true) and the input field is an array, the engine does membership matching — equivalent to $inc. This lets you write tags: "billing" instead of tags: { $inc: "billing" }, and environment: "production" matches whether you wrote the env's name or its ID (since environment is exposed as [id, name]). Scalar-vs-scalar equality is unchanged.

$any for event payload checks:

# Did the caller mention 'refund'?
assertion:
  events:
    $any:
      name: "transcript_part"
      data.role: "user"
      data.content: { $icontains: "refund" }

# Did the agent close with a goodbye?
assertion:
  events:
    $any:
      name: "transcript_part"
      data.role: "agent"
      data.content: { $icontains: "goodbye" }

Preconditions

Any evaluator type can declare a precondition to gate whether it runs. If the predicate doesn't satisfy, the evaluator is skipped — the row is persisted with status="skipped" and a skipReason naming the failing field, no LLM call. Audit skipped rows with vr evaluation list --status skipped.

apiVersion: voicerun/v1
kind: Evaluator
metadata:
  name: objection-handling
spec:
  title: Objection Handling
  evalType: judge
  targetFormat: transcript
  systemPrompt: "…"
  responseSchema:
    type: object
    properties:
      score: { type: integer }
  successCriteria: { score: { $gte: 4 } }
  precondition:
    turn_count: { $gte: 3 }
    duration_seconds: { $gte: 30 }

Templates

agent.yaml

Defines your agent's metadata:

apiVersion: voicerun/v1
name: my-agent
description: "My voice agent description"

handler.py

The main entry point for your agent. Must contain an async def handler() function:

from primfunctions.events import (
    Event, StartEvent, TextEvent, StopEvent, InterruptEvent, TextToSpeechEvent
)
from primfunctions.context import Context

async def handler(event: Event, context: Context):
    if isinstance(event, StartEvent):
        yield TextToSpeechEvent(text="Hello! How can I help you?")
    elif isinstance(event, TextEvent):
        # Handle user speech transcription
        user_text = event.data.get("text", "")
        yield TextToSpeechEvent(text=f"You said: {user_text}")
    elif isinstance(event, StopEvent):
        pass
    elif isinstance(event, InterruptEvent):
        pass

Links

License

MIT License

Git Worktrees (Parallel Agent Development)

This repo supports running multiple coding agents in parallel using git worktrees. Each agent gets an isolated working directory with its own branch while sharing the same git object store.

Worktrees are stored in .worktrees/ (gitignored).

Create a worktree

git worktree add .worktrees/feature-xyz -b feature-xyz

List active worktrees

git worktree list

Remove a worktree

git worktree remove .worktrees/feature-xyz

Clean up stale worktrees

git worktree prune

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

voicerun_cli-1.7.5.tar.gz (396.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

voicerun_cli-1.7.5-py3-none-any.whl (263.0 kB view details)

Uploaded Python 3

File details

Details for the file voicerun_cli-1.7.5.tar.gz.

File metadata

  • Download URL: voicerun_cli-1.7.5.tar.gz
  • Upload date:
  • Size: 396.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.8

File hashes

Hashes for voicerun_cli-1.7.5.tar.gz
Algorithm Hash digest
SHA256 29060928e1187584d60142269cedaf9cb2cc0f6aefda9dcc45b912f75d9670d2
MD5 00c1f0b9ca87d5a610011879dae5cfc0
BLAKE2b-256 93dfedf0483652c9be00f9322b6b128a75c8fd4c32bd46ad3f058fb1cc07347e

See more details on using hashes here.

File details

Details for the file voicerun_cli-1.7.5-py3-none-any.whl.

File metadata

File hashes

Hashes for voicerun_cli-1.7.5-py3-none-any.whl
Algorithm Hash digest
SHA256 0daca48acb38a6e5e604f4bce51a70078e136c939daa8b4f024ac2de116ff549
MD5 e86650ce789da0062844c1a79ab01db7
BLAKE2b-256 52391d8d0516afc3ccda49816ce6659f652e676bf1640f052287e99276240f75

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page