Metadata-Version: 2.4
Name: voicerun-cli
Version: 1.6.4
Summary: VoiceRun command-line interface
Author-email: VoiceRun <support@voicerun.com>
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: black>=23.3.0
Requires-Dist: requests>=2.32.4
Requires-Dist: typer>=0.16.0
Requires-Dist: websocket-client>=1.6.0
Requires-Dist: websockets>=11.0.0
Requires-Dist: rich>=13.0.0
Requires-Dist: aiohttp>=3.8.6
Requires-Dist: loguru>=0.7.3
Requires-Dist: primfunctions>=0.1.13
Requires-Dist: six>=1.17.0
Requires-Dist: pyyaml>=6.0.0
Requires-Dist: jsonschema>=4.0.0
Requires-Dist: pytest>=8.4.1
Requires-Dist: toml>=0.10.2
Requires-Dist: prompt_toolkit>=3.0.0
Requires-Dist: questionary>=2.0.0
Provides-Extra: test
Requires-Dist: pytest>=7.0.0; extra == "test"
Requires-Dist: pytest-mock>=3.10.0; extra == "test"
Requires-Dist: pytest-cov>=4.0.0; extra == "test"
Requires-Dist: pytest-asyncio>=0.21.0; extra == "test"

# VoiceRun CLI

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

## Table of Contents

- [Installation](#installation)
- [Quick Start](#quick-start)
- [Authentication](#authentication)
- [Global Options](#global-options)
  - [--version](#vr---version)
  - [--update](#vr---update)
- [Commands](#commands)
  - [setup](#vr-setup)
  - [signin](#vr-signin)
  - [signout](#vr-signout)
  - [init](#vr-init)
  - [validate](#vr-validate)
  - [pull](#vr-pull)
  - [push](#vr-push)
  - [deploy](#vr-deploy)
  - [release](#vr-release)
  - [debug](#vr-debug)
  - [open](#vr-open)
  - [render](#vr-render)
  - [test](#vr-test)
  - [simulate](#vr-simulate)
  - [evaluation](#vr-evaluation)
  - [get](#vr-get)
  - [describe](#vr-describe)
  - [create](#vr-create)
  - [delete](#vr-delete)
  - [context](#vr-context)
  - [metrics](#vr-metrics)
  - [experiments](#vr-experiments)
  - [report](#vr-report)
  - [update](#vr-update)
- [.vrignore](#vrignore)
- [Project Structure](#project-structure)
- [Declarative Resources](#declarative-resources)
- [Templates](#templates)
- [Values Files](#values-files)
- [Configuration](#configuration)
- [Environment Variables](#environment-variables)

## Installation

### Prerequisites

- Python 3.10 or higher

### Install from PyPI

```bash
pip install voicerun-cli
```

### Install from Source

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

### Install a Specific Version

```bash
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):

```bash
uv tool install --force -e .
```

## Quick Start

```bash
# 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)

```bash
vr signin
```

Opens your default browser for secure OAuth-style authentication.

### Email/Password

```bash
vr signin
# Then select option 2 when prompted
```

### API Key

```bash
vr signin
# Then select option 3 when prompted
```

### Sign Out

```bash
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.

```bash
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.

```bash
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:**

```bash
# Update everything
vr --update

# Short form
vr -U
```

---

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

### `vr setup`

Set up the VoiceRun CLI environment by installing required dependencies.

```bash
vr setup
```

**Example:**

```bash
vr setup
```

---

### `vr signin`

Sign in to the VoiceRun API.

```bash
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:**

```bash
vr signin
# Select authentication method when prompted
```

---

### `vr signout`

Sign out and clear stored credentials.

```bash
vr signout
```

---

### `vr init`

Create a new voice agent project from templates.

```bash
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:**

```bash
# 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.

```bash
vr validate
```

**Options:**

| Option | Description |
|--------|-------------|
| `--environment`, `-e` | Environment to render templates for |
| `--quiet`, `-q` | Only output errors |

**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:**

```bash
# 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.

```bash
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 |

**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:**

```bash
# 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.

```bash
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 |

**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:**

```bash
# 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.

```bash
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 |

**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:**

```bash
# 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.

```bash
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 in `.voicerun/` to overlay (e.g. `prod.yaml`). Without this flag, only `.voicerun/values.yaml` is loaded — no environment-specific values file is auto-resolved by name. |
| `--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. |

**Prerequisites:**

- Run `vr push` first to generate `agent.lock`, or pass `--function` explicitly
- The target environment must already exist (see [`vr create environment`](#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:**

```bash
# 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`

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

```bash
vr debug
```

**Options:**

| Option | Description |
|--------|-------------|
| `--skip-push`, `-s` | Skip pushing code, use the existing deployment |
| `--environment`, `-e` | Environment name (default: `debug`) |
| `--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 |
| `--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) |

**Prerequisites:**

- Node.js must be installed for the debugger (not required for `--outbound` mode)

**What it does:**

- **Inside a voicerun 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.
- **Outside a project:** Opens the Pipeline Debugger with no prefilled agent info, so you can connect manually.
- **Headless mode:** Runs the debugger without a GUI window — streams JSONL events to stdout and accepts text input on stdin (one message per line). Useful for CI pipelines and coding agents.
- **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.

**Example:**

```bash
# Push and debug (inside a project)
vr debug

# Debug without pushing (use existing deployment)
vr debug --skip-push
vr debug -s

# Debug specific environment
vr debug -e staging

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

# Headless mode (CI / coding agents)
vr debug --headless
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

# Place an outbound phone call
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.

```bash
vr open
```

Requires `agent.lock` to exist (created after `vr push`). Opens your default browser to the agent's function page.

---

### `vr render`

Render VoiceRun templates and display the output.

```bash
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 |

**Example:**

```bash
# 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.

```bash
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 |

**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:**

```bash
# 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)`.

```bash
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 in `.voicerun/` to overlay for local listing/preview (e.g. `prod.yaml`). Without this flag, only `.voicerun/values.yaml` is loaded. 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. |

**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`](#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:**

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

**Example:**

```bash
# 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-release).

#### `vr evaluation list`

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

```bash
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`). |
| `--type`, `-T` | Filter by eval type (`judge`, `extraction`, `script`). |
| `--limit`, `-l` | Page size. |
| `--page`, `-p` | Page number. |
| `--json`, `-j` | Output as JSON. |
| `--table`, `-t` | Output as table (default for interactive terminals). |

**Example:**

```bash
# 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
```

#### `vr evaluation info`

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

```bash
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:**

```bash
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
- Prompt and completion token usage
- 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.

#### `vr get agents`

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

```bash
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.

```bash
vr get functions [AGENT]
```

**Arguments:**

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

**Example:**

```bash
# 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.

```bash
vr get environments
```

**Example:**

```bash
vr get environments
```

#### `vr get agentenvironments`

List legacy per-agent environments. For org-scoped environments, use [`vr get environments`](#vr-get-environments).

```bash
vr get agentenvironments [AGENT]
```

**Arguments:**

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

**Example:**

```bash
# 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.

```bash
vr get releases
```

**Options:**

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

**Example:**

```bash
# 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).

```bash
vr get entrypoints
```

**Options:**

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

**Example:**

```bash
# 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.

```bash
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:**

```bash
# 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`](#vr-create-variable) with `--masked` when you need a value readable via `context.variables.get()`.

```bash
vr get secrets
```

**Options:**

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

**Example:**

```bash
# List organization secrets
vr get secrets
```

#### `vr get phonenumbers`

List organization phone numbers.

```bash
vr get phonenumbers
```

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

#### `vr get telephony`

List organization telephony providers.

```bash
vr get telephony
```

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

#### `vr get assignments`

List all phone number assignments for an agent.

```bash
vr get assignments [AGENT]
```

**Arguments:**

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

**Example:**

```bash
# 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.

```bash
vr get templates
```

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

---

### `vr describe`

Show detailed information about a specific resource.

#### `vr describe assignment`

Show detailed information about a phone number assignment.

```bash
vr describe assignment [AGENT] <ASSIGNMENT_ID>
```

**Arguments:**

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

**Example:**

```bash
# 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.

```bash
vr describe agent [NAME_OR_ID]
```

**Arguments:**

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

**Example:**

```bash
# 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
- Debug & tracing settings
- Timestamps

#### `vr describe function`

Show detailed information about a function.

```bash
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:**

```bash
# 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.

```bash
vr describe environment <NAME_OR_ID>
```

**Arguments:**

| Argument | Description |
|----------|-------------|
| `NAME_OR_ID` | Environment name or UUID |

**Example:**

```bash
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`](#vr-describe-environment).

```bash
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:**

```bash
# 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.

```bash
vr describe release <RELEASE_ID>
```

**Arguments:**

| Argument | Description |
|----------|-------------|
| `RELEASE_ID` | Release UUID |

**Example:**

```bash
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 and organization ID

#### `vr describe entrypoint`

Show detailed information about an entrypoint.

```bash
vr describe entrypoint <NAME_OR_ID>
```

**Arguments:**

| Argument | Description |
|----------|-------------|
| `NAME_OR_ID` | Entrypoint name or UUID |

**Example:**

```bash
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.

```bash
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:**

```bash
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).

```bash
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:**

```bash
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.

```bash
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:**

```bash
# 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.

```bash
vr describe telephony <NAME_OR_ID>
```

**Arguments:**

| Argument | Description |
|----------|-------------|
| `NAME_OR_ID` | Telephony provider name or UUID |

**Example:**

```bash
vr describe telephony my-twilio
```

**Output includes:**
- Provider name, type, and ID
- Organization ID
- Timestamps

---

### `vr create`

Create resources.

#### `vr create assignment`

Assign a phone number to an agent environment.

```bash
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:**

```bash
# 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-release).

```bash
vr create environment <NAME>
```

**Arguments:**

| Argument | Description |
|----------|-------------|
| `NAME` | Environment name (unique within the organization) |

**Options:**

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

**Example:**

```bash
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`](#vr-create-environment).

```bash
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 |

**Example:**

```bash
# 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
```

#### `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.

```bash
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`](#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`

```bash
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:**

```bash
# 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`

```bash
vr create entrypoint web <NAME> [--release <ID>[:<WEIGHT>]] --allowed-origin <ORIGIN>
```

**Options:**

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

**Example:**

```bash
vr create entrypoint web widget \
  --release rel-latest \
  -o https://acme.com -o https://app.acme.com
```

##### `vr create entrypoint native`

```bash
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:**

```bash
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).

```bash
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:**

```bash
# 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.

```bash
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:**

```bash
# 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:

```python
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`](#vr-create-variable) with `--masked` instead.

```bash
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:**

```bash
# 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.

```bash
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:**

```bash
# 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.

```bash
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:**

```bash
# 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.

```bash
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:**

```bash
# 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.

```bash
vr delete assignment [AGENT] <ASSIGNMENT_ID>
```

**Arguments:**

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

**Example:**

```bash
# 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.

```bash
vr delete agent <NAME_OR_ID>
```

**Arguments:**

| Argument | Description |
|----------|-------------|
| `NAME_OR_ID` | Agent name or ID |

**Example:**

```bash
vr delete agent my-agent
```

#### `vr delete function`

Delete a function from an agent.

```bash
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:**

```bash
# 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.

```bash
vr delete environment <NAME_OR_ID>
```

**Arguments:**

| Argument | Description |
|----------|-------------|
| `NAME_OR_ID` | Environment name or ID |

**Example:**

```bash
vr delete environment staging
```

#### `vr delete agentenvironment`

Delete a legacy per-agent environment. For org-scoped environments, use [`vr delete environment`](#vr-delete-environment).

```bash
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 |

**Example:**

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

# Explicit agent
vr delete agentenvironment my-agent staging
```

#### `vr delete release`

Delete a release by ID.

```bash
vr delete release <RELEASE_ID>
```

**Arguments:**

| Argument | Description |
|----------|-------------|
| `RELEASE_ID` | Release UUID |

**Example:**

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

#### `vr delete entrypoint`

Delete an entrypoint by name or ID.

```bash
vr delete entrypoint <NAME_OR_ID>
```

**Arguments:**

| Argument | Description |
|----------|-------------|
| `NAME_OR_ID` | Entrypoint name or ID |

**Example:**

```bash
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.

```bash
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:**

```bash
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.

```bash
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:**

```bash
vr delete secret MY_API_KEY
```

#### `vr delete phonenumber`

Delete or release an organization phone number.

```bash
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:**

```bash
# 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.

```bash
vr delete telephony <NAME_OR_ID>
```

**Arguments:**

| Argument | Description |
|----------|-------------|
| `NAME_OR_ID` | Telephony provider name or ID |

**Example:**

```bash
vr delete telephony my-twilio
```

---

### `vr context`

Manage API contexts for different environments (development, staging, production).

#### `vr context list`

List all available contexts and show the current one.

```bash
vr context list
```

#### `vr context current`

Show the current context with API and frontend URLs.

```bash
vr context current
```

#### `vr context switch`

Switch to a different context.

```bash
vr context switch <NAME>
```

#### `vr context create`

Create a new user-defined context.

```bash
vr context create <NAME> <API_URL> <FRONTEND_URL>
```

**Example:**

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

#### `vr context delete`

Delete a user-defined context.

```bash
vr context delete <NAME>
```

#### `vr context set-url`

Set a custom API URL for the current session.

```bash
vr context set-url <API_URL>
```

#### `vr context set-org`

Set the organization ID to operate under. Useful when your account belongs to multiple organizations.

```bash
vr context set-org <ORGANIZATION_ID>
```

**Arguments:**

| Argument | Description |
|----------|-------------|
| `ORGANIZATION_ID` | Organization ID to use (pass empty string to clear) |

**Example:**

```bash
# Set organization ID
vr context set-org org_123456

# Clear organization override (use default from session)
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.

```bash
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:**

```bash
# 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.

```bash
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:**

```bash
# 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.

```bash
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:**

```bash
# 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.

```bash
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:**

```bash
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.

```bash
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:**

```bash
# 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.

```bash
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:**

```bash
# 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.

```bash
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:**

```bash
# 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.

```bash
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:**

```bash
# 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

---

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

```bash
vr report bug
```

**Subcommands:**

| Subcommand | Description |
|------------|-------------|
| `bug` | Submit a bug report |

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

**Examples:**

```bash
# 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
```

---

## 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`](#vr-render); validate spec keys with [`vr validate`](#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.

```yaml
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`](#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.

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

```yaml
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`](#vr-evaluation) and [`vr evaluation info`](#vr-evaluation).

```yaml
apiVersion: voicerun/v1
kind: Evaluator
metadata:
  name: resolution-judge
spec:
  evalType: judge            # judge | extraction | script
  targetFormat: transcript   # events | 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: {}
  code: null                 # script evaluators only
  apiProvider: openai
  model: gpt-4o
  organizationSecretName: OPENAI_API_KEY
```

## Templates

### agent.yaml

Defines your agent's metadata:

```yaml
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:

```python
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

- [VoiceRun Documentation](https://voicerun.com/docs)
- [Report Issues](https://github.com/VoiceRun/voicerun-cli/issues)

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

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

### List active worktrees

```bash
git worktree list
```

### Remove a worktree

```bash
git worktree remove .worktrees/feature-xyz
```

### Clean up stale worktrees

```bash
git worktree prune
```
