Skip to content

lavallee/spindle

Repository files navigation

Spindle

Spindle composes source skills into tight, surface-specific blends.

CI License: MIT

📖 Documentation site: https://lavallee.github.io/spindle/ — the rationale, how it works, the evaluation model, and a practical guide. Machine-readable surface for agents: llms.txt and a single-file bundle.md.

Why

Agent "skills" — the reusable instruction files a coding agent loads to do a job well — multiply fast. The instinct is to install every useful skill globally so it's always available. That instinct is right; the result is not. A global pile is never vetted as a set: it spends context budget on skills the repo will never use, combines skills from different authors in ways no author tested (a "pidgin"), pushes each skill toward one-size-fits-all bloat, ignores that different surfaces want different skills phrased differently, and lets guardrails erode.

Spindle keeps each skill small and canonical and puts coherence at the composition layer. It resolves a tight subset per surface, renders it for the target harness and model, checks it before anything lands — and, separately, proves a skill actually improves behavior rather than merely being present. One command does it:

spindle bind /path/to/repo --harness claude
# classify → select → resolve → render → lint → materialize → record  (fails closed)

See the rationale for the full argument, including why that extra step pays for itself.

Quick start

uv sync --extra dev

spindle dist install examples/spindle-sample/distributions/spindle-sample
spindle dist activate spindle-sample

spindle doctrine show
spindle skill list
spindle bind /path/to/repo --harness claude

spindle bind classifies the target repo, selects the channels it subscribes to, resolves them into one blend, renders through the active harness/model profiles, lints the blend for coherence, and materializes the selected skills into the surface's harness-native skills directory (.claude/skills/, .agents/skills/, …).

Harnesses

Most harnesses discover project skills repo-locally, so bind symlinks into a directory inside the target repo:

Harness Materialization target
claude <repo>/.claude/skills/
codex <repo>/.agents/skills/
pi <repo>/.pi/skills/
hermes ~/.hermes/skills/spindle/ (global)

Hermes

Hermes only discovers skills by recursively walking its global ~/.hermes/skills/ tree (following symlinks); it does not read repo-local .hermes/skills directories. spindle bind <repo> --harness hermes therefore symlinks the blend into a dedicated, spindle-owned category directory — ~/.hermes/skills/spindle/ by default, overridable with SPINDLE_HERMES_SKILLS_DIR — so hand-curated Hermes categories are never touched. The repo argument still names the binding surface; only the target directory is global, and reconcile/unbind semantics are identical to the other harnesses (only spindle-owned symlinks are ever removed).

Caveat: because the target is one shared directory, skills from different surfaces bound with --harness hermes share a namespace there. And there is no hermes dialect profile yet — skills land in their claude-reference dialect; rendering/profile transforms for hermes are future work.

Concepts

Term Meaning
package A pip-installable project that declares skills and capabilities in [tool.spindle.package].
distribution A pip-installable bundle that declares [tool.spindle.distribution] and depends on packages.
channel A versioned (scope × harness) manifest listing the skills a surface should receive.
surface A repo or agent that consumes a skill blend.
profile A harness/model renderer such as identity, terse, or trim.
blend The resolved skill subset for a surface, plus the absolutes in force.
doctrine The versioned first-principles set (preferences, absolutes, meta-principles) skills are checked against.

Full walkthrough of the data model and the pipeline: How it works.

Reference layout

examples/spindle-sample/
  packages/sample-planning/              # [tool.spindle.package]
  distributions/spindle-sample/          # [tool.spindle.distribution]
  channels/system/system/claude/         # sample channel
  profiles/                              # harness/model render profiles
  doctrine/                              # minimal doctrine used by lint/render
  peers/ verdicts/ scout/ roster/        # optional learning/marketplace scaffolds

Build your own

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

Spindle discovers installed packages through [tool.spindle.package] metadata and installed distributions through [tool.spindle.distribution]. The guide covers authoring skills, writing channels, and tuning per-surface profiles.

Pluggable sinks

The OSS base includes local reference implementations; private infrastructure lives in separate adapter packages that depend on Spindle rather than being imported by Spindle core.

  • spindle ingest writes a topo-ordered task queue to SPINDLE_TASK_QUEUE or $SPINDLE_HOME/tasks.jsonl unless SPINDLE_TASK_URL is set.
  • spindle gate file writes decision gates to SPINDLE_GATE_QUEUE or $SPINDLE_HOME/gates.jsonl.
  • spindle scout materializes per-peer prompts and emits commands from SPINDLE_SCOUT_COMMAND.

Behavioral evaluation

Rendering and binding prove that a skill is available, not that it improves an agent. Spindle evaluation manifests run the same cases with and without a skill, randomize pair order from a seed, and write a receipt whose promotion gate uses only held-out behavioral scores.

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 runner is an argv contract rather than a built-in model client. A local test harness or isolated executor can implement it while Spindle owns the manifest, hashes, pairing, evidence validation, and promotion decision. See Behavioral Skill Evaluations and the evaluation overview.

Documentation site

The site under docs/ is an artoo artifact (see artifact.toml). It is served by GitHub Pages directly from the /docs folder on main — no build step — so Settings → Pages → Source = Deploy from a branch, main / docs is all it needs. Edit the pages in docs/ and push.

Development

uv run --extra dev pytest

MIT licensed. Contributions welcome; see CONTRIBUTING.md. Release process and versioning: RELEASING.md.

About

Compose source skills into surface-specific blends

Topics

Resources

License

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages