Skip to content
Weaveweave / docs
Get started ↗
Docs/Reference/CLI Reference

CLI Reference

Complete reference for all Weave CLI commands

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.

Install the CLI globally with Bun. The CLI runs on Bun, not Node.js.

Terminal window
bun add --global @weaveio/weave-cli@0.2.0
weave --version

To run it once without installing:

Terminal window
bunx @weaveio/weave-cli@0.2.0 --help

Pre-releases are published on the next channel (@weaveio/weave-cli@next).

The CLI renders a colorful WEAVE banner when terminal color is supported. To disable color output:

Terminal window
NO_COLOR=1 weave --help

When color is disabled or stdout is not a TTY, output remains readable plain text.


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.

Terminal window
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 Default directory Purpose
global ~/.weave Shared user-level defaults across projects
local <projectRoot>/.weave Project-level configuration for the current repository
  • Existing config.weave is skipped by default
  • --force writes config.weave.bak before overwriting
  • --yes / -y accepts safe defaults without prompts
  • Non-TTY invocations do not hang; use decisive flags such as --scope and --yes in scripts
  • Prompt cancellation exits cleanly with code 0
Terminal window
# Interactive local init
weave init --scope local
# Non-interactive global init
weave init --scope global --yes
# Custom directory
weave init --scope local --install-dir ./custom-weave --yes
# Install for specific harness
weave init --scope local --yes --harness opencode
# Install for all detected harnesses
weave init --all-harnesses --yes

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


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.

Terminal window
weave init migrate [--scope <scope>] [--yes]
Flag Description
--scope <scope> Target scope: global or local
--yes, -y Non-interactive migration (required for non-TTY)

Explicit migrate mode - direct invocation:

Terminal window
weave init migrate --scope local
weave init migrate --scope global
weave init migrate --scope local --yes
weave init migrate --scope global --yes

Ordinary init discovery - migration is offered after scope selection when the legacy source exists:

Terminal window
weave init --scope local # offers migration if .opencode/weave-opencode.jsonc exists
weave init --scope global # offers migration if ~/.config/opencode/weave-opencode.jsonc exists
weave init --yes # auto-migrates non-interactively when legacy source is found
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.

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.

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

When 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 warnings
  • Validation before write: generated .weave DSL is validated through the normal parseConfig() 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 1 before the preflight and writes nothing. Ordinary weave init also exits 1 in this case.

  • No invented settings: migration never writes the starter template. When every legacy field is skipped, config.weave holds only the provenance comment and the skipped-field warnings.

  • Overwrite backup: when the destination already exists, exactly one backup is written at <destination>.bak before the destination is overwritten.

  • Source preservation: the legacy JSONC source file is never renamed or deleted after successful migration.

  • Provenance comment: generated config.weave begins 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.

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 builtin

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

  • agents entries are treated as overrides of existing builtin agent names (loom, tapestry, shuttle, pattern, thread, spindle, weft, warp). Non-builtin names under agents are warned and skipped.
  • custom_agents entries become new agent <name> blocks when the name does not collide with a builtin. Collisions are warned and skipped.
  • categories become category <name> blocks. The current DSL generates shuttle-<category> semantics automatically.

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_file wins over an inline prompt. When the file can’t be read, the inline prompt is 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_file on builtin agent overrides (agents.<name>), so migration warns and skips it there, and the builtin prompt stays in effect.

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.


Validates effective, scoped, or explicit Weave config. See the DSL Configuration guide for configuration syntax and structure.

Terminal window
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
Terminal window
# Validate effective config for the current project
weave validate
# Validate project config only
weave validate --project
# Validate global config only
weave validate --global
# Validate specific file
weave validate --path file.weave
# JSON output
weave validate --path file.weave --json

Human-readable success output summarizes counts only:

Weave config is valid.
agents: 8
categories: 2
workflows: 3
disabled: 0
log_level: INFO

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


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.

Terminal window
weave prompt <subcommand> [--json]

Prints available agent names, including generated category shuttle agents.

Terminal window
weave prompt list
weave prompt list --json

Expected output:

Available agents:
loom
tapestry
shuttle
shuttle-backend
shuttle-frontend
pattern
thread
spindle
weft
warp

Renders the fully composed prompt for the requested agent.

Terminal window
weave prompt inspect loom
weave prompt inspect loom --json

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


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.

Terminal window
weave prompt self-modify [--scope <scope>]
Flag Description
--scope <scope> Target scope: global (default) or local
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.

The printed guide includes:

  • The selected scope label (global (~/.weave/) or local (.weave/))
  • The canonical config file path and prompts directory path for the scope
  • A pre-flight checklist naming docs/dsl-reference.md and docs/config-loading.md as required reading
  • A note that docs/prompt-composition.md must 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 in docs/ 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)
Terminal window
# Guide for global scope (default)
weave prompt self-modify
# Explicit global scope
weave prompt self-modify --scope global
# Guide for project scope
weave prompt self-modify --scope local

Composes agent prompts with adapter-specific formatting.

Terminal window
weave compose --adapter <adapter> <agent>
Flag Description
--adapter <adapter> Target adapter: claude-code
Terminal window
weave compose --adapter claude-code loom

Inspects runtime status and journal entries.

Terminal window
weave runtime <subcommand>

Shows current runtime status.

Terminal window
weave runtime status

Expected output:

Runtime status:
Harness: opencode
Version: 1.0.0
Status: running
PID: 12345

Shows recent runtime journal entries.

Terminal window
weave runtime journal

Expected 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 initialized

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.

Terminal window
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)

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.

evals/model-matrix.json is the closed set of models:

  • A plain run uses every default: true model: the full matrix, the setting for a baseline.
  • --models dev uses the dev: true models instead, at most two (currently deepseek/deepseek-v4-flash-0731 and openai/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.

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.

Terminal window
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.

All filters use strict exact-match:

  • --agent must match either the suite ID or the short alias.
  • --model must exactly match a model id in evals/model-matrix.json. No substring matching.
  • --case must exactly match the id field in a case fixture file. No glob or prefix matching.
  • --models dev cannot 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.

Every flag except --dry-run and --raw-artifacts has an environment variable form, which the CI workflow uses:

Terminal window
WEAVE_EVAL_AGENT=loom weave eval run
WEAVE_EVAL_MODEL=anthropic/claude-sonnet-4.5 weave eval run
WEAVE_EVAL_MODELS=dev weave eval run
WEAVE_EVAL_CASE=loom-route-backend-api weave eval run
WEAVE_EVAL_REPEAT=3 weave eval run
WEAVE_EVAL_TRACK=text weave eval run

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

Terminal window
# Full default matrix, every suite: the baseline setting
weave eval run
# Every suite on the dev subset, each case three times per model
weave eval run --models dev --repeat 3
# One suite on the dev subset
weave 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 diagnosis
weave 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 free
weave eval run --models dev --repeat 3 --dry-run

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

Each 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/5 or FAIL 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 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.

Terminal window
weave eval run --agent weft --models dev --repeat 3 --dry-run
Eval dry run — no execution will occur
Agent filter: weft
Model set: dev
Repeats: each case 3 times per model

Security warning: --raw-artifacts is 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.

  • 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 dev with --model, a --repeat outside 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.

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.

Terminal window
weave eval compare <baseline> <candidate>

Each argument is a run ID (looked up under eval-bundles/runs/) or a run directory.

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)
  • 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.

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.

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


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.

Terminal window
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.


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.

Terminal window
weave init --harness opencode2 --yes # configure one harness
weave init --all-harnesses --yes # configure every detected harness, skipping unsupported ones

You can also skip weave init and add the plugin entry yourself. See Install for OpenCode, Install for OpenCode 2, and Install for Claude Code.


Never do any of the following:

  • Commit or log OPENROUTER_API_KEY values.
  • Commit or log EVAL_RESULTS_REPO_TOKEN values.
  • Use --raw-artifacts in any CI workflow step.
  • Commit files from eval-bundles/runs/<runId>/raw/ or any file containing composedPrompt or rawContent.
  • Pass raw artifacts to ArtifactBundleWriter - all publishable output must go through sanitizer.ts.