Skip to main content

Why I rebuilt from scratch

About the point in time this series describes

This series is a record based on the harness environment as it existed at the time of writing (file contents, run logs, file counts). The harness has kept evolving since this series was written, so quoted file contents, counts, and procedures may differ from the current state. The focus of this series is the design ideas (five-facet separation, verification gates, growth discipline) rather than the specific values.

This chapter covers the starting point of this series: why I rebuilt from scratch.

Before the rebuild, ~/.claude/ had grown into a setup of a few hundred files, accumulated over about a year. On the surface it ran adequately, but underneath it was clearly saturated. This chapter organizes the symptoms from that time into four, explains why I chose a full rebuild from zero instead of partial fixes, and introduces the four design decisions that shaped the rebuild.

1.1. Starting point: the setup before the rebuild

Before the rebuild, ~/.claude/ was a setup where directories of very different natures coexisted: rules/ skills/ agents/ hooks/, plus references/ (local copies of official Anthropic docs and industry articles), teams/, scripts/, commands/, and learnings/.

Looking at the breakdown, learnings/ and references/ made up a large share, but those weren't the only source of growth — the bodies of rules / skills / agents had accumulated in the same way.

The pre-rebuild harness, listed by section header, looked like this:

  • CLAUDE.md: a long hub, mixing index entries and normative rules
  • rules/: git-workflow.md / commit-policy.md / verification.md / fact-check.md / interaction.md / unverified-claims.md / mcp-loading.md and more — dozens of files
  • skills/: /spec-design / /grill-me / /autodev / /code-review / /verify / /learn / /record-learnings / /init-repo and more — also dozens
  • agents/: architect / code-reviewer / implementer / test-strategist / auditor / ux-reviewer / general-purpose-helper — a full cast
  • hooks/: just check-suppression.sh / check-protected-files.sh, disproportionately thin next to the other directories
  • references/: numerous excerpts from Anthropic official docs, pricing tables, Claude Code spec notes, and locally saved industry articles

Externally this looked organized, but in practice there was a constant dissonance: "I can't hold the whole picture in my head," "the same norm is scattered across multiple places," and "when I spawn a subagent, several norms disappear at the moment of spawn."

1.2. The four observed symptoms

This section breaks the symptoms into four, each with concrete examples.

Symptom 1: asymmetry of easy add vs hard delete

This was the deepest-rooted symptom.

When a failure was observed in the harness, the typical response went like this:

  • The author says "please don't run git commit on your own"
  • rules/git-workflow.md gets a one-line addition: "don't commit until an explicit trigger word appears"
  • Violations recur a few more times
  • A line with the same intent is added to a different rule (such as rules/safety-gate.md)
  • And then skills/commit/SKILL.md step list gets "confirm before commit" appended

Additions happened with every failure, so they accumulated naturally. The judgment for putting one norm into one file wasn't sharp, so similar norms ended up being split-written across multiple facets.

The deletion side was even worse:

  • Whether a rule is actually working can only be checked by removing it
  • "Maybe it's referenced elsewhere," "what if removal causes a regression" — these doubts were the default
  • "Keep it just in case" always won
  • Even when it had zero references for 30 days, even when it had been added half a year earlier, there was no motivation to delete

With no friction at the entrance and no pull at the exit, the file count had no choice but to grow monotonically. Ballooning to a few-hundred-file scale is the result of letting that asymmetry run unchecked for a year.

Symptom 2: the same instruction scattered across multiple facets

As an accumulated result of symptom 1, "the same point is written in three or four places" became normal.

For example, "don't run git commit until an explicit trigger word appears" was written in four places before the rebuild (the originals have been archived; the content below is reconstructed from notes):

  • CLAUDE.md "main rules" section: "commit / push only on explicit human instruction"
  • rules/git-workflow.md: "when running git commit, check whether the most recent user turn contains a trigger word"
  • rules/safety-gate.md: "destructive operations (commit / push / delete) require a human gate"
  • skills/commit/SKILL.md: "Step 0: check whether the most recent user message has a trigger word; if not, use AskUserQuestion"

In the author's head there were reasons such as "slightly different angles, so separate files" or "rules/git-workflow.md is about git operations in general, rules/safety-gate.md is about destructiveness, CLAUDE.md is the summary, the SKILL is the procedure." But the actual behavior of the running Claude looked like this:

  • Only the places that happened to be loaded out of the four would take effect (because constantly-loaded and on-demand-Read rules were mixed in probabilistic compliance)
  • The four wordings differed subtly from each other, so it wasn't clear which one Claude was making its judgment from
  • Rewriting just one of the four left the other three with their old wording
  • Every revision required finding all the places and changing all of them

The direct cause was the fuzzy facet boundaries. The boundaries between Persona / Policy / Instruction were left to operational judgment, so the author kept re-deciding "is this Policy or Instruction" each time, and the initial placement ended up ad hoc.

Symptom 3: context that doesn't reach the subagent

The third symptom was context that doesn't reach the subagent.

A Claude Code subagent (an isolated context spawned via the Agent tool) is severed from the main agent's context at the moment of spawn. Concretely:

  • The norms the main agent had in CLAUDE.md / rules/ don't automatically carry over to the subagent
  • The subagent gets only its own system prompt (the body of agents/<name>.md) and path-scoped rules from claude settings
  • The per-repo CLAUDE.md the main agent had been reading (~/.claude/repos/<repo>/CLAUDE.md) also doesn't carry over (workspace-external)

Before the rebuild there were 7 subagent types, and each one had its own version of the norms written into the body of agents/<name>.md. For example agents/implementer.md had commit discipline and verification discipline written in different wording from the main agent's rules/, agents/code-reviewer.md had its own version of the fact-check rules, agents/auditor.md had its own evidence-based audit rules, and so on — the same norms duplicated across subagents.

This is a typical context-loss issue along the spawning path and is fundamentally a Claude Code behavior. But the harness at the time addressed it the simple way — copy the norms per subagent — which produced secondary issues:

  • The same norm gets written 8 times (main + 7 subagents)
  • Consistency cost grows exponentially with every revision
  • Adding subagent kinds doubles the count again
  • File-count growth and norm duplication form a positive feedback loop

A significant portion of the overall total had grown along this path.

Symptom 4: silent drop

The fourth symptom is what I call silent drop. The term is widely used in harness engineering for the phenomenon where an LLM probabilistically misses parts of an instruction and goes on as if nothing happened.

It showed up in a specific operational pattern. Several SKILL.md files before the rebuild had wording like:

## Linking with related skills
This skill loads and composes the following at runtime:
- `~/.claude/skills/verify-loop/SKILL.md`
- `~/.claude/skills/spec-design/SKILL.md`
- `~/.claude/rules/git-workflow.md`

The design intent was "narrow the responsibility of this SKILL while delivering the needed norms by reading other SKILLs and rules on demand." On paper this is a clean composition strategy.

In actual runs the following happened:

  • When Claude starts a SKILL, it first reads the SKILL.md body
  • The Read targets listed under "Linking with related skills" aren't recognized until the body is read
  • In parallel with body interpretation, those Read calls get probabilistically skipped (context-window pressure plus priority judgments)
  • Only half of the listed related skills end up actually Read
  • And since Claude itself responds as if nothing went wrong, the drop is invisible from the human side

This is a classic silent failure where an Inferential Guide ("read the other SKILL") fails probabilistically. Without a path to enforce things Computationally (hook / settings), instructions can't be backed by structure — that's the essential lesson of harness engineering.

Silent drop also worsens both norm duplication (symptom 2) and subagent context loss (symptom 3). The decision "don't write it here, the other SKILL will be read in" means that if Read doesn't fire, the norm never arrives.

How the four symptoms relate

The four symptoms didn't occur in isolation — they amplified each other:

Symptom 1 was the engine of accumulation; symptoms 2 / 3 / 4 amplified it. Growing to this scale is the outcome of letting this 4-symptom feedback loop run for about a year.

1.3. Why a full rebuild rather than partial fixes

Listing the symptoms alone, partial fixes would have been an option:

  • Consolidate duplicated norms into one file
  • Delete rules with 30 days of zero reference each month
  • Inline the Read enumeration of any silent-dropping SKILL
  • Rework the path for delivering norms to subagents

From mid-to-late May, partial fixes were tried in this direction. After a few days the conclusion became clear:

  • Partial fixes only address individual symptoms and never touch the roots — the fuzzy facet boundaries and the missing design for composition
  • Each revision required walking through the whole bloated setup, and accumulation outpaced revision
  • The cognitive map (knowing where everything is) didn't recover, so revision judgments lacked their prerequisite
  • Cleaning up only one area still let saturation re-emerge from the uncleaned areas

To pull out the root, the entire set of facet boundaries had to be redrawn. Doing that redraw with the whole bloated setup still in place would cost more in cognitive load and consistency risk than archiving everything once and redrawing the boundaries on empty directories.

At a certain point I moved the entire prior setup aside and started rebuilding from an empty ~/.claude/. That is the starting point of this series.

Premise of a full rebuild

Deciding to "wipe everything and rewrite from empty" is intentionally releasing a large amount of retained knowledge. In practice the archive was left accessible for selective references, and the new harness was built by actively choosing what to keep. The process of placing the burden of proof on the "keep" side — the prototype of the later inverted approval — was born during this rebuild period.

1.4. Four design decisions for the rebuild

When rebuilding from zero, four design decisions were made up front.

Decision 1: lock the philosophy to one shape

The first decision was classifying everything into five concerns.

Decide what is Persona, what is Policy, what is Instruction, what is Knowledge, what is Output Contract. With these five covering everything, the cost of "where do I put it when I'm unsure" disappears.

Details are in the next chapter (02. Faceted Prompting), but the gist is:

  • Persona = who (the actor behind the behavior)
  • Policy = how (norms, "this is how it should be")
  • Instruction = what to do (procedure)
  • Knowledge = what is (descriptive knowledge)
  • Output Contract = what comes out (artifact template)

By limiting to five, there is also an explicit "no faceting needed" exit for items that don't fit any of them. Before the rebuild, items with no clear placement would get dumped into rules/ or skills/ "for now," and items that shouldn't have been faceted at all contributed to the bloat.

Decision 2: design composition explicitly

The second decision was to start from the premise that Claude Code has no composer.

The pre-rebuild harness tried to weave all facets together via Read at runtime (the source of silent drop in symptom 4). That assumed "there is a composer."

In the new harness, with no composer as the explicit assumption, three delivery tiers are split:

  • gating facet (norms that determine the loop verdict) → inline into the agent body, enforced deterministically
  • Instruction (procedure) → delivered to the subagent by composing/embedding it into story.md or the spawn prompt (the main agent itself just reads the SKILL.md directly)
  • Knowledge / descriptive Policy → reference from an index + Read on demand (body-copy is prohibited only at this tier)

Details are in Chapter 4 (Directory structure and composition rules). The important shift is "do not leave composition to a probabilistic path (Read); design deterministic paths by importance tier."

Decision 3: friction at the entrance, pull at the exit

The third decision was to flip the asymmetry the other way.

The pre-rebuild era grew through "easy add, hard delete." The new harness deliberately reverses this:

  • Entrance (add): the author's approval required, file-size cap, usage-driven (two manual repetitions before considering)
  • Exit (delete): monthly /harness-prune detects 30-days-zero-references / size-cap-overrun / orphan hooks / dangling references, and inverted approval (ask why to keep) processes deletions

Inverted approval is especially effective. Asking "OK to delete this?" makes "keep it just in case" the default, but asking "what's the reason to keep this?" moves the burden of proof to the keeper. "Might use it someday" can't keep anything in this structure.

Details are in Chapter 7 (Growth discipline and reverse ratchet).

Decision 4: structure how norms reach subagents

The fourth decision was to give up the simple "copy norms per subagent" path and solve it structurally:

  • Policies required to reach subagents (verification.md / git.md etc.) are constantly loaded without paths:
  • Per-repo knowledge (CLAUDE.md / CONTEXT.md / handoff) is injected explicitly via absolute path in the spawn prompt by the orchestrator (it's outside the workspace, so no automatic delivery)
  • Gating output contracts (VERDICT: PASS|FAIL) are inlined into the agent body and used via grep for fail-closed branching

With this, the duplication doesn't grow even when subagent kinds are added. Details are in Chapter 5 (Facet deep-dive) and Chapter 6 (autodev flow).

1.5. How the zero-rebuild actually played out

After rebuilding under these four design decisions, ~/.claude/ looks completely different. What matters is that this wasn't a case of shrinking once and being done.

The zero-rebuild was, first, an act of compressing everything down hard. Directories with fuzzy, ambiguous purposes that had piled up over time — references/, teams/, scripts/, commands/ — were retired, narrowing everything down to five facets (rules/ / skills/ / agents/, plus the newly introduced output-contracts/ and knowledge/). CLAUDE.md itself shrank substantially too, going from an index mixed with norms down to just the index and the philosophy.

That said, operation didn't stop the moment things were compressed. After bootstrap, whenever the pattern "I gave the same correction by hand twice" surfaced during actual use, the discipline of faceting it (usage-driven addition, Chapter 7) kicked in, and rules / skills grew back only as much as was actually needed. What makes the zero-rebuild meaningful isn't "compress and stop" — it's whether the growth that followed the compression stayed under the same discipline instead of sliding back into the same lack of restraint as before.

Hooks were the one facet that grew early, ahead of the others, from early in the bootstrap. This reflects a policy shift: among the norms written as Inferential Guides (rules), the ones that truly can't be compromised on get stopped deterministically by a Computational Sensor instead. Concretely, norms where probabilistic violations have real impact — the commit gate (check-git-commit-gate.sh), plain-question detection (check-plain-question.sh) — became hooks. A log-only Computational Sensor that watches for missing Reads before Edit / Write / MultiEdit was also added later, out of actual operation.

The appearance of output-contracts/ is symbolic of this round of changes. It is a layer that templatizes subagent output formats so that the main agent can grep / parse them mechanically — the foundation that makes the autodev flow (the verification-gate loop), covered later, work.

1.6. Summary of this chapter

Key points
  • The pre-rebuild setup, grown to a few-hundred-file scale, was the product of four mutually amplifying symptoms: easy add / hard delete, same instruction across facets, subagent context loss, silent drop
  • The four symptoms were not independent; they formed a feedback loop. Partial fixes couldn't reach the root
  • The full rebuild kept the archive accessible for selective reference while making the decision to place the burden of proof on the "keep" side
  • Four design decisions: (1) classify into five concerns, (2) design composition explicitly (no composer), (3) entrance friction / exit pull, (4) structure norm delivery to subagents
  • The zero-rebuild wasn't a case of "compress and done" — it functioned as a process of regrowing afterward under usage-driven addition while keeping the same discipline. Only hooks grew early, ahead of the other facets, reflecting the shift to deterministic stopping of Inferential Guides with Computational Sensors

The next chapter dives into the core of the rebuild — Faceted Prompting (5-concern separation) — along the boundaries of each facet and the routing rules between them.