Skip to content

Configuration

Toolbox config lives in two files:

Layer Path Format Scope
Global ~/.claude/toolboxes.json JSON Every repo on this machine
Per-repo .toolbox.yaml (project root) YAML This repo only, overrides global

Per-repo entries shadow global entries with the same name. Fields absent from the per-repo file fall back to the global value.

Schema

{
  "version": 1,
  "toolboxes": {
    "<name>": {
      "description": "human-readable purpose",

      // Skills to load before the trigger fires
      "pre": ["python-patterns", "docs-lookup"],

      // Agents to run after
      "post": [
        "code-reviewer",
        "security-reviewer",
        "architect-review"
      ],

      "scope": {
        // "diff" | "dynamic" | "full"
        "analysis": "dynamic",
        // Optional: restrict to these glob projects
        "projects": ["*"],
        // Optional: restrict to these file globs
        "files": ["src/**/*.py"]
      },

      "budget": {
        "max_tokens": 60000,
        "max_seconds": 180
      },

      "dedup": {
        // "fresh" = always re-run, "user-configurable" = skip
        // if same files already reviewed this session
        "policy": "user-configurable",
        "window_seconds": 3600
      },

      "trigger": {
        "slash": true,
        "session_start": false,
        "file_save": false,
        "pre_commit": true,
        "session_end": false
      },

      // If true, HIGH/CRITICAL verdicts block pre-commit
      "guardrail": true
    }
  }
}

Field reference

pre and post

  • pre — skills to load before work starts. Loaded into the session's skill manifest, unloaded when the session ends.
  • post — agents to invoke after the trigger. Each runs in its own sub-agent context window.

Either list can be empty. A toolbox with only pre is a skill preloader; one with only post is a review council.

scope.analysis

Controls what files the council sees:

Value Behavior
diff Only files with uncommitted changes. Cheapest, fastest.
dynamic Diff + import graph blast radius. Catches downstream regressions.
full Every tracked file. Most thorough; expensive — reserve for security sweeps.

budget

Enforced by council_runner. When the plan would exceed max_tokens, the runner truncates the file list; when time exceeds max_seconds, the trigger exits 0 without running remaining agents.

dedup

fresh always re-runs. user-configurable skips a council run when the same file set was reviewed within window_seconds. Dedup state lives at ~/.claude/toolbox-runs/<plan_hash>.json.

trigger

At least one trigger must be true. Multiple triggers are allowed — a ship-it toolbox typically enables slash, pre_commit, and session_end.

guardrail

When true and the trigger is pre_commit, the hook reads <plan_hash>.verdict.json after the council runs and exits 2 (blocks the commit) if level is HIGH or CRITICAL. See Verdicts & guardrails.

Editing tools

# List all toolboxes, both layers merged
ctx-toolbox list

# Show resolved config for one toolbox
ctx-toolbox show ship-it

# Activate a starter preset
ctx-toolbox activate ship-it

# Export merged config
ctx-toolbox export > my-toolboxes.yaml

# Import from file
ctx-toolbox import my-toolboxes.yaml

Validation

toolbox_config.load() validates on read:

  • version must equal 1.
  • Every toolbox needs at least one trigger.
  • scope.analysis must be one of diff, dynamic, full.
  • budget.max_tokens and budget.max_seconds must be positive ints.

Invalid entries raise ValueError with the offending key.