Keeping adopted packs current
Pull pack-definition changes into an already-adopted ctxgrd.toml without
losing your hand edits.
Background
pack add writes a self-contained snapshot of the pack’s namespace blocks into
ctxgrd.toml and stamps each block with a provenance comment:
# pack: [email protected] sha:a1b2c3d4
The version and content fingerprint let ctxgrd later detect two things:
- Drift – the pack’s definition has evolved since your block was generated.
- Hand edits – you have changed the block after generation (the on-disk bytes no longer match the fingerprint).
The older bare # pack: <name> form (written by binaries before 0.35.0) is
still valid. An older binary treats the @version sha: suffix as an inert
comment and keeps linting normally.
Typical workflow after a ctxgrd upgrade
1. Check for drift
ctxgrd pack outdated
Reports every block whose pack shape has evolved since it was generated. Read-only – nothing is written.
Exit codes:
0– all blocks are current.1– one or more blocks have drifted.2– config error (ctxgrd.tomlunreadable or malformed).
2. Preview the migration
ctxgrd pack migrate --dry-run
Shows what the migration would do without touching ctxgrd.toml. For each
provenance-stamped block ctxgrd determines:
- Clean block – on-disk bytes match the fingerprint. The block would be rewritten to the pack’s current shape and re-stamped.
- Dirty block – bytes differ from the fingerprint (you hand-edited it). The block would be left untouched; the diff between the on-disk block and the proposed shape is shown for you to reconcile.
For agent or CI use, request structured output:
ctxgrd pack migrate --dry-run --format json
3. Apply the migration
ctxgrd pack migrate
Rewrites every clean block in place and re-stamps its provenance. Dirty blocks are left untouched and their diffs are printed to stdout so you can reconcile them by hand (or hand the diff to an agent).
Running pack migrate a second time on an already-migrated config is a no-op.
Exit codes:
0– migration complete; no dirty blocks remain.1– migration ran but one or more dirty blocks were left for manual resolution.2– config error.
4. Resolve dirty-block diffs
For each dirty block the output shows:
- On-disk – what is currently in
ctxgrd.toml. - Proposed – what the pack’s current shape would write.
Open ctxgrd.toml and reconcile the two by hand. Common cases:
- You added a rule the new shape also includes – keep it once.
- You added a rule the new shape does not include – keep your addition, accept the structural changes around it.
- You renamed or removed a namespace section – incorporate the structural rename from the proposed block and preserve your customizations.
After editing, run ctxgrd to confirm the config lints clean, then run
ctxgrd pack outdated again – a dirty block you have fully reconciled still
shows as dirty (the fingerprint reflects the original generated bytes, not your
hand-edited version). That is expected: fingerprint-dirty blocks will always
report as drift candidates. If you want the block to be tracked as clean going
forward, delete it and re-add the pack namespace by hand or run pack add
after removing the old block.
Machine-readable output
Both commands support --format json for use in CI or agent-driven fleet
workflows:
ctxgrd pack outdated --format json
ctxgrd pack migrate --dry-run --format json
The exit-code contract (0 / 1 / 2) is stable across formats, so a script
or agent can branch on outcome without parsing text.
What migration does not do
- It does not remove namespace blocks whose
pathsglob matches no files on disk. That cleanup (e.g. a[GEMINI]block in a repo with noGEMINI.md) is a separate step not yet surfaced as a command. - It does not merge hand-edited lines into the new shape automatically. The diff is yours to resolve.
- It does not push or commit anything. Migration rewrites
ctxgrd.tomlin place; committing the result is your step.