featuring · v0.1.0 · 2026-03-31 · sha256 bbe260c9372179ec

featuring v0.1.0A

Immutable. This exact content is served forever at /api/v1/blob/bbe260c9372179ec.

---
name: featuring
description: >-
  Generate _FEATURES.md files that describe what a codebase DOES from a user/consumer
  perspective, anchored to source symbols via tree-sitting. Produces top-down feature
  documentation organized by capability, not file structure. Use when someone says
  "what does this do", "document features", "feature inventory", "_FEATURES.md",
  or needs to understand a codebase's purpose before modifying it. Complements
  tree-sitting (structural) with semantic (why/what-for) layer.
metadata:
  version: 0.1.0
---

# Featuring

Generate `_FEATURES.md` files — top-down documentation of what a codebase **does**,
organized by feature/capability, anchored to specific source symbols.

**tree-sitting** tells you WHAT symbols exist.
**_FEATURES.md** tells you WHY they exist and what they accomplish together.

## Dependency

Requires **tree-sitting** skill. Uses its engine for AST scanning.

```bash
uv venv /home/claude/.venv 2>/dev/null
uv pip install tree-sitter-language-pack --python /home/claude/.venv/bin/python
```

## Workflow

### Step 1: Gather structural data

```bash
/home/claude/.venv/bin/python /mnt/skills/user/featuring/scripts/gather.py /path/to/repo \
  --skip tests,.github,node_modules --source-budget 8000
```

This scans the codebase via tree-sitting and outputs a structured summary:
entry points, public API, types, import graph, and key source excerpts.
The `--source-budget` controls how much source code is included (chars).

### Step 2: Synthesize features (LLM)

Read the gather output. Identify features by asking:

1. **What can a user/consumer DO with this?** (capabilities, commands, API endpoints)
2. **What problems does it solve?** (the WHY behind the code)
3. **What are the main workflows?** (how features compose)
4. **What are the constraints/invariants?** (rules the code enforces)

Group related symbols into features. A feature is NOT a file — it's a capability
that may span multiple files. A single file may contribute to multiple features.

### Step 3: Write _FEATURES.md

Output a single `_FEATURES.md` file at the repo root (or per major subsystem
for large repos).

## _FEATURES.md Format

```markdown
# Features: {project-name}

> One-sentence description of what this codebase is and does.

## {Feature Name}

{2-3 sentences: what this feature does from a user perspective.
What problem it solves. When you'd use it.}

**Key symbols:**
- `file.py#function_name` — role in this feature
- `file.py#ClassName` — role in this feature

**Workflow:** {Brief description of how a user exercises this feature,
or how the symbols collaborate to deliver it.}

**Constraints:** {Invariants, limits, rules this feature enforces.}

---

## {Next Feature}
...
```

### Format rules

- **Organized by capability**, not by file/directory
- **Symbol references** use `file#symbol` notation (relative paths)
- **Leading paragraph** per feature: what a user gets, not implementation details
- **Key symbols**: the 2-6 most important symbols, with their role explained
- **Workflow**: how the feature works end-to-end (optional, include when non-obvious)
- **Constraints**: rules/invariants (optional, include when they exist)
- **No source code** in _FEATURES.md — it's a map, not a mirror

### What makes a good feature entry

Good: "**Memory Storage** — Persist observations across sessions. Stores typed,
tagged memories to a Turso database with BM25 full-text search. Memories have
priority levels that affect retrieval ranking."

Bad: "**memory.py** — Contains `remember()`, `recall()`, `forget()`, and
`supersede()` functions."

The first tells you WHAT you can do. The second describes file contents —
tree-sitting already gives you that.

### Identifying features

Heuristics for finding feature boundaries:

- **Entry points** (main, CLI commands, route handlers) often map 1:1 to features
- **Public API functions** that aren't helpers are usually feature surfaces
- **Type hierarchies** (class + methods) often represent a cohesive feature
- **Config/constants clusters** sometimes reveal features (e.g., a group of
  timeout constants → a retry feature)
- **Import clusters** — files that import each other heavily are likely
  co-implementing a feature

Features to SKIP in _FEATURES.md:
- Pure infrastructure (logging, error handling) unless it's the project's purpose
- Internal utilities that only serve other features
- Test code (unless the testing approach IS a feature, e.g., a testing framework)

## Keeping _FEATURES.md in Sync

Three mechanisms, layered:

### 1. Check script (detect drift)

```bash
/home/claude/.venv/bin/python /mnt/skills/user/featuring/scripts/check.py /path/to/repo \
  [--features _FEATURES.md] [--skip tests,.github]
```

Parses `file#symbol` references from _FEATURES.md, resolves them against the
live codebase via tree-sitting, and reports:

- **Broken refs** — symbol deleted or renamed (exit code 1)
- **Moved symbols** — symbol exists but in a different file than referenced
- **Dead features** — ALL key symbols in a feature section are gone
- **Uncovered symbols** — new public API not mentioned in any feature

Exit code 0 = clean, 1 = drift detected. Suitable for CI or pre-commit hooks.

### 2. Agent instructions (prevent drift)

Add to CLAUDE.md or equivalent:

```markdown
## Feature Documentation

- `_FEATURES.md` documents what this codebase does, organized by capability.
- After changing behavior (new feature, renamed API, deleted functionality):
  run `python featuring/scripts/check.py .` and fix any broken refs.
- After adding a new public API surface: add it to the appropriate feature
  section, or create a new feature section if it's a new capability.
- Run check before committing. Broken refs = broken documentation.
```

### 3. Targeted regeneration (fix drift)

When check reports broken refs, the fix is usually surgical: update the
`file#symbol` reference to the new name/location. For dead features (all refs
gone), either delete the section or regenerate it:

```bash
# Re-gather structural data for the affected area
/home/claude/.venv/bin/python /mnt/skills/user/featuring/scripts/gather.py /path/to/repo

# Then use LLM to rewrite just the broken feature sections
```

Full regeneration (re-running gather + LLM synthesis for everything) is the
nuclear option. Prefer targeted updates — they're cheaper and preserve
hand-written narrative.

### CI Integration

```yaml
# .github/workflows/features-check.yml
name: Check _FEATURES.md
on: [push, pull_request]
jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: astral-sh/setup-uv@v4
      - run: uv pip install tree-sitter-language-pack
      - run: python featuring/scripts/check.py . --skip tests
```

## Claude Code Integration

In Claude Code, the tree-sitting MCP server replaces the gather script.
The agent should:

1. Call `scan()` to parse the codebase
2. Call `tree_overview()` for orientation
3. Call `dir_overview()` and `file_symbols()` to understand each module
4. Call `get_source()` for key symbols where intent isn't clear from signatures
5. Write `_FEATURES.md` directly

Add to CLAUDE.md:
```markdown
## Codebase Understanding

Read `_FEATURES.md` for top-down feature orientation before modifying code.
Use tree-sitting MCP tools for structural queries (symbol lookup, source retrieval).
After adding new features or changing behavior, update `_FEATURES.md`.
```

## Example

For the `remembering` skill (memory system), gather.py would produce structural
data showing 21 functions in memory.py, 6 in config.py, etc. The synthesized
_FEATURES.md would group these into:

- **Memory Storage** — `memory.py#remember`, `memory.py#remember_batch`
- **Memory Retrieval** — `memory.py#recall`, `memory.py#recall_batch`, `memory.py#recall_since`
- **Memory Lifecycle** — `memory.py#forget`, `memory.py#supersede`, `memory.py#reprioritize`
- **Memory Maintenance** — `memory.py#consolidate`, `memory.py#curate`, `memory.py#prune_by_age`
- **Decision Tracing** — `memory.py#decision_trace`, `memory.py#get_alternatives`, `memory.py#get_chain`
- **Configuration** — `config.py#config_get`, `config.py#config_set`
- **Task Tracking** — `task.py#Task`, `task.py#task`, `task.py#task_resume`
- **Boot** — `boot.py#boot`, `boot.py#profile`, `boot.py#ops`

Each with narrative explaining what a user gets, not just what the function does.

## Large Repos

For repos with >50 files across distinct subsystems, generate one `_FEATURES.md`
per subsystem directory rather than a single monolithic file. Link them from a
root `_FEATURES.md` index:

```markdown
# Features: {project}

- [{subsystem-a}](subsystem-a/_FEATURES.md) — what subsystem-a does
- [{subsystem-b}](subsystem-b/_FEATURES.md) — what subsystem-b does
```

## Relationship to Other Skills

| Skill | What it provides | Drift detection |
|-------|-----------------|-----------------|
| **tree-sitting** | Structural inventory (symbols, signatures) | N/A (live queries) |
| **featuring** | Feature documentation (what/why) | `check.py` — one-directional (docs → code) |
| **generating-lattice** | Bidirectional knowledge graph | `lat check` — bidirectional (docs ↔ code) |
| **mapping-webapp** | Web app behavioral docs (pages, flows) | None |

featuring's check is lighter than lattice's: no source code annotations needed,
no `@lat:` comments, just reference resolution. The trade-off is that new code
without docs is only flagged as "uncovered symbols" — it's advisory, not
enforced. Use lattice when you need strict bidirectional traceability; use
featuring when you need good-enough orientation docs that catch renames and
deletions.