DEV Community

Olivia Craft
Olivia Craft

Posted on • Originally published at oliviacraft.lat

CLAUDE.md for Multi-Agent Claude Code: 11 Rules to Stop Your Agents Conflicting

If you've spent any time in the #claude-code Discord, you've seen the
same three questions every week:

  • "How do I stop two parallel Claude Code sessions from clobbering the same file?"
  • "What goes in CLAUDE.md when I have multiple agents running at once?"
  • "My subagent overwrote my main agent's work — how do I prevent this?"

The honest answer: most people are running multi-agent Claude Code with no
rules at all
. They open three terminals, point them at the same repo, hope
for the best, and lose two hours of work the first time both sessions edit
package.json.

This article gives you a CLAUDE.md you can drop in the root of your repo
today to prevent the most common failure modes. Eleven concrete rules.
Every rule has a code pattern the agent can copy-paste. Companion gist with
the full file at the bottom.

Heads up: this is a CLAUDE.md for multi-agent setups. If you only run
one Claude Code session at a time you don't need this — but you should
still steal rules 6, 8, 9, and 11 because they're useful even solo.


What "multi-agent" actually means here

Three setups all count as multi-agent and all have the same failure modes:

  1. You open multiple terminals, each running claude against the same repo. (Common: backend agent + frontend agent + test agent.)
  2. You use the Task tool inside one Claude Code session to spawn subagents that run in parallel.
  3. A CI orchestrator (or ralphy, or a cron job) launches Claude Code non-interactively, sometimes more than one job at a time.

All three break in the same ways: file collisions, log overwrites,
runaway subagents, and silent drift from the original task.


Rule 1 — Workdir isolation per agent

Every agent gets its own scratch directory. No two agents write to the same
path unless they hold a lock (rule 2).

AGENT_ID="${AGENT_ID:-$(uuidgen | cut -c1-8)}"
SCRATCH="/tmp/claude-agents/${AGENT_ID}"
mkdir -p "$SCRATCH"
cd "$SCRATCH"
echo "agent=${AGENT_ID} scratch=${SCRATCH}" >> /tmp/claude-agents/registry.log
Enter fullscreen mode Exit fullscreen mode

Rule for the agent: never write to ./tmp, ./scratch, ./out at the
repo root. Always $SCRATCH/.... This single rule prevents 80% of the
"two agents overwrote each other's intermediate files" incidents.


Rule 2 — No cross-agent file writes without a lock check

If two agents need to edit the same file in the shared repo, one of them
MUST acquire a lock first. Use filesystem-level flock so locks survive
process death.

LOCKFILE="/tmp/claude-agents/locks/$(echo "$TARGET" | tr / _).lock"
mkdir -p "$(dirname "$LOCKFILE")"

(
  flock -n 9 || { echo "LOCKED, skipping"; exit 1; }
  echo "$AGENT_ID $(date -u +%FT%TZ)" > "$LOCKFILE.owner"
  # ...do the edit...
  rm "$LOCKFILE.owner"
) 9>"$LOCKFILE"
Enter fullscreen mode Exit fullscreen mode

Rule for the agent: before any Edit or Write to a file another agent
might touch (CLAUDE.md, package.json, migrations, shared config), check
/tmp/claude-agents/locks/ and acquire flock first. Can't get the lock
in 30s? Stop and report. Do not retry forever.


Rule 3 — Shared memory is append-only

Multiple agents writing to one log file is fine if every write is an
append
, never a rewrite. Overwrites are how agent A erases agent B's
3-hour task log.

# GOOD
echo "[$(date -u +%FT%TZ)] [${AGENT_ID}] finished step 4" >> shared/agents.log

# BAD — overwrites whatever agent B just wrote
cat > shared/agents.log <<EOF
my new state
EOF
Enter fullscreen mode Exit fullscreen mode

Rule for the agent: for any file under shared/, memory/, or logs/
use >> not >. If you genuinely need to rewrite, take a lock (rule 2)
and write a .bak first.


Rule 4 — Tag every tool call with AGENT_ID

When several agents run in the same project, observability dies fast.
Tag every meaningful tool call (shell command, MCP call, HTTP request)
with AGENT_ID so the trace is greppable.

run() {
  local cmd="$*"
  echo "[$(date -u +%FT%TZ)] [${AGENT_ID}] CMD: ${cmd}" >> /tmp/claude-agents/trace.log
  eval "$cmd"
}

run git status
run npm test
Enter fullscreen mode Exit fullscreen mode

For HTTP calls, set a header:

curl -H "X-Agent-Id: ${AGENT_ID}" -H "X-Agent-Trace: ${TRACE_ID}" ...
Enter fullscreen mode Exit fullscreen mode

Rule for the agent: never run a destructive command (rm, git push,
DB write) without first logging it to /tmp/claude-agents/trace.log with
your agent id.


Rule 5 — Subagent caps: depth, timeout, retry

Spawning sub-agents is the #1 way to burn $200 of tokens in 10 minutes.
Cap it.

  • Max depth: 2 — a subagent CANNOT spawn its own subagents.
  • Per-subagent timeout: 10 minutes wall clock, then kill.
  • Retry: 1 retry on transient failure, 0 on logic failure.
  • Parallel cap: never more than 4 sibling subagents at once.
// .claude/agent-policy.json — read this at boot
{
  "max_subagent_depth": 2,
  "subagent_timeout_seconds": 600,
  "max_parallel_siblings": 4,
  "retry_on_transient": 1,
  "retry_on_logic_error": 0
}
Enter fullscreen mode Exit fullscreen mode

Rule for the agent: before spawning a subagent, read
.claude/agent-policy.json. If you're already at depth 2, do the work
yourself
instead of delegating.


Rule 6 — git status before every write

Before any Edit or Write on a tracked file, the agent runs git status
and git diff --name-only to confirm no other agent has staged or
modified that file.

TARGET="src/foo.ts"

if git diff --name-only HEAD | grep -qx "$TARGET"; then
  if [ ! -f "/tmp/claude-agents/locks/$(echo "$TARGET" | tr / _).lock.owner" ] \
     || ! grep -q "^${AGENT_ID} " "/tmp/claude-agents/locks/$(echo "$TARGET" | tr / _).lock.owner"; then
    echo "CONFLICT: ${TARGET} dirty in worktree but lock not owned by ${AGENT_ID}"
    exit 1
  fi
fi
Enter fullscreen mode Exit fullscreen mode

Rule for the agent: if you see uncommitted changes to a file you're
about to edit and you don't own the lock, stop. Do not "merge" — surface it.


Rule 7 — Nightly memory consolidation by ONE agent

Per-agent append-only logs grow forever. Once a day, a single
consolidator agent (and only one) compacts them into structured memory.

DATE=$(date -u +%F)
OUT="memory/${DATE}.md"

flock -n /tmp/claude-agents/locks/consolidate.lock -c "
  cat /tmp/claude-agents/*/trace.log \
    | grep -E '\[(WIN|FAIL|DECISION)\]' \
    | sort -u > '${OUT}'
  : > /tmp/claude-agents/*/trace.log   # truncate, do not delete
"
Enter fullscreen mode Exit fullscreen mode

Rule for the agent: never run consolidation in a worker agent. Only
the designated nightly job. Workers just append with [WIN],
[FAIL], [DECISION] tags so the consolidator can find them.


Rule 8 — Agent identity declaration at session start

Every Claude Code session opens by declaring who it is in a structured
header. This makes parallel sessions debuggable from the outside.

{
  "agent_id": "ag_a1b2c3d4",
  "role": "frontend-refactor",
  "spawned_by": "human:carla",
  "started_at": "2026-05-04T14:22:11Z",
  "scratch_dir": "/tmp/claude-agents/ag_a1b2c3d4",
  "branch": "agent/ag_a1b2c3d4/refactor-cart",
  "max_runtime_minutes": 45
}
Enter fullscreen mode Exit fullscreen mode

Rule for the agent: if AGENT_ID is not set in env, generate one
and print this header before doing any work
. No anonymous agents.


Rule 9 — Hard escalation triggers

Autonomy without escalation is a runaway. The agent stops and pings the
human under any of these:

  • 3+ consecutive tool failures with the same error class
  • About to run any of: rm -rf, git push --force, DROP TABLE, truncate, gh pr merge, payment / billing API call
  • About to write to a file outside the repo or outside $SCRATCH
  • A subagent at depth 2 returns a result the parent does not understand
  • Wall-clock runtime exceeds the value declared in rule 8
escalate() {
  local reason="$1"
  echo "[ESCALATE] ${AGENT_ID}: ${reason}" >> /tmp/claude-agents/escalations.log
  # Send to whatever channel you use — Telegram, Slack, etc.
  exit 42
}
Enter fullscreen mode Exit fullscreen mode

Rule for the agent: escalation is not a failure. Not escalating when
one of these conditions hits is a failure.


Rule 10 — Output format: structured first, prose second

When agents talk to each other (or to a parent orchestrator), prose is
unparseable. Every inter-agent message is a JSON or fenced markdown block,
never just a paragraph.

// Subagent → parent return value
{
  "agent_id": "ag_a1b2c3d4",
  "status": "completed",
  "summary": "Refactored CartProvider to use Zustand. 12 files changed.",
  "artifacts": [
    { "type": "file", "path": "src/cart/CartProvider.tsx" },
    { "type": "file", "path": "src/cart/store.ts" }
  ],
  "next_actions": [
    "Run npm test in the parent agent",
    "Open PR if tests pass"
  ],
  "warnings": []
}
Enter fullscreen mode Exit fullscreen mode

Rule for the agent: if you're reporting back to another agent, the
first thing in your output is the JSON block above. Free-text comes
after, not before.


Rule 11 — Checkpoint every N minutes

Every agent declares a max_runtime_minutes (rule 8). It is also required
to checkpoint every N minutes — write current state to its scratch
dir, flush its trace log, and ask itself: "is what I'm doing still
aligned with the original task?"

CHECKPOINT_INTERVAL=15  # minutes
LAST_CHECKPOINT=$(date +%s)

checkpoint() {
  local now=$(date +%s)
  local elapsed_min=$(( (now - LAST_CHECKPOINT) / 60 ))
  if [ "$elapsed_min" -ge "$CHECKPOINT_INTERVAL" ]; then
    cat > "$SCRATCH/checkpoint.json" <<EOF
{
  "agent_id": "${AGENT_ID}",
  "at": "$(date -u +%FT%TZ)",
  "current_step": "${CURRENT_STEP}",
  "files_touched": $(git diff --name-only HEAD | jq -R . | jq -s .),
  "still_on_task": "${STILL_ON_TASK:-unknown}"
}
EOF
    LAST_CHECKPOINT=$now
  fi
}
Enter fullscreen mode Exit fullscreen mode

Rule for the agent: call checkpoint between every major step. If
still_on_task would be "no", stop and escalate (rule 9) instead of
silently drifting.


TL;DR — the 11 rules

  1. Workdir isolation — every agent gets its own scratch dir
  2. No shared writes without a lockflock or skip
  3. Append-only shared memory>>, never >
  4. Tag every tool call with AGENT_ID — observability or death
  5. Subagent caps — depth 2, 10-min timeout, max 4 siblings
  6. Pre-write git status check — never edit a dirty file you don't own
  7. Nightly consolidation by ONE agent — workers only append
  8. Identity header at session start — no anonymous agents
  9. Hard escalation triggers — 3 fails, destructive ops, runtime overrun
  10. Structured output first, prose second — JSON for inter-agent talk
  11. Checkpoint every N min — drift detection or stop

Why these specific rules

I run multiple Claude Code sessions in parallel every day for content
generation, code review, and admin tasks. The list above is the
distilled set of rules that came out of incidents — not theory:

  • Two agents both rewrote package.json and one's deps silently disappeared. → rules 2, 6.
  • A "shared memory" markdown file was overwritten every 4 minutes and the tail of the day's work was gone every morning. → rule 3.
  • A subagent spawned a subagent spawned a subagent and the bill was $180 before I noticed. → rule 5.
  • One agent committed and force-pushed over another agent's branch. → rule 9.
  • An agent drifted from "fix this bug" to "refactor the whole module" somewhere in hour 2 and I had to revert 40 files. → rule 11.

Every rule maps to one of those incidents. If you're running multi-agent
Claude Code without these guards, you're going to hit the same incidents.
The only question is whether it costs you a morning or a week.


Get the full pack

This is one file in a larger collection. The full CLAUDE.md Rules
Pack
has battle-tested templates for Python, TypeScript, Go, Rust,
Next.js, FastAPI, Postgres, Redis, Docker, Kubernetes, GraphQL, MongoDB,
Swift, C#, Elixir
and more — every file written for actual Claude Code
sessions, not for show.

If you want the full set of language-specific CLAUDE.md templates for
your stack, grab the CLAUDE.md Rules Pack
https://oliviacraftlat.gumroad.com/l/skdgt

Companion gist with the raw CLAUDE-multi-agent.md file (copy-paste
ready): https://gist.github.com/oliviacraft/8a23472e8157822bd9042fa91c46c35d

More content and free samples at oliviacraft.lat.

Top comments (0)