The three-copy rule
Exhaustive reference for where DOS skills, hooks, and config live — the three canonical copies and how to keep them in sync.
Every DOS skill, hook, and configuration file lives in three places at once. When you edit one, you must edit all three. Skipping any copy silently desynchronizes the system.
From Durante/CLAUDE.md:
| Location | Purpose |
|---|---|
~/.claude/skills/ | Live installation (what runs in your current session) |
Releases/v0.0.3/.claude/skills/ | Submodule tracked in cc-durante-studio, tagged per release |
Packs/*/src/ | Pack source — distributable, generic, safe to publish standalone |
<!-- brand-voice:exempt — technical invariant, not marketing claim --> Each copy serves a different audience and lifecycle. Dropping any one breaks a guarantee:
- Without
~/.claude/, you cannot test the change in a real session before committing it. - Without the submodule, the next
durante upgradeoverwrites your work with the old version. - Without
Packs/*/src/, downstream distribution regresses.
The rule in one example
Edit a skill only under ~/.claude/skills/simplify/SKILL.md. It works in your current session. Next week, someone runs durante upgrade. The upgrade clones the release, wipes ~/.claude/, restores your backups — and your edit, which never made it into the submodule, is gone. The pack source is also stale, so the next Pack publish ships the old behavior.
Edit ~/.claude/skills/simplify/SKILL.md and validate in a live session. Mirror into Releases/v0.0.3/.claude/skills/simplify/SKILL.md and commit inside the submodule. Mirror into Packs/Utilities/src/Simplify/SKILL.md. Commit the updated submodule pointer in the parent repo. Now all three stay in lockstep through upgrades and Pack publishes.
Submodule workflow
Always commit the submodule first, then the parent. The parent repo only stores a pointer to a commit inside the submodule — committing the parent first creates a dangling reference that cannot be fetched.
When all three must update
| Change | Live | Submodule | Pack |
|---|---|---|---|
Skill body / SKILL.md edit | yes | yes | yes |
| New skill file | yes | yes | yes |
Hook handler in hooks/handlers/ | yes | yes | yes |
Prompt templates under Prompts/ | yes | yes | yes |
settings.json schema-level change | yes | yes | n/a |
New tool under DOS/Tools/ | yes | yes | yes (pack src/Lib/ if pack-scoped) |
Edit just one copy and assume it will be overwritten the next time the other two sync.
When one copy is intentional
- PRDs under
MEMORY/WORK/— private work tracking for the current machine. Never mirrored. MEMORY/state — work.json, reflections, session progress, licenses. Backed up duringdurante upgradeand restored, but never committed.- Work in progress — half-written skills iterate under
~/.claude/first, then fold into the submodule and pack source when stable. - Pack documentation —
INSTALL.md,VERIFY.md, andREADME.mdinside a pack live only underPacks/*/.
Ordering in practice
- Edit under
~/.claude/and validate in a live session. - Mirror into
Releases/v0.0.3/.claude/and commit inside the submodule. - Mirror into
Packs/*/src/and commit in the parent. - Commit the updated submodule pointer in the parent repo.
The parent commit always lands last so the parent reference can never point at an unpushed submodule state.
Was this page helpful?