CLI reference

ReferenceUpdated 47 min read
View as Markdown
On this page

Current version: @opvs-ai/cli@0.27.11 — read from npmjs.com and npm.opvs.ai by direct HTTP on 2026-11-06 15:58 UTC; both serve the same version.

Marked "0.20.1" below: flags that 0.16.1 did not have and 0.20.1 added (measured in the published tarballs). The one that matters most is the health exit codes: on 0.16.1, opvs boards health prints the verdict but exits 0 whatever it is.

Verify a version yourself with npm view @opvs-ai/cli version --@opvs-ai:registry=https://registry.npmjs.org. A bare --registry flag does not beat a scope pin in a local .npmrc, on reads either.

New in 0.16.1: commands that delete or cancel something now ask first, and refuse without --yes when nobody is at a terminal (Destructive commands). There is also a new scheduled-runs command group.

The OPVS CLI (@opvs-ai/cli) gives terminal-based AI agents and developers direct access to AgentBoard task management and AgentDocs documentation.

How this relates to the Marketplace: The CLI is a developer tool — it exposes a fixed command set for the tools that ship with @opvs-ai/cli. It is independent of what skill packages your brand has installed in the marketplace. Marketplace installs add tools to your OPVS-hosted agents (on app.opvs.ai), not to your CLI. Both channels operate on the same backend data, so a task you create from the CLI is visible to your OPVS agents and vice versa.

Installation

npm install -g @opvs-ai/cli

Or as a project dependency:

npm install @opvs-ai/cli

Requirements: Node.js 18+

Authentication

OPVS uses AI-native authentication: the agent requests a token, a human approves it via email.

# Set your API URL
opvs config set api_url https://app.opvs.ai

# Request access — admin email only (recommended)
# Auto-discovers all workspaces the admin manages
opvs auth request -e <admin-email>

# Legacy: request access to a specific workspace
opvs auth request -w <workspace-slug> -e <admin-email>

# The CLI polls automatically — once approved, tokens are saved
# Multi-workspace: each brand is saved as a separate workspace

Agent Shortcuts

  • Self-assignment: Use --assign self in tasks create or tasks update to assign tasks to yourself without knowing your agent UUID.

  • Column by name: Use --column "Done" or --column "In Progress" in tasks create and tasks move instead of looking up column UUIDs.

  • Auto-assign on create: Tasks are automatically assigned to the creating agent when no --assign is specified.

Global Options

Every command accepts these global options:

Option

Description

-w, --workspace <slug>

Run command against a specific workspace

-h, --help

Show help for a command

Destructive commands need --yes

Since 0.16.1, every command that deletes, removes or cancels something asks before it acts:

  • At a terminal, it prints what is about to go and waits for y.

  • When stdin is not a terminal (an agent loop, CI, a pipe), it does not ask. It refuses,

exits 1 and sends nothing, unless you pass --yes (or -y).

opvs boards delete <board-id> < /dev/null
# → Refused: Delete board …? … stdin is not a terminal. Re-run with --yes to confirm.   (exit 1)

opvs boards delete <board-id> --yes
# → Deleted board …                                                                    (exit 0)

A non-interactive stdin is not treated as consent. If an agent or script ran these commands before 0.16.1, add --yes where you really mean to delete.

Errors:

Condition

Message

Resolution

A destructive command ran without --yes, with stdin not a terminal

Refused: <what it would do>? … stdin is not a terminal. Re-run with --yes to confirm.

Add --yes if you mean it. Nothing was sent. Exit 1.

Commands that take --yes:

Group

Commands

boards

delete, move-to-project (it removes the board from every other project)

tasks

delete

stages

delete

links

delete, delete-doc

members

remove

markers

delete

board-links

delete

columns

delete

files

delete

docs

delete, project-delete, branch-delete

code

context, summary, tree, files, symbols, resolve, changes, graph

scheduled-runs

cancel

employees

hire (spends a plan seat and may bill), cancel

mail

draft delete

tools

uninstall

auth

revoke

workspace

remove

config

reset

Run opvs <group> <command> --help to see what a command will remove. Help for these commands says "Asks first; needs --yes off a terminal."


Auth Commands

opvs auth request

Request a PAT token. Sends an approval email to the admin and polls until approved.

opvs auth request -e admin@acme.com          # Recommended: auto-discover all workspaces
# → approved in 42 seconds; token written to "~/.opvs/config.json"

opvs auth request -w acme -e admin@acme.com  # Legacy: one named workspace

Option

Required

Description

-e, --email <email>

Yes

Admin email (who approves the request)

-w <slug>

No

Workspace slug (global flag). Omit for auto-discover.

Errors: the command polls, so these arrive after the email is sent.

Condition

Message

Resolution

Approver clicked Deny

Access denied by workspace owner.

Ask the admin why; re-request once resolved. Exit 1.

Request outlived its window

Request expired. Try again.

Re-run the command. Exit 1.

Poll window elapsed unanswered

Request timed out. The owner may not have seen the email.

Check the admin received it, then re-run. Exit 1.


opvs auth status

Show current authentication status — user ID, email, brand, and scopes.

opvs auth status
# → user_id, email, brand, and the 12 scopes the token carries

Errors:

Condition

Message

Resolution

401 from the server

Token is invalid or expired. Run \opvs auth request\ to re-authenticate.

Re-authenticate. Exit 1.

Any other failure

Error: <detail>

Read the detail; check opvs config get api_url. Exit 1.


opvs auth revoke

Revoke the token for the current workspace (both server-side and local config).

opvs auth revoke --yes
# → "Token revoked on server." then "Local config cleared for workspace \"acme\"."

Errors: the local config is cleared even when the server call fails, so the command is safe to re-run.

Condition

Message

Resolution

Token already gone server-side

Token not found on server (may already be revoked).

None — local config is still cleared. Exit 0.

Server unreachable or rejects

Server revoke failed (<detail>), but local config cleared.

Revoke from the dashboard; the local token is already gone. Exit 0.


opvs auth list

List all agent tokens for the workspace (admin only).

opvs auth list
# → JSON array of agent tokens for workspace "acme", newest first

Errors:

Condition

Message

Resolution

Caller is not a workspace admin

Error: <detail>

Admin-only command; ask an admin to run it. Exit 1.

Request failed with no detail

Error: Failed to list agents

Check connectivity and opvs auth status. Exit 1.


Workspace Commands

opvs workspace list                   # List all configured workspaces
opvs workspace use <slug>             # Switch active workspace
opvs workspace current                # Show current workspace
opvs workspace remove <slug> --yes    # Remove a saved workspace

Board Commands

opvs boards list                      # List all boards
opvs boards get <id>                  # Board details + columns
opvs boards create -n "Name"          # Create board (default columns)
opvs boards update <id> --name "New"  # Update board
opvs boards delete <id> --yes         # Soft delete (--yes: see Destructive commands)
opvs boards health <id> --profile factory   # Structural audit (see Board and project health)
opvs boards apply-preset <id> factory-full  # Preview reshaping the columns to a preset; --yes applies it

Task Commands

opvs tasks list --board <id>                      # Tasks on a specific board
opvs tasks list --self                             # Your assigned tasks (all boards)
opvs tasks list --self --status pending            # Filter by status
opvs tasks get <id>                                # Full task details
opvs tasks create --board <id> -t "Title"          # Create task (auto-assigns to you)
opvs tasks create --board <id> -t "Title" --column "In Progress" --labels "bug,urgent"
opvs tasks update <id> --status review             # Update task
opvs tasks update <id> --result-file out.md        # Attach result from file
opvs tasks delete <id> --yes                       # Soft delete
opvs tasks move <id> --column "Done"               # Move by column name
opvs tasks transfer <id> --board <key>             # Move the card to another board; its old ref keeps opening it
opvs tasks copy <id> --board <key> --column "To Do" # New linked card on another board; the original stays
opvs tasks subtasks <id>                           # List subtasks
opvs tasks search -q "keyword"                     # Full-text search across tasks
opvs tasks search -q "bug" --board <id>            # Scoped search
opvs tasks batch-get --ids id1,id2,id3             # Get multiple tasks (max 50)

transfer and copy need @opvs-ai/cli 0.27.5 or later. What each one carries, and every refusal, is in Move or copy a card to another board.


Agent Commands

Agent-optimized convenience commands for multi-agent workflows.

opvs agent my-tasks                                # All your tasks across all boards
opvs agent my-tasks --status in_progress           # Filter by status
opvs agent delegations                             # Tasks you delegated to others
opvs agent batch-create --file tasks.json          # Create multiple tasks at once
opvs agent progress <id> --percent 50 --message "Halfway done"
opvs agent complete <id>                           # Mark done (auto-walks state machine)
opvs agent complete <id> --status failed --summary "Blocked by X"
opvs agent delegate <id> --to maya --instructions "Please review"
opvs agent mention <id> --agent maya --message "Need your input"
opvs agent tasks-by maya                           # Tasks assigned to a specific agent

Command

Description

my-tasks

Cross-board task aggregation with board names

delegations

Tasks you handed off to other agents

batch-create

Create multiple tasks from a JSON file

progress <id>

Report progress (percent + message + operation)

complete <id>

Smart completion — walks through state machine automatically

delegate <id>

Reassign to another agent by slug

mention <id>

@mention an agent on a task to trigger a response

tasks-by <slug>

List tasks assigned to a specific agent


Stage Commands

Sequential in-card steps with multi-agent handoff.

opvs stages list <taskId>                          # List stages (ordered)
opvs stages create <taskId> -t "Research"          # First auto-activates
opvs stages create <taskId> -t "Review" --assign-agent <id>
opvs stages update <taskId> <stageId> -t "New title"
opvs stages delete <taskId> <stageId> --yes        # Delete pending stage
opvs stages reorder <taskId> --order id1,id2,id3

Task relationships (spawned, blocked_by, related).

opvs links list <taskId>                           # Incoming + outgoing links
opvs links create <taskId> --target <id> --type blocked_by
opvs links delete <linkId> --yes                   # Remove a link (hard delete)

Member Commands

Board member management.

opvs members list <boardId>                        # List board members
opvs members add <boardId> --user <id>             # Add member
opvs members remove <boardId> <userId> --yes       # Remove member

Marker Commands

Color-coded tags for tasks.

opvs markers list                                  # List all markers
opvs markers create -n "Urgent" --color "#ff0000"
opvs markers get <id>                              # Marker details
opvs markers update <id> --color "#00ff00"
opvs markers delete <id> --yes
opvs markers toggle <id> --task <taskId>           # Mark the marker complete, or reopen it

markers toggle flips the marker's own completed state. It does not attach the marker to a task: the CLI requires --task and sends it, and the server ignores it.


Cross-board relationships.

opvs board-links list                              # List board links
opvs board-links create --source <id> --target <id> --type related
opvs board-links update <id> --label "depends on"
opvs board-links delete <id> --yes

Comment Commands

opvs comments list <taskId>                        # List task comments
opvs comments add <taskId> "message"               # Add comment
opvs comments add <taskId> -f output.md            # Comment from file

Views (Agent-Optimized)

Single-call endpoints that return everything an agent needs.

opvs views session <boardId>                       # Board + columns + your tasks (one call)
opvs views overview <boardId>                      # Board overview with column structure
opvs views tasks <boardId>                         # Filtered task list view
opvs views task <taskId>                           # Single task detail with full context

Activity Feed

opvs activity board <boardId> --limit 25           # Board activity feed
opvs activity task <taskId> --limit 25             # Task activity feed

Metrics

opvs metrics summary --board <id> --days 7         # Board KPIs
opvs metrics velocity --days 30                    # Task velocity over time
opvs metrics agents --days 30                      # Agent performance comparison
opvs metrics costs --days 30                       # LLM cost data
opvs metrics distribution --board <id>             # Task status distribution

Column Management

opvs columns list <boardId>
opvs columns create <boardId> --name "Name" --color "#hex"
opvs columns update <columnId> --name "Name" --wip-limit 5
opvs columns update <columnId> --health-column-age-days 30   # 0.20.1+: this column's own staleness threshold
opvs columns reorder <boardId> --order id1,id2,id3
opvs columns delete <columnId> --yes

File Attachments

opvs files list <taskId>
opvs files upload <taskId> <path> --type result --description "desc"
opvs files download <fileId> -o ./out.pdf
opvs files delete <fileId> --yes

Board and project health

A structural audit of a board or a project. OPVS reports the structure and you pass the thresholds; a check whose threshold you did not pass reports NOT CHECKED, and the verdict is then INCOMPLETE, never HEALTHY. The routes, every check and the three profiles are documented in Board health.

opvs boards health

opvs boards health ASP --profile factory
# → Board health — AgentBoard Surface Parity (ASP)
# → Verdict: NOT HEALTHY — at least one check failed
# → Profile: factory
# → Counts:  10 PASS · 1 FAIL · 5 WARN · 1 INFO · 1 NOT CHECKED
# → Not supplied (so their checks made no finding): --preset

Option

Since

Description

--profile <name>

0.16.1

planner-orchestration, factory or crm: a named set of the thresholds below

--preset, --required-column-fields, --required-task-fields

0.16.1

The structure and field requirements. Each overrides the profile's value.

--stale-days, --column-age-days, --star-fanout

0.16.1

The numeric thresholds. Each overrides the profile's value.

--json

0.16.1

Print the report as JSON

--format <fmt>

0.20.1

text (default), json (the report verbatim), md or yaml

--all-checks

0.20.1

On a NOT HEALTHY report, print every check, not only the failures

--require-complete

0.20.1

Make INCOMPLETE exit 2 as well

Exit codes (0.20.1 and later) — a script can gate on these:

Exit

Meaning

0

HEALTHY — every check ran and none failed

0

INCOMPLETE — you did not pass a threshold, so a check did not run. That is about your request, not the board. --require-complete makes it 2.

2

NOT HEALTHY — at least one check failed

1

The CLI could not get a verdict: network, auth, a bad reference, or a verdict it does not recognise. Never 0.

⚠️ On 0.16.1 the exit code is 0 for every verdict, and 1 only when the request fails, so opvs boards health X && deploy deploys a board that just failed. If you are still on 0.16.1, upgrade, or gate on the JSON:

opvs boards health ASP --profile factory --json | jq -e '.verdict == "healthy" or .verdict == "incomplete"'
# → false        (jq exits 1: this board is not_healthy)

jq -e exits 0 for a healthy or incomplete board, 1 for a failed one, and 4 when the CLI printed nothing because the request failed, so the gate fails closed. Remove or .verdict == "incomplete" if a check that did not run should fail the gate too.

Errors:

Condition

Message

Resolution

Not a board key, UUID prefix or UUID

Error: path.board_id: 'ZZZNOPE9!' is not a valid board reference. …

Use a key like PC, 8 or more hex characters, or a full UUID. Exit 1.

No such board, or a private board you are not on

Error: Board not found

Check the reference and your workspace. Exit 1.

Unknown profile

Error: unknown profile 'nope' — known profiles: crm, factory, planner-orchestration

Use one of the three. Exit 1.

opvs projects health

Audits a project and each of its member boards, with the same options and exit codes as boards health. A member board that comes back INCOMPLETE counts against the project, so a project never reads healthier than its boards.

opvs projects health 812228dc-9e9f-4d12-8acb-91054d41ee79 --profile factory
# → Project health — opvsRunner
# → Verdict: NOT HEALTHY — at least one check failed
# → Counts:  3 PASS · 1 FAIL · 0 WARN · 0 INFO · 0 NOT CHECKED
# → (exit 2 from 0.20.1; an unknown project id prints "Error: Project not found", exit 1)

Errors:

Condition

Message

Resolution

Not a full project UUID

Error: path.group_id: '812228dc' is not a valid reference. …

Pass the full UUID from opvs projects list. A prefix is refused today even though the message suggests one. Exit 1.

No such project in your brand

Error: Project not found

Check the id with opvs projects list. Exit 1.


Project Commands

A project groups many boards under one container, and carries a bundle of commands, skills, and standing rules that every card on its member boards inherits when an agent claims it. A board can belong to more than one project.

opvs projects list                                 # Roll-ups per project
opvs projects list --archived                      # Include archived ones
opvs projects get <id>                             # One project + member boards
opvs projects create -n "Name"                     # Empty container
opvs projects create -n "Name" -b <boardUuid> -b <boardUuid>
opvs projects update <id> -n "New name"
opvs projects set-status <id> active               # active | on_hold | completed
opvs projects archive <id>                         # Hide from the default list
opvs projects archive <id> --undo                  # Unarchive
opvs projects add-board <id> <boardId>
opvs projects remove-board <id> <boardId>          # The board itself stays live
opvs projects tasks <id>                           # All tasks across member boards
opvs projects tasks <id> --include-done

create -b takes a full board UUID. Board keys and refs are not accepted on that flag, because board_ids is not on the gateway's ref allowlist.

Project Bundles

The three bundle fields do not share a delivery path. commands and skills are names — fetched once and installed onto the desk. rules are the constraint text itself, inlined verbatim into every brief and charged to every build of every card in the project. A rule should be one sentence stating one constraint; anything with a body, steps, or examples wants to be a skill.

Caps: 50 commands and 50 skills at 200 characters each, 20 rules at 500 each.

opvs projects bundle get

opvs projects bundle get 4f21c7a8-9d3e-4b15-8c60-2a7e51d9b3f4
# → {"commands": ["ship"], "skills": ["agentboard"], "rules": ["Never force-push to main"]}

Empty lists mean nothing is configured for that field — not that the project is missing.

Errors:

Condition

Message

Resolution

Project id unknown or not yours

Error: <detail>

Check the id with opvs projects list. Exit 1.

Request failed with no detail

Error: Failed to get project bundle

Check connectivity and opvs auth status. Exit 1.

opvs projects bundle set

opvs projects bundle set 4f21c7a8-9d3e-4b15-8c60-2a7e51d9b3f4 \
  -c ship -c review \
  -s agentboard -s agentdocs \
  -r "Never force-push to main"
# → the updated bundle: 2 commands, 2 skills, 1 rule

opvs projects bundle set 4f21c7a8-9d3e-4b15-8c60-2a7e51d9b3f4 --clear-skills

Warning: A passed list REPLACES that field bundle set does not append. Sending -s agentdocs to a project that already has three skills leaves it with one — and returns 200 with exactly the bundle you asked for, which is what makes this the mistake that survives review. Read the current lists with bundle get first and send them all back. Omitting a field leaves it untouched; --clear-* empties it deliberately.

Errors:

Condition

Message

Resolution

Both set and cleared one field

Cannot both set and clear skills. Drop --clear-skills or the repeated flag.

Pick one intent per field. Exit 1.

No field given at all

Nothing to update. Provide --command / --skill / --rule, or --clear-commands / --clear-skills / --clear-rules

Name at least one field. Exit 1.

A cap or length exceeded

Error: <detail> (422 from the server)

Trim to the caps above. Exit 1.

Request failed with no detail

Error: Failed to set project bundle

Check connectivity and opvs auth status. Exit 1.

A bundle reaches a card only when its board belongs to exactly one active project. A board in two active projects is ambiguous and inherits nothing; archived projects no longer count toward that total.


Scheduled Runs

A scheduled run starts a factory project later. At --run-at, the project (or one member board, with --board) is armed, the same as pressing Play. The factory starts claiming its cards, those builds spend, and the project stays armed until someone pauses or stops it. Scheduling a run costs nothing. The run starts spending when it fires. The scheduler checks about once a minute, so a time in the past fires on the next check.

opvs scheduled-runs list                                   # Waiting runs, soonest first
opvs scheduled-runs list --state all --project <uuid>      # scheduled | fired | failed | cancelled | all
opvs scheduled-runs get <id>                               # State, when it fired, last_error
opvs scheduled-runs create --project <uuid> --run-at 2026-09-18T08:00:00Z
opvs scheduled-runs create --project <uuid> --board <uuid> --run-at 2026-09-18T08:00:00Z
opvs scheduled-runs cancel <id> --yes                      # Only a run that has not fired yet
  • --run-at is ISO 8601 with a time zone (for example Z).

  • --project and --board take full UUIDs.

  • --params <json> stores a JSON object with the run (notes, a notify list). Nothing reads it to

change how the run behaves.

  • create and cancel need a brand admin (otherwise 403). list and get are reads.

  • cancel does not stop a run that already fired. Pause or stop the project for that. A fired,

failed or cancelled run comes back unchanged.

  • A run whose arming failed shows state: failed with the reason in last_error.


Documentation Commands

Full AgentDocs management — projects, pages, revisions, media, branches.

# Basic (existing)
opvs docs list                                     # List doc projects
opvs docs get <project> <slug>                     # Read a page
opvs docs create <project> -t "Title" -s "slug" -f content.md
opvs docs update <project> <slug> -f content.md
opvs docs search "query"                           # Search docs

# Project CRUD
opvs docs project-create -n "Name"
opvs docs project-update <project> -n "New Name" --visibility private
opvs docs project-delete <project> --yes

# Page operations
opvs docs pages <project>                          # List pages (flat or --view tree)
opvs docs move <project> <slug> --path "/guides"
opvs docs delete <project> <slug> --yes

# Revision history
opvs docs history <pageId>                         # Revision history
opvs docs diff <pageId> --from <rev> --to <rev>
opvs docs rollback <pageId> --revision <rev>

# Media & bulk
opvs docs media <project>                          # List media files
opvs docs bulk-create <project> -f pages.json
opvs docs export <project> -o export.zip

# Branches
opvs docs branches <project>
opvs docs branch-create <project> -n "draft-v2"
opvs docs branch-merge <project> draft-v2
opvs docs branch-delete <project> draft-v2 --yes

Code Index Commands

Requires @opvs-ai/cli 0.24.1 or later; opvs code graph folders and opvs code changes --order / --before need 0.26.0 or later, opvs code callers needs 0.27.0 or later, opvs code check-card needs 0.27.1 or later, and opvs code tests-for needs 0.27.6 or later. Check yours with opvs --version.

The opvs code group is the terminal face of a project's code index: a read-only query door over a tenant's structural index, scoped to one project per call. Every command needs --project <id> (the project's board_groups.id; tests-for needs it only with --remote, and check-card also reads OPVS_CODE_PROJECT) and an OPVS_TOKEN whose scope carries code:read. A plain opvs auth request does not ask for code:read; request it explicitly with --scopes, for instance:

opvs auth request -e <workspace-admin> \
    --scopes board:read,board:write,docs:read,docs:write,code:read

An approved token is never widened after the fact, so mint a new one if the existing token lacks the scope — a CLI call against an approved token without code:read fails with Token missing required scope: code:read. The ingest scope (code:write) is withheld by default: only the box's own sidecar token writes the index, never a customer agent, and rewriting it changes what every later agent session on that repo believes.

The way these commands answer depends on whether the project has an attached repository at all, and on whether that repository carries a ready index:

Command

No attached repository (another brand's project, an id that does not exist)

Repository attached, no ready index

context, summary, tree, files, symbols

200 with indexed: false

200 with indexed: false

resolve

404 with project not found

200; each anchor returns state: unknown (the ledger has the path-derived id but has never seen the node)

changes

404 with index not found

200; if a branch is attached, the events recorded so far (or empty if none yet); if no branch is attached, branch: null with a reason

graph

404 with index not found

404 with index not found (no ready index means no edges to read)

graph folders

200 with indexed: false

200 with indexed: false

callers

Exit 1 with project not found

Exit 0; each anchor reads NOT IN INDEX, or index: unavailable with callers unknown

check-card

Exit 2 with CANNOT: project not found

Exit 2 with CANNOT: code index unavailable

Another brand's project and a project id that does not exist get the identical answer on each command, so the route still cannot be used to discover another brand's project. Keeping "we searched and found nothing" and "there is no index to search" as two separate facts stops a client from reporting an unmeasured answer as a measured one.

Every command except tests-for, callers and check-card accepts --format yaml | md | json. yaml is the default and is more token-efficient; md is for human reading; json skips the renderer and returns the raw response.


opvs code context <query>

The pre-write check: does <query> already exist in this project's repo? Matches on symbol name (spelling) and on the symbol's first doc line (meaning). The answer is exists, similar, or none — never yes/no.

opvs code context "resolveBrand" --project 9d7642c4-8151-4c3e-977e-9f30d5a52844
# → indexed: true; verdict: exists; matches: 1 (path: src/auth/brand.ts, kind: function)

Option

Required

Description

--project <id>

Yes

Project id (board_groups.id where kind=project).

--kind <kind>

No

Restrict to one symbol kind (function, class, …).

--branch <name>

No

Answer from a specific indexed branch.

--limit <n>

No

Max matches to return (server max is 50).

--format <fmt>

No

yaml (default) | md | json — overrides the configured default.

Errors:

Condition

Message

Resolution

Server unreachable or rejected

Error: <detail>

Read the detail; check opvs config get api_url. Exit 1.

A project that belongs to another brand, or that simply has no ready index, returns indexed: false with an empty matches list — that is a successful read, not an error, and the CLI exits 0.


opvs code summary

Repo orientation as data: languages in the project, the test command, the shape of the code (kind counts), and the files carrying the most symbols (where the code lives). The shape is the same as the API's GET /api/v1/code/{project_id}/summary; this command is the curl-free path to it.

opvs code summary --project 9d7642c4-8151-4c3e-977e-9f30d5a52844 --format yaml
# → project_id, indexed, repo_url, freshness, languages (files, lines, symbols per language),
#   entry_points, test_command, kind_counts (per symbol kind), top_files[]
# → exit 1 "Error: Token missing required scope: code:read" when the token lacks code:read

Option

Required

Description

--project <id>

Yes

Project id (board_groups.id where kind=project).

--branch <name>

No

Answer from a specific indexed branch.

--format <fmt>

No

yaml (default) | md | json — overrides the configured default.

Errors:

Error

When

Resolution

Error: Token missing required scope: code:read (exit 1)

The token was approved without code:read.

Request a new token with --scopes …,code:read.

Error: <detail> (exit 1)

The server was unreachable or refused the call.

Read the detail; check opvs config get api_url.

An unindexed or other-brand project returns indexed: false, not an error.


opvs code tree

A directory map of the project's index. The tree endpoint reports directory tiles with their own counts and subtree counts — a directory tile is sized by its subtree_files, never by symbol counts or scanned lines. The endpoint's index_truncated, scan_truncated, enumeration_incomplete, and symbols_dropped_at_ingest flags are separate fields; collapsing them would let a partial index render as a census.

opvs code tree --project 9d7642c4-8151-4c3e-977e-9f30d5a52844 --depth 2 --branch main
# → directories[] with files, lines, files_scanned, subtree_files,
#   subtree_files_scanned, subtree_lines; freshness block (with edge_count, files_on_edges,
#   edges_incomplete); directories_capped, truncated
# → exit 1 with a validation error (HTTP 422) for --depth 4: the server stores 3 levels

Option

Required

Description

--project <id>

Yes

Project id.

--branch <name>

No

Answer from a specific indexed branch.

--depth <n>

No

1-based; can only narrow the stored tree.

--format <fmt>

No

yaml (default) | md | json.

Underlying route: GET /api/v1/code/{project_id}/tree.

Errors:

Error

When

Resolution

Error: Token missing required scope: code:read (exit 1)

The token was approved without code:read.

Request a new token with --scopes …,code:read.

Validation error, HTTP 422 (exit 1)

--depth is outside 1 to 3.

--depth can only narrow the stored tree; use 1, 2 or 3.


opvs code files [directory]

Files with symbols beneath a directory. The default is the repository root. With --direct, the response lists only files directly inside that directory (not descendants). The route does not list files with no stored symbols; pass --limit to cap a single response page (truncated reports the cap was hit, with truncated_reason saying what was left out).

opvs code files src/auth --project 9d7642c4-8151-4c3e-977e-9f30d5a52844 --direct --limit 50
# → files[] with file_path, symbol_count, derivation_counts; file_count, symbol_count, truncated
# → exit 1 "Error: directory must be repo-relative: '/src/auth'" for an absolute path

Option

Required

Description

--project <id>

Yes

Project id.

[directory]

No

A path inside the index, or . for the repo root. Defaults to root.

--direct

No

List only files directly inside [directory], not descendants.

--branch <name>

No

Answer from a specific indexed branch.

--limit <n>

No

Max files to return.

--format <fmt>

No

yaml (default) | md | json.

Underlying route: GET /api/v1/code/{project_id}/files.

Errors:

Error

When

Resolution

Error: Token missing required scope: code:read (exit 1)

The token was approved without code:read.

Request a new token with --scopes …,code:read.

Error: directory must be repo-relative (exit 1)

[directory] starts with / or has a .. segment.

Pass a path relative to the repository root, or ..


opvs code symbols <file_path>

Symbols in one file, in source order. Each symbol carries name, kind, line_start, line_end, signature, doc_first_line, and derivation (parsed vs regex). The response reports containment and source order; it does not report relationships, callers, or call sites.

opvs code symbols src/auth/brand.ts --project 9d7642c4-8151-4c3e-977e-9f30d5a52844 --branch main
# → symbols[] with name, kind, line_start, line_end, signature, doc_first_line, derivation
# → exit 1 "Error: file_path must be repo-relative: '../brand.ts'" for a path outside the repository

Option

Required

Description

--project <id>

Yes

Project id.

<file_path>

Yes

A repository-relative path; the file must contain stored symbols.

--branch <name>

No

Answer from a specific indexed branch.

--limit <n>

No

Max symbols to return.

--format <fmt>

No

yaml (default) | md | json.

Underlying route: GET /api/v1/code/{project_id}/symbols.

Errors:

Error

When

Resolution

Error: Token missing required scope: code:read (exit 1)

The token was approved without code:read.

Request a new token with --scopes …,code:read.

Error: file_path must be repo-relative (exit 1)

<file_path> starts with / or has a .. segment.

Pass the path relative to the repository root.

A file with no stored symbols answers an empty symbols list, not an error.


opvs code resolve <anchor...>

Resolve one or more text anchors to the current state of stable ledger nodes. An anchor is one of four shapes:

Form

Resolves to

path

a file node (the file at that repository-relative path)

dir/

a directory node

./

the repository root as a directory node

path#qname

a symbol node (the # is the separator; qname is everything after the first #)

Each item reports state as one of live | removed | moved | unknown. For moved or removed items, the response also carries moved_to_anchor or removed_commit. A symbol lookup that would miss but whose file ends .ts/.tsx and whose qname contains a . returns the file node INSTEAD, carrying fallback: file — a single node, not the symbol plus the file.

Up to 1000 anchors per call; over the limit is refused (422), not split — split into batches at the caller. The response is a bare list of CodeNodeResolution objects (one per anchor, in input order), not wrapped.

This is the read path for "did this land?" — write a name, get back the node that owns the name on the current commit. Node ids are UUIDv5 (deterministic, derived from project + repo + kind + path + qname), so a resolved node_id can be passed back to opvs code graph or opvs code changes without translation.

opvs code resolve \
    src/auth/brand.ts \
    src/auth/ \
    ./ \
    "src/auth/brand.ts#resolveBrand" \
    --project 9d7642c4-8151-4c3e-977e-9f30d5a52844
# → [
#     { anchor: "src/auth/brand.ts", node_id: "a6c34f5e-7d1e-5c12-b0b1-2c6c7d8e9f01", state: "live" },
#     { anchor: "src/auth/",        node_id: "8b1f6e4d-2c8a-5d4e-9a7b-3f0c1d2e3a4b", state: "live" },
#     { anchor: "./",               node_id: "3c4d5e6f-7a8b-5c9d-8e0f-1a2b3c4d5e6f", state: "live" },
#     { anchor: "src/auth/brand.ts#resolveBrand",
#       node_id: "c9f0e9d2-3a8e-5b7f-bb41-1d9e0a2b3c45", state: "live" }
#   ]
# → exit 1 "Error: project not found" (HTTP 404) when the project has no attached repository

Option

Required

Description

--project <id>

Yes

Project id.

<anchor...>

Yes

One or more anchors (path, dir/, ./, or path#qname). Up to 1000 per call.

--format <fmt>

No

yaml (default) | md | json.

Underlying route: POST /api/v1/code/{project_id}/nodes/resolve.

A project that has no attached repository at all — including another brand's project, or a project id that does not exist — returns 404 project not found.

Errors:

Error

When

Resolution

Error: Token missing required scope: code:read (exit 1)

The token was approved without code:read.

Request a new token with --scopes …,code:read.

Error: project not found (HTTP 404, exit 1)

No attached repository, another brand's project, or an id that does not exist.

Check the project id; attach a repository to it.

Validation error, HTTP 422 (exit 1)

More than 1,000 anchors, or an anchor the grammar cannot read.

Split into batches of 1,000; use the four anchor forms above.


opvs code changes

The attached repo's stable-node events — the audit trail for "what did the ledger see?" since the last ready index. They come oldest first (ascending event id) by default; --order desc returns them newest first.

Each order has its own cursor. With the default --order asc, page forward with --after, passing the prior response's next_after. With --order desc, page back with --before, passing the same next_after (it is the id of the last event returned, in either order). Mixing them is refused locally, before any request, with exit 1: Error: after is only valid with order=asc or Error: before is only valid with order=desc.

Each event carries id, event, node_id, path, node_kind, other_node, qname, other_path, commit_hash, at. The event is one of baseline | born | removed | moved | revived. node_id, path, and node_kind are null only on the one baseline marker written for a new ledger; qname is set on symbol rows only; other_node and other_path are set on moved rows only (the new node's id and path).

A project that has no attached repository at all — including another brand's project — returns 404 index not found. A project whose repository is attached but has no branch is a real project state, not a missing status: the response carries branch: null and a top-level reason of "no branch is attached, so no history is recorded", with an empty changes list. (That is separate from history_skipped_reason, which records the ready index's ledger outcome — a different fact.)

opvs code changes --project 9d7642c4-8151-4c3e-977e-9f30d5a52844 \
    --after 1024 --limit 100 \
    --node-id 4d7c8e2a-1f93-5b7e-9a4d-2c1b8e6f3a92 \
    --path-prefix src/store
# → changes[] (id, event, node_id, path, node_kind, other_node,
#   qname, other_path, commit_hash, at);
#   next_after, truncated, limit_clamped, history_applied_at, history_skipped_reason
# → exit 1 "Error: index not found" (HTTP 404) when the project has no attached repository

Newest first, then one page further back:

opvs code changes --project 9d7642c4-8151-4c3e-977e-9f30d5a52844 \
    --order desc --limit 20
# → changes[] with ids 1304 down to 1285; next_after: 1285; truncated: true
opvs code changes --project 9d7642c4-8151-4c3e-977e-9f30d5a52844 \
    --order desc --before 1285 --limit 20
# → changes[] with ids 1284 down to 1265
# → exit 1 "Error: before is only valid with order=desc" if --order desc is left out

Option

Required

Description

--project <id>

Yes

Project id.

--order <asc|desc>

No

Event id order. asc (default) is oldest first; desc is newest first. Needs CLI 0.26.0.

--after <id>

No

Return events after this event id. Only with --order asc.

--before <id>

No

Return events before this event id. Only with --order desc; omit it for the newest page. Needs CLI 0.26.0.

--limit <n>

No

Max events to return (server max is 500).

--node-id <id>

No

A stable node UUID. Repeat to select up to 100 nodes; a batch over 100 is refused locally with exit 1.

--path-prefix <path>

No

A repo-relative path. Matches the path itself and everything beneath it (--path-prefix src/store matches src/store and src/store/..., not src/storex).

--format <fmt>

No

yaml (default) | md | json.

Underlying route: GET /api/v1/code/{project_id}/nodes/changes.

Errors:

Error

When

Resolution

Error: Token missing required scope: code:read (exit 1)

The token was approved without code:read.

Request a new token with --scopes …,code:read.

Error: after is only valid with order=asc (exit 1, no request sent)

--after with --order desc.

Use --before to page a desc read.

Error: before is only valid with order=desc (exit 1, no request sent)

--before without --order desc.

Add --order desc, or page with --after.

Error: too many --node-id values (exit 1, no request sent)

More than 100 --node-id values.

Split the nodes into batches of 100.

Error: index not found (HTTP 404, exit 1)

No attached repository, another brand's project, or an id that does not exist.

Check the project id; attach a repository to it.


opvs code graph <node_id>

Adjacency for one node — what imports it or is imported by it. The graph carries import edges only: file-to-file (TypeScript / JavaScript, via regex) and module-to-module (Python, via the AST). The scanner emits no import edges for Go. Call edges need type resolution and remain a separate, later decision.

node_id is a UUIDv5 (the same id that opvs code resolve returns, or that a brand's own tooling can recompute from the project + repo + kind + path + qname). Direction is in, out, or both; depth is 1 or 2. Each neighbour carries node_id, path, node_kind, state, kind, derivation, hop — hop is 1 for a direct neighbour and 2 for one reached through a direct neighbour (--depth 2 only); state is the ledger state of the neighbour node (live | removed | moved), kind is the edge kind (always import today), and derivation is parsed (Python ast) for files the AST lane walked, or regex for TypeScript / JavaScript files matched by the regex lane.

opvs code graph 4d7c8e2a-1f93-5b7e-9a4d-2c1b8e6f3a92 \
    --project 9d7642c4-8151-4c3e-977e-9f30d5a52844 \
    --direction both --depth 1 --limit 25 --branch main
# → project_id, node_id, commit_hash, branch, direction, depth;
#   neighbours[] each carrying
#   node_id, path, node_kind, state (live | removed | moved),
#   kind (import), derivation (parsed | regex), hop (1 | 2);
#   truncated, limit_clamped, effective_limit
# → exit 1 "Error: index not found" (HTTP 404) for an unknown node or a project with no ready index

Option

Required

Description

--project <id>

Yes

Project id.

<node_id>

Yes

A ledger node id (UUIDv5).

--direction <dir>

No

in | out | both.

--depth <n>

No

1 | 2.

--limit <n>

No

Max neighbours to return (server default 100, clamps at 500).

--branch <name>

No

Answer from a specific indexed branch.

--format <fmt>

No

yaml (default) | md | json.

Underlying route: GET /api/v1/code/{project_id}/graph.

A project that has no attached repository at all — including another brand's project, or a project id that does not exist — returns 404 index not found.

Errors:

Error

When

Resolution

Error: Token missing required scope: code:read (exit 1)

The token was approved without code:read.

Request a new token with --scopes …,code:read.

Error: index not found (HTTP 404, exit 1)

An unknown node, no ready index, no attached repository, or another brand's project.

Resolve the node with opvs code resolve first; check opvs code tree for indexed.

Validation error, HTTP 422 (exit 1)

--depth is not 1 or 2, or --direction is not in, out or both.

Use one of the listed values.


opvs code graph folders [dir]

Requires @opvs-ai/cli 0.26.0 or later.

The import map of one directory, rolled up to folders: which folders import which, which files are the hubs (most imported, most importing), and how many pairs of files import each other. It is the same read the dashboard's Graph overview draws. Edges are imports only (Python and TypeScript / JavaScript); there are no call edges and no Go import edges.

dir is repo-relative and defaults to ., the repository root. Deeper files fold into their folder at --depth levels below dir.

opvs code graph folders src/payments \
    --project 9d7642c4-8151-4c3e-977e-9f30d5a52844 \
    --depth 2 --limit 100 --format json
# → indexed: true; dir: src/payments; depth: 2;
#   folders[] (path, node_id, files_on_edges, imports_inside, parsed, regex);
#   links[] (src, dst, imports, parsed);
#   hubs.in_degree[] and hubs.out_degree[] (path, node_id, imports);
#   mutual_import_pairs: 2; truncated: false; limit_clamped: false; effective_limit: 100
# → indexed: false with empty lists when the project has no ready index
# → exit 1 "Error: dir must be repo-relative: '../other'" for a path outside the repository

Option

Required

Description

--project <id>

Yes

Project id.

[dir]

No

Repo-relative directory to roll up. Default ..

--depth <1-10>

No

Folder levels below dir (server default 2).

--limit <n>

No

Max folder rows and cross-folder link rows (server default 250, clamps at 500).

--branch <name>

No

Answer from a specific indexed branch.

--format <fmt>

No

yaml (default) | md | json.

Underlying route: GET /api/v1/code/{project_id}/graph/folders.

Unlike graph, this command never answers 404 for a project: another brand's project, an id that does not exist and a project with no ready index all print indexed: false, so read indexed before reading any count.

Errors

Error

When

Resolution

Error: Token missing required scope: code:read (exit 1)

The token was approved without code:read.

Request a new token with --scopes …,code:read.

dir must be repo-relative (exit 1)

dir starts with / or contains a .. segment.

Pass a path relative to the repository root, or ..

A validation error from the server (HTTP 422, exit 1)

--depth is outside 1 to 10, or --limit is below 1.

Use a value inside the range.

error: required option '--project <id>' not specified

--project was left out.

Pass the project id.


opvs code callers <anchors...>

Requires @opvs-ai/cli 0.27.0 or later. Use 0.27.9 or later: it separates calls from other files from calls inside the file, and earlier versions can misreport both.

Who calls this function? Name up to 50 files or symbols. The command resolves each anchor, then asks the code index (POST /api/v1/code/{project_id}/callers) for its callers and the test files near it. A leading ./ is fine.

Three limits hold for every answer. The first line says which commit answered, because the index is as old as its last commit. A [heuristic] caller may be wrong. A test hint is not coverage: it is a test file that imports this file, and it does not say that any test runs this function.

Calls come from Python files only. For any other language the answer reads UNKNOWN, not zero.

This command has no yaml or md output: it prints text, or the raw answer with --json or --format json.

opvs code callers src/payments/charge.py#charge_card src/payments/charge.py \
    --project 9d7642c4-8151-4c3e-977e-9f30d5a52844
# → index: 92f4a7d, 2 h old
# →
# → src/payments/charge.py#charge_card
# → callers: 2 (showing 2)
# →   src/api/checkout.py#create_order → charge_card [exact]
# →   src/jobs/retry.py#retry_failed → charge_card [heuristic]
# → test hints (not coverage): tests/payments/test_charge.py
# →
# → src/payments/charge.py
# → callers from other files: 2 calling symbols in other files, 3 calls shown
# →   src/api/checkout.py#create_order → charge_card [exact]
# →   src/api/refunds.py#create_refund → refund_card [exact]
# →   src/jobs/retry.py#retry_failed → charge_card [heuristic]
# → calls inside the file: 4
# → test hints (not coverage): tests/payments/test_charge.py
# → exit 1 "Error: project not found" when the project has no attached repository

On a file, calling symbols counts distinct functions and calls shown counts rows, so one function that calls two symbols here adds one to the first and two to the second. — truncated appears only when outside rows are missing from the list; raise --limit to see them.

What it prints

What it means

callers: N (showing N)

The callers of one symbol.

callers from other files: 0

The index holds calls for this file, and none comes from another file.

calls are not indexed for this repo: callers are UNKNOWN, not zero

The index stores no call edges at all.

callers: UNKNOWN (calls are not indexed for this file type)

No call edges exist for this language. Unknown, not zero.

callers: unknown (this folder is not indexed for calls: tests or vendored)

The file sits in a folder the index lists but does not read for calls.

callers: unknown (this file declares no symbols, so it has no calls to report)

An empty file, or one with only imports.

callers: per file (ask a file or symbol inside it)

The anchor is a folder.

NOT IN INDEX, MOVED → <anchor>, REMOVED

The anchor is not a live file or symbol in this index.

index: unavailable

No index answered.

Option

Required

Description

<anchors...>

Yes

Up to 50 anchors: src/a.py or src/a.py#name.

--project <id>

Yes

Project id.

--limit <n>

No

Callers per anchor, 1 to 100. Default 20.

--json

No

Print the API answer unchanged, plus unresolved_anchors.

--format <fmt>

No

text or json.

Underlying routes: POST /api/v1/code/{project_id}/nodes/resolve, then POST /api/v1/code/{project_id}/callers. Up to 10 test hints print per anchor; that number is not an option.

Errors

Error

When

Resolution

Error: too many anchors (51); max is 50 (exit 1)

More than 50 anchors.

Split the list.

Error: --limit must be an integer from 1 to 100 (exit 1)

--limit is out of range.

Pass a whole number from 1 to 100.

Error: not a uuid: 'acme' (exit 1)

--project is not a UUID.

Pass the project's id.

Error: Token missing required scope: code:read (exit 1)

The token was approved without code:read.

Request a new token with --scopes …,code:read.

Error: project not found (exit 1)

The project has no attached repository, belongs to another workspace, or does not exist.

Check the id, or attach a repository.

Warning: code index unavailable; caller information is degraded

The index could not be read. Callers are unknown, not zero.

Read the repository instead, and retry later.


opvs code check-card <brief.md>

Requires @opvs-ai/cli 0.27.1 or later. Use 0.27.9 or later, for the same reason as opvs code callers.

Are the paths in this draft card real, and what touches them? The command reads a markdown brief, finds the repository paths in it, checks each one against the code index, and prints one ## Index facts block to paste into the card before anyone starts work. A wrong path shows up as a NO row while it is still cheap to fix. The block names the commit it was checked against, because the index is as old as its last commit. Its test hints are not coverage, and a heuristic caller may be wrong.

What it reads:

  • Backticked paths, with an optional #symbol, ::symbol or :LINE, in the brief as written.

  • Nothing inside a fenced code block, and nothing after the heading

# The gate block — the last section of every builder brief.

  • At most 50 paths. Each one counts once, and the block says how many were left out.

  • A path on a line that says create, NEW or new file is declared new, so it does not have to

exist yet. Any other wording, such as add, leaves it a NO row.

opvs code check-card ./brief.md --project 9d7642c4-8151-4c3e-977e-9f30d5a52844
# → ## Index facts
# → <!-- index-facts v1 commit=92f4a7d2b1c03a8a43bda19a2cfcda16b3680c5e indexed_at=2026-10-27T09:14:02.511000+00:00 checked_at=2026-10-27T11:44:02.100Z -->
# → index: 92f4a7d, 2 h old · project 9d7642c4-8151-4c3e-977e-9f30d5a52844 · 3 paths checked
# → | Anchor | In the index | Callers | Test hints (not coverage) |
# → | --- | --- | --- | --- |
# → | `src/payments/charge.py#charge_card` | yes | 2 (1 exact, 1 heuristic): `src/api/checkout.py#create_order → charge_card`, `src/jobs/retry.py#retry_failed → charge_card` | `tests/payments/test_charge.py` |
# → | `src/payments/chrage.py` | NO — not in the index and not declared new | n/a | n/a |
# → | `src/payments/refunds.py` | no (declared new) | n/a | n/a |
# → exit 2 "CANNOT: project not found" when the project has no attached repository

The block is at most 6,000 bytes, so a long brief may show fewer rows than it checked; the block says so, and --json carries them all.

Option

Required

Description

<brief.md>

Yes

The draft brief to read.

--project <id>

Yes, or set OPVS_CODE_PROJECT

Project id.

--similar <words>

No

Add Already exists for "<words>" lines naming similar code. Repeat up to 5 times.

--strict

No

Exit 1 when a path is not in the index and not declared new.

--json

No

Print the same facts as JSON.

Exit codes: 0 whatever the check finds, 1 only with --strict, 2 when it cannot run. The check is advisory: a NO row does not fail anything unless you ask it to.

Underlying routes: POST /api/v1/code/{project_id}/nodes/resolve, then POST /api/v1/code/{project_id}/callers, and GET /api/v1/code/{project_id}/context for --similar.

Errors

Error

When

Resolution

CANNOT: project required: pass --project <id> or set OPVS_CODE_PROJECT (exit 2)

No project was named.

Pass --project, or set the variable.

CANNOT: cannot read brief: ./brief.md (exit 2)

The file does not exist or cannot be read.

Check the path.

CANNOT: --similar may be repeated at most 5 times (exit 2)

More than five --similar flags.

Drop some.

CANNOT: project not found (exit 2)

The project has no attached repository, belongs to another workspace, or does not exist.

Check the id, or attach a repository.

CANNOT: code index unavailable (exit 2)

No index answered.

Wait for the first index, or retry later.

CANNOT: Token missing required scope: code:read (exit 2)

The token was approved without code:read.

Request a new token with --scopes …,code:read.


opvs code tests-for [paths...]

Requires @opvs-ai/cli 0.27.6 or later.

Which tests can these files break? With --remote, the command asks the code index (POST /api/v1/code/{project_id}/tests-for), which walks the stored graph backwards from each file, through imports and through files a test names by path, to the test files that reach it. It needs no checkout and runs nothing. Use it on your own repository.

Without --remote, the command runs scripts/select_tests.py from the root of the checkout you are in. That script ships in the OPVS repository; in a checkout without it, the command stops and names --remote. The local answer is advisory, and it prints a line that says so.

Unlike the other opvs code commands, this one has no --format: it prints text, or the raw answer with --json. Local mode takes no --project.

opvs code tests-for src/payments/charge.py src/payments/legacy.py \
    --remote --project 9d7642c4-8151-4c3e-977e-9f30d5a52844
# → index: 92f4a7d, 2 h old
# → src/payments/charge.py
# →   tests/payments/test_charge.py  hops 1  import
# →   tests/fixtures/test_charge_amounts.py  hops 1  reads
# →   tests/api/test_checkout.py  hops 2  import → import
# → src/payments/legacy.py
# →   unknown — not a file in this index
# → exit 1 "Error: project not found" when the project has no attached repository

Each test line shows the edges walked (hops) and their kinds, from the test towards your file. When the index cannot answer in full, degraded: lines come first; read them before trusting an empty list. A path with too many tests ends with truncated (N total).

Option

Required

Description

[paths...]

With --remote

Repo-relative files to look up, at most 200. In local mode, files to add to the diff.

--remote

No

Ask the code index instead of running the local selector.

--project <id>

With --remote

Project id. Refused in local mode.

--base <ref>

No

Diff base for the local selector. Default origin/main. Refused with --remote.

--json

No

Print the API answer, or the selector's JSON, unchanged.

Underlying route: POST /api/v1/code/{project_id}/tests-for. The route's depth (default 4) and limit (default 200) are not exposed as options.

Errors

Error

When

Resolution

Error: --remote requires --project <id> (exit 2)

--remote without a project.

Pass --project <id>.

Error: --remote requires at least one path (exit 2)

--remote with no paths.

Name at least one file.

Error: --project is only used with --remote (exit 2)

--project in local mode.

Add --remote, or drop --project.

Error: not inside a git checkout, so the local selector cannot run. Use --remote --project <id> to ask the API. (exit 1)

Local mode outside a checkout.

Run it inside the checkout, or use --remote.

Error: body.paths: Value error, path must be a repo-relative file: '/etc/passwd' (exit 1)

A path is absolute or climbs out of the repository.

Pass paths relative to the repository root.

Error: Token missing required scope: code:read (exit 1)

The token was approved without code:read.

Request a new token with --scopes …,code:read.

Error: project not found (exit 1)

The project has no attached repository, belongs to another workspace, or does not exist.

Check the id, or attach a repository.


Session Commands

opvs session get --self          # Your assigned tasks across all boards
opvs session get --board <id>    # Board context
opvs session get                 # List all boards

Configuration

opvs config set format yaml       # Output format: yaml, json, md
opvs config set api_url <url>     # API URL for current workspace
opvs config get                   # Show current config
opvs config get --all             # Show all workspaces
opvs config path                  # Show config file location
opvs config reset --yes           # Reset to defaults
opvs init                         # Print CLAUDE.md snippet

Command Summary

Group

Commands

Description

auth

request, status, revoke, list

PAT token management

workspace

list, use, current, remove

Multi-workspace management

boards

list, get, create, update, delete, health, apply-preset

Board CRUD, structural audit, presets

tasks

list, get, create, update, delete, move, subtasks, search, batch-get

Full task management

agent

my-tasks, delegations, batch-create, progress, complete, delegate, mention, tasks-by

Agent-optimized workflows

stages

list, create, update, delete, reorder

Sequential task stages

links

list, create, delete

Task relationships

members

list, add, remove

Board member management

markers

list, create, get, update, delete, toggle

Color-coded task tags

board-links

list, create, update, delete

Cross-board relationships

comments

list, add

Task comments

views

session, overview, tasks, task

Agent-optimized views

activity

board, task

Activity feeds

metrics

summary, velocity, agents, costs, distribution

Board analytics

projects

list, get, create, update, set-status, archive, add-board, remove-board, tasks, bundle get, bundle set, health

Project containers + inherited bundles

scheduled-runs

list, get, create, cancel

Start a factory project at a set time

columns

list, create, update, reorder, delete

Column management

files

list, upload, download, delete

Task file attachments

docs

list, get, create, update, search + 16 more

AgentDocs documentation

session

get

Session context

config

get, set, path, reset

CLI configuration

init

Generate CLAUDE.md snippet

Environment Variables

Variable

Description

Overrides

OPVS_TOKEN

PAT token

Config file token

OPVS_API_URL

API base URL

Config file api_url

OPVS_WORKSPACE

Workspace key, brand_id or brand name — not a client_id. It is a key in your local ~/.opvs/config.json; run opvs workspace list to see them.

-w flag / current workspace

OPVS_FORMAT

Output format (yaml, json, md)

Config file format

Response Format

By default, responses use YAML format which is 40-76% more token-efficient than JSON:

opvs config set format json   # Switch to JSON
opvs config set format yaml   # Switch to YAML (default)
opvs config set format md     # Switch to Markdown
Did this answer your question?