Skip to content
andrew.dunn.dev

rune

Source

rune was a Rust command-line tool that managed three kinds of markdown under a project’s .claude/ directory: skills (workflow instructions an agent reads to perform a task), subagent definitions, and rules (conditional instructions scoped to a context). It worked the way a package manager works: a git repository, a registry in rune’s vocabulary, held the canonical copy; each project’s .claude/skills/, .claude/agents/ and .claude/rules/ was a synced working copy; a lockfile recorded what was installed and from where. The packages were prompts an agent read mid-session, so the tool also had to tell the agent when its copy had drifted.

rune push, the only way backCANONICALregistryone git repoPER PROJECT.claudesynced copyON EVERY WRITEhook firessame turnLOCKFILErune checkcopy vs pinnedDRIFTfour statesnamed exactly
Registry, synced copies and drift hook
  • One git registry held the skills, subagents and rules.
  • Every project carried a synced copy under .claude.
  • A hook named the drift in the same turn as the write.
  • Push was the only way back to the registry.

The lockfile is what made the check exact.

rune syncon synca write landscompared againstrune checkrune push, the only path back to the registryREGISTRYa git repositorycanonicalskills, agents, rules@version pins per itemWORKING COPYone synced copy.claude/skills, agents,and rules, per projecta commit shipped nothingLOCKFILE.claude/rune.lockper item: content hash,source registry, and theregistry-side commitPOSTTOOLUSE HOOKfires on every writeunder .claude/skills,agents, or rulesdrift in the same turnFOUR DRIFT STATESexact, not heuristicCURRENT, MISSINGDRIFTED (with direction)REGISTRY MISSING
Sync, lockfile, drift states, push
  • sync wrote the items into .claude and .claude/rune.lock: per item, the source registry, a content hash and the registry-side commit.
  • rune setup installed a Claude Code PostToolUse hook on Edit and Write; a write under .claude ran rune check on that file and handed the result to the agent as context.
  • check compared the local and registry hashes against the locked one: CURRENT, DRIFTED with a direction (local newer, registry newer, diverged), MISSING, or REGISTRY MISSING.
  • push copied the edited file into the registry’s working tree, committed there and pushed.

A git-sourced registry supported push and @version pins, resolved to a commit and enforced on every later sync, so a moved tag was a hard error; an archive-sourced one (a read-only tarball) could do neither and said so. Skills imported from third-party registries carried pedigree metadata: origin, upstream commit, whether the local copy had changed. The command surface was measured with jig, the agent-shape harness, from an agent-shape.toml in the repository.

rune managed the .claude layout and nothing else: no other runtime’s directory, no sync across runtimes.


Created Apr 2026 · Archived Jun 2026
Retrospective →