# Build Your Own Karpathy+ System

**A handoff guide for AI agents (Claude, etc.) to recreate this context system for a new user.**

Version 1 · 2026-04-20 · Paired with the essay at [eqctrl.io/karpathy+](https://eqctrl.io/karpathy+)

---

## How to use this document

You are reading this because your user wants to build a persistent, structured memory system for working with an LLM. Your job is to walk them through the build and then be the first inhabitant of the system: its primary reader, its primary writer, and the agent that maintains it over time.

This guide is deliberately opinionated. Every rule below exists because something broke without it. You can adapt the specifics, but the core architecture is load-bearing. If you diverge from it, name the reason.

Work through the steps in order. Ask the user for missing facts (name, domains, project list) before drafting content. Prefer creating empty scaffolds the user fills in over inventing placeholder content that goes stale.

---

## What you're building

A three-layer knowledge system:

```
Sources ──> Wiki ──> Schema ──> Session
(raw/messy)   (curated)   (~50 lines)   (context-aware LLM)
```

- **Sources** (`wiki/sources/`) are raw inputs: transcripts, bookmarks, tool feeds, exports. Messy. The LLM curates them upward.
- **Wiki** (`wiki/`) is the curated layer. Target 15 to 30 pages. LLM-maintained.
- **Schema** (`CLAUDE.md` or equivalent) is behavior rules plus wiki conventions. About 50 lines. No knowledge lives here; it tells the LLM how to read the wiki.

Outcomes when built correctly:

- Build time: under an hour.
- Steady-state maintenance: a few minutes of human review per week.
- Failure mode closed: silent drift (where context silently diverges from reality without anyone noticing until something breaks).

---

## Core concepts the user should understand before you build

Walk the user through these before touching the filesystem.

**1. The boundary rule.** Knowledge goes in one place (for example, `~/AI/`). Runtime goes somewhere else (for example, `~/.claude/`). One rule, strictly enforced. Prevents the "same knowledge in three files, drifting independently" failure that kills most LLM memory systems.

**2. Progressive disclosure.** The LLM does not load the wiki. It loads a lightweight index and reads only the two to four pages relevant to the current task. A system that requires loading everything before working is a system that gets skipped in long sessions.

**3. Three operations.** The wiki is not a static collection. It has three operations that keep it alive: ingest (write new knowledge after a change), query (read 2 to 4 pages at session start), lint (scheduled health check).

**4. Defense in depth.** No single enforcement layer is enough. Behavior rules, a session hook, scheduled lint, git history, and a completion gate each catch different failures. The system fails only if every layer fails at once.

**5. Propagation is a snapshot.** Copies detach from their source at propagation time. Auto-memory, UI instructions, and forwarded session prompts are all snapshots, not live references. Verify at consumption.

---

## Step 1: Decide the boundary

Ask the user:

- Where does their AI runtime configuration live? (For Claude Code, this is `~/.claude/`.)
- Where do they want knowledge and project work to live? (Common choice: `~/AI/` or `~/knowledge/` or `~/notes/`.)

Pick two clean, separate directories. Never collapse them. The separation IS the rule.

For the rest of this guide, call them:

- `KNOWLEDGE_ROOT` (e.g., `~/AI/`)
- `RUNTIME_ROOT` (e.g., `~/.claude/`)

---

## Step 2: Create the wiki structure

Inside `KNOWLEDGE_ROOT`, create `wiki/` with this structure:

```
wiki/
├── INDEX.md              # Read FIRST every session. Catalog + heartbeat.
├── log.md                # Chronological: changes, decisions, judgments
├── system/               # Infrastructure knowledge (ALL-CAPS filenames)
│   └── HOW-THE-WIKI-WORKS.md
├── projects/             # One page per project
├── patterns/             # Reusable patterns, regressions, conventions
├── personal/             # Bio, career, long-form reference
├── plans/                # Forward-looking plans (see `last_reconciled:` note)
└── sources/              # Raw input before curation
```

Naming conventions:

- `system/` files are ALL-CAPS (visually distinct, these are operating-manual pages).
- Everything else uses lowercase topic names.
- No archive directory inside `wiki/`. Git history is the archive. Old pages are deleted, not moved.

---

## Step 3: Write the schema

Create `CLAUDE.md` (or the equivalent for your agent) at `RUNTIME_ROOT`. Keep it under 80 lines. Below is a template. Fill in the `[bracketed]` placeholders by asking the user.

```markdown
# BOOTSTRAP — EXECUTE BEFORE ANY RESPONSE
Read `KNOWLEDGE_ROOT/wiki/INDEX.md` NOW. Do not respond until you have read it.

# Schema

You are working with [USER NAME]. [ONE-LINE USER CONTEXT: role, focus areas].

## Wiki

All knowledge lives in `KNOWLEDGE_ROOT/wiki/`. Read only the 2-4 pages you need per session. If `KNOWLEDGE_ROOT/wiki/.update-queue` exists, process it (update wiki pages for listed changed files, then clear the queue).

After any session that changes state: update the relevant wiki page(s) and append to `KNOWLEDGE_ROOT/wiki/log.md`. Include a `Judgment:` line for fixes, tradeoffs, and decisions.

`log.md` is write-only during sessions. Do not read at session start; use `git log` or read the last 10 entries on demand.

## File Placement

No loose files at `KNOWLEDGE_ROOT/` root. Every file lives in a bucket:

| Bucket | For |
|---|---|
| `wiki/` | Curated canonical knowledge |
| `<project>/` | Active project code |
| `[YOUR CATEGORIES]` | [personal, career, outputs, etc.] |
| `inbox/` | Untriaged arrivals |
| `scratch/` | Throwaway |

Archive and backups live OUTSIDE `KNOWLEDGE_ROOT/` (for example at `~/Archive/`) to keep scoped tools (MCP servers, search indexes) clean.

## Style

[USER STYLE RULES: brevity, tone, formatting preferences.]

## Trigger Phrases

"log this" -> update relevant wiki page + log.md
"do it / defer it / kill it" -> lint triage responses
[ADD YOUR OWN]

## Forwarded Instructions

When a session starts with a forwarded or terse instruction that references a plan or prior session ("build X per plan.md"), treat it as a claim, not a direction. Re-derive scope from current wiki before executing. Propagation is a snapshot.
```

Why this works:

- Bootstrap directive forces `INDEX.md` read on every session. No opt-out.
- File placement rules prevent stray writes to root.
- Trigger phrases give the user conversational control.
- Forwarded-instructions rule prevents executing against stale plans.

---

## Step 4: Create INDEX.md

This is the entry point every session reads. Keep it under 50 lines. Each line under 150 characters.

```markdown
---
schema_version: 1.0
last_updated: [TODAY]
---
# Wiki Index

Last updated: [TODAY] (N pages across M sections) | Last lint: [TODAY] — 0 issues

## Projects
- [project-a](projects/project-a.md) -- [one-line status]

## System
- [HOW-THE-WIKI-WORKS](system/HOW-THE-WIKI-WORKS.md) -- Operating manual for the system

## Patterns
- [regressions](patterns/regressions.md) -- Correction log, rules the system enforces

## Plans
- [todo.md](todo.md) -- Active task backlog
```

One line per page. Short descriptions. The index is the progressive-disclosure gate; it has to fit cheap in every session's context.

---

## Step 5: Create the first pages

Write three to five pages covering the user's most-repeated context.

**Must-haves:**

1. `wiki/system/HOW-THE-WIKI-WORKS.md` — the operating manual, a copy/adaptation of this architecture explanation.
2. `wiki/log.md` — seed with today's entry: `## [DATE] -- Wiki system bootstrapped`.

**Likely also useful:**

3. `wiki/personal/bio.md` — user identity, role, business structure, working preferences.
4. One project page in `wiki/projects/` for each active project.
5. `wiki/patterns/regressions.md` — running log of corrections and the rules they crystallized.

Ask the user for the content. Don't invent specifics.

---

## Step 6: Page template

Standardize on this template so lint has a contract and the LLM has a predictable parse target:

```markdown
---
last_updated: YYYY-MM-DD
tags: [project, active]
---
# Page Title

## Status        (project pages only) current state, read first
## Key Facts     quick-reference table or bullets
## Details       prose — the actual knowledge
## Tasks         - [ ] tracked items, - (?) thoughts
## Links         cross-references to other pages
```

Plans get one extra frontmatter key: `last_reconciled: YYYY-MM-DD` (semantics: "all references in this plan have been re-verified against current project state as of this date"). This is distinct from `last_updated`, which bumps on any edit.

---

## Step 7: Set up the session hook (optional but recommended)

A simple Python script that runs at session end and writes changed project-file paths to `wiki/.update-queue`. The next session or lint pass reconciles it.

Minimal version (`RUNTIME_ROOT/hooks/wiki-session-hook.py`):

```python
#!/usr/bin/env python3
"""Session-end hook: record changed files for later wiki update."""
import json, re, sys, os
from datetime import datetime
from pathlib import Path

WIKI_DIR = Path(os.path.expanduser("~/AI/wiki"))  # adjust for your KNOWLEDGE_ROOT
QUEUE = WIKI_DIR / ".update-queue"
WATCHED = ["project-a", "project-b"]  # ask user for project names

transcript = sys.stdin.read()
changed = set()
for m in re.finditer(r'"(?:file_path|path)":\s*"([^"]+)"', transcript):
    for proj in WATCHED:
        if f"/{proj}/" in m.group(1):
            changed.add(m.group(1).split(f"/{proj}/", 1)[1])
            break

if changed:
    session_id = os.environ.get("CLAUDE_SESSION_ID", "unknown")[:8]
    with open(QUEUE, "a") as f:
        f.write(f"\n## {datetime.now():%Y-%m-%d %H:%M} (session: {session_id})\n")
        for p in sorted(changed): f.write(f"- {p}\n")
```

Register in your runtime settings (`RUNTIME_ROOT/settings.json` for Claude Code):

```json
{
  "hooks": {
    "SessionEnd": [{"hooks": [{"type": "command", "command": "python3 ~/.claude/hooks/wiki-session-hook.py"}]}]
  }
}
```

The hook is a tripwire, not a brain. It records that something changed. A future session (or `/wiki-lint`) reasons about the changes.

---

## Step 8: Create the lint command

A slash command that performs a multi-step health check. Save to `RUNTIME_ROOT/commands/wiki-lint.md`:

```markdown
---
name: wiki-lint
description: Scan wiki for stale pages, broken links, overdue tasks, drift
---

Run a comprehensive wiki lint pass. Follow each step in order.

1. **Process update queue.** Check `wiki/.update-queue`. Read each entry, determine which wiki pages need updating, update them, clear the queue.
2. **Freshness check.** Compare `last_updated` frontmatter against git activity. Flag project pages >1 week stale relative to their repo.
3. **Broken links.** Scan all pages for markdown links. Verify targets exist. Auto-fix obvious renames.
4. **Task aggregation.** Collect all `- [ ]` items across pages. Age via git blame. Write top 10 to `wiki/tasks-open.md`.
5. **Log gap check.** Flag if most recent `log.md` entry is >3 days old.
6. **Unprocessed sources.** Flag files in `wiki/sources/` without `processed: true` frontmatter, older than 5 days.
7. **Log rotation.** If `log.md` has entries older than 30 days, archive them to `wiki/sources/log-archive-YYYY-MM.md`.
8. **Root cleanliness.** List KNOWLEDGE_ROOT contents. Flag anything not in the approved bucket list. Ask triage: do it / defer it / kill it.
9. **Auto-memory drift check.** Diff key facts between runtime auto-memory and wiki. Auto-fix obvious staleness.
10. **Plan reconciliation.** For each `wiki/plans/*.md`, compare `last_reconciled` to `last_updated` of any referenced project. Flag if plan predates its dependencies.
11. **Heartbeat.** Write current timestamp to `wiki/.lint-heartbeat`. Update `INDEX.md` line 2 with lint summary.
12. **Report.** Present findings: auto-fixed (just report) and needs-attention (ask triage per item).
13. **Remote sync** (optional). If wiki has a git remote, `git add -A && git commit && git push` when clean.
```

Run weekly or on demand. Output is an auto-fix pass for mechanical issues plus a triage report for judgment calls. User responds `do it` / `defer it` / `kill it`.

Step 10 (plan reconciliation) is the youngest and is optional. Build it only when you have plans that might go stale.

---

## Step 9: Operating rhythm

Once the scaffolding is up, the system runs like this:

**Every session (automatic):**

- Schema loads. Bootstrap reads `INDEX.md`. LLM picks 2 to 4 relevant pages. Does the work.
- At session end, hook writes changed paths to `.update-queue`.

**After any change (human says "log this"):**

- LLM updates the affected wiki pages.
- Appends an entry to `log.md` with a `Judgment:` line explaining the reasoning.

**Weekly (user runs `/wiki-lint`):**

- 13-step pass. Auto-fix + triage report. User responds to each needs-attention item.

**On corrections (human says "log this"):**

- Update `patterns/regressions.md` with the new rule. Future sessions load it.

---

## Step 10: The completion gate

Install this as a non-overridable rule:

> **Nothing is "done" until all three are true:**
> 1. The change works (smoke test, verification, whatever fits).
> 2. The docs reflect the change (wiki page + `log.md`).
> 3. Any deploy or script change followed its checklist.

This is the constitutional rule. Skipping it under pressure is the exact failure that caused most past incidents. Speed without verification is not speed, it's rework.

---

## Step 11: Trigger phrases the user should learn

Conversational controls, not exact commands:

| Phrase | What it triggers |
|---|---|
| `log this` | Update regressions + relevant wiki page + log.md |
| `switching to [domain]` | Scope to that domain only |
| `do it / defer it / kill it` | Lint triage responses |
| `promote to [tracker]` | Create tracker issue from a wiki checkbox |

Teach these. Without them, corrections evaporate with the session.

---

## Adapt to the user's context

Keep these (universal, load-bearing):

- Three layers: sources / wiki / schema.
- Boundary rule between knowledge and runtime.
- Progressive disclosure (don't load the whole wiki).
- `INDEX.md` as entry point.
- `log.md` with `Judgment:` lines.
- Lint as scheduled enforcement.
- Defense in depth (schema + hook + lint + git + heartbeat + completion gate).

Adapt these (context-local):

- **Page categories.** System / projects / patterns works for infrastructure-heavy work. Clients / research / processes works for research-heavy. Match the user's domains.
- **Lint schedule.** Weekly by default. Daily for high-churn teams. Manual at the start is fine.
- **Trigger phrases.** Add what matches the user's vocabulary.
- **Task tracker.** Linear, Jira, GitHub, none. Doesn't matter.
- **Surface routing.** Skip if single-surface. Add if multi-surface (desktop + mobile + CLI).

---

## Common failure modes to preempt

**Over-eagerness.** Do not write five detailed pages in the first session. The system matures through use. Start minimum viable; grow when the user notices themselves repeating context.

**Pretending to verify.** If you claim something is current, you checked it this session. Never assert based on remembered state from earlier. Re-read before reporting.

**Fighting the progressive disclosure rule.** The temptation is to read more pages "just in case." Resist it. The rule prevents context bloat; breaking it for one task is how the failure mode returns.

**Creating helper abstractions.** If you're tempted to add a sixth script or a new frontmatter field to solve a problem, ask: has this problem fired twice? If no, wait. Lint will surface it if it returns.

---

## Closing

The system is small on purpose. Three layers, one boundary rule, three operations, a handful of enforcement layers. Everything beyond that is earned by use, not added by default.

When your user asks "should I add X to the wiki?", the answer is usually: not yet, put it in sources/, let it accumulate, it'll surface if it matters.

The wiki's quality is a function of what you notice and what the user corrects. Your job is to notice more than you forget, and to force the user to make decisions fast (`do it / defer it / kill it`) rather than letting issues sit.

Build it, use it for two weeks, then ask what needs adjustment. Not before.

---

*Based on [eqctrl.io/karpathy+](https://eqctrl.io/karpathy+) · v1 · 2026-04-20. Adapt freely. Credit if you publish a fork.*
