guide

Using Spindle.

Start with a read-only intent card, try exact bytes in one disposable session, borrow only when useful, and adopt only after the runtime evidence is sound. Composition and authoring are deeper paths, not prerequisites for trying a skill.

On this page
  1. Drive it from Codex or Claude Code
  2. Inspect, try, and borrow
  3. Verify startup
  4. Adopt, update, and retire
  5. Managed distributions
  6. Bind a managed blend
  7. Work ahead: advance & liaison
  8. Build your own
  9. Evaluate a skill
  10. Policy, certification, and recovery
  11. Extending Spindle
  12. CLI reference

Drive it from Codex or Claude Code

Install Spindle from the public marketplace, then let its namespaced operator inspect and set up one small project-local operator as the ordinary control surface. The catalog name is shared, but each harness has its own marketplace manifest and commands:

bash + harness
# Codex: install once, then start a new session
$ codex plugin marketplace add lyra-forge/marketplace
$ codex plugin add spindle@lyra-forge
 $spindle:spindle set up Spindle for this repository

# Claude Code: install once, then start a new session
$ claude plugin marketplace add lyra-forge/marketplace
$ claude plugin install spindle@lyra-forge
 /spindle:spindle set up Spindle for this repository

The plugin includes the exact pinned Spindle source and a deterministic launcher, so it needs no separate Python package install. Python 3.11 or newer is required. Marketplace skills are namespaced to avoid conflicts; after project setup and a new session, use the shorter $spindle in Codex or /spindle in Claude Code.

The project-local operator reads live lifecycle state and exact command contracts from the CLI, so its prose stays small while Spindle evolves:

bash + harness
$ spindle harness setup --harness codex --here --dry-run
$ spindle harness setup --harness codex --here

# after starting a new Codex session
 $spindle show me which skills are active and why

# Claude Code uses its native slash invocation
 /spindle try this review skill once; do not adopt it

harness setup snapshots the operator's exact bytes into the Spindle cache, projects an owned symlink into .agents/skills/spindle or .claude/skills/spindle, and merges stable project startup hooks. It can bootstrap even when unrelated ambient conflicts already block strict startup; the operator then reports those conflicts rather than hiding or deleting them. The operator link points to a machine-local immutable cache and should not be committed. Review the hook configuration separately: commit it as shared project policy, or ignore it for a local-only setup.

Three separate checks harness status reports operator version/custody, hook definition, and observed hook heartbeat separately. For Codex, trust the project layer and exact command through /hooks; definition presence alone is configured-unverified. Run harness remove --dry-run to preview removal of only Spindle-owned state.

Inspect, try, and borrow

Local inspection imports nothing, runs nothing, and writes no candidate state. A remote inspection may populate only a verified provenance/source cache; it does not activate the candidate.

bash
$ spindle inspect ./candidate/review \
    --for "review this migration" --harness codex --here --json

# preview, then run one disposable read-only session
$ spindle try ./candidate/review --harness codex \
    --task-file task.md --here --dry-run
$ spindle try ./candidate/review --harness codex \
    --task-file task.md --here

# keep the exact snapshot temporarily without adopting it
$ spindle borrow ./candidate/review --harness codex \
    --until 2h --here --dry-run
$ spindle release sha256:<lease-id> --harness codex --here --dry-run

try retains startup, activation, run, and cleanup receipts but no adoption. borrow adds one exact, expiring lease over the current blend. Executable resources, network, credentials, and tool expansion are separate grants; an inspection result is never permission to execute them.

Verify startup

Use the portable pre-discovery boundary even when native hooks are available. It compares the exact surface lock with the effective harness inventory and reconciles only receipt-owned projections:

bash
$ spindle inventory --effective --harness codex --here
$ spindle bootstrap --harness codex --here --check
$ spindle bootstrap --harness codex --here --reconcile-owned
$ spindle launch codex --here --

# stable definitions; mutable pins remain in Spindle state
$ spindle hooks plan --harness codex --scope repo --here
$ spindle hooks install --harness codex --scope repo --here --dry-run
$ spindle hooks status --harness codex --scope repo --here --effective

Foreign state is inventoried and preserved. A same-name collision blocks strict startup unless an exact path-and-content decision exists. A mismatch found after discovery reports restart-required.

Adopt, update, and retire

A successful zero-exit lease can be promoted into durable maintenance custody. Updates are tested beside the incumbent and never inherit its evaluation claims:

bash
$ spindle adopt sha256:<lease-id> --scope repo --here --dry-run --json
$ spindle health --harness codex --here
$ spindle update plan --harness codex --here --json
$ spindle update try review --harness codex --task-file task.md --here
$ spindle rollback review --harness codex --reason regression --here
$ spindle retire review --harness codex --reason obsolete --here --dry-run

Rollback and status changes append decisions rather than rewrite history. Retirement removes only the current projection proven by an ownership receipt. Use vendor or distill to inspect alternate custody paths without changing adoption.

Managed distributions

Spindle also supports authored, pip-installable distributions carrying packages, doctrine, channels, and profiles. This is the composition path for a managed skill set, not a prerequisite for candidate trials:

bash
$ uv sync --extra dev

# install the reference distribution and its packages, then activate it
$ spindle dist install examples/spindle-sample/distributions/spindle-sample
$ spindle dist activate spindle-sample

# confirm what's live
$ spindle dist list
$ spindle doctrine show
$ spindle skill list
$ spindle capability list

dist install is the durable compatibility path: it installs the distribution, links its skills into Spindle's global skill surface, and records the event and ownership. Activation selects the doctrine, channels, and profiles used for managed composition. Use inspect, try, or borrow when you do not want a durable global install.

Bind a managed blend

bind classifies a repository, resolves its active distribution channels, renders the selected skills for the harness and model, checks the blend, and materializes it with exact ownership:

bash
$ spindle bind /path/to/repo --harness claude

# target a model tier (changes rendering density), or preview first
$ spindle bind /path/to/repo --harness claude --model frontier
$ spindle bind /path/to/repo --harness claude --dry-run

# see how Spindle classifies a repo without binding
$ spindle appclass /path/to/repo

# remove exactly the skills Spindle materialized
$ spindle unbind /path/to/repo --harness claude

The materialized skills land in the harness's native directory — .claude/skills/ for Claude — so the agent discovers them with no extra configuration. Useful flags: --dry-run (compute, don't write), --no-render (select only, skip profiles), and --force (materialize despite lint problems — use sparingly; it's the escape hatch past the fail-closed gate).

Work ahead: advance & liaison

Because a bind is deterministic and cached, you can do it before anyone needs it. The advance team binds every configured surface up front — from an advance/surfaces.toml or a project registry — so the common case is a warm cache, and the "extra step" is already paid.

bash
# precompute blends for every known surface
$ spindle advance run --from-registry

# capture an ad-hoc need as a demand signal (optionally bind it now)
$ spindle liaison request /path/to/repo --intent "audit accessibility" --bind
$ spindle liaison log repo

The liaison records what a surface asked for, so a recurring one-off can graduate into a precomputed skill instead of being re-derived every time.

Build your own

A package is an ordinary pip project with a [tool.spindle.package] table; a distribution is one with [tool.spindle.distribution] that depends on packages. Scaffold both:

bash
$ spindle package new my-tools --dest ./packages/my-tools \
      --skill clarify --skill review --capabilities planning

$ spindle dist new my-dist --dest ./distributions/my-dist \
      --source-dir ../../ --package my-tools==0.1.0

Author a skill

A skill is a directory with a SKILL.md: YAML frontmatter plus a short, canonical body. Keep it small; put guardrails as ALWAYS/NEVER lines so rendering will protect them:

# packages/my-tools/my_tools/skills/design/SKILL.md
---
name: design
description: Convert a clarified request into an implementation design.
---

# design

Use after the request has a clear outcome and acceptance criteria.

1. Read the relevant code and existing conventions first.
2. Propose the smallest coherent change that satisfies the outcome.
3. Name the affected files, data contracts, and tests.

ALWAYS prefer existing local patterns over new abstractions.

Declare the package

# packages/my-tools/pyproject.toml
[tool.spindle.package]
name = "my-tools"
version = "0.1.0"
distribution = "my-dist"
skills = ["clarify", "design", "review"]
capabilities = ["technical-design", "plan-review"]

[[tool.spindle.package.sources]]        # provenance, optional
peer = "upstream-lib"
url  = "https://github.com/org/upstream-lib"
transposed_at = "2026-07-11"

Write a channel

A channel decides which of your installed skills a surface receives at a given scope and harness. Place it under the distribution's source_dir at channels/<scope>/<name>/<harness>/channel.toml. The system channel is the broad default; add cluster channels for app-types and a repo channel to override a single surface.

# channels/system/system/claude/channel.toml
version = "0.1.0"
absolutes = ["A1", "A2"]
skills = ["clarify", "design", "review"]

[tiers]
review = "judgment"

Tune per surface with profiles

Add a harness profile (dialect) and a model profile (density) to change how skills render without touching their source. See Rendering for the transforms.

# profiles/codex/profile.toml
version = "1"
transform = "terse"

# profiles/models/frontier/profile.toml
version = "1"
transform = "trim"
tier = "frontier"

Evaluate a skill

Before you trust a new or edited skill, prove it helps. Write an eval.toml, point it at a runner, and gate on held-out scores:

bash
$ spindle eval validate examples/evaluation-sample/eval.toml
$ spindle eval run      examples/evaluation-sample/eval.toml
$ spindle eval show     examples/evaluation-sample/receipts/<receipt>.json

The full contract — the runner's env vars, the result JSON, and the promotion gate — is on the Evaluation page. Named-arm matrices add no-skill, invariant-core, candidate-overlay, incumbent, and ablation comparisons with explicit runtime gates:

bash
$ spindle eval matrix validate matrix.toml
$ spindle eval matrix run matrix.toml
$ spindle eval distill classify ./candidate/review
$ spindle eval distill plan ./candidate/review --json

Use spindle optimize for the older paired-edit path. Use eval distill stage for one bounded deletion proposal; staging never changes adoption.

Policy, certification, and recovery

Harness claims are tied to one build. Organization policy can restrict source providers, authority ceilings, required hooks and attestations, exact adapter builds, and certification requirements:

bash
$ spindle adapter matrix --harness codex --build 0.146.0
$ spindle adapter verify certification.json
$ spindle policy check --harness codex \
    --harness-build 0.146.0 --here --json

# deterministic custody and crash recovery
$ spindle state export spindle-state.tar.gz --dry-run --json
$ spindle state recover --json
$ spindle state gc --json
$ spindle migrate plan --harness codex --here --json

Import merges only absent or byte-identical files. Recovery rebuilds mutable indexes from immutable receipts. GC applies an exact rechecked plan over unreferenced verified cache bytes. Migration audits legacy state without adopting or deleting it.

Extending Spindle

Spindle is open-core: the compose-render-materialize-evaluate machinery and the contracts are public; the infrastructure behind them is meant to be your own. The core ships local reference sinks (JSONL files under $SPINDLE_HOME) and swaps them out through environment variables and injectable callables. Private adapters depend on Spindle — never the reverse.

SeamEnv varDefault
State rootSPINDLE_HOME~/.spindle
Active distributionSPINDLE_ACTIVE_DIST_NAME / _DIRthe activated dist
Task sinkSPINDLE_TASK_QUEUE / SPINDLE_TASK_URLlocal JSONL queue
Gate sinkSPINDLE_GATE_QUEUElocal JSONL queue
Scout runnerSPINDLE_SCOUT_COMMANDillustrative default
LLM render / proposeANTHROPIC_API_KEYabsent → those steps skip, not fail

Around the core sits an optional learning & marketplace layer — scout, peers, verdict, roster, broker, gate, ingest, fleet. Treat it as a set of extension seams: discovery passes, a judgment store, a marketplace facade, decision-gate and task queues, and cross-machine ledger sync. The public base wires the contracts and offline defaults; the live providers are yours to supply.

CLI reference

The command surface, grouped by what it touches:

AreaCommands
Distributionsdist list · show · install · uninstall · activate · new
Packages / skillspackage list · show · new · skill list · show · capability list · show
Inspect / leaseinspect · try · borrow · release · source
Harness operatorharness setup · status · context · remove
Compose / activatebind · bootstrap · launch · hooks · realize · inventory · why · diff
Maintainadopt · update plan · try · health · rollback · disable · enable · deprecate · retire
Doctrinedoctrine show · validate
Evaluate / tuneeval validate · run · show · matrix · distill · optimize · rate
Adapter / policyadapter matrix · certify · verify · policy show · check
Learn / marketpeers · verdict · roster · broker · acquisitions · scout
Infra sinksingest · gate file · from-result · fleet status · sync
Custodystate show · rebuild · export · import · recover · gc · migrate plan · apply

Run any command with --help for its flags, or read the bundle for the whole story in one file.