all topics

Workflow

The Clone Iteration Workflow

Stepwise design iteration where every stage is a clean, self-contained project — and nothing is ever thrown away.

TLDR;

Most development workflows treat iteration as mutation: you open the project, make changes, commit, and the previous state survives only in git history. That works well for shipping software. It works less well for design exploration — where you want to be able to return to any prior state, run it live, compare it against a later version, and hand it to someone else as a complete, working artifact without explaining what branch to check out or what environment to configure.

The clone iteration workflow treats each significant stage as its own self-contained project. Every iteration is a full copy of the previous one — source, configuration, and Docker setup included. You move forward by cloning, cleaning, and building on top. Nothing is destroyed. Any stage can be stood up independently with one command.

For AI-assisted development with Claude Code, this workflow has a second advantage: it gives Claude a clean context at each stage. Stale memories, resolved decisions, and previous-iteration cruft don't accumulate into a context that grows noisier over time. Each clone starts lean. The signal-to-noise ratio stays high.

The Structure

Horizontal chain of five project boxes — mrworkbook1 through mrworkbook5 — connected by arrows labelled 'clone + clean'. Each box shows what was added at that stage. The current iteration is highlighted green. A note below explains that any prior stage can be stood up with docker compose up.
Each iteration is a complete, runnable project. Any stage can be stood up independently. Comparing two iterations means opening two terminal tabs — not checking out a branch.

Each project lives in its own directory with a sequential suffix:

C:\aiwork\
├── mrworkbook1\   # initial scaffold — typography, tokens, layout
├── mrworkbook2\   # first topic pages added
├── mrworkbook3\   # member auth, sign-in flow
├── mrworkbook4\   # design refinement, additional topics
└── mrworkbook5\   # current iteration — this project

Each directory is a complete, runnable copy of everything that existed at the end of the previous stage. No shared state. No symlinks. No "run this migration first." Clone it, run docker compose up, and it works.

Why Not Use Git Branches?

Git branches are the right tool for feature work and collaborative development. They are less suited to design iteration for a few reasons:

  • Standing up a prior state requires switching context. With clones, comparing two iterations means opening two terminal tabs. With branches, it means stashing work, checking out, waiting for a rebuild, checking back out, unstashing.
  • Claude Code's memory is project-scoped, not branch-scoped. Memory files, CLAUDE.md, and hook configurations are in the working directory. A new clone gets a deliberate, curated starting context. A new branch inherits everything from the current branch including anything you haven't cleaned up yet.
  • Docker container names are directory-derived. Two clones can run simultaneously (on different ports) without configuration. Two branches of the same repo share the same compose project name and will conflict.
Branches are for collaboration and history. Clones are for stages you want to be able to stand up, demo, and hand off independently.

Have it Both Ways

Each iteration clone is its own directory — mrworkbook1, mrworkbook2, and so on — all sitting inside a shared parent directory. That parent can be a git repository.

Commit the parent after each clone, with a message that captures what changed and why. The clone directories become snapshots in git history: you can see the exact state of every iteration, compare any two stages with git diff, and restore a previous one without having to remember which port it was on or what container name it used.

# Parent directory layout
aiwork/
├── mrworkbook1/    # iteration 1 — initial layout experiment
├── mrworkbook2/    # iteration 2 — added auth
├── mrworkbook3/    # iteration 3 — current
└── .git/           # parent repo — tracks all iterations as commits

This gives you the best of both approaches. The clones remain fully isolated — independent containers, independent Claude contexts, no cross-contamination between stages. But the parent repo gives you the history and recoverability of git without the branch-per-iteration constraints that break Docker naming and force you to carry forward everything you were trying to leave behind.

Step-by-Step: Starting a New Iteration

Step 1 — Stop the current project's container

Port 8080 is shared across all iterations. The previous container must be stopped before the new one can bind to it.

# In the current project directory
docker compose down

Step 2 — Clone the directory

Copy the entire project directory to the next iteration name. Use robocopy on Windows or cp -r on Unix. Do not use git clone — this is a filesystem copy, not a repository operation.

# Windows
robocopy C:\aiwork\mrworkbook5 C:\aiwork\mrworkbook6 /E /XD .git

# Unix / WSL
cp -r /aiwork/mrworkbook5 /aiwork/mrworkbook6

The /XD .git flag excludes the git directory. The new project starts with no git history — it is a clean working directory, not a fork. If you want version control inside the new iteration, initialise a fresh repository after copying.

Step 3 — Open the new project in Claude Code

# Navigate to the new directory and open Claude Code
cd C:\aiwork\mrworkbook6
claude

Claude Code scopes its memory and settings to the working directory. Opening the new project directory gives Claude a clean session context tied to the new iteration, separate from the previous one.

Two-panel diagram. Left panel labelled Carry Forward shows a green list: all source files, Dockerfile, .htaccess, settings, CLAUDE.md (trim before starting), user and feedback memory files. Right panel labelled Reset at Clone Boundary shows an orange list: delete project memories, exclude .git, prune stale CLAUDE.md notes, docker compose down on previous container.
What to carry forward and what to handle at the clone boundary. The left column copies automatically. The right column requires deliberate action before your first session.

Step 4 — Clean up carried-over memory files

If the previous project accumulated Claude Code memory files, they copied across. Some of that memory is worth keeping. Some is now stale. The rule:

.claude/memory/
├── user_*.md      → KEEP — describes you, valid across all projects
├── feedback_*.md  → KEEP — how Claude should work with you
├── reference_*.md → KEEP — pointers to external systems
└── project_*.md   → DELETE — describes the previous iteration's state
# Delete stale project memories
del .claude\memory\project_*.md        # Windows
rm .claude/memory/project_*.md         # Unix

# Then update MEMORY.md to remove the deleted entries

Step 5 — Update CLAUDE.md

CLAUDE.md is loaded at the start of every Claude Code session. After a clone, it reflects the previous iteration. Do one pass before starting any work:

  • Remove any notes specific to problems that were resolved in the last iteration
  • Update anything that describes current project state (sprint goals, known issues)
  • Add the new iteration number or stage name if you use one
  • Verify that the "how to run" section still matches the project

Keep it under 300 tokens. Anything longer is carrying context that should be in a task-specific file loaded on demand, not in the always-on project context.

Step 6 — First boot with rebuild

The first start in a new clone should always use --build to ensure the Docker image is fresh. Subsequent starts in the same iteration can use docker compose up alone.

docker compose up --build

Verify the site loads at http://localhost:8080 before starting work. A broken first boot is easier to diagnose on a clean clone than after several hours of edits.

Step 7 — Commit a baseline

If you initialised git in step 2, make a baseline commit immediately after the first successful boot. This gives you a clean rollback point before any changes in the new iteration, and a clear marker of where the stage started.

git init
git add .
git commit -m "baseline: clone from mrworkbook5"

Adding a New Topic in This Workflow

Adding topics follows the same four-file pattern regardless of which iteration you are in. The clone workflow does not change the process — it just ensures you are starting from a known-good state.

# 1. Create the topic page
cp topics/_template.php topics/<slug>.php
# Edit: $page_title, $page_subtitle, $topic_tag, $topic_accent, body content

# 2. Create the icon
# Add topics/assets/icons/<slug>.svg — 22×22 viewBox, single accent color

# 3. Register the topic
# Add entry to $topics array in includes/topics.php
# Fields: slug, name, tag, desc, glow, color, icon, new, member

# 4. Verify
# Visit http://localhost:8080 — card should appear in the grid
# Click through to the topic page — confirm it loads without error

For member-only topics, set 'member' => true in the topics array and add the session check at the top of the topic file:

// top of topics/<slug>.php for a member-only page
<?php
session_start();
if (empty($_SESSION['signed_in'])) { header('Location: /sign-in.php'); exit; }
$page_title    = '...';
// rest of page setup
Two stacked bar charts side by side. Left bar labelled Raw Clone shows a taller bar with orange sections for stale project memories and stale CLAUDE.md notes on top of green sections for valid context. Right bar labelled Cleaned Clone shows a shorter bar with only the green valid context — the orange noise has been removed, represented by a dotted empty region.
The cleaned clone doesn't just load fewer tokens — the signal quality is higher. Claude starts each session with accurate context rather than a mix of current state and resolved history.

What Stays, What Goes

The decision of what to carry forward and what to leave behind at each clone is the core discipline of this workflow. The wrong call in either direction has a cost: carry too much and the new iteration is burdened by the last one; carry too little and you rebuild things that were already working.

Always carry forward:
  [ ] All source files (PHP, CSS, JS, assets)
  [ ] Docker and Apache configuration
  [ ] CLAUDE.md (trimmed)
  [ ] user_*.md and feedback_*.md memory files
  [ ] .htaccess, settings.json, hooks

Evaluate and trim:
  [ ] CLAUDE.md — remove resolved issues, update current state
  [ ] project_*.md memory files — delete if stale, update if still live

Leave behind (do not copy):
  [ ] .git directory — start history fresh or don't use git
  [ ] Any temp files, logs, or local-only overrides

The Token Efficiency Argument

Every Claude Code session starts by loading CLAUDE.md and any relevant memory files. In a long-running project without iteration boundaries, these files accumulate: decisions that were made and then superseded, notes about bugs that were fixed, context that was true six weeks ago and is misleading now. Claude reads all of it.

The clone workflow enforces a periodic cleanup. At each iteration boundary, you make a deliberate decision about what context is worth carrying forward. The result is a CLAUDE.md that describes the project as it is right now, not as it has been through every stage of its development. Sessions start faster, stay on topic, and produce fewer responses that are confidently wrong about the current state of the codebase.

A clean CLAUDE.md at the start of a new iteration is worth more than any prompt engineering you do mid-session. It is the context that shapes every answer.

Quick Reference

New iteration checklist:
  [ ] docker compose down in the previous project
  [ ] robocopy / cp -r to new directory (exclude .git)
  [ ] Delete project_*.md from .claude/memory/
  [ ] Update MEMORY.md index to remove deleted entries
  [ ] Trim CLAUDE.md — remove stale, update current state
  [ ] docker compose up --build in new directory
  [ ] Verify site loads at localhost:8080
  [ ] git init + baseline commit (if using git)

Adding a topic checklist:
  [ ] cp topics/_template.php topics/<slug>.php
  [ ] Write content — $page_title, $page_subtitle, $topic_tag, $topic_accent, body
  [ ] Add assets/icons/<slug>.svg (22×22 viewBox)
  [ ] Add entry to $topics in includes/topics.php
  [ ] Set member => true and add session guard for private topics
  [ ] Confirm card appears on index / topics-member page
  [ ] Confirm topic page loads and reads correctly
top