repoctl is a repo-agnostic command-line tool for deterministic local repository indexing, search, and navigation.
Use it when you want a lightweight catalog of a directory: Markdown documents, headings, links, chunks for full-text search, extracted record-like items, relationships, diagnostics, and a small review-gated knowledge overlay. It is designed as boilerplate for arbitrary repositories, not as a hosted search service or content-management system.
repoctl helps you answer questions such as:
- What documents and extracted items exist in this repo?
- Where is a topic mentioned?
- What links to this file or item?
- Which local Markdown links are broken?
- Which extracted items have upcoming
target_dateorreview_datevalues? - What human-reviewed relationships or notes should supplement source content?
repoctl does not make generated files canonical. Your source files remain the source of truth. Everything under index/generated/ and index/reports/ can be deleted and rebuilt.
From this project checkout:
pip install -e /path/to/repoctl
repoctl --helpFor development, install the optional test dependencies:
pip install -e /path/to/repoctl[dev]
pytest -q /path/to/repoctl/testsRun repoctl from the directory you want to index:
pip install -e /path/to/repoctl
cd /path/to/your/repo
repoctl init
repoctl index build
repoctl find onboarding
repoctl search "release checklist"
repoctl show README.md
repoctl related docs/example.md
repoctl index doctorrepoctl init creates an index/ scaffold in the current directory. repoctl index build scans the current directory, writes deterministic generated artifacts, and builds a local SQLite catalog.
After initialization, the target repository contains:
index/
README.md
config/
rules.yaml
aliases.json
overrides.jsonl
ignore-globs.txt
knowledge/
curated.jsonl
ai-suggestions.jsonl
rejected.jsonl
schema/
*.schema.json
Tracked, durable files:
index/README.mdexplains the local scaffold.index/config/controls scanning, classification, aliases, overrides, and extractors.index/knowledge/stores accepted, suggested, and rejected overlay records.index/schema/documents JSONL shapes for generated and knowledge records.
Generated, disposable files:
index/generated/contains JSONL outputs,stats.json, andcatalog.sqlite.index/reports/contains diagnostic reports such as broken links and stale-index findings.
Commit the tracked scaffold files if you want collaborators to share the same indexing behavior. Do not commit generated output unless you intentionally want to snapshot it.
Common commands:
repoctl initcreates the trackedindex/scaffold. Use--dry-runto preview and--forceto overwrite existing scaffold files.repoctl index buildscans files, parses Markdown, extracts configured items, resolves links, writes JSONL artifacts, and builds the SQLite catalog.repoctl index statssummarizes generated tables, views, and search indexes.repoctl index doctorruns deterministic diagnostics and refreshes reports.repoctl find <query>resolves documents and items by path, title, alias, ID, or key.repoctl search <query>runs full-text search over documents, chunks, and items.repoctl show <target>displays one document or item.repoctl related <target>shows outbound relationships.repoctl backlinks <target>shows inbound relationships.repoctl list --entity documentorrepoctl list --entity itemlists catalog records.repoctl stalereports stale generated output and old draft/working documents.repoctl duereports open extracted items withtarget_dateorreview_datevalues.repoctl knowledge ...manages the review-gated knowledge overlay.repoctl enrich suggest --dry-runpreviews conservative generic enrichment suggestions.
Most query commands support --json for machine-readable output. Relationship queries can use --include-knowledge to include accepted curated overlay assertions.
The main configuration file is index/config/rules.yaml. The default scaffold is intentionally generic:
- common noise directories are excluded;
- common binary/data formats are tracked as metadata only;
- Markdown files are classified as generic
markdown_documentrecords; - no special extractors are enabled by default.
A minimal default classification rule looks like this:
classification_rules:
- path_glob: "**/*.md"
doc_type: markdown_document
domain: repo
canonical: true
status: active
source_kind: markdownUseful companion files:
index/config/ignore-globs.txtadds line-based ignore patterns.index/config/aliases.jsonmaps friendly aliases to paths or IDs.index/config/overrides.jsonlrecords explicit metadata overrides with reasons.
After changing configuration, run repoctl index build again.
Extractors turn structured Markdown content into generic record_items. They are opt-in and configured under special_extractors in index/config/rules.yaml.
Supported extractors:
markdown_table_recordsextracts one item per table row.section_recordsextracts one item per structured Markdown section.
Given docs/tasks.md:
# Tasks
| id | title | status | owner | target_date |
| --- | --- | --- | --- | --- |
| TASK-001 | Draft release checklist | open | Alex | 2026-06-15 |
| TASK-002 | Review onboarding notes | done | Sam | 2026-06-30 |Enable extraction:
special_extractors:
- path: docs/tasks.md
extractor: markdown_table_records
item_kind: taskThe table extractor looks for an item key in columns such as id, item_id, key, item_key, slug, or name. It maps common fields such as title, status, owner, priority, target_date, and review_date into structured item attributes. Other columns remain available in the generated item fields.
Given sections like:
## DEC-001 Choose release process
- status: accepted
- owner: Alex
- review_date: 2026-09-01
- notes: Keep the process lightweight.Enable extraction:
special_extractors:
- path: docs/decisions.md
extractor: section_records
item_kind: decisionThe section extractor uses a semantic ID in the heading when present, or fields such as id, item_id, key, item_key, or date.
The knowledge overlay stores reviewed assertions that supplement, but do not replace, source content.
index/knowledge/curated.jsonlcontains accepted human-curated assertions.index/knowledge/ai-suggestions.jsonlcontains untrusted suggestions awaiting review.index/knowledge/rejected.jsonlrecords rejected suggestions.
Example curated relationship:
repoctl knowledge add --from README.md --relation related_to --to docs/example.md
repoctl knowledge list
repoctl related README.md --include-knowledgeAI suggestions are not included in normal query results. Promote or reject them explicitly:
repoctl knowledge review
repoctl knowledge accept know:ai:0001
repoctl knowledge reject know:ai:0002repoctl index doctor and related commands provide repository health checks that are useful across domains:
- stale generated output;
- broken Markdown links;
- unresolved item-like mentions;
- orphan documents;
- duplicate document titles;
- alias collisions;
- parse errors;
- due or overdue extracted items based on
target_dateandreview_date.
Reports are written under index/reports/ and can be regenerated at any time.
repoctl separates durable inputs from rebuildable outputs:
- Track:
index/config/,index/knowledge/,index/schema/, andindex/README.md. - Ignore:
index/generated/andindex/reports/.
The project template .gitignore excludes generated index output. If you initialize an existing repository, make sure its ignore rules also exclude these directories unless you intentionally commit generated snapshots.
- Source files remain canonical.
- Index builds are deterministic and local.
- Generated outputs are disposable.
- Configuration is generic and repository-owned.
- Structured extraction is opt-in.
- AI and human-added knowledge is review-gated and cannot override source content.
- The base tool avoids domain-specific assumptions and favors simple configuration over hidden behavior.
For details on how this standalone boilerplate was extracted from its source implementation, see the migration notes under docs/.