Public copy of this guide (no login): https://dist.cortexbuild.dev/guides/modernization.html — always the latest published version. Onboarding: https://dist.cortexbuild.dev/guides/onboarding.html
The plugin modernizes; CortexBuild proves it was done safely, measures it, and keeps the lessons.
This guide is for a repo that already has, or is about to get, Anthropic's
code-modernization plugin running against it in Claude Code — an
analysis/<system>/ artefact tree, or a legacy/<system>/ frozen-source
tree, or both. CortexBuild does not replace the plugin's commands, agents, or
Workflow scripts — those stay exactly as Anthropic ships them. What follows is
the governance CortexBuild wraps around each turn that runs one of them.
Licensed commands. Every
cortexbuildcommand below exceptauthrequires a valid licence — the same one Client Onboarding walks you through activating. If you seelicense required, runcortexbuild auth activate --key <token>and try again.
If this repo is not onboarded yet, do that first — see
Client Onboarding for the license, package install,
and PATH setup. Once cortexbuild render has run at least once, .cortexbuild/
and the rendered surfaces (CLAUDE.md, .claude/skills/, etc.) already
exist, so the plugin installs into a repo CortexBuild already governs rather
than the other way around.
Install the plugin from Anthropic's official marketplace inside Claude Code,
per Anthropic's own instructions for code-modernization. Nothing about that
install step changes under CortexBuild.
.claude/settings.json denyThe plugin recommends denying writes to its own frozen baseline. Add it (or
confirm it is present) alongside whatever CortexBuild has already rendered
into .claude/settings.json:
{
"permissions": {
"deny": ["Edit(legacy/**)", "Write(legacy/**)"]
}
}
This deny is advisory, not a guarantee — a Bash shell edit (sed -i,
git apply, a script) bypasses a permissions deny entirely, since the deny
governs the Edit/Write tools, not the shell. That is exactly why
rule-modernization-invariants (below) exists as an independent check rather
than relying on this file alone.
cortexbuild adoptRun the usual onboarding/adoption pass so CortexBuild's own analysis (harvest, debt heat-map, structural signals) is current for this repo:
cortexbuild adopt
Once an analysis/<system>/ or legacy/<system>/ directory exists on disk,
CortexBuild's structural detector fires the modernization signal on the next
cortexbuild render, which activates rule-modernization-invariants for this
repo — it renders into CLAUDE.md, AGENTS.md,
.github/copilot-instructions.md, and .cursor/rules/ alongside everything
else, the same as any other adaptive rule. A repo with no such directory never
sees this rule; it is not noise for repos that aren't running a modernization
programme.
cortexbuild doctor checksOnce legacy/<system>/ exists, cortexbuild doctor gains three checks specific
to a modernization programme, alongside its usual ones:
| Check | Catches |
|---|---|
legacy-deny-missing |
No permissions.deny entry for legacy/** in .claude/settings.json |
secrets-gitignore-missing |
No analysis/.gitignore covering SECRETS.local.md / *.local.patch |
secrets-tracked |
A SECRETS.local.md (or *.local.patch) that was force-added and is now tracked in git despite the gitignore |
Run it the same way you would on any other repo:
cortexbuild doctor
Any of the three findings above exits non-zero and names the exact fix
(.claude/settings.json deny entry to add, analysis/.gitignore to write, or
the git rm --cached command to run) — none of them require guessing what
"fix the modernization setup" means.
The plugin ships no telemetry of its own — the one thing this pack exists
to close. After every /modernize-* turn (preflight, assess, map,
extract-rules, brief, uplift, transform, reimagine, harden,
status), record which stage ran and which of the plugin's specialist agents
ran it:
cortexbuild telemetry record \
--features modernize:assess \
--agents modernization-analyst
Omit --tokens unless a meter or your host reported the count to you
(rule-telemetry-emission) — never invent one. On Claude Code the rendered
Stop hook meters the turn automatically, and this call defers to it.
<stage> in modernize:<stage> is one of preflight | assess | map |
extract-rules | brief | uplift | transform | reimagine | harden | status.
This is what lets an estate-wide view roll a repo's modernization activity up
alongside everything else CortexBuild already measures — without this line,
a whole programme's worth of work is invisible to any dashboard.
brief and upliftAt brief: the plugin's own plan-mode prompt is not, by itself, an
approval record — plan mode can be entered and exited without anyone
confirming the brief's contents. Route MODERNIZATION_BRIEF.md through the
same plan-confirmation gate every other CortexBuild-governed change goes
through (rule-plan-confirmation): a human replies "approved" / "go" (or
declines and asks for a revision), and the input artefacts the brief was built
from (PREFLIGHT.md, ASSESSMENT.md, topology.json, BUSINESS_RULES.md)
and their timestamps are named in the approval — a brief citing artefacts
older than the current PREFLIGHT.md/ASSESSMENT.md on disk is a signal the
brief was drafted against a stale analysis and assess should re-run first.
At uplift (and transform / reimagine / harden): each phase's exit
criteria, as stated in the brief and PLAYBOOK.md, are a test-evidence
obligation (rule-test-evidence) — the named tests must actually run and
their output must be captured in the same turn/PR, not just claimed. Any of
these phases that also touches a schema, a migration, or a deploy target
inherits the full existing safety stack
(rule-schema-migration-safety, rule-rollback-readiness,
rule-stale-branch-guard) exactly as it would for any other change touching
those surfaces — the modernization framing changes nothing about those
obligations.
One more thing both brief and uplift share: BUSINESS_RULES.md and
SECURITY_FINDINGS.md are LLM-generated summaries of code the plugin's own
safety note calls untrusted input. Before a later stage treats either
file's content as fact or instruction, it is worth running through the same
input guard any other untrusted text goes through — a match blocks the
later stage from acting on it, fail-closed.
Once uplift (or transform/reimagine) completes, PLAYBOOK.md carries
whatever the run actually learned. Turn each lesson into a durable guard the
next repo's programme inherits, the same way any other recurrence class does:
cortexbuild ledger add \
--id <slug> \
--title "<the lesson>" \
--class modernization
Without this step, the lesson lives only in one PLAYBOOK.md, in one repo,
until someone happens to read it again.
All of the above — the pre/post steps around every /modernize-* command, in
order — is also bundled as skill-govern-modernization, rendered into
.claude/skills/ and .github/skills/ on any repo where the modernization
signal is active. Read it if you want the step-by-step version rather than
this narrative one; it also covers what to do on a host that cannot run the
plugin's own commands (see below).
The plugin's /modernize-* commands, agents, and Workflow scripts exist only
in Claude Code — Copilot, Cursor, and Codex CLI cannot run them, and this
guide does not attempt to reproduce map / extract-rules / reimagine by
hand on those hosts. Instead:
cortexbuild adopt's
harvest output and debt heat-map are the cheap, continuous signal for
which system in an estate most needs modernizing — no plugin required to
get that signal.Friction with this guide? cortexbuild feedback submit --kind improvement -m
"..." — that channel is watched.