lean-context
Distill verbose project documentation into a terse context file containing only what agents cannot discover by grepping source code.
Phase 1: Freshness Check
- Look for
.claude/docs/lean-context-manifest.json in the target project root.
- If the manifest is missing: mark as stale, proceed to Phase 2.
- If the manifest exists:
a. For each source file listed in the manifest, compute its SHA-256 hash.
b. Compare against the stored hash in the manifest.
c. Glob for new doc sources (see Phase 2 step 1) not present in the manifest.
d. If all hashes match AND no new sources exist: fresh.
- Read
.claude/docs/lean-context.md and use it. Stop here.
e. If any hash differs OR new sources found: stale, proceed to Phase 2.
To compute hashes portably, use:
python3 -c "import hashlib,sys; print(hashlib.sha256(open(sys.argv[1],'rb').read()).hexdigest())" FILE
If python3 is unavailable, fall back to sha256sum or shasum -a 256.
Phase 2: Generation
Step 1: Discover sources
Glob for documentation sources in the target project:
Root-level files:
README.md, CONTRIBUTING.md, DEVELOPMENT.md, SETUP.md
Makefile, justfile, Taskfile.yml
package.json, pyproject.toml, Cargo.toml
docker-compose.yml, docker-compose.yaml
.env.example, .env.sample
Documentation directories:
Monorepo patterns:
packages/*/README.md, packages/*/CONTRIBUTING.md
apps/*/README.md, apps/*/CONTRIBUTING.md
If no sources found: write .claude/docs/lean-context.md with the single line:
<!-- No documentation sources found. --> and do NOT write a manifest. Stop.
Step 2: Read and filter
For each discovered source, read the file and apply the filtering criteria defined in the Filtering Criteria section below. Categorize each extracted item into one of the output categories.
Step 3: Write lean-context.md
Create .claude/docs/lean-context.md in the target project with this exact format:
<!-- Generated by lean-context. Do not edit manually. -->
## Commands
- `pytest --no-header -rN -x`: run tests (flags not obvious from config)
## Caveats
- Tests must run sequentially, shared database state causes corruption in parallel
- Price calculations must use Decimal, not float. Existing code mixes both.
## Deprecated Patterns
- /api/v1/ handlers use raw SQL. New endpoints must use the ORM.
## Environment
- Requires Node 20+ (uses native fetch, fails silently on 18)
## Dependencies
- pg_dump v15+ required for backup scripts
Format rules:
- One dash-prefixed line per item. No prose, no paragraphs.
- Omit categories with zero items entirely.
- If sources exist but nothing passes the filter, write:
<!-- No actionable agent context found in project documentation. -->
Step 4: Write manifest
Create .claude/docs/lean-context-manifest.json:
{
"version": 1,
"generated": "ISO-8601 timestamp",
"sources": {
"README.md": { "hash": "sha256-hex-string" },
"docs/setup.md": { "hash": "sha256-hex-string" }
}
}
Include every source file that was read during generation, whether or not it contributed extractable items.
Step 5: Report
Tell the user how many sources were scanned and how many items were extracted. Then check if the project's CLAUDE.md (or AGENTS.md) already references .claude/docs/lean-context.md. If it doesn't, suggest the user add this line to their CLAUDE.md:
Read `.claude/docs/lean-context.md` for essential project context.
This ensures the generated context is loaded every session without the skill needing to trigger.
Filtering Criteria
The Core Test
For every piece of information found in a documentation source, ask two questions:
"Could an agent discover this via Grep/Glob/Read of source code?"
- If YES: discard. The agent will find it when it needs it.
- Examples: function signatures, class hierarchies, API route definitions, config file formats, directory structure.
"Would not knowing this cause the agent to fail or waste significant time?"
- If YES: extract. This is high-value non-discoverable context.
- Examples: a test suite that silently corrupts data if run in parallel, a build command that requires a specific flag not present in any config file, an env var that must be set but has no
.env.example entry.
Both conditions must be satisfied: not discoverable AND failure-causing. Information that is merely "nice to know" does not qualify.
EXTRACT Categories
Commands
Extract when:
- The command includes flags/options not obvious from config files
- The command differs from what a standard tool would suggest
- The command has a required execution order or prerequisite
- Running the wrong command causes silent data corruption or hard-to-debug failures
Examples of extractable commands:
pytest --no-header -rN -x (flags not in pytest.ini or pyproject.toml)
docker compose up --build --force-recreate (required for local dev, not documented in compose file)
npm run build && npm run migrate (order matters, not enforced anywhere)
Do NOT extract:
npm install / pip install -r requirements.txt (obvious)
npm run test when the script is defined in package.json (discoverable)
make build when the Makefile target is self-documenting
Caveats
Extract when:
- Behavior is surprising or counterintuitive
- A common action leads to a non-obvious failure
- There is a hidden ordering dependency
- Something that works locally fails in CI (or vice versa) for non-obvious reasons
- A project-specific constraint causes silent bugs and isn't visible in code
Examples:
- "Tests share a database, running in parallel causes flaky failures"
- "Hot reload does not work for files in /server, must restart manually"
- "The linter config extends a shared config that disallows semicolons, but the formatter adds them. Run linter AFTER formatter."
- "Deleting a migration file without reverting it first corrupts the DB schema"
- "Price calculations must use Decimal, not float. Existing code mixes both but float causes rounding bugs in billing."
- "The /api/reconcile endpoint is called by the batch-processor service daily. It must be idempotent because the caller retries on timeout."
- "This service is triggered by a scheduled job, not user requests. Error handling must not assume a caller is waiting for a response."
Do NOT extract:
- "The app uses React" (discoverable from package.json)
- "Tests are slow" (vague, not actionable)
- "Don't commit to main" (standard practice, not project-specific)
- "Follow PEP 8" (standard, enforced by linters)
- Constraints where violation produces a clear error message (agent will self-correct)
Deprecated Patterns
Extract when:
- Code exists in the repo that works but should not be copied or extended
- An agent grepping for conventions would find the pattern and replicate it
- The "right" way differs from what the majority of existing code shows
Examples:
- "The /api/v1/ handlers use raw SQL. All new endpoints must use the ORM. Do not copy the v1 pattern."
- "Several components use class-based state management. New components must use hooks. The old pattern is kept for backwards compatibility only."
Do NOT extract:
- Deprecated code marked with clear comments or annotations (discoverable)
- Old code that follows the same patterns as new code (no conflict)
Environment
Extract when:
- A specific version is required and the reason is non-obvious
- An environment variable must be set but is not in .env.example
- A system dependency is required but not in package manifests
- A service must be running locally (database, cache, queue)
Examples:
- "Requires Node 20+ (uses native fetch, fails silently on 18)"
- "GITHUB_TOKEN env var required for integration tests, not in .env.example"
- "PostgreSQL 15+ required, uses MERGE syntax unavailable in 14"
- "Redis must be running on port 6380 (non-standard) for session storage"
Do NOT extract:
- "Requires Node.js" (obvious from package.json existing)
- "Uses PostgreSQL" (discoverable from connection config)
- Version requirements already specified in package.json engines field
Dependencies
Extract when:
- A system-level tool is required but not in package manifests
- An implicit dependency exists between components
- A specific version of an external tool is needed for scripts
- Build/deploy depends on something not captured in lock files
Examples:
- "pg_dump v15+ required for backup scripts (called via subprocess)"
- "The auth service must be deployed before the API service, hard dependency not captured in docker-compose"
- "The notifications service consumes from the orders Kafka topic. Changing the message schema here breaks notifications silently."
- "graphviz must be installed for doc generation (dot command)"
- "protoc v3.21+ required, generates code checked into repo"
Do NOT extract:
- npm/pip/cargo dependencies (in manifest files)
- Docker base images (in Dockerfiles)
- CI tool versions (in CI config files)
DISCARD Categories
Always discard the following. Agents find this faster by reading source code:
Architecture Overviews (Code Structure)
- "The app uses a vertical slice architecture"
- Component diagrams, data flow descriptions
- Module responsibility descriptions
- NOTE: This means internal code organization, which agents discover by reading source. External integration contracts (what calls this service, what it depends on, message schemas shared with other services) are NOT architecture overviews. Extract those as Caveats or Dependencies if they affect code correctness.
Code Structure Documentation
- "The /src/controllers directory contains route handlers"
- File tree listings
- "Each module exports a default function"
- Import/export patterns
Feature Lists
- "The app supports OAuth, SAML, and LDAP"
- Changelog entries
- Release notes
- Roadmap items
API Documentation
- Endpoint descriptions, request/response schemas
- Authentication flow descriptions
- Rate limiting documentation
- Unless the API has a non-discoverable caveat (then extract the caveat only)
General Development Practices
- "We use Git Flow"
- "PRs require two approvals"
- "Run the linter before committing"
- Code style guides (enforced by tooling)
Tutorials and Walkthroughs
- "Getting Started" guides
- Step-by-step instructions for common tasks
- Onboarding documentation
- Unless a step contains a non-obvious command or caveat (extract just that item)
Source-Specific Guidance
README.md
- Skip: project description, badges, feature lists, screenshots, license
- Check: "Quick Start" or "Development" sections for non-obvious commands
- Check: "Prerequisites" for version requirements not in manifests
- Check: "Troubleshooting" or "Known Issues" for caveats
CONTRIBUTING.md
- Skip: PR process, code review guidelines, style guides
- Check: build/test commands with special flags
- Check: "Before you start" sections for hidden requirements
package.json
- Skip: dependencies list, metadata, standard scripts
- Check:
scripts for commands with non-obvious flags or pipelines
- Check:
engines only if it contradicts or adds to what's in .nvmrc/.node-version
- Check:
overrides/resolutions for forced dependency versions (potential caveat)
pyproject.toml
- Skip: dependencies, metadata, standard tool config
- Check:
[tool.pytest.ini_options] for non-obvious test configuration
- Check:
[tool.setuptools] for unusual package discovery rules
- Check: custom script entries for non-obvious commands
Makefile / justfile / Taskfile.yml
- Skip: targets that are self-documenting (name matches action)
- Check: targets with complex command chains or non-obvious flags
- Check: variables that must be set externally
- Check: targets that must run in specific order
docker-compose.yml
- Skip: standard service definitions
- Check: non-standard ports (anything other than the tool's default)
- Check: required environment variables without defaults
- Check: volume mounts that imply local setup requirements
- Check: depends_on with conditions that imply startup order caveats
.env.example / .env.sample
- Skip: variables with obvious names and example values
- Check: variables where the required format is non-obvious
- Check: variables that reference external services requiring setup
- Check: comments indicating caveats or required values
Deduplication
- Extract each fact exactly once. If multiple sources say the same thing, pick one and move on.
- If two sources give conflicting information, ask the user which is correct before extracting.
Edge Cases
- Deleted source files: If a manifest lists a file that no longer exists, treat the manifest as stale and regenerate.
- Binary/non-text files: Skip silently.
1---2name: lean-context3description: Scan project documentation and generate a terse, agent-optimized context file. Use when a project has verbose or lengthy documentation, large README files, /docs folders, or when the user wants to optimize their project context for coding agents.4---56# lean-context78Distill verbose project documentation into a terse context file containing only what agents cannot discover by grepping source code.910## Phase 1: Freshness Check11121. Look for `.claude/docs/lean-context-manifest.json` in the target project root.132. If the manifest is **missing**: mark as stale, proceed to Phase 2.143. If the manifest **exists**:15 a. For each source file listed in the manifest, compute its SHA-256 hash.16 b. Compare against the stored hash in the manifest.17 c. Glob for new doc sources (see Phase 2 step 1) not present in the manifest.18 d. If all hashes match AND no new sources exist: **fresh**.19 - Read `.claude/docs/lean-context.md` and use it. Stop here.20 e. If any hash differs OR new sources found: **stale**, proceed to Phase 2.2122To compute hashes portably, use:23```bash24python3 -c "import hashlib,sys; print(hashlib.sha256(open(sys.argv[1],'rb').read()).hexdigest())" FILE25```26If python3 is unavailable, fall back to `sha256sum` or `shasum -a 256`.2728## Phase 2: Generation2930### Step 1: Discover sources3132Glob for documentation sources in the target project:3334**Root-level files:**35- `README.md`, `CONTRIBUTING.md`, `DEVELOPMENT.md`, `SETUP.md`36- `Makefile`, `justfile`, `Taskfile.yml`37- `package.json`, `pyproject.toml`, `Cargo.toml`38- `docker-compose.yml`, `docker-compose.yaml`39- `.env.example`, `.env.sample`4041**Documentation directories:**42- `docs/**/*.md`4344**Monorepo patterns:**45- `packages/*/README.md`, `packages/*/CONTRIBUTING.md`46- `apps/*/README.md`, `apps/*/CONTRIBUTING.md`4748If **no sources found**: write `.claude/docs/lean-context.md` with the single line:49`<!-- No documentation sources found. -->` and do NOT write a manifest. Stop.5051### Step 2: Read and filter5253For each discovered source, read the file and apply the filtering criteria defined in the Filtering Criteria section below. Categorize each extracted item into one of the output categories.5455### Step 3: Write lean-context.md5657Create `.claude/docs/lean-context.md` in the target project with this exact format:5859```markdown60<!-- Generated by lean-context. Do not edit manually. -->61## Commands62- `pytest --no-header -rN -x`: run tests (flags not obvious from config)6364## Caveats65- Tests must run sequentially, shared database state causes corruption in parallel66- Price calculations must use Decimal, not float. Existing code mixes both.6768## Deprecated Patterns69- /api/v1/ handlers use raw SQL. New endpoints must use the ORM.7071## Environment72- Requires Node 20+ (uses native fetch, fails silently on 18)7374## Dependencies75- pg_dump v15+ required for backup scripts76```7778**Format rules:**79- One dash-prefixed line per item. No prose, no paragraphs.80- Omit categories with zero items entirely.81- If sources exist but nothing passes the filter, write:82 `<!-- No actionable agent context found in project documentation. -->`8384### Step 4: Write manifest8586Create `.claude/docs/lean-context-manifest.json`:8788```json89{90 "version": 1,91 "generated": "ISO-8601 timestamp",92 "sources": {93 "README.md": { "hash": "sha256-hex-string" },94 "docs/setup.md": { "hash": "sha256-hex-string" }95 }96}97```9899Include every source file that was read during generation, whether or not it contributed extractable items.100101### Step 5: Report102103Tell the user how many sources were scanned and how many items were extracted. Then check if the project's CLAUDE.md (or AGENTS.md) already references `.claude/docs/lean-context.md`. If it doesn't, suggest the user add this line to their CLAUDE.md:104105```106Read `.claude/docs/lean-context.md` for essential project context.107```108109This ensures the generated context is loaded every session without the skill needing to trigger.110111---112113## Filtering Criteria114115### The Core Test116117For every piece of information found in a documentation source, ask two questions:1181191. **"Could an agent discover this via Grep/Glob/Read of source code?"**120 - If YES: **discard**. The agent will find it when it needs it.121 - Examples: function signatures, class hierarchies, API route definitions, config file formats, directory structure.1221232. **"Would not knowing this cause the agent to fail or waste significant time?"**124 - If YES: **extract**. This is high-value non-discoverable context.125 - Examples: a test suite that silently corrupts data if run in parallel, a build command that requires a specific flag not present in any config file, an env var that must be set but has no `.env.example` entry.126127Both conditions must be satisfied: not discoverable AND failure-causing. Information that is merely "nice to know" does not qualify.128129### EXTRACT Categories130131#### Commands132Extract when:133- The command includes flags/options not obvious from config files134- The command differs from what a standard tool would suggest135- The command has a required execution order or prerequisite136- Running the wrong command causes silent data corruption or hard-to-debug failures137138Examples of extractable commands:139- `pytest --no-header -rN -x` (flags not in pytest.ini or pyproject.toml)140- `docker compose up --build --force-recreate` (required for local dev, not documented in compose file)141- `npm run build && npm run migrate` (order matters, not enforced anywhere)142143Do NOT extract:144- `npm install` / `pip install -r requirements.txt` (obvious)145- `npm run test` when the script is defined in package.json (discoverable)146- `make build` when the Makefile target is self-documenting147148#### Caveats149Extract when:150- Behavior is surprising or counterintuitive151- A common action leads to a non-obvious failure152- There is a hidden ordering dependency153- Something that works locally fails in CI (or vice versa) for non-obvious reasons154- A project-specific constraint causes silent bugs and isn't visible in code155156Examples:157- "Tests share a database, running in parallel causes flaky failures"158- "Hot reload does not work for files in /server, must restart manually"159- "The linter config extends a shared config that disallows semicolons, but the formatter adds them. Run linter AFTER formatter."160- "Deleting a migration file without reverting it first corrupts the DB schema"161- "Price calculations must use Decimal, not float. Existing code mixes both but float causes rounding bugs in billing."162- "The /api/reconcile endpoint is called by the batch-processor service daily. It must be idempotent because the caller retries on timeout."163- "This service is triggered by a scheduled job, not user requests. Error handling must not assume a caller is waiting for a response."164165Do NOT extract:166- "The app uses React" (discoverable from package.json)167- "Tests are slow" (vague, not actionable)168- "Don't commit to main" (standard practice, not project-specific)169- "Follow PEP 8" (standard, enforced by linters)170- Constraints where violation produces a clear error message (agent will self-correct)171172#### Deprecated Patterns173Extract when:174- Code exists in the repo that works but should not be copied or extended175- An agent grepping for conventions would find the pattern and replicate it176- The "right" way differs from what the majority of existing code shows177178Examples:179- "The /api/v1/ handlers use raw SQL. All new endpoints must use the ORM. Do not copy the v1 pattern."180- "Several components use class-based state management. New components must use hooks. The old pattern is kept for backwards compatibility only."181182Do NOT extract:183- Deprecated code marked with clear comments or annotations (discoverable)184- Old code that follows the same patterns as new code (no conflict)185186#### Environment187Extract when:188- A specific version is required and the reason is non-obvious189- An environment variable must be set but is not in .env.example190- A system dependency is required but not in package manifests191- A service must be running locally (database, cache, queue)192193Examples:194- "Requires Node 20+ (uses native fetch, fails silently on 18)"195- "GITHUB_TOKEN env var required for integration tests, not in .env.example"196- "PostgreSQL 15+ required, uses MERGE syntax unavailable in 14"197- "Redis must be running on port 6380 (non-standard) for session storage"198199Do NOT extract:200- "Requires Node.js" (obvious from package.json existing)201- "Uses PostgreSQL" (discoverable from connection config)202- Version requirements already specified in package.json engines field203204#### Dependencies205Extract when:206- A system-level tool is required but not in package manifests207- An implicit dependency exists between components208- A specific version of an external tool is needed for scripts209- Build/deploy depends on something not captured in lock files210211Examples:212- "pg_dump v15+ required for backup scripts (called via subprocess)"213- "The auth service must be deployed before the API service, hard dependency not captured in docker-compose"214- "The notifications service consumes from the orders Kafka topic. Changing the message schema here breaks notifications silently."215- "graphviz must be installed for doc generation (dot command)"216- "protoc v3.21+ required, generates code checked into repo"217218Do NOT extract:219- npm/pip/cargo dependencies (in manifest files)220- Docker base images (in Dockerfiles)221- CI tool versions (in CI config files)222223### DISCARD Categories224225Always discard the following. Agents find this faster by reading source code:226227#### Architecture Overviews (Code Structure)228- "The app uses a vertical slice architecture"229- Component diagrams, data flow descriptions230- Module responsibility descriptions231- NOTE: This means internal code organization, which agents discover by reading source. External integration contracts (what calls this service, what it depends on, message schemas shared with other services) are NOT architecture overviews. Extract those as Caveats or Dependencies if they affect code correctness.232233#### Code Structure Documentation234- "The /src/controllers directory contains route handlers"235- File tree listings236- "Each module exports a default function"237- Import/export patterns238239#### Feature Lists240- "The app supports OAuth, SAML, and LDAP"241- Changelog entries242- Release notes243- Roadmap items244245#### API Documentation246- Endpoint descriptions, request/response schemas247- Authentication flow descriptions248- Rate limiting documentation249- Unless the API has a non-discoverable caveat (then extract the caveat only)250251#### General Development Practices252- "We use Git Flow"253- "PRs require two approvals"254- "Run the linter before committing"255- Code style guides (enforced by tooling)256257#### Tutorials and Walkthroughs258- "Getting Started" guides259- Step-by-step instructions for common tasks260- Onboarding documentation261- Unless a step contains a non-obvious command or caveat (extract just that item)262263### Source-Specific Guidance264265#### README.md266- Skip: project description, badges, feature lists, screenshots, license267- Check: "Quick Start" or "Development" sections for non-obvious commands268- Check: "Prerequisites" for version requirements not in manifests269- Check: "Troubleshooting" or "Known Issues" for caveats270271#### CONTRIBUTING.md272- Skip: PR process, code review guidelines, style guides273- Check: build/test commands with special flags274- Check: "Before you start" sections for hidden requirements275276#### package.json277- Skip: dependencies list, metadata, standard scripts278- Check: `scripts` for commands with non-obvious flags or pipelines279- Check: `engines` only if it contradicts or adds to what's in .nvmrc/.node-version280- Check: `overrides`/`resolutions` for forced dependency versions (potential caveat)281282#### pyproject.toml283- Skip: dependencies, metadata, standard tool config284- Check: `[tool.pytest.ini_options]` for non-obvious test configuration285- Check: `[tool.setuptools]` for unusual package discovery rules286- Check: custom script entries for non-obvious commands287288#### Makefile / justfile / Taskfile.yml289- Skip: targets that are self-documenting (name matches action)290- Check: targets with complex command chains or non-obvious flags291- Check: variables that must be set externally292- Check: targets that must run in specific order293294#### docker-compose.yml295- Skip: standard service definitions296- Check: non-standard ports (anything other than the tool's default)297- Check: required environment variables without defaults298- Check: volume mounts that imply local setup requirements299- Check: depends_on with conditions that imply startup order caveats300301#### .env.example / .env.sample302- Skip: variables with obvious names and example values303- Check: variables where the required format is non-obvious304- Check: variables that reference external services requiring setup305- Check: comments indicating caveats or required values306307### Deduplication308309- Extract each fact exactly once. If multiple sources say the same thing, pick one and move on.310- If two sources give conflicting information, ask the user which is correct before extracting.311312---313314## Edge Cases315316- **Deleted source files**: If a manifest lists a file that no longer exists, treat the manifest as stale and regenerate.317- **Binary/non-text files**: Skip silently.318