Skip to content

Regenerating from agentic.config.json to see what upstream changed

There is no sync service and no template remote. Regenerate a clean copy from your recorded selection, diff it against your repo, and take only the agent layer.

Next.js on Vercel4 min readships at docs/solutions/nextjs-vercel/regenerate-from-config-and-diff.md

Tags: generator · upgrades · diffing · agentic-config · maintenance

Three months after generating your repo, the boilerplate upstream has improved. Two new guard hooks. A rule that catches a mistake your team made twice. Eight new solution docs for the batteries you selected. You would like those.

What you would not like is anything touching src/, which is now 40,000 lines of your product and shares almost nothing with what was generated.

Every mechanism people reach for here makes that trade badly.

The wrong ways

Add the boilerplate as a git remote and merge. The generated repo was never a fork: it is the output of a program run with your selection. Your first commit is a squashed snapshot with no shared ancestry, so a merge is a several-hundred-file conflict in which every hunk is a manual decision.

Regenerate over the top of your repo. Some generators support this. It overwrites package.json, CLAUDE.md, .env.example and every merged file, losing the dependencies you added and the rules you wrote. You find out which ones tomorrow.

Copy files across by hand from memory. You get the three you remember and miss the two that mattered, and there is no record of what you skipped, so the next person starts from zero.

The right way: regenerate beside, diff, copy deliberately

agentic.config.json, committed at the root of your repo, records exactly what was generated: the selection, the resolved plugin ids, the layer counts, and a content hash.

{
  "version": 1,
  "selection": {
    "projectName": "acme",
    "stack": "nextjs-vercel",
    "pm": "bun",
    "batteries": ["better-auth", "neon", "prisma", "stripe"],
    "design": "editorial",
    "mode": "team",
    "targets": ["claude", "codex"],
    "admin": true
  },
  "plugins": ["nextjs-vercel", "neon", "prisma", "better-auth", "stripe", "editorial"],
  "counts": { "agents": 6, "skills": 11, "rules": 14, "hooks": 8, "solutions": 27, "mcp": 3 },
  "hash": "9f2c…"
}

Because generation is deterministic (no timestamps, no random ids, sorted keys) the same config always produces byte-identical output. That is what makes a diff meaningful: every difference is either an upstream change or a change you made. Nothing is noise.

1. Regenerate into a sibling directory

bunx create-agentic-boilerplate@latest --config ./agentic.config.json --dir ../acme-upstream

Never into your repo, never with --dir .. The point is to produce a clean reference copy to compare against.

2. Diff the agent layer only

diff -ru --new-file \
  --exclude=node_modules --exclude=.next --exclude=.git \
  ./.claude ../acme-upstream/.claude | less

diff -ru --new-file ./docs/solutions ../acme-upstream/docs/solutions

Read it in three passes: files present upstream and absent locally (new rules, hooks, docs (usually pure gain); files present locally and absent upstream (yours, keep them); files present in both and different (the only ones needing thought) did you edit it, or did upstream?).

3. Copy what is safe

PathSafe to takeWhy
.claude/hooks/Yes, unless you edited a scriptSelf-contained; verify after
.claude/rules/New files yes; changed files read firstYou may have tightened one
.claude/agents/, .claude/skills/Yes for new, read for changedSame
docs/solutions/Yes, alwaysAdditive knowledge, no behaviour
src/**NoThis is your product now
package.json, tsconfig.jsonNo: read and apply by handMerged files; you have added to them
CLAUDE.md, README.md, .env.exampleNo: apply by handSame

A copy that is genuinely safe:

# new hooks and rules only, never overwrites a file you have edited
cp -rn ../acme-upstream/.claude/hooks/. ./.claude/hooks/
cp -rn ../acme-upstream/.claude/rules/. ./.claude/rules/
cp -rn ../acme-upstream/docs/solutions/. ./docs/solutions/

cp -n never overwrites. Anything it skipped is a file that exists in both and needs a human decision: go back to the diff for those, one at a time.

4. Wire up and verify

A new hook script is inert until .claude/settings.json references it. Copy the matching entry from the upstream settings file by hand (that file is merged, so never replace it wholesale) then:

bun run verify:hooks
bun run typecheck
bun run lint
bun run test

verify:hooks is the one that matters here: it attempts each blocked action and confirms it was stopped, which is the only proof a newly copied guard is actually wired in.

5. Commit it separately

git checkout -b chore/upstream-agentic-layer
git add .claude docs/solutions
git commit -m "chore(agentic): pull upstream rules, hooks and solution docs"

One commit, nothing else in it. If a new guard turns out to be wrong for your repo, you revert one commit rather than untangling it from a feature.

Then delete ../acme-upstream. It is a scratch artefact: regenerating it again costs seconds, and keeping it around invites someone to edit the wrong copy.

Checking whether anything changed at all

The hash in agentic.config.json is a sha256 over the sorted (path, content) pairs of the generated output. Regenerate and compare:

bunx create-agentic-boilerplate@latest --config ./agentic.config.json --dir ../acme-upstream
diff <(grep '"hash"' agentic.config.json) <(grep '"hash"' ../acme-upstream/agentic.config.json) \
  && echo "identical: upstream has not changed for this selection"

Same hash, nothing to do. Worth running monthly; it takes a minute and answers the question honestly.

Two caveats

Changing the selection is not an upgrade. Adding a battery to agentic.config.json and regenerating produces files for a battery your src/ has never integrated with. Add batteries deliberately, one at a time, reading their onboarding steps, not through a diff.

Keep agentic.config.json committed and current. It is the only record of what this repo was generated from. If someone deletes it, this entire workflow stops being available, and reconstructing the selection from the file tree is guesswork.

A native --diff flag that does the compare-and-report step for you is on the roadmap. Until then the four commands above are the whole mechanism, and they work today.