Skip to content

v0.2.2 - Checkout Inside Another Repo Is Now Refused (guard was bypassed at the CLI layer)

Latest

Choose a tag to compare

@djdarcy djdarcy released this 25 Jul 14:22
v0.2.2
1e4ff17

dazzle-claude-config v0.2.2

Git-backed sync for your Claude Code configuration -- skills, commands, agents, hooks, and CLAUDE.md -- across every machine you work on, with credential guards on the way in and backups on every write.

A safety guard that existed, was tested, and was quietly bypassed before it ever reached you.

What's fixed in v0.2.2

A checkout inside another git repository is now refused (behavior change)

If your payload checkout was a plain folder living inside some other git repository -- a monorepo, a scratch tree, anything with a .git above it -- ccs proceeded as though it were an ordinary non-git folder. That was never safe: it meant binding to the outer repository, and it silently switched off two guarantees:

  • the verification that files collected into your payload actually reach git's index, so a stray ignore rule cannot quietly drop config from the repo
  • the refusal to apply while the checkout has unresolved merge conflicts

Neither omission was reported. You would see a normal, successful run.

ccs now stops:

ccs: not a git repository root: /path/to/checkout (inside repo /path/to/outer)
     -- ccs will not bind to a parent repository; move the checkout outside it, or `git init` it

If this affects you, either move the checkout outside the enclosing repository, or run git init inside it so it becomes its own repository. The error names both.

If it does not, nothing changes: a checkout that is already its own git repository, and a plain folder that is not inside any repository, both behave exactly as before.

The refusal had been written, tested, and documented since v0.1.0 -- the test asserted "must be refused" and passed the whole time, because it exercised the internal guard directly while the command-line layer downgraded the same condition to "this is just a plain folder." A guard is only as good as the layer that surfaces it. Found by a post-release checklist run against the published PyPI artifact; the report ships in tests/checklists/results/.

Plainer language in user-facing docs

The changelog had been describing fixes with internal shorthand -- acceptance-check IDs like A4 and A8 that map to project-private design documents no reader outside the project can open. Those entries now name each guarantee by what it does. The public test checklists, which ship for external testers, gained legend tables defining every code they use, so they stand on their own.

Everything from v0.2.1 still applies

v0.2.1 was the first public release. If you are arriving now, that is the feature set:

  • Any repo can be a payload. With a ccs-manifest.json, that file declares exactly what syncs where. Without one, ccs recognizes a repo that simply looks like a ~/.claude directory and synthesizes the manifest -- so a config folder pushed to GitHub as-is already works.
  • Secrets are structurally fenced, in both directions. A hard deny-list (.credentials.json, .claude.json, settings.local.json, plugin state, databases) overrides the manifest, and collect scans every file type for credential shapes. apply enforces the deny-list too, so a denied file committed into a payload is refused rather than installed.
  • Protected files are not drift. A file that can never sync is annotated and the run still reports clean; only credential-shaped content raises an alarm.
  • Nothing is destroyed. Every overwrite is preceded by a timestamped backup under ~/claude/backups/ccs/; removals are staged, never deleted in place; apply refuses over unresolved merge conflicts; and if your home directory is itself a git repository, ccs refuses to operate on it.
  • Output written for someone who has not read the docs, colorized on a TTY and plain when piped.

Try it against a public collection without committing to it:

git clone https://github.com/DazzleML/dazzle-claude-code-config ~/claude/dazzle-config
ccs diff  --checkout-dir ~/claude/dazzle-config    # look first
ccs apply --only dotclaude/skills --checkout-dir ~/claude/dazzle-config

apply merges into your live config rather than replacing it, and treats CLAUDE.md as seed-if-absent -- your own memory file is never clobbered.

Installation

pip install --upgrade dazzle-claude-config

Installs ccs (alias: dazzle-claude-config). Set CCS_CHECKOUT_DIR to your payload checkout and --checkout-dir becomes optional. ccs --help carries a getting-started section.

Version History (0.2.x)

Version Key Change
v0.2.2 Current -- checkout-inside-another-repo now refused instead of silently bypassing two guards
v0.2.1 First PyPI release: deny-aware apply, readable colorized output, CCS_CHECKOUT_DIR
v0.2.0 Layout-agnostic payloads: any bare ~/.claude mirror works without a manifest (tag only)
v0.1.0 MVP: collect / apply / status / diff, guard stack, backups, staged removals (tag only)

Platform Support

Platform Status
Windows 10/11 Tested -- primary development, daily use against a real config
Linux CI-tested -- full matrix; verified end-to-end on a second machine
macOS / BSD Expected -- no platform-specific code; pathlib throughout, git shelled out

CI runs Windows and Ubuntu across Python 3.10-3.13, plus a syntax check against the declared 3.10 floor.

Requirements

  • Python 3.10+ (stdlib only -- git is the sole external dependency)
  • Git

Alpha status

Working and in daily use; surfaces are not frozen. The Phase 2 set -- templated settings rendering, declarative plugin installs, and one-command ccs bootstrap onboarding -- is still landing, and command surfaces may change until it does. Please file issues for anything rough, and as with any sync tool, keep an independent copy of anything irreplaceable.

Validation: 75 automated tests across 9 CI jobs; two adversarial tester-agent runs plus a post-release checklist run against the published artifact, all reported in tests/checklists/.