# Headroom Learn Offline failure learning for coding agents. Analyzes past conversations, finds what went wrong, correlates it with what eventually worked, and writes specific project-level learnings that prevent the same mistakes next session. ## Quick Start ```bash # See recommendations for current project (dry-run, no changes) headroom learn # Write recommendations to CLAUDE.local.md (gitignored, personal default) headroom learn --apply # Write to the shared team file instead headroom learn --apply --target CLAUDE.md # Analyze a specific project headroom learn --project ~/my-project --apply # Analyze all projects headroom learn --all --apply ``` ## How It Works ``` Past Sessions → Plugin → Analyzer → Writer → Agent-native context file │ │ │ │ │ └─ Writes marker-delimited sections │ │ (replaced on re-run, not duplicated) │ │ │ └─ LLM-based analysis: finds failure patterns, │ success correlations, and actionable rules │ └─ Plugin reads agent-specific logs: • Claude Code: ~/.claude/projects/*.jsonl • Codex: ~/.codex/sessions/*.json • Gemini CLI: ~/.gemini/tmp/*/chats/session-*.json ``` ### Success Correlation The core innovation. Instead of cataloging failures ("Read failed 5 times"), Headroom finds what the model did to fix each failure: - **Failed**: `Read axion-formats/src/main/java/.../FirstClassEntity.java` - **Then succeeded**: `Read axion-scala-common/src/main/scala/.../FirstClassEntity.scala` - **Learning**: "`FirstClassEntity` is at `axion-scala-common/`, not `axion-formats/`" This produces specific, actionable corrections — not generic advice. ## What It Learns ### 1. Environment Facts → CLAUDE.md Which runtime commands work vs fail. ```markdown ### Environment - **Python**: use `uv run python` (not `python3` — modules not available outside venv) ``` ### 2. File Path Corrections → CLAUDE.md Wrong paths the model keeps guessing, with the correct locations. ```markdown ### File Path Corrections - `axion-common/src/.../AxionSparkConstants.scala` → actually at `axion-spark-common/src/.../AxionSparkConstants.scala` ``` ### 3. Search Scope → CLAUDE.md Which directories to search in (narrow paths fail, broader ones work). ```markdown ### Search Scope - Don't search `axion-model/` → use `axion/` (the repo root) ``` ### 4. Command Patterns → CLAUDE.md How commands should (and shouldn't) be run. ```markdown ### Command Patterns - **user_prefers_manual**: User rejected gradle 18 times — show the command, don't execute - **python_runtime**: Use `uv run python` not `python3` (ModuleNotFoundError) ``` ### 5. Known Large Files → CLAUDE.md Files that need `offset`/`limit` with Read. ```markdown ### Known Large Files - `proxy/server.py` (~8000 lines) — always use offset/limit ``` ### 6. Retry Prevention → MEMORY.md Specific suggestions derived from actual corrections. ### 7. Permission Notes → MEMORY.md Commands repeatedly rejected — model should suggest them to the user instead. ## Where Learnings Go | Pattern | Claude Code | Codex | Gemini CLI | |---------|-------------|-------|-----------| | Environment, paths, commands | **CLAUDE.local.md** (default) or `CLAUDE.md` (with `--target CLAUDE.md`) | **AGENTS.md** | **GEMINI.md** | | Retry patterns, permissions | **MEMORY.md** | **instructions.md** | **GEMINI.md** | Output files are agent-native: Claude Code writes to `CLAUDE.local.md` by default (gitignored, personal); pass `--target CLAUDE.md` for the shared team file. Codex uses `AGENTS.md`, Gemini uses `GEMINI.md`. The same learnings, written to the format each agent reads. ## Marker-Based Updates Headroom manages a clearly-delimited section in each file: ```markdown ## Headroom Learned Patterns *Auto-generated by `headroom learn` — do not edit manually* ... ``` On re-run, only the content between markers is replaced. Your existing file content is preserved. ## Architecture (Plugin System) Headroom Learn uses a plugin architecture where each agent is a self-contained plugin: ``` Plugin Registry (auto-discovered) ├── ClaudeCodePlugin → Analyzer (LLM) → ClaudeCodeWriter → CLAUDE.md / MEMORY.md ├── CodexPlugin → Analyzer (LLM) → CodexWriter → AGENTS.md / instructions.md ├── GeminiPlugin → Analyzer (LLM) → GeminiWriter → GEMINI.md └── (your plugin) → Analyzer (LLM) → (your writer) → (your file) ``` **Plugins** bundle scanning, detection, and writing for one agent. Built-in plugins are auto-discovered from `headroom.learn.plugins.*`. External plugins register via the `headroom.learn_plugin` entry point. **The Analyzer** is shared — it uses an LLM (Sonnet, GPT-4o, or Gemini Flash) to find patterns. Same analysis for any agent. ### Adding Support for a New Agent 1. Create `headroom/learn/plugins/myagent.py` 2. Implement `LearnPlugin` + `ConversationScanner` (scanner + writer + detection) 3. Add `plugin = MyAgentPlugin()` at module scope 4. Done — `headroom learn --agent myagent` works automatically Or install an external plugin: `pip install headroom-learn-cursor` (registers via entry point). ## CLI Reference ``` headroom learn [OPTIONS] Options: --project PATH Project directory (default: current directory) --all Analyze all discovered projects (mutually exclusive with --project) --apply Write recommendations (default: dry-run) --target TEXT Context file to write (default: CLAUDE.local.md for Claude Code) --main-only Write only to the main context file, skip MEMORY.md --agent [auto|claude|codex|gemini] Which agent to analyze (default: auto-detect) --model TEXT LLM for analysis (default: auto from API keys or CLI) --workers / -j INTEGER Parallel analysis workers (min 1, default: auto) --verbosity Analyze verbosity level instead of failure patterns --llm-judge Use an LLM to score verbosity quality (requires --verbosity) ``` ### Verbosity learning (`--verbosity`) `headroom learn --verbosity` analyzes past sessions to infer the ideal output verbosity level for your project and writes a `verbosity.json` profile. **Important**: the output shaper is **off by default**. Running `--verbosity --apply` will either: - Hot-enable the output shaper on a running proxy (`POST /admin/runtime-env`), OR - Print instructions to set `HEADROOM_OUTPUT_SHAPER=1` before `headroom wrap ...` To keep the shaper on across proxy restarts, add `export HEADROOM_OUTPUT_SHAPER=1` to your shell profile before starting the proxy. **Flag interactions**: - `--all` and `--project` are mutually exclusive - `--llm-judge` requires `--verbosity` - `--verbosity --all --apply` is rejected (verbosity persists a single global level) ### Supported Agents | Agent | Scanner | Writer | Output Files | |-------|---------|--------|-------------| | **Claude Code** | Reads `~/.claude/projects/*.jsonl` | ClaudeCodeWriter | CLAUDE.md, MEMORY.md | | **OpenAI Codex** | Reads `~/.codex/sessions/*.json` | CodexWriter | AGENTS.md, instructions.md | | **Gemini CLI** | Reads `~/.gemini/tmp/*/chats/session-*.json` | GeminiWriter | GEMINI.md | ## LLM Backend Selection `headroom learn` needs an LLM to analyze your sessions. It picks one automatically using this priority: | Priority | Source | Example | |----------|--------|---------| | 1 | `--model` flag | `headroom learn --model gpt-4o` | | 2 | API key env var | `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `GEMINI_API_KEY` | | 3 | `HEADROOM_LEARN_CLI` env var | `export HEADROOM_LEARN_CLI=gemini` | | 4 | Auto-detect installed CLIs | Checks PATH for `claude`, `gemini`, `codex` | ### Using without an API key If you use Claude Code, Gemini CLI, or Codex via subscription (no raw API key), `headroom learn` can call them directly: ```bash # Auto-detects claude in PATH — no API key needed headroom learn # Explicitly select a CLI backend headroom learn --model gemini-cli # Pin a CLI via environment variable export HEADROOM_LEARN_CLI=codex headroom learn ``` Valid values for `HEADROOM_LEARN_CLI`: `claude`, `gemini`, `codex`. ## Real-World Results Tested on 67,583 tool calls across 23 projects: | Metric | Value | |--------|-------| | Failure rate | 7.5% (5,066 failures) | | Corrections extracted | 164 per project (avg) | | Specific path corrections | 22 (axion project) | | Search scope corrections | 24 (axion project) | | Command patterns learned | 5 (axion project) | | Estimated preventable waste | ~27 MB across corpus |