Article · Apr 28, 2026

How I document AI-built projects: a CLAUDE.md, ISSUES.md, and prompts/ workflow

Four files that fix the missing context in AI-built codebases: CLAUDE.md, ISSUES.md, a prompts/ folder, and a two-AI handoff workflow.

If you have inherited a Lovable, Cursor, or Claude Code project and the codebase looks fine but feels haunted, you are not alone. Bugs surface that nobody understands, AI suggestions keep violating rules nobody wrote down, and the only people who could explain why a pattern exists are a stateless model from six weeks ago and a founder who pasted prompts at midnight. The fix is not more tests. It is the four documents that should already have been in the repo.

Why the normal recovery moves fail on AI-built code

In an ordinary codebase, when you hit a confusing pattern you have three ways to recover the why. You read the commit message that introduced the change. If that is thin, you pull up the PR description. If that is also thin, you ask the original author on Slack.

AI-built codebases break all three at once.

The commits are mechanical: “Update dashboard layout.” “Add auth flow.” Generic verbs because the AI tool generated them with the same template every time. The PR descriptions, where they exist, restate the diff. They tell you what changed, not why this pattern over the alternative the model considered. And there is no author on Slack, because the conversation was either thrown away or buried in a tool nobody opens, and even if you find it, the model that wrote the code is no longer the same checkpoint available today.

The fix is to reconstruct the missing context as you go, in the repo, in a form that survives the next time someone needs it.

1. ISSUES.md as a learning log, not a status board

ISSUES.md: a flat markdown file at the repo root, version-controlled alongside the code. One entry per bug, grep-able from the command line. Not a Linear board. Not a GitHub Projects view.

The first file I add to any inherited repo is ISSUES.md. Every bug, every weird behaviour, every “why does this happen on Tuesdays” gets an entry with four parts:

## #017 · Webhook payload nested one level deeper

**Repro**
Trigger the form submission. Inspect the workflow run. Note that
every field arrives as `undefined`.

**Root cause**
The provider wrapped the payload. Yesterday it returned `data`.
Today it returns `{ data: { ... } }`. The downstream code reads
the top level.

**Fix reasoning**
Read from `payload.data.*`. Add a shape check at ingest so the
next provider change crashes loud, not silent.

**Related**
Surfaces #009 (similar shape mismatch on the Stripe webhook).

The format is not the point. The Fix reasoning line is what earns the file’s keep, because three months from now when an analogous bug shows up at a different ingest point, the same reasoning applies and you can find it with grep -i 'shape mismatch' ISSUES.md.

On one active project, this file holds 78 closed entries. The Related lines between them form a dependency graph: when entry #017’s fix re-broke entry #009, the link was already in the file. The next person who reads the new bug walks straight to the old one.

2. The prompts/ folder

prompts/: a directory at the repo root containing one markdown file per non-trivial AI instruction. Named <id>-<topic>.md. Records intent, not output.

Every non-trivial instruction gets saved before I run it. Each file captures:

  • The intent. What I am trying to change, in one sentence.
  • The constraints. What the AI must not break: other features, schema invariants, public contracts.
  • The files in scope. A short list. If the change is a refactor, the boundary is named explicitly.
  • The failure modes I expect on the first attempt. Written before running the prompt. The act of writing them surfaces edge cases I would otherwise hit by accident.

What stays out: anything that would let a future reader rerun the prompt verbatim and expect the same diff. The goal is not reproducibility. It is traceability.

On that same project, this folder holds 17 files covering the last six weeks of substantive work. Most are under 50 lines. Their value is as the only documentation that captures the half-decision, the half-spec, the moment when the work was still negotiable. That window closes the moment the diff merges.

3. CLAUDE.md at the repo root

CLAUDE.md: a file at the repo root that Claude Code reads automatically at the start of every session. It turns a stateless model into a collaborator that knows the project’s rules.

The single rule that every CLAUDE.md guide converges on: keep it under 80 lines. Longer than that, and Claude starts discounting the sections that come last. I keep mine to four sections in a fixed order.

Commands

How to run, test, lint, build. Exact strings, copy-paste ready: npm run dev, npm run build, npm run test. If there is a non-obvious env var, name it. If a deploy step requires a secret, point to where it lives.

This section is first because ninety percent of “the AI suggested something that broke our setup” mistakes happen when the AI guesses at the command and gets it half right.

Architecture

The handful of patterns this codebase actually uses. Naming conventions, layering, where data flows in and out. Three to five paragraphs, not exhaustive. The point is to give Claude the right priors so its first guess about where to put new code matches yours.

Guardrails

Hard rules. Imperative voice. No hedging.

Never write to production directly. Always use the typed client. Never bypass row-level security. Never delete data without a confirmation prompt.

A guardrail with the word “usually” in it is not a guardrail.

What not to touch

The fragile corners. Migration scripts that have run once and must not run again. Payment paths that are audited. Webhook signature verification. Anything whose blast radius is larger than the line you would change.

Naming these explicitly is the cheapest insurance the project has. Without this file, AI suggestions are plausible-looking and routinely violate project rules. With it, the hit rate on first-try prompts climbs and the wasted-prompt count drops.

4. The two-AI, one-referee workflow

The fourth piece is a workflow, not a file. Claude Code plans, audits, documents, and reviews. Lovable (or Cursor, or Bolt) ships the actual edits. I approve every handoff.

The split exists because the tools are good at different things:

  • Claude Code reads a repo end-to-end, compares approaches, flags risks, and writes the surrounding documentation. It is slow at the rapid scaffold of a new component or a UI tweak that needs to land in five minutes.
  • Lovable / Cursor / Bolt ship visible UI changes quickly and agree to almost any change you ask for. They rarely refuse on their own, and they do not read CLAUDE.md.

If you let either run alone, the failure mode is predictable. Claude Code alone will reason for ten minutes about a change that should have taken thirty seconds to scaffold. Lovable alone will ship something that violates a rule the project established a month ago.

The pattern is: plan, approve, ship, review, document.

  1. Claude Code plans the change. Plain English diff, files it intends to touch, risks surfaced.
  2. I read the plan and approve, push back, or rewrite it. The human referee step.
  3. Lovable ships the approved plan. The diff lands in the preview branch.
  4. Claude Code reviews the diff against the plan, updates CLAUDE.md, ISSUES.md, and the prompts folder, and writes the commit message.
  5. I merge.

Without step 2, the two tools will agree to changes neither of them should be confident about. The result passes tests and breaks in production.

Which document are you missing?

The four pieces are not interchangeable, and no combination of three is sufficient.

A prompts/ folder without a CLAUDE.md is a graveyard: the prompts assume context the AI doesn’t have at session start. A CLAUDE.md without an ISSUES.md goes silently out of date, because nothing in the workflow forces it to absorb what the project just learned. An ISSUES.md without the two-AI referee step fills up with regressions, because there is no checkpoint that asks “is this a class of bug we’ve seen before?” before the diff lands.

Not tests. Not types. The connective tissue between the work that has happened and the work that is about to happen.

If you are a SaaS founder or product team across North America, the UK and Ireland, the EU and EEA, or the ANZ region, and you have inherited an AI-built project that needs this scaffolding installed properly, let’s talk. The four-part system above is what gets installed on day one of every engagement.

Frequently asked questions

How do I document an AI-built project I just inherited?

Install four documents in the repo on day one. An ISSUES.md learning log at the root, with one entry per bug containing repro, root cause, fix reasoning, and a Related line. A prompts/ folder with one file per non-trivial AI instruction, capturing intent, constraints, files in scope, and likely first-attempt failure modes. A CLAUDE.md at the repo root with four sections: commands, architecture, guardrails, and what not to touch. A two-AI workflow where Claude Code plans and reviews, Lovable or Cursor ships the edits, and you act as the human referee on every handoff.

What should go in a CLAUDE.md file?

Keep CLAUDE.md under 80 lines or Claude starts ignoring parts of it. Use four sections in this order. Commands: the exact strings to run, test, lint, and build, copy-paste ready, plus any non-obvious env vars. Architecture: three to five paragraphs naming the patterns the codebase actually uses, the layering, and the data flow. Guardrails: hard rules in imperative voice with no hedging (never write to production directly, always use the typed client, never bypass row-level security). What not to touch: the fragile corners like migration scripts, payment paths, webhook signature verification, and anything load-bearing.

What is ISSUES.md and how is it different from a Linear board?

ISSUES.md is a flat markdown file at the root of the repo, version-controlled with the code, grep-able from the command line. Each entry has a numbered ID, a Repro section, a Root cause section, a Fix reasoning section, and a Related line linking other entries that surface the same class of bug. Unlike a Linear board, ISSUES.md travels with the code, so the next person who reads a similar bug walks straight to the dependency graph in the file. It is a learning log, not a status board. The Fix reasoning line is what earns the file its keep months later.

Why use both Claude Code and Lovable or Cursor on the same project?

The two tools are good at different things. Claude Code reasons over a repo end-to-end, compares approaches, flags risks, and writes the surrounding documentation, but it is slow at scaffolding new UI. Lovable and Cursor ship visible UI changes quickly but rarely refuse a change on their own and will happily violate a rule in your CLAUDE.md. The pattern is: plan, approve, ship, review, document. Claude Code plans and reviews. Lovable or Cursor ships. You approve every handoff. The split prevents either tool's blind spot from reaching production.

How long should a CLAUDE.md file be?

Under 80 lines. Claude reads the whole file at session start, but attention degrades on longer context windows in practice. If your CLAUDE.md is 200 lines, the guardrails at the bottom are getting less weight than the commands at the top. Four tight sections, imperative voice, no prose padding. If a rule needs a paragraph of justification to feel credible, that justification belongs in a separate ADR (architecture decision record), not in CLAUDE.md.

What goes in the prompts/ folder?

One file per non-trivial AI instruction, named with an ID and a topic (e.g. 014-auth-refactor.md). Each file captures four things: the intent in one sentence, the constraints the AI must not violate, the files in scope, and the failure modes you expect on the first attempt. That last field is the most valuable. Writing the likely failure modes before you run the prompt surfaces edge cases you would otherwise hit by accident. The goal is traceability, not reproducibility. Four months later, when you look at a commit and ask what you were actually trying to do, the prompt file is the answer.