rune
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.
- 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.
syncwrote the items into.claudeand.claude/rune.lock: per item, the source registry, a content hash and the registry-side commit.rune setupinstalled a Claude Code PostToolUse hook onEditandWrite; a write under.clauderanrune checkon that file and handed the result to the agent as context.checkcompared the local and registry hashes against the locked one: CURRENT, DRIFTED with a direction (local newer, registry newer, diverged), MISSING, or REGISTRY MISSING.pushcopied 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.