| name | index-init |
| description | Generate a complete project index with per-module README files for efficient code navigation. Use when starting work on a new project or after major restructuring. Run once per project. |
| disable-model-invocation | true |
| allowed-tools | ["Read","Write","Edit","Glob","Grep","Bash","AskUserQuestion"] |
/index-init
Generate a complete project index with per-module README files.
Step 1: Announce
Say: "I'm using the index-init skill to generate a project index."
Step 2: Detect project type
Glob the root directory for these signals. Use first match wins priority:
| Priority | Signal | Type | Module detection |
|---|
| 1 | CMakeLists.txt containing add_subdirectory() | cpp-cmake | Each add_subdirectory() argument = module |
| 2 | Cargo.toml containing [workspace] | rust-cargo | Each members entry = crate |
| 3 | go.work or multiple go.mod | go | Each use directive or go.mod directory = module |
| 4 | package.json containing "workspaces" | node-workspaces | Each workspace pattern match = package |
| 5 | *.sln file | dotnet | Each .csproj referenced = project |
| 6 | pom.xml containing <modules> | java-maven | Each <module> = subproject |
| 7 | build.gradle or settings.gradle containing include | java-gradle | Each include(':...') = subproject |
| 8 | pyproject.toml or setup.py | python | Packages or top-level dirs with __init__.py |
| 9 | pubspec.yaml | dart-flutter | Top-level or packages/ dirs |
| 10 | Fallback | generic | Top-level dirs containing source files (.cpp, .py, .js, .ts, .rs, .go, .java, .cs, .dart) |
For each detected type, extract:
- Modules: from build/manifest files as described above
- Purpose: from comments, description fields, docstrings, existing README content
- Dependencies: from link directives (
target_link_libraries), imports, manifest deps
- Public API: from interface files (I*.h), exports, pub functions โ names + method signatures only
- Files: use
git ls-files (respects .gitignore) to list source + config files per module. Fallback to Glob if not a git repo.
Never index: .env, .env.*, .git/, *.key, *.pem, .npmrc, .pypirc, .aws/, .ssh/, *credentials*, *secret*, *token*, binary blobs (images, compiled objects, archives).
Step 3: Generate <Module>/README.md for each module
For each module, create or update <Module>/README.md using this template:
# <Module Name>
<!-- AUTO-GENERATED by /index-init โ do not edit above CUSTOM section -->
## Purpose
<1-2 sentences describing what this module does>
## Architecture
<ASCII diagram if inferrable from code structure, otherwise omit this section>
## Public API
- **IClassName** โ `method1()`, `method2()`, `method3()`
- **ClassName** โ `publicMethod1()`, `publicMethod2()`
## Files
| File | Tags | Description |
|------|------|-------------|
| `relative/path/to/file.ext` | [tag1, tag2] | Short description (<80 chars) |
## Dependencies
- **Internal**: Module1, Module2
- **External**: Library1 v1.2, Library2
## Configs & Scripts
| File | Description |
|------|-------------|
| `CMakeLists.txt` | Build configuration |
| `config.json` | Runtime configuration |
<!-- AUTO-GENERATED END -->
<!-- CUSTOM โ your notes below survive re-indexing -->
Rules:
- If README.md already exists and contains a
<!-- CUSTOM section, PRESERVE its content entirely
- Generate tags from: file name patterns, class names found in file, function names, import/include keywords
- Generate descriptions from: first comment block, docstring, class/function declarations, or inferred from naming
- Include non-code files:
.json, .yaml, .toml, Dockerfile, *.sh, *.ps1, CI config files
- Keep file descriptions under 80 characters
Step 4a: Generate .claude/index.summary.md
This lightweight file is injected at session start. Hard cap: 4KB.
# Project Index (Summary)
<!-- AUTO-GENERATED by /index-init -->
Generated: <YYYY-MM-DD HH:MM> | Type: <project-type> | Modules: <count> | Files: <total-count>
Read `.claude/index.md` for full index with dependency graph and tag index.
Read `<Module>/README.md` for detailed module documentation.
## Modules
| Module | Purpose | Key Tags |
|--------|---------|----------|
| ModuleName | Short purpose (<60 chars) | tag1, tag2, tag3 |
<!-- AUTO-GENERATED END -->
Rules:
- No CUSTOM section (auto-regenerated, never hand-edited)
- Keep module purposes under 60 chars
- If the file would exceed 4KB, truncate the module table with:
| ... | N more modules. See .claude/index.md | |
Step 4b: Generate .claude/index.md
Full index file. Claude reads this on demand for details.
# Project Index
<!-- AUTO-GENERATED by /index-init -->
Generated: <YYYY-MM-DD HH:MM> | Type: <project-type> | Modules: <count> | Files: <total-count>
## How to Use
The summary is injected at session start. Read module READMEs for file-level detail.
See CLAUDE.md "Code Navigation" section for the search strategy.
## Modules
| Module | Purpose | Tags | README |
|--------|---------|------|--------|
| ModuleName | Short purpose | [tag1, tag2] | [README](../ModuleName/README.md) |
## Dependency Graph
ModuleA โ (foundation)
โโโ ModuleB โ ModuleA
โโโ ModuleC โ ModuleA, ModuleB
โโโ MainApp โ all modules
## Tag Index
tag-name: Module1, Module2
another-tag: Module3, Module4
<!-- AUTO-GENERATED END -->
<!-- CUSTOM -->
Step 5: Update CLAUDE.md
Read the existing CLAUDE.md. If it already has a "Code Index" or "Code Navigation" section, update it. Otherwise, append this section:
## Code Navigation
When you need to search the codebase and don't already know the exact file:
1. Read `.claude/index.md` โ Tag Index to find which module(s) own the topic
2. Read `<Module>/README.md` โ exact file paths, classes, responsibilities
3. Grep/glob within that module โ not the whole repo
Skip this if you already know the file path. This is for discovery, not mandatory ritual.
Index files: `.claude/index.md` (full), `.claude/index.summary.md` (session start), `<Module>/README.md` (per-module). Re-index: `/index-init`
Step 6: Handle --gitignore flag
If $ARGUMENTS contains --gitignore:
Step 7: Completion
Summarize what was generated:
- Project type detected
- Number of modules indexed
- Number of files catalogued
- Remind user that hooks are provided by the plugin (auto-registered via hooks.json)
- Suggest running
/index-status to verify