lean-context

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.

install
source · Clone the upstream repo
git clone https://github.com/asarnaout/lean-context
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/asarnaout/lean-context "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/lean-context/skills/lean-context" ~/.claude/skills/asarnaout-lean-context-lean-context && rm -rf "$T"
manifest: plugins/lean-context/skills/lean-context/SKILL.md
source content

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

  1. Look for
    .claude/docs/lean-context-manifest.json
    in the target project root.
  2. If the manifest is missing: mark as stale, proceed to Phase 2.
  3. 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:

  • docs/**/*.md

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:

  1. "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.
  2. "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.