A read-only agent that walks into a legacy codebase and hands you a plan to stabilize it with the least possible effort — not a rewrite proposal. Runs on Claude Code and Codex CLI.
Every senior engineer has inherited the codebase that pages them at 3am. Logan's Revenge is the diagnostician you wish you'd had: it performs deep static analysis across eight engineering lenses, scores every finding by real production risk, and tells you the smallest change that removes each defect — including which defects to leave alone.
It never edits your code. It diagnoses, and it plans. Fixing stays a human-approved step.
Most "audit" tools optimize for finding the most problems. That's the wrong objective for a legacy system that is already in production. The prime directive here is the opposite:
Stabilize the existing architecture. Minimize refactoring. Transform only when a defect genuinely cannot be removed any other way.
A working-but-ugly system left running beats a "clean" rewrite that destabilizes it. The agent is built around that belief.
Before judging anything, it reads your manifests, lockfiles, container/IaC config, and framework setup to establish the runtime, concurrency model, datastore, and deploy target. Findings are only meaningful relative to how the thing actually runs.
| Lens | Hunts for |
|---|---|
| Architecture & pattern erosion | Layer violations, God classes, circular dependencies, boundary breaches |
| Database & persistence | N+1 queries, eager-fetch cascades, transaction-scope bloat, missing indexes, Cartesian explosions |
| Performance & scalability | Unbounded materialization, single-node state that blocks horizontal scaling, hot-path waste |
| Correctness & state integrity | Races on shared mutable state, proxy/AOP self-invocation traps, swallowed exceptions |
| Systems engineering | Build/deploy health, env parity, dependency & CVE posture, secrets in source |
| Stability & resilience | Failure-mode cascades, missing timeouts/retries/breakers, observability gaps |
| Data architecture | Schema-vs-code drift, unsafe migrations, referential integrity, data lifecycle |
| Security posture | AuthZ gaps, injection surfaces, exposed secrets, reachable dependency vulns |
Each finding carries four axes:
- Risk — Critical / High / Medium / Low (likelihood × severity under real load and failure)
- Blast radius — Isolated → Module → Service-wide → Systemic
- Effort — S (one config/guard/index/annotation) / M (a few files) / L (structural, cross-cutting)
- Confidence — Verified (traced) / Likely / Speculative
Speculative findings never drive churn — they go to a separate "verify next" list.
Tier 1 — Diagnosis: every defect, grouped by lens, with the traced mechanism and the evidence.
Tier 2 — Stabilization plan, in three ranked buckets:
- A. Stabilize now — high-value, low-effort, verified. The smallest change that removes each risk.
- B. Watch / schedule — real risk, but effort or uncertainty argues for later; names the trigger that promotes it.
- C. Do-not-touch — low-risk/high-effort or long-tolerated defects where the churn is worse than the disease. Recommending inaction is a first-class outcome.
The agent's eight lenses are stack-agnostic. Concrete, idiom-level checks live in pluggable adapters:
- Java / Spring / Hibernate-JPA / Angular — JPA N+1,
FetchType.EAGERcascades,@Transactionalscope & proxy self-invocation, RxJS subscription leaks, template-method change-detection thrash, and more. - Next.js / TypeScript / Postgres / Drizzle — per-row queries in
.map, Server Action / RSC pitfalls, transaction boundaries around outbound work, missing indexes on scoped queries, in-process caches that break across instances. - Generic fallback — the eight lenses applied at the language-agnostic level for any other stack, with a note naming the adapter worth adding.
Adding an adapter is a documentation edit, not a code change — extend the appendix in the agent file.
Logan's Revenge is one portable agent definition that runs on both Claude Code and Codex CLI. Clone the repo, then run install.sh:
git clone https://github.com/loganmcleod/Logans-Revenge.git
cd Logans-Revenge
./install.sh both # Claude (global) + Codex
# or pick one:
./install.sh claude # ~/.claude/agents (every project)
./install.sh claude ~/work/legacy # per-project: <dir>/.claude/agents
./install.sh codex # ~/.codex/prompts (invoke with /logans-revenge)Claude Code. The agent is a subagent — a Markdown file with frontmatter — inheriting whatever model your session runs, restricted to read-only tools (Read, Grep, Glob, Bash).
Codex CLI. Codex has no tool-restricted subagents, so install.sh derives a prompt from the same file (frontmatter stripped) and drops it in your Codex prompts dir — $CODEX_HOME/prompts/ if set, else ~/.codex/prompts/. The filename becomes the command: type /logans-revenge in the Codex composer to run it. Read-only behavior is enforced by the agent's own contract — it never edits code — not by tooling.
The Claude agent file (.claude/agents/logans-revenge.md) is the single source of truth; the Codex prompt is generated from it, so the two never drift.
Claude, per project:
mkdir -p .claude/agents
curl -o .claude/agents/logans-revenge.md \
https://raw.githubusercontent.com/loganmcleod/Logans-Revenge/v1.1/.claude/agents/logans-revenge.mdClaude Code — invoke by name, or let it self-trigger:
- By name:
Use the logans-revenge agent to diagnose this repo and give me a stabilization plan. - Self-triggers on requests like "audit / diagnose / evaluate / triage this legacy codebase" or "how do I stabilize this?"
Codex CLI — type the slash command in the composer:
/logans-revenge diagnose the order-service module and give me a stabilization plan
Point it at a whole repo, a module, or a single subsystem. The tighter the scope, the deeper the trace.
A two-tier report. Tier 1 diagnoses; Tier 2 tells you the smallest change per fix — and what to leave alone. Trimmed example:
TIER 1 — DIAGNOSIS
### N+1 on order line items
- Lens: Database & Persistence
- File(s)/Line(s): src/orders/repo.ts:88
- Risk: High · Blast radius: Service-wide · Confidence: Verified
- Mechanism: `await` inside `.map` issues one query per line item; a 200-line
order fires 200 round-trips, saturating the pool under checkout load.
- Evidence: rows.map(async r => db.select()... ) with no batching.
TIER 2 — STABILIZATION PLAN
A. Stabilize now
- Batch the line-item fetch — Effort: S · Removes: the N+1 pool exhaustion ·
Smallest change: one `inArray(ids)` query, no schema/interface change.
C. Do-not-touch
- The 900-line OrderService god class — high effort, no active failure; splitting
it now risks more than the smell costs. Revisit only if it blocks a feature.
MIT — see LICENSE.