CLI Reference
Complete reference for all Weave CLI commands
CLI Reference
Section titled “CLI Reference”The Weave CLI is the user-facing command surface for creating, validating, and managing Weave configuration. It creates .weave configuration directories and safely hands Weave intent to supported harness installers. It does not start, supervise, or drive third-party harness runtimes.
Note: weave run is not supported. Weave configures harnesses; harnesses run themselves. Use weave init and harness-specific launch commands instead.
Installation
Section titled “Installation”Install the CLI globally with Bun. The CLI runs on Bun, not Node.js.
bun add --global @weaveio/weave-cli@0.2.0weave --versionTo run it once without installing:
bunx @weaveio/weave-cli@0.2.0 --helpPre-releases are published on the next channel (@weaveio/weave-cli@next).
Accessibility
Section titled “Accessibility”The CLI renders a colorful WEAVE banner when terminal color is supported. To disable color output:
NO_COLOR=1 weave --helpWhen color is disabled or stdout is not a TTY, output remains readable plain text.
weave init
Section titled “weave init”Creates a starter Weave config directory containing config.weave and prompts/. See the DSL Configuration guide for configuration syntax.
The starter config.weave leaves the builtin agents (Loom, Tapestry, Shuttle and the rest) exactly as they ship. It shows how to extend one with prompt_append in a comment. A project value merges over the builtin, so setting prompt on loom replaces its whole orchestration prompt.
Synopsis
Section titled “Synopsis”weave init [--scope <scope>] [--install-dir <path>] [--harness <name>] [--all-harnesses] [--force] [--yes]| Flag | Description |
|---|---|
--scope <scope> |
Target scope: global (default: ~/.weave) or local (default: <projectRoot>/.weave) |
--install-dir <path> |
Custom installation directory (overrides default scope path) |
--harness <name> |
Configure one harness: opencode, opencode2, or claude-code. See Harness detection and installation. pi is accepted but has no installer yet |
--all-harnesses |
Install for all detected supported harnesses |
--force |
Overwrite existing config.weave (creates .bak backup) |
--yes, -y |
Accept safe defaults without prompts (required for non-TTY) |
Scope defaults
Section titled “Scope defaults”| Scope | Default directory | Purpose |
|---|---|---|
global |
~/.weave |
Shared user-level defaults across projects |
local |
<projectRoot>/.weave |
Project-level configuration for the current repository |
Safety behavior
Section titled “Safety behavior”- Existing
config.weaveis skipped by default --forcewritesconfig.weave.bakbefore overwriting--yes/-yaccepts safe defaults without prompts- Non-TTY invocations do not hang; use decisive flags such as
--scopeand--yesin scripts - Prompt cancellation exits cleanly with code
0
Examples
Section titled “Examples”# Interactive local initweave init --scope local
# Non-interactive global initweave init --scope global --yes
# Custom directoryweave init --scope local --install-dir ./custom-weave --yes
# Install for specific harnessweave init --scope local --yes --harness opencode
# Install for all detected harnessesweave init --all-harnesses --yesOutput
Section titled “Output”weave init prints the files it created or skipped, what each harness installer changed, the harnesses it detected, and the next steps (edit the config, then run weave validate).
weave init migrate
Section titled “weave init migrate”Converts a legacy OpenCode JSONC config (weave-opencode.jsonc) from the @opencode_weave/weave plugin into the current .weave DSL. Migration is also offered automatically during ordinary weave init when a legacy source file is detected for the chosen scope.
For the full upgrade, including swapping the OpenCode plugin, see Upgrading from legacy Weave.
Synopsis
Section titled “Synopsis”weave init migrate [--scope <scope>] [--yes]| Flag | Description |
|---|---|
--scope <scope> |
Target scope: global or local |
--yes, -y |
Non-interactive migration (required for non-TTY) |
Entry paths
Section titled “Entry paths”Explicit migrate mode - direct invocation:
weave init migrate --scope localweave init migrate --scope globalweave init migrate --scope local --yesweave init migrate --scope global --yesOrdinary init discovery - migration is offered after scope selection when the legacy source exists:
weave init --scope local # offers migration if .opencode/weave-opencode.jsonc existsweave init --scope global # offers migration if ~/.config/opencode/weave-opencode.jsonc existsweave init --yes # auto-migrates non-interactively when legacy source is foundScope-aware legacy source paths
Section titled “Scope-aware legacy source paths”| Scope | Legacy source path |
|---|---|
local |
<projectRoot>/.opencode/weave-opencode.jsonc |
global |
~/.config/opencode/weave-opencode.jsonc |
Only .jsonc files are detected. Rename a weave-opencode.json file to weave-opencode.jsonc first; plain JSON is valid JSONC. When no legacy file exists for the scope, migration prints No legacy config found for scope "local". and exits with code 1.
Canonical migration destinations
Section titled “Canonical migration destinations”Migration always writes to the canonical Weave config paths:
| Scope | Destination |
|---|---|
local |
<projectRoot>/.weave/config.weave |
global |
~/.weave/config.weave |
Note: --install-dir is ignored in migrate mode. Migration always writes to the canonical scope destination to ensure the config loader can discover the file at runtime.
Preflight summary
Section titled “Preflight summary”Before any file is written, migration shows a preflight summary:
Migration preflight
Source: /project/.opencode/weave-opencode.jsonc Destination: /project/.weave/config.weave Scope: local Overwrite: no (destination does not exist) Skipped fields: noneWhen the destination already exists:
Migration preflight
Source: /project/.opencode/weave-opencode.jsonc Destination: /project/.weave/config.weave Scope: local Overwrite: yes - backup will be created at /project/.weave/config.weave.bak Skipped fields: 2 field(s) will be skipped with warningsSafety behavior
Section titled “Safety behavior”-
Validation before write: generated
.weaveDSL is validated through the normalparseConfig()pipeline before any file is mutated. If validation fails, migration aborts with no destination or backup written. -
Unconvertible source: when the legacy config can’t be parsed, or its structure is unsafe, migration exits with code
1before the preflight and writes nothing. Ordinaryweave initalso exits1in this case. -
No invented settings: migration never writes the starter template. When every legacy field is skipped,
config.weaveholds only the provenance comment and the skipped-field warnings. -
Overwrite backup: when the destination already exists, exactly one backup is written at
<destination>.bakbefore the destination is overwritten. -
Source preservation: the legacy JSONC source file is never renamed or deleted after successful migration.
-
Provenance comment: generated
config.weavebegins with a comment block naming the legacy source, scope, and generator, followed by any skipped fields:/project/.opencode/weave-opencode.jsonc # Migrated from legacy OpenCode JSONC config# Scope: local# Generated by: weave init migrate## Legacy fields that were not migrated:# - skill_directories: legacy skill_directories are not migrated; move or symlink those skills into a directory your harness discovers (for OpenCode, .opencode/skills/) -
JSONC parsing: comments and trailing commas in the legacy file are accepted. Comments aren’t carried into the generated DSL; only structured field values are converted. Duplicate keys, malformed input, and oversized input fail safely.
Warning semantics
Section titled “Warning semantics”Migration uses best-effort partial conversion: supported fields are written even when some legacy fields are skipped. When fields are skipped, a warning summary is printed after the success message:
⚠ Migration warnings — the following legacy fields were skipped:
• disabled_tools: legacy disabled_tools are not migrated; use tool_policy on agents or categories instead • skill_directories: legacy skill_directories are not migrated; move or symlink those skills into a directory your harness discovers (for OpenCode, .opencode/skills/) • custom_agents.code-reviewer.triggers: legacy structured triggers ({ domain, trigger }) are not migrated; add string triggers to the agent if Loom should route to it • categories.backend.patterns: patterns are removed; describe routing with category description and string triggers • workflows: legacy workflow definitions are not supported in migration v1; define workflows using the current DSL workflow syntax • custom_agents.loom: "loom" collides with a builtin agent name; skipped to avoid silently overriding the builtinThe same warnings are recorded as comments at the top of the migrated config.weave.
Exit codes:
| Exit code | When |
|---|---|
0 |
The destination was written, with or without warnings |
1 |
No legacy config was found for the scope, the legacy config couldn’t be parsed or converted (nothing is written), or the command ran without a TTY and without --yes |
Supported field conversions
Section titled “Supported field conversions”| Legacy field | Current DSL output | Notes |
|---|---|---|
disabled_agents |
disable agents [...] |
Direct mapping |
disabled_hooks |
disable hooks [...] |
Direct mapping |
disabled_skills |
disable skills [...] |
Direct mapping |
log_level |
settings { log_level <VALUE> } |
Direct mapping |
agents.<name> |
agent <name> { ... } |
Builtin override only |
custom_agents.<name> |
agent <name> { ... } |
New agent (no builtin collision) |
custom_agents.<name>.description |
description "..." |
Falls back to display_name |
custom_agents.<name>.prompt_file |
prompt_file "<name>.md" |
File copied to .weave/prompts/<name>.md |
categories.<name> |
category <name> { ... } |
Direct mapping |
model + fallback_models |
models [primary, ...fallbacks] |
Combined into array; provider/model IDs are kept |
tools |
tool_policy { ... } |
Known tools only |
Skipped with a warning: workflows, continuation, analytics, background, skill_directories, disabled_tools, tmux, experimental, agent and custom agent skills, custom agent structured triggers, category patterns, builtin override prompt and prompt_file, and any other agent, custom agent, or category field without a current equivalent (for example variant, top_p, maxTokens, modelOptions, review_models).
Ignored silently: $schema.
Agent namespace rules
Section titled “Agent namespace rules”agentsentries are treated as overrides of existing builtin agent names (loom,tapestry,shuttle,pattern,thread,spindle,weft,warp). Non-builtin names underagentsare warned and skipped.custom_agentsentries become newagent <name>blocks when the name does not collide with a builtin. Collisions are warned and skipped.categoriesbecomecategory <name>blocks. The current DSL generatesshuttle-<category>semantics automatically.
Prompt file translation
Section titled “Prompt file translation”Legacy Weave read a custom agent’s prompt_file relative to the legacy config directory (.opencode/, or ~/.config/opencode/ for the global config). Migration reads the same file and copies it to .weave/prompts/<agent>.md, which the generated prompt_file "<agent>.md" references. A different file already at that path is backed up to <file>.bak first.
- As in legacy Weave, a readable
prompt_filewins over an inlineprompt. When the file can’t be read, the inlinepromptis used instead. - Absolute paths, paths containing
.., and files that can’t be read are warned and skipped. - A custom agent left without any prompt is skipped with a warning, because harness adapters can’t register an agent without a prompt.
- Legacy Weave ignored
prompt_fileon builtin agent overrides (agents.<name>), so migration warns and skips it there, and the builtin prompt stays in effect.
Post-migration flow
Section titled “Post-migration flow”After a successful migration write, weave init migrate continues into the normal harness selection and configuration flow. This matches the behavior of ordinary weave init - migration is not a terminal command.
weave validate
Section titled “weave validate”Validates effective, scoped, or explicit Weave config. See the DSL Configuration guide for configuration syntax and structure.
Synopsis
Section titled “Synopsis”weave validate [--project | --global | --path <file>] [--json]| Flag | Description |
|---|---|
--project |
Validate ./.weave/config.weave only (syntax and schema) |
--global |
Validate ~/.weave/config.weave only (syntax and schema) |
--path <file> |
Validate specific config file |
--json |
Output machine-readable JSON |
Examples
Section titled “Examples”# Validate effective config for the current projectweave validate
# Validate project config onlyweave validate --project
# Validate global config onlyweave validate --global
# Validate specific fileweave validate --path file.weave
# JSON outputweave validate --path file.weave --jsonExpected output
Section titled “Expected output”Human-readable success output summarizes counts only:
Weave config is valid.agents: 8categories: 2workflows: 3disabled: 0log_level: INFOWith no flags, weave validate validates the effective config (builtins, global, and project merged) and also checks that every agent can be registered by the harness adapters. An agent with no prompt, a missing prompt_file, or a prompt template that references an unknown field is reported, and the command exits with code 1:
agent "reviewer" cannot be registered by harness adapters: Agent "reviewer" must define either prompt or prompt_file.agent "helper" cannot be registered by harness adapters: Failed to read prompt file for agent "helper": /project/.weave/prompts/missing.md--project, --global, and --path check a single file’s syntax and schema only.
The CLI intentionally avoids printing full private prompt/config content in normal success output. Parse and validation failures use file:line:column: message formatting where the DSL pipeline provides location data.
weave prompt
Section titled “weave prompt”Inspects composed agent prompts or lists available agent names from the effective config. See the Agents guide for information about agent roles and the Prompt Composition guide for how prompts are composed.
Synopsis
Section titled “Synopsis”weave prompt <subcommand> [--json]Subcommands
Section titled “Subcommands”weave prompt list
Section titled “weave prompt list”Prints available agent names, including generated category shuttle agents.
weave prompt listweave prompt list --jsonExpected output:
Available agents:
loom tapestry shuttle shuttle-backend shuttle-frontend pattern thread spindle weft warpweave prompt inspect <agent>
Section titled “weave prompt inspect <agent>”Renders the fully composed prompt for the requested agent.
weave prompt inspect loomweave prompt inspect loom --jsonExpected output:
Agent: loom
# Role
You are **loom**, the orchestration coordinator...
[Full composed prompt text]| Flag | Description |
|---|---|
--json |
Emit machine-readable output |
Running weave prompt without a subcommand prints inline usage and exits with code 1.
weave prompt self-modify
Section titled “weave prompt self-modify”Prints a deterministic, text-only guide that tells an agent exactly which files to read, what rules to follow, and how to verify changes when modifying Weave’s own configuration.
Synopsis
Section titled “Synopsis”weave prompt self-modify [--scope <scope>]| Flag | Description |
|---|---|
--scope <scope> |
Target scope: global (default) or local |
v1 constraints
Section titled “v1 constraints”| Constraint | Detail |
|---|---|
| Text-only output | The guide is always plain Markdown text. --json is rejected with exit code 1. |
| Scope-only tailoring | The only accepted flag is --scope global|local. No other tailoring flags are accepted. |
| Default scope: global | When --scope is omitted, the guide targets the global scope (~/.weave/). |
| No extra positional args | Any extra positional arguments after self-modify are rejected with exit code 1. |
| No config loading | The command does not load or validate the current Weave config. It prints the guide unconditionally. |
What the guide covers
Section titled “What the guide covers”The printed guide includes:
- The selected scope label (
global (~/.weave/)orlocal (.weave/)) - The canonical config file path and prompts directory path for the scope
- A pre-flight checklist naming
docs/dsl-reference.mdanddocs/config-loading.mdas required reading - A note that
docs/prompt-composition.mdmust be read before any prompt-related change - A clear statement that
packages/docs/is a public mirror, not the canonical source - the authoritative docs live indocs/at the repo root - Target-aware rules (global vs. local scope differences)
- A step-by-step workflow: identify → read DSL section → edit config → place prompt files → validate → inspect
- Common DSL patterns (override builtin, add agent, add category, disable agent)
- Prompt-specific rules (allowed Mustache context fields, mutual exclusivity of
prompt/prompt_file) - Verification commands (
weave validate,weave prompt list,weave prompt inspect)
Examples
Section titled “Examples”# Guide for global scope (default)weave prompt self-modify
# Explicit global scopeweave prompt self-modify --scope global
# Guide for project scopeweave prompt self-modify --scope localweave compose
Section titled “weave compose”Composes agent prompts with adapter-specific formatting.
Synopsis
Section titled “Synopsis”weave compose --adapter <adapter> <agent>| Flag | Description |
|---|---|
--adapter <adapter> |
Target adapter: claude-code |
Examples
Section titled “Examples”weave compose --adapter claude-code loomweave runtime
Section titled “weave runtime”Inspects runtime status and journal entries.
Synopsis
Section titled “Synopsis”weave runtime <subcommand>Subcommands
Section titled “Subcommands”weave runtime status
Section titled “weave runtime status”Shows current runtime status.
weave runtime statusExpected output:
Runtime status:
Harness: opencode Version: 1.0.0 Status: running PID: 12345weave runtime journal
Section titled “weave runtime journal”Shows recent runtime journal entries.
weave runtime journalExpected output:
Runtime journal:
2026-08-27 10:30:15 [info] Session started 2026-08-27 10:30:16 [info] Loaded config from .weave/config.weave 2026-08-27 10:30:17 [info] Agent loom initializedweave eval run
Section titled “weave eval run”Runs the agent evaluation suites. Each case gives one built-in agent a realistic task and scores what it does. Evals are a contributor tool: run them from the root of a checkout of the Weave repository, where the cases, rubrics and model matrix live. In a checkout, bun packages/cli/src/main.ts stands in for weave. For what evals measure and step-by-step recipes, see Agent Evals.
Synopsis
Section titled “Synopsis”weave eval run [--agent <suite>] [--case <id>] [--model <id> | --models default|dev] [--repeat <n>] [--track text|trajectory] [--dry-run] [--raw-artifacts]| Flag | Description |
|---|---|
--agent <suite> |
Run one suite, by suite ID or short alias |
--case <id> |
Run one case (exact case ID) |
--model <id> |
Run one model (exact ID from evals/model-matrix.json) |
--models default|dev |
Run the full default matrix (the default) or the cheap development subset |
--repeat <n> |
Run each case n times per model, 1 to 20, and report pass rates |
--track text|trajectory |
Run only the text cases or only the harness trajectory cases. Without it, both run |
--dry-run |
Validate the selection and print what would run. No model calls |
--raw-artifacts |
Write raw transcripts locally for debugging (never in CI) |
Agent suites
Section titled “Agent suites”There are eight suites. Every suite has text cases, which score a single answer. Three suites also have trajectory cases, which run a real OpenCode session in a Podman sandbox and score what the agent did: who it delegated to, which commands it ran, and whether a hidden verifier passes.
| Suite ID | Alias | What it checks | Tracks |
|---|---|---|---|
loom-routing |
loom |
Loom picks the right agent or category shuttle | text, trajectory |
tapestry-execution |
tapestry |
Tapestry executes a plan step and judges a specialist’s report | text, trajectory |
tapestry-category-routing |
tapestry |
Tapestry routes work to the right shuttle-<category> |
text |
shuttle-execution |
shuttle |
Shuttle’s completion report is honest about what it did and verified | text, trajectory |
spindle-tools |
spindle |
Spindle’s research answer cites sources and states confidence | text |
pattern-planning |
pattern |
Pattern’s plan has scope, ordered file-backed tasks and acceptance criteria | text |
weft-review |
weft |
Weft’s review verdict and blockers that cite a file | text |
warp-security |
warp |
Warp’s security verdict and evidence-backed findings | text |
The tapestry alias selects both Tapestry suites.
Models
Section titled “Models”evals/model-matrix.json is the closed set of models:
- A plain run uses every
default: truemodel: the full matrix, the setting for a baseline. --models devuses thedev: truemodels instead, at most two (currentlydeepseek/deepseek-v4-flash-0731andopenai/gpt-6-luna). This is the setting for iterating on a prompt, case or rubric.- Trajectory cases pin their own
allowed_models, so a model runs on them only if the case lists it. On the dev subset, five of the six trajectory cases run, all on DeepSeek V4 Flash.
Scoring and the judge
Section titled “Scoring and the judge”Every case is scored from 0 to 1 on routing, delegation, execution and rationale; dimensions that do not apply to a case are left out. A case passes when one of its applicable routing, delegation or execution dimensions reaches 0.95. A case its rubric does not mark required can also pass on a weighted total of 0.5 or more.
Deterministic rules score what can be read from the answer, such as the chosen route. The rest is judged by TypeSafe Jev (typesafe/jev-1.13, pinned to typesafe/jev-1.13-20260917). Jev is a judging model, not a chat model, so it is never one of the models under test and never grades its own answers. It reads the rubric, the reference and the agent’s actual answer. Every run records the judge’s ID and version in its bundle and report, and weave eval compare refuses to compare runs scored by different judges.
Required environment variable
Section titled “Required environment variable”export OPENROUTER_API_KEY=<your-key>OPENROUTER_API_KEY must be set before a live weave eval run. The runner validates it at startup and aborts immediately if absent or empty. The key value is never logged, printed, or serialized anywhere in the eval pipeline.
Exception: weave eval run --dry-run makes no model calls and does not require OPENROUTER_API_KEY.
Filter semantics
Section titled “Filter semantics”All filters use strict exact-match:
--agentmust match either the suite ID or the short alias.--modelmust exactly match a modelidinevals/model-matrix.json. No substring matching.--casemust exactly match theidfield in a case fixture file. No glob or prefix matching.--models devcannot be combined with--model, which already names the one model to run.
No filter means all values in that dimension are included. A filter that is valid on its own but leaves a suite with nothing to run (for example a --model that no case in the suite allows) fails the run with NoCasesFound. It is never reported green.
Environment variable filters
Section titled “Environment variable filters”Every flag except --dry-run and --raw-artifacts has an environment variable form, which the CI workflow uses:
WEAVE_EVAL_AGENT=loom weave eval runWEAVE_EVAL_MODEL=anthropic/claude-sonnet-4.5 weave eval runWEAVE_EVAL_MODELS=dev weave eval runWEAVE_EVAL_CASE=loom-route-backend-api weave eval runWEAVE_EVAL_REPEAT=3 weave eval runWEAVE_EVAL_TRACK=text weave eval runCLI flags and env vars are merged. Conflicting values for the same filter (CLI vs env) cause a hard DuplicateConflictingInput error. Same-value duplicates are silently collapsed. Empty env values are treated as unset.
Examples
Section titled “Examples”# Full default matrix, every suite: the baseline settingweave eval run
# Every suite on the dev subset, each case three times per modelweave eval run --models dev --repeat 3
# One suite on the dev subsetweave eval run --agent pattern --models dev
# Only the text cases (no Podman needed)weave eval run --models dev --track text
# One case on one model, with raw transcripts for diagnosisweave eval run --agent weft-review --case weft-review-traced-true-positive \ --model deepseek/deepseek-v4-flash-0731 --raw-artifacts
# Check suite, case and model names for freeweave eval run --models dev --repeat 3 --dry-runExpected output
Section titled “Expected output”A live run prints a report on stdout: one line per passing case and a block per case that did not pass, with every applicable dimension and its score. ✗ marks a score below its bar (0.95 for routing, delegation and execution; 0.70 for rationale).
Eval run b42a14b-2026-09-23-001: 1 case, 0 passed, 1 failed Bundle: …/eval-bundles/runs/b42a14b-2026-09-23-001 (local only; nothing was published)
FAIL weft-review-traced-true-positive on deepseek/deepseek-v4-flash-0731 (weft-review, required) Weighted total 0.00 (pass mark 0.50) ✗ executionCompleteness 0.00 below 0.95 ✗ rationaleQuality 0.00 below 0.70 Why: required execution case failed; dimensions: executionCompleteness, rationaleQuality Raw transcript: …/eval-bundles/runs/b42a14b-2026-09-23-001/raw/case-weft-review-traced-true-positive-deepseek_deepseek-v4-flash-0731-2026-09-23T06-01-43-182Z.jsonEach case on each model gets one verdict:
- PASS / FAIL: the case was scored. FAIL means the answer fell short of the rubric.
- ERROR: the case was not scored. The answer came back empty or truncated on every attempt, the request failed, or the judge could not answer. An errored case is never counted as a failure and is left out of pass rates.
- With
--repeat n, the verdict is a pass rate over the attempts:PASS 5/5,FLAKY 3/5orFAIL 0/5. Errored attempts are counted separately and left out of the rate.
Every run writes a sanitized bundle to eval-bundles/runs/<run-id>/ (run IDs look like <sha7>-<date>-<NNN>). It stays local. Results are published to tryweave.io/evals only from the CI workflow.
--dry-run
Section titled “--dry-run”Dry-run prints the selection and confirms no execution will occur. No model calls are made, no artifacts are written, and secrets are not required. It still performs the same input validation and suite fixture/rubric loading as a live run, so it is the cheapest way to check a command before spending anything.
weave eval run --agent weft --models dev --repeat 3 --dry-runEval dry run — no execution will occur
Agent filter: weft Model set: dev Repeats: each case 3 times per model--raw-artifacts - local-only, never CI
Section titled “--raw-artifacts - local-only, never CI”Security warning:
--raw-artifactsis rejected in CI environments (CI=true). Passing it in a CI workflow step is a hard validation error. Raw artifacts contain composed prompt text and full transcripts and must never be committed or published.
When enabled locally, one raw file per case (per attempt, with --repeat) is written to eval-bundles/runs/<runId>/raw/. It holds the composed prompt, the model’s answer, the judge’s rationale (which criteria fell short) and the runner’s diagnostics, such as the required signals it did not detect. Add this directory to .gitignore. Raw files must never be committed to any repository.
Exit codes
Section titled “Exit codes”- 0: the run completed and every selected case was scored, even when some cases failed.
- 1: the run could not measure everything it set out to: invalid input (an unknown filter,
--models devwith--model, a--repeatoutside 1 to 20), a missing API key, a filter that leaves a suite with nothing to run (NoCasesFound), any errored case (CasesErrored), or another hard failure such as a bundle write error.
weave eval compare
Section titled “weave eval compare”Compares two eval runs and says, per suite and model, whether the pass rate changed by more than the noise. It reads only the two local bundles: it makes no model calls and needs no API key.
Synopsis
Section titled “Synopsis”weave eval compare <baseline> <candidate>Each argument is a run ID (looked up under eval-bundles/runs/) or a run directory.
Expected output
Section titled “Expected output”For each suite and model it prints both pass rates with 95% intervals, the difference, and a verdict. Under each row it lists the cases whose pass rate moved. It also names each agent whose composed prompt changed (by hash) and the judge each run records.
Eval compare 86eb974-2026-09-23-001 → 1a2b3c4-2026-09-23-001 Commits: 86eb974 → 1a2b3c4 Design: 2 cases × 1 model, each case 5 times per model Judge: typesafe/jev-1.13@typesafe/jev-1.13-20260917 Prompts: 1 agent changed loom aaaaaaaaaaaa → cccccccccccc
loom-routing deepseek/deepseek-v4-flash-0731 baseline 1/10 10% [2–40%] candidate 10/10 100% [72–100%] IMPROVED (+90 points) p < 0.001, Holm-adjusted p < 0.001 Cases whose pass rate moved: loom-route-backend-api 0/5 → 5/5 (p = 0.008, unadjusted) loom-route-frontend-ui 1/5 → 5/5 (p = 0.048, unadjusted)Verdicts
Section titled “Verdicts”- IMPROVED / REGRESSED: the difference passes Fisher’s exact test after Holm adjustment across the rows (p < 0.05). Errored attempts are left out.
- no detectable change: the data cannot tell the two runs apart. It does not mean they are equal. With 25 attempts a side, a move from 60% to 80% usually goes undetected. Raise
--repeat, or include more cases, to detect smaller changes. - no detectable change: too few scored attempts: the row is too small ever to reach significance. Re-run both sides with a higher
--repeat. - not compared: one run has no scored attempt for that suite and model.
What it refuses
Section titled “What it refuses”A changed prompt is expected; that is what a comparison is for. Anything else that changes the experiment is refused:
| Refusal | When |
|---|---|
ModelSetMismatch |
The runs used different models |
CaseSetMismatch |
The runs ran different cases, or different case × model pairs |
RepeatCountMismatch |
The runs used different --repeat values |
JudgeMismatch |
Both runs record a judge and they differ |
DryRunBundle |
Either run is a dry run |
BundleNotFound, BundleUnreadable, BundleInvalid |
A run cannot be found or read |
Runs from before the judge was recorded have an unknown judge; they are compared, and the output says it assumes the same judge.
Exit codes
Section titled “Exit codes”- 0: the runs were compared, whatever the verdicts.
- 1: the comparison was refused, or the arguments were wrong (it needs exactly two runs).
The output contains only identifiers, counts, rates, p-values, short hashes and the judge ID, never prompts or answers, so it is safe in a CI log.
weave eval reindex
Section titled “weave eval reindex”For maintainers of the published results. Rebuilds every dashboard index in weave-io/weave-agent-evals from the runs published there, and uploads the index files. It never writes a run’s own files. The text run and the runtime-scenario (trajectory) run keep separate pointers: latest.json and latest-trajectory.json. tryweave.io/evals reads both.
Synopsis
Section titled “Synopsis”EVAL_RESULTS_REPO_TOKEN=$(gh auth token) weave eval reindex [--dry-run]--dry-run rebuilds the indexes locally under eval-bundles/reindex/ and uploads nothing. The command prints the runs it found and indexed, the runs it could not read and why, and the run each pointer now names. It needs EVAL_RESULTS_REPO_TOKEN with write access to the results repository, and exits 1 without it.
Harness detection and installation
Section titled “Harness detection and installation”weave init configures the harnesses you choose: the one named by --harness, every detected one with --all-harnesses, or the ones you pick in the interactive prompt. --yes on its own writes only the Weave config. A harness named with --harness is configured even if it wasn’t detected.
| Harness | What weave init does |
|---|---|
opencode (OpenCode 1.x) |
Adds @weaveio/weave-adapter-opencode@<version> to the plugin list in opencode.json / opencode.jsonc |
opencode2 (OpenCode 2) |
Adds @weaveio/weave-adapter-opencode2@<version> to the plugins list in opencode.jsonc / opencode.json |
claude-code |
Runs weave compose --adapter claude-code --init in the project, then prints the claude --plugin-dir ... launch command |
pi |
Nothing yet: Weave for Pi is not published. --harness pi exits with code 1; --all-harnesses skips it |
<version> is the adapter version released with the CLI, so weave init from @weaveio/weave-cli@0.2.0 pins 0.2.0. With --scope local the project’s config file is edited, with --scope global the one in ~/.config/opencode/. Existing entries and comments are kept, and running weave init again changes nothing.
For the OpenCode hosts, a legacy @opencode_weave/weave entry is replaced, and one config file can carry both entries: OpenCode 1.x reads plugin, OpenCode 2 reads plugins.
Detection itself is side-effect free: it checks PATH binaries, version strings, and config paths, but does not create directories, edit config, or launch harness runtimes. OpenCode 1.x is an opencode binary that reports version 1.x; OpenCode 2 is the opencode2 binary.
weave init --harness opencode2 --yes # configure one harnessweave init --all-harnesses --yes # configure every detected harness, skipping unsupported onesYou can also skip weave init and add the plugin entry yourself. See Install for OpenCode, Install for OpenCode 2, and Install for Claude Code.
Security warnings
Section titled “Security warnings”Never do any of the following:
- Commit or log
OPENROUTER_API_KEYvalues.- Commit or log
EVAL_RESULTS_REPO_TOKENvalues.- Use
--raw-artifactsin any CI workflow step.- Commit files from
eval-bundles/runs/<runId>/raw/or any file containingcomposedPromptorrawContent.- Pass raw artifacts to
ArtifactBundleWriter- all publishable output must go throughsanitizer.ts.