Loading...
Loading...
Maintains persistent codebase knowledge across sessions through a structured knowledge graph stored in a local Obsidian vault (.doctrack/). Use this skill whenever you have just made meaningful code changes (new features, modified components, refactoring, bug fixes) to update the project's documentation. Also use it when the user asks to document code, update docs, sync documentation, initialize documentation for an existing project, or when you want to understand the existing codebase structure at the start of a session. This skill should be used proactively after any significant code modification — don't wait for the user to ask. If you changed code, update the docs. Think of it as your long-term memory system: read before working, write after changing. Also use this when a user says "doctrack init", "doctrack refresh", "refresh docs", "update docs", "sync docs", "initialize docs", "document this project", or wants to bootstrap documentation for a codebase that has no .doctrack/ vault yet.
npx skill4agent add liamstar97/doctrack doctrack.doctrack/bitbonsai/mcpvault[[wikilinks]]| Node | Directory | Purpose | Audience |
|---|---|---|---|
| Features | | What the system does. High-level functional units. | Claude |
| Components | | How pieces work internally. Dense implementation details. | Claude |
| Concepts | | Cross-cutting ideas and patterns spanning multiple features. | Claude + Human |
| Decisions | | Why things are the way they are — including rejected alternatives. | Claude + Human |
| Interfaces | | Contracts and boundaries between features or packages. | Claude + Human |
| Guides | | Procedural docs only: build, deploy, test, setup workflows. | Human |
| Specs | | Machine-readable specifications (OpenAPI, schemas). | Machine |
| References | | Imported pre-existing docs and user-provided materials. | Claude |
internal-linkgraph TD
A[Auth Service] --> B[Token Validator]
B --> C[User Store]
class A,B,C internal-link;.mdinternal-link[[wikilinks]]classDefclassDef internal fill:#e1f5fe#e1f5fe#| Category | Tags |
|---|---|
| Type | |
| Status | |
| Audience | |
doctrack/project/{name}doctrack/package/{name}doctrack/dojo/authkeycloakmongodb.doctrack/.doctrack/_project.mddoctrack init_project.mdCurrent phasecompletedoctrack init.doctrack/CLAUDE.mdmcp__obsidian__*_project.md.mcp.json.mcp.json{
"mcpServers": {
"obsidian": {
"command": "npx",
"args": ["@bitbonsai/mcpvault@latest", ".doctrack"]
}
}
}.doctrack.mcp.json.doctrack/_project.mddoctrack_versiontimeout 2 doctrack-mcp --version 2>/dev/null || echo "unknown"doctrack-mcp {version} ({git-hash})0.1.0command not foundcargocargo install --git https://github.com/liamstar97/doctrack.git dt-mcpunknowncargo install --git https://github.com/liamstar97/doctrack.git dt-mcp --forcecargomcp__doctrack__*cargo install --git https://github.com/liamstar97/doctrack.git dt-mcprefresh_docspatch_notewrite_noteresolve_symbollast_updatedvalidate_noterefresh_docsrefresh_docscheck_impactvalidate_noterefresh_docsproject-root/
├── .doctrack/ # Obsidian vault — committed to git
│ ├── .obsidian/ # Obsidian config
│ ├── _project.md # Project config — always read first
│ ├── features/
│ ├── components/
│ ├── concepts/
│ ├── decisions/
│ ├── interfaces/
│ ├── guides/
│ ├── specs/
│ └── references/
├── README.md
├── CLAUDE.md
└── src/.doctrack/
├── _project.md # Root: package map, cross-package deps
├── packages/
│ └── {package-name}/
│ ├── _package.md
│ ├── features/ components/ concepts/ decisions/ interfaces/
│ └── ...
├── concepts/ # Monorepo-wide concepts
├── decisions/ # Monorepo-wide decisions
├── interfaces/ # Cross-package contracts
├── guides/
└── references/projects/{name}/_doctrack.md_project.md---
project: {project-name}
type: index
doctrack_version: "3.0.0"
monorepo: false
initialized: YYYY-MM-DD
last_updated: YYYY-MM-DD
---
# {Project Name}
## Features
| Feature | Note | Description | Status |
|---------|------|-------------|--------|
## File Registry
List individual source files, not directories. Each row maps a specific file to its feature and component.
| Source File | Feature | Component |
|------------|---------|-----------|
| src/controllers/UserController.java | user-management | user-controller |
| src/services/AuthService.java | authentication | auth-service-impl |doctrack/type/indexdoctrack/status/activedoctrack/audience/claudefeatures/{name}.md---
feature: feature-name
type: feature
doctrack_version: "3.0.0"
files:
- src/path/to/file.ts
last_updated: YYYY-MM-DD
status: active
---
# Feature Name
## Purpose
What this feature does and why it exists.
## Architecture
```mermaid
flowchart TD
A[Entry Point] --> B{Router}
B --> C[Handler]
C --> D[Service Layer]
class A,B,C,D internal-link;src/path/to/file.ts
Tags: `doctrack/type/feature`, `doctrack/status/active`, `doctrack/audience/claude`
### Component note (`components/{feature}/{name}.md`)
```markdown
---
feature: parent-feature
type: component
files:
- src/path/to/component.ts
last_updated: YYYY-MM-DD
status: active
---
# Component Name
## Responsibility
Single-sentence description.
## Internal Logic
```mermaid
stateDiagram-v2
[*] --> Idle
Idle --> Active : trigger()
Active --> Idle : complete()
Tags: `doctrack/type/component`, `doctrack/status/active`, `doctrack/audience/claude`
### Concept note (`concepts/{name}.md`)
Cross-cutting ideas that span multiple features. Create one when a pattern, model, or architectural idea connects disparate parts of the codebase.
```markdown
---
type: concept
related_features:
- feature-a
- feature-b
last_updated: YYYY-MM-DD
status: active
---
# Concept Name
## What it is
Clear explanation and why it matters.
## Where it appears
```mermaid
graph LR
C[Concept] --> F1[Feature A]
C --> F2[Feature B]
C --> I[Interface]
class C,F1,F2,I internal-link;
Tags: `doctrack/type/concept`, `doctrack/status/active`, `doctrack/audience/claude`
### Decision note (`decisions/{name}.md`)
Records **why** something was built a certain way — including rejected alternatives. This prevents re-proposing approaches that were already considered.
```markdown
---
type: decision
status: accepted|rejected|superseded
date: YYYY-MM-DD
superseded_by: other-decision # only if superseded
related_features:
- feature-a
last_updated: YYYY-MM-DD
---
# Decision: Title
## Status
**Accepted** | **Rejected** | **Superseded by [[decisions/other|Other]]**
## Context
What problem were we solving? What constraints existed?
## Decision
What we chose (or chose NOT to do, if rejected).
## Alternatives considered
| Alternative | Pros | Cons | Why rejected |
|-------------|------|------|-------------|
| Option A | Fast | Fragile | Couldn't handle scale |
| Option B | Simple | Limited | Missing feature X |
## Consequences
What changed. Trade-offs accepted. Known limitations.doctrack/type/decisiondoctrack/status/{accepted|rejected}doctrack/audience/claudeinterfaces/{name}.md---
type: interface
implementors:
- feature-a
- feature-b
consumers:
- feature-c
last_updated: YYYY-MM-DD
status: active
---
# Interface: Name
## Contract
```mermaid
classDiagram
class HealthData {
+String _id
+int current_heart_rate
+int total_steps
}
Tags: `doctrack/type/interface`, `doctrack/status/active`, `doctrack/audience/claude`
### Guide note (`guides/{name}.md`)
**Procedural docs only** — things a developer follows step-by-step.
Valid guides: `deployment.md`, `development.md`, `setup.md`, `testing.md`
NOT guides: architecture overviews (→ concepts), feature explanations (→ features), API docs (→ specs/interfaces).
Tags: `doctrack/type/guide`, `doctrack/status/active`, `doctrack/audience/human`
## Doctrack MCP integration
When the `doctrack` MCP server is available (tools prefixed `mcp__doctrack__`), use it to write better documentation and keep the vault healthy. The MCP server maintains a bidirectional index between code symbols and vault notes.
### Available tools
| Tool | Input | Purpose |
|------|-------|---------|
| `validate_note` | `note` (vault-relative path) | Check a note for stale refs, broken wikilinks, ambiguous references |
| `docs_for_file` | `file` (project-relative path) | Find all vault notes that document a code file |
| `resolve_symbol` | `name` (e.g. `SessionManager`) | Look up where a symbol is defined and which notes reference it |
| `check_impact` | `file` (project-relative path) | After code changes, find which vault notes may need updating |
| `refresh_docs` | *(none)* | Scan vault and generate prioritized plan of stale documentation |
| `coverage_report` | *(none)* | Vault health — note count, code files, link coverage, undocumented files |
| `stale_report` | *(none)* | Full list of broken file refs and wikilinks across the vault |
| `search_index` | `query` (keywords) | Fuzzy search across note titles, summaries, tags, and code symbols |
### During code changes
1. **Before modifying code**: Call `docs_for_file` with the file you're about to change. Read the linked vault notes to understand the documented architecture and contracts before making changes.
2. **After modifying code**: Call `check_impact` with the changed file path to see which vault notes reference it. Update those notes if the changes affect documented behavior, renamed symbols, or moved files.
### During documentation writing
1. **Before writing a note**: Call `resolve_symbol` to get accurate file paths and line numbers for symbols you're documenting. Use the resolved paths in `files:` frontmatter and `file-registry` entries — don't guess or abbreviate paths.
2. **After writing or updating a note**: Call `validate_note` with the note path (relative to vault root, e.g. `features/auth.md`). Fix any stale references, ambiguous file refs, or broken wikilinks it reports before moving on.
### Refreshing stale documentation
Call `refresh_docs` to get a prioritized plan of what needs updating. It compares note `last_updated` timestamps against code file modification times, detects new/missing symbols, and finds broken references. Use it:
- **At session start** (after reading `_project.md`) to see what's drifted since last session
- **After a batch of code changes** to identify all impacted docs at once
- **After updating docs** to verify nothing remains stale (idempotent — returns empty when everything is current)
The tool returns a prioritized list (HIGH/MEDIUM/LOW) with specific reasons per note. Work through them in priority order — HIGH means broken refs or code changed significantly, LOW means minor symbol drift.
### For vault health
- Call `coverage_report` during Phase 4 verification to see overall vault health, undocumented code files, and stale reference counts.
- Call `stale_report` to get the full list of broken references for a cleanup pass.
- Call `search_index` to find existing notes before creating duplicates.
### File path best practices (for MCP indexing)
The MCP server resolves file references in your notes. Help it by:
- **Use full relative paths** in `files:` frontmatter: `custom-actions/src/main/java/com/iointel/ci/actions/Action.java` not `Action.java` or `.../Action.java`
- **Avoid `...` abbreviations** in paths — the indexer can expand them but full paths are more reliable
- **Avoid glob patterns** like `*Exception.java` in file references — they can't be resolved
- **Use backtick code spans** for inline file references: `` `src/auth/session.rs` `` — the indexer extracts these
## Important principles
1. **Read before writing.** Search for existing notes before creating new ones.
2. **Dense internal docs.** Features and components are for Claude — pack them with information.
3. **Document decisions, especially rejections.** The "why not" is as valuable as the "why."
4. **Concepts connect the graph.** When a pattern spans features, create a concept note and link everything to it.
5. **Interfaces define boundaries.** When features communicate, document the contract.
6. **Guides are procedural only.** Build, deploy, test, setup. Not explanations.
7. **Mermaid everywhere.** All diagrams. No ASCII art. Use `class NodeId internal-link;` to make nodes clickable links to notes — never put `[[wikilinks]]` inside Mermaid code blocks.
8. **Incremental updates.** Surgical edits, not full rewrites.
9. **Timestamp everything.** Update `last_updated` on every modification.
10. **Local vault is the default.** `.doctrack/` in the project directory, committed to git.
11. **Wikilinks are edges.** Every cross-reference uses `[[path|Display]]` syntax.
---
## Version tracking and migration
Current version: `3.0.0`.
### Version history
| Version | Key changes |
|---------|-------------|
| **1.x** | Filesystem-only (`.claude_docs/` + `docs/`). Docs as files in repo. |
| **2.0** | Local Obsidian vault (`.doctrack/`). Knowledge graph (concepts, decisions, interfaces). Mermaid diagrams. Depth-first init. Delegates vault I/O to obsidian skill (mcpvault). |
| **3.0** | Companion `doctrack-mcp` Rust binary. Bidirectional code↔doc index via tree-sitter. MCP tools for validation, impact analysis, coverage, search. Claude Code hooks for proactive feedback. LSP server for editor integration. |
### Version checking (during session init)
After reading `_project.md`, check `doctrack_version`:
1. **Missing** → v1.x filesystem docs. Offer migration.
2. **Matches** → proceed normally.
3. **Same major, older minor** → proceed, silently update version stamp.
4. **Older major** → inform user, offer migration. Don't auto-migrate.
5. **Newer than skill** → warn user, proceed carefully.
### Migration: v1 → v3
When `.claude_docs/` exists but no `.doctrack/`:
1. Read v1 docs (index, features, components — they have structured frontmatter)
2. Create `.doctrack/` vault with `.obsidian/` and `.gitignore`
3. Convert v1 notes to vault notes (convert cross-refs to wikilinks, add tags)
4. Extract implicit concepts and decisions from v1 content
5. Write `_project.md` from v1 index
6. Write `CLAUDE.md` section
7. Ask user: archive or clean up old `.claude_docs/` and `docs/`
### Migration: v2 → v3
When `_project.md` exists with `doctrack_version: "2.x"`:
1. Add `concepts/`, `decisions/`, `interfaces/` directories
2. Move non-procedural guides to `concepts/` or deprecate
3. Convert ASCII art to Mermaid in existing notes
4. Update version stamp
5. If vault is external, offer to move to local `.doctrack/`
---
## Project initialization
When the user says "doctrack init" or asks to document a project.
### Pre-init
#### Step 1: Install dependencies
**Check for obsidian skill**: Look for `mcp__obsidian__*` tools in the available tools.
If MCP tools are NOT available:
1. Check if `.mcp.json` exists in the project root. If it has an `obsidian` server entry, the MCP server is configured but Claude Code needs a restart.
2. If no `.mcp.json`, check if the obsidian skill is installed by looking for `.claude/skills/obsidian/` or `.agents/skills/obsidian/`.
3. If the obsidian skill is not installed, install it:
```bash
npx skills add bitbonsai/mcpvault --yes.mcp.json{
"mcpServers": {
"obsidian": {
"command": "npx",
"args": ["@bitbonsai/mcpvault@latest", ".doctrack"]
},
"doctrack": {
"command": "doctrack-mcp"
}
}
}.doctrackdoctrack-mcpDOCTRACK_ROOT.mcp.jsondoctrackdoctrack-mcpwhich doctrack-mcp.doctrack/.doctrack/.obsidian/.doctrack/.gitignore.mcp.jsondoctrack-mcpwhich doctrack-mcpcargo install --git https://github.com/liamstar97/doctrack.git dt-mcpcargocargo install dt-mcpdoctrack.mcp.jsonobsidiandoctrack-mcpdoctrack.mcp.jsondoctrack-mcp --setup-hooks.claude/settings.json"I've set up the doctrack dependencies:
- Installed the obsidian skill (mcpvault)
- Configured the MCP server(s) in
.mcp.json- Created the
vault directory.doctrack/- Installed Claude Code hooks (if doctrack-mcp is available)
Please restart Claude Code (exit and relaunch), then sayagain. The MCP server needs a restart to connect to the vault."doctrack init
.doctrack/.doctrack/.obsidian/.doctrack/.gitignore.obsidian/workspace.json
.obsidian/workspace-mobile.json
.obsidian/appearance.json
.obsidian/hotkeys.json
.obsidian/app.json
.obsidian/graph.jsonget_vault_stats.mcp.jsonobsidian open path="{absolute-path}/.doctrack".doctrack/package.jsonname.claude_docs/_project.mdworkspacespackage.jsonpnpm-workspace.yamllerna.jsonturbo.jsonnx.json<modules>pom.xmlincludesettings.gradlesettings.gradle.kts[workspace]Cargo.tomlgo.mod.gitmodulespackages/apps/services/libs/.git_project.mdpom.xmlpackage.jsonbuild.gradleCargo.tomlREADME.mdCLAUDE.mddocs/documentation/wiki/adr/decisions/.mdreferences/imported/{filename}.mdoriginal_pathdoctrack/type/reference.doctrack/archive/_project.mdStatus## Init Progress
Current phase: **phase-1**
### Modules
| Module | Files | Status | Components |
|--------|-------|--------|------------|
| ci-model | 43 | pending | — |
| ci-common | 11 | pending | — |
| story-service | 300 | pending | — |
### Phase 3 Checklist
| Category | Target | Created | Status |
|----------|--------|---------|--------|
| Concepts | 6-10 | 0 | pending |
| Decisions | 5-8 | 0 | pending |
| Interfaces | 4-8 | 0 | pending |
| References | all docs | 0 | pending |
| README | — | — | pending |
| CLAUDE.md | — | — | pending |
| Guides | — | — | pending |Current phasephase-1phase-2phase-3phase-4completedoneCreatedStatus| Module size | Expected components |
|---|---|
| 1-2 files | 0 (feature note is sufficient) |
| 3-10 files | 2-5 components |
| 10-30 files | 5-15 components |
| 30-100 files | 15-30 components |
| 100+ files | 30+ components |
_project.mdpatch_noteCurrent phasephase-2doneYou are documenting the "{module-name}" module for doctrack. Go DEEP.
Module path: {path}
Source files: {count} files
Module dependencies: {list of other modules this depends on}
Already-documented modules (for cross-referencing): {list with vault paths}
CRITICAL: Write each note IMMEDIATELY after creating it — do NOT batch writes.
The session may end at any time due to usage limits. Every note you write to
the vault before that happens is preserved. Every note you defer is lost.
Workflow:
1. Read source files in groups of 5-10
2. Write features/{module-name}.md as soon as you understand the architecture
3. Write components/{module-name}/{component}.md ONE AT A TIME as you identify each
4. Tag each note immediately after writing
5. Return: vault paths created + file registry entries (individual files)
A module with {count} files should produce roughly {count/5 to count/3} components.
Use internal-link class in Mermaid nodes. Use [[wikilinks]] in markdown content only.
Do NOT use classDef with hex colors (#e1f5fe etc.) — Obsidian creates spurious tags.
Vault paths must be clean note paths (e.g., features/auth.md, components/auth/token.md).
Never write notes with paths containing wildcards, code patterns, or Java package names.Current phasephase-3_project.md_project.md_project.mdCreated: {count}Status: donedonedonereferences/imported/{filename}.mddoctrack/type/referencedoneREADME.mdCLAUDE.md# Doctrack# Doctrack
This project maintains a knowledge graph in `.doctrack/` (Obsidian vault).
## BEFORE writing any code
You MUST read relevant documentation before planning or implementing changes:
1. Read `.doctrack/_project.md` for project structure and module map
2. Search the vault for features related to the code you'll touch:
- Use `mcp__obsidian__search_notes` with the module/feature name
- Read the matching feature note and its component notes
3. Check `concepts/` for cross-cutting patterns that may affect your approach
4. Check `decisions/` for past choices and rejected alternatives — do NOT re-propose
approaches that were already considered and rejected
This context prevents duplicate work, respects architectural decisions, and ensures
your changes align with existing patterns.
## AFTER modifying code files
You MUST update the knowledge graph to reflect your changes:
1. Update the feature note if the feature's architecture, dependencies, or API changed
2. Update or create component notes for any classes/modules you modified or added
3. Create a decision note if you made a non-trivial design choice — include
alternatives you considered and why you rejected them
4. Update interfaces if contracts between modules changed
5. Create a concept note if you introduced a new cross-cutting pattern
6. Update `_project.md` file registry if you added new source files
Do NOT skip documentation updates. The knowledge graph is how future sessions
understand this codebase without re-reading source files.
## Vault connection
- Vault path: `.doctrack/`
- MCP servers: configured in `.mcp.json` (obsidian server for vault I/O, doctrack server for code↔doc index)
- If MCP tools are unavailable: read/write `.doctrack/` files directly from filesystem.claude/settings.json.claude/settings.json{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "test -f .doctrack/_project.md && echo 'Doctrack vault detected at .doctrack/. Read _project.md and relevant feature/component notes before starting work. Check decisions/ for past architectural choices.' || true",
"statusMessage": "Checking for doctrack..."
}
]
}
]
}
}doctrack-mcpwhich doctrack-mcpdoctrack-mcp --setup-hooks.claude/settings.json.claude/settings.jsonguides/development.mdguides/deployment.mdspecs/openapi.mdCurrent phasephase-4_project.mdCurrent phasecomplete_project.md_project.mdCurrent phaseCurrent phasephase-1Current phasephase-2pendingdoneCurrent phasephase-3pendingdonependingCurrent phasephase-4Current phasecomplete.doctrack/doctrack init<modules>include[workspace].gitmodulesgo.mod_project.mdpackages/{name}/doctrack/package/{name}_project.mdediting_agentuser-authentication.mdtoken-validator.mdhealth-data-model.mdchose-firestore.mdrejected-websockets.mdhealth-data-schema.md