/index — Knowledge Index Builder
Scan all promoted knowledge files, normalize tags, detect issues, and regenerate {knowledge_folder}/index.md.
Runtime Gate (per ADR-094)
Canonical resolution: This is the Claude Code variant. When both plugin-claude-code and plugin-claude-cowork are loaded in the same session (most common in Claude Desktop), bare /index resolves to this skill — aria-knowledge (Code) is the canonical owner of all 24 dual-port skills per ADR-094 §Part 1. The Cowork variant is namespaced-only: /aria-cowork:index.
Before Step 0: Check that the Bash tool is available in this session. If Bash is NOT available (you are running in Claude Cowork or another non-Code runtime), surface the following notification and wait for explicit user confirmation:
⚠️ Runtime mismatch — you invoked aria-knowledge's
/indexfrom a non-Code runtime.This variant supports
projects_enabled/projects_shared_knowledgeconfig keys not present in Cowork'saria-config.md. For the Cowork-native variant (simpler index, no shared-knowledge tier), use/aria-cowork:index.Use
/aria-cowork:indexinstead? (y/n)
Wait for an explicit reply:
y/yes— Use theSkilltool to invokearia-cowork:indexwith the same arguments the user provided to this invocation. Do not proceed with this skill's steps; the cowork variant takes over and runs to completion. This is the default-yes path — auto-redirect is the helpful action.n/no— Proceed with this (aria-knowledge) variant anyway despite the runtime mismatch. The user has explicitly opted in.- No response / any other reply — Treat as "do not proceed" and exit cleanly without running either variant.
This gate applies even when mode = auto per ADR-094 §Part 3. Auto mode's "implicit-yes on all gates" rule is suspended for the runtime-mismatch check — auto trusts that the user invoked the correct variant, and this gate enforces that precondition. All other auto-mode gates remain bypassed. The friction cost is now low: on y, the auto-redirect runs the correct variant with the original args.
If Bash is available, proceed to Step 0.
Step 0: Resolve Config
Read ~/.claude/aria-knowledge.local.md and extract:
knowledge_folder— base path for all operationsfreeform_promotion_threshold— minimum file count before suggesting promotion (default: 3)staleness_threshold_months— months before a file is flagged stale (default: 6)projects_enabled— defaultfalse; controls whether project tier is scanned and indexedprojects_list— default empty; comma-separatedtag:pathpairs; only relevant ifprojects_enabled: trueprojects_promotion_threshold— default2; minimum projects sharing a similar pattern to surface as a cross-project promotion candidateprojects_shared_knowledge— default empty; comma-separated list of project tags enabled for shared knowledge. When non-empty, scan each listed project's_project-knowledge/folder for team-shared knowledge. Tags not in this list are skipped (their_project-knowledge/folders, if any exist on disk, are NOT indexed).
If the config file doesn't exist, stop: "aria-knowledge is not configured. Run /setup to get started."
Step 1: Scan Promoted Folders
Scan these directories for .md files (excluding directory README stubs that only contain a few lines of boilerplate):
{knowledge_folder}/approaches/{knowledge_folder}/decisions/{knowledge_folder}/guides/(recursive — includes subdirectories){knowledge_folder}/references/(recursive — includessources/and other subdirectories)
Do NOT scan: archive/, intake/, rules/, top-level logs/*.md (audit-log files like config-audit-log.md, knowledge-audit-log.md, hook-debug.log), or root-level files (README.md, LOCAL.md, OVERVIEW.md, index.md).
Carve-out for review reports: the two subfolders logs/prospect/ and logs/retrospect/ ARE scanned as a separate "reviews tier" — see the dedicated sub-step below. Review reports use the same frontmatter scanning convention as cross-project files (tags, Last updated, first heading).
For each .md file found:
- Read the file
- Extract YAML frontmatter (content between
---markers at the top of the file) - From frontmatter, extract:
tags:— array of tags (e.g.,tags: [api, pagination, django]). If missing, record as untagged.Last updated:— date string (YYYY-MM-DD). If missing, record as unknown.semantic-hints:— array of free-form phrases (e.g.,semantic-hints: [cursor pagination, keyset pagination]). Optional; if missing, treat as empty list. Added 2.16.0.
- Extract the first
#heading as the file's description - Store:
{path, tags[], hints[], description, last_updated, source: "cross-project"}
Report: "Scanned N files in approaches/, decisions/, guides/, references/."
Reviews tier scan (always run if either review subfolder exists)
After the cross-project scan, scan logs/prospect/ and logs/retrospect/ for review reports written by the /prospect and /retrospect skills.
For each .md file found in either subfolder:
- Read the file
- Extract YAML frontmatter — review reports have a richer schema than cross-project files. Pull:
tags:— array of tags. Always includesprospectorretrospectplus the scope keyword. If missing (legacy reports written before the structured-frontmatter format), record as untagged and emit a soft warning (one-line) suggesting the file be re-run or hand-tagged.Last updated:— fall back todate:ifLast updated:is absent (review reports usedate:for the report-creation date).type:—prospectorretrospect. Used to bucket the file under "Retrospects" or "Prospects" in the## Review Indexsection ofindex.md(see Step 9).scope:— the scope keyword (e.g.,release,deployment,commit,plan).tickets:— for cross-reference enrichment (consumed by/context).
- Extract the first
#heading as the file's description (typically "/prospect — <goal>" or "/retrospect — <goal>"). - Store:
{path, tags[], description, last_updated, source: "review", review_type: <prospect|retrospect>, scope: <keyword>, tickets: [...]}
Report: "Scanned R review reports across logs/prospect/ and logs/retrospect/ (P prospect, Q retrospect)."
If neither subfolder exists yet on disk, skip this sub-step silently (first run before any /prospect or /retrospect has been invoked).
Project tier scan (only if projects_enabled: true and projects_list is non-empty)
After the cross-project scan, scan the project tier:
For each tag:path pair in projects_list:
- Glob
{knowledge_folder}/projects/{tag}/**/*.mdrecursively - Exclude
projects/{tag}/README.md(per-project navigation, not knowledge content) - Exclude
projects/README.md(the projects/ tier README, plugin-managed) - For each file found, perform the same frontmatter extraction as above.
- Path-derived tag union (Decision #9): automatically add
{tag}to the file's tag set even if not in YAML frontmatter. The union of YAML tags + path tag is what gets indexed. This means project files don't have to manually include the project tag in their frontmatter. - Store:
{path, tags[], description, last_updated, source: "project-specific", project: tag}
Report: "Scanned M files across N project subdirectories: [project tags]."
If projects_enabled: false or projects_list is empty, skip this sub-step entirely. Project tier files (if any exist on disk) won't be indexed.
Team-shared scan (only if projects_shared_knowledge list is non-empty)
After the project tier scan, scan each enabled project's _project-knowledge/ folder. Only projects whose tags appear in projects_shared_knowledge are scanned — non-listed projects are skipped, even if their _project-knowledge/ folders exist on disk.
For each tag in `pro