Modernizing with CortexBuild¶
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.
1. Install the plugin inside a governed repo¶
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.
The recommended .claude/settings.json deny¶
The 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.
2. cortexbuild adopt¶
Run 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.
3. What cortexbuild doctor checks¶
Once 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.
4. Stage-by-stage telemetry¶
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.
5. What our gates add at brief and uplift¶
At 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.
6. After a playbook — file the lessons to the ledger¶
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.
Full procedure, in one place¶
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).
On a non-Claude host¶
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:
- Assess from what CortexBuild already has.
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. - Hand off to a Claude Code session for the plugin stages themselves, pointed at the same repo and this same guide/skill — the telemetry, plan-confirmation, and ledger obligations above apply regardless of which host originated the request.
Getting help¶
Friction with this guide? cortexbuild feedback submit --kind improvement -m
"..." — that channel is watched.