Skip to content
Back to skills

Vault

ASecurity

Generate an Obsidian LLM wiki vault from a project's source code and any static documents in raw/

  • 4 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added June 5, 2026
ai-agentsgoshellbashnodegitapidocumentation

Works with

  • api

Security analysis

A100/100

Pro scans all 7 files and shows the line behind each finding

Scanned June 5, 2026

npx -y skills add burakolgun/vault-anything --skill vault --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Vault?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Vault
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/burakolgun-vault/badge)](https://www.skillsdirectory.com/skills/burakolgun-vault)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: vault
description: Generate an Obsidian LLM wiki vault from a project's source code and any static documents in raw/
argument-hint: "[project-dir] [--workspace <dir>] [--lang <code>]"
---

# /vault-anything:vault

Analyzes a project's source code and any static documents the user has placed under `raw/`, then generates a Karpathy-style Obsidian wiki vault where every page is self-contained and useful as either human documentation or LLM context.

## Arguments

| Argument | Default | Description |
|----------|---------|-------------|
| `project-dir` | current directory | Source code to analyze |
| `--workspace` | `<project>/vault-anything/` | Where `raw/` and `vault/` are written |
| `--lang` | `en` | Vault page output language (must match a file in `locales/`) |

---

## Phase 0 — Pre-flight

Run the resolvers to get plugin and workspace paths. Save the outputs into shell variables you'll use throughout:

```bash
set -e
PLUGIN_ROOT=$(node "$CLAUDE_SKILL_DIR/resolve-plugin-root.mjs")
WORKSPACE=$(node "$PLUGIN_ROOT/skills/vault/resolve-workspace.mjs" "$@")
```

Parse `$WORKSPACE` (it's a JSON object) into shell variables with `jq`:

```bash
PROJECT_DIR=$(echo "$WORKSPACE"   | jq -r '.projectDir')
PROJECT_NAME=$(echo "$WORKSPACE"  | jq -r '.projectName')
WORKSPACE_DIR=$(echo "$WORKSPACE" | jq -r '.workspaceDir')
RAW_DIR=$(echo "$WORKSPACE"       | jq -r '.rawDir')
VAULT_DIR=$(echo "$WORKSPACE"     | jq -r '.vaultDir')
EXISTS=$(echo "$WORKSPACE"        | jq -r '.exists')
VAULT_LANG="en"   # parse from --lang argument if user provided one
```

**Decision:**
- If `$EXISTS` is `"true"`, this project has been analyzed before. Ask the user which path to take:
  - **(a)** Full re-analysis (all phases run again)
  - **(b)** Just update what changed → tell the user to run `/vault-anything:vault-update` instead, then STOP.
  - **(c)** Skip scan + analyze, regenerate vault from existing `raw/` (jump to Phase 3).
- If `$EXISTS` is `"false"`, proceed with full analysis.

### Set up progress tracking

Before running the phases, use the **TaskCreate** tool to create a top-level task list the user can watch. The tasks are:

1. Phase 1: Scan project files
2. Phase 2: Analyze files
3. Phase 3: Cluster concepts + write skeleton
4. Phase 4: Write pages
5. Phase 5: Quality review

If the user picked option (c) above (regenerate from existing raw/), mark tasks 1 and 2 as `completed` immediately (they're being skipped, but recorded as already done so the user sees what's happening).

At the start of every subsequent phase, call **TaskUpdate** to mark the task `in_progress`. At the end of each phase, mark it `completed`.

---

## Phase 1 — SCAN

Mark "Phase 1" as `in_progress`. Report to the user: `[Phase 1/5] Scanning project files...`

Run the analyzer script. It scans files, detects frameworks and entry points deterministically, builds an import map, and produces batch plans for the file-analyzer agents:

```bash
SCAN=$(node "$PLUGIN_ROOT/skills/vault/run-analyze.mjs" \
  "$PROJECT_DIR" "$RAW_DIR" "$PROJECT_NAME")
```

Extract counts to report to the user:

```bash
FILE_COUNT=$(echo  "$SCAN" | jq -r '.files')
LANGUAGES=$(echo   "$SCAN" | jq -r '.languages | join(", ")')
BATCH_COUNT=$(echo "$SCAN" | jq -r '.batches | length')
```

Check whether a commit hash was captured:

```bash
COMMIT_HASH=$(echo "$SCAN" | jq -r '.commitHash')
SUBREPO_COUNT=$(echo "$SCAN" | jq -r '.subRepos | length')
```

If `$COMMIT_HASH` is the string `"null"`, the root isn't under git (or has no commits yet). This is fine — analysis proceeds — but mention it to the user, and distinguish the multi-project case:

- If `$SUBREPO_COUNT` is greater than 0, the root is a parent directory holding several git repos (a multi-project run). List them from `echo "$SCAN" | jq -r '.subRepos[].name'` and print:

  ```
  Note: The workspace root isn't a git repo, but <SUBREPO_COUNT> sub-repositories
  were detected (<names>). Their HEADs are recorded for reference, but per-project
  incremental code-change detection isn't supported yet (planned for multi-project
  support). For now, re-running regenerates from scratch; static-file changes in
  raw/ are still tracked.
  ```

- Otherwise (no sub-repos either) print:

  ```
  Note: This project is not under git. Code change detection won't be available
  for incremental updates; only static-file changes in raw/ will be tracked.
  ```

Now print a short plan summary for the user:

```
Plan
  Project:    <PROJECT_NAME> (<FILE_COUNT> files, languages: <LANGUAGES>)
  Workspace:  <WORKSPACE_DIR>
  Will dispatch <BATCH_COUNT> file-analyzer agent(s) and (after clustering) one page-writer agent per category.
```

If `$FILE_COUNT` is greater than 200, warn the user this may take a while and ask them to confirm before continuing.

Mark "Phase 1" as `completed`.

---

## Phase 2 — ANALYZE FILES

Mark "Phase 2" as `in_progress`. Report: `[Phase 2/5] Analyzing files...`

For each batch (`batch-1`, `batch-2`, ...) add a sub-task under "Phase 2" so the user can watch individual batches complete. Use TaskCreate with `parentId` set to the Phase 2 task id, or use a single TaskUpdate that lists batch progress in the description — whichever your runtime supports.

For each batch in `$SCAN.batches`, dispatch a `vault-anything:file-analyzer` subagent **via the Agent tool**. Run up to 5 agents concurrently — in a single message with multiple Agent tool calls.

For each batch, the Agent tool call uses:
- `subagent_type`: `vault-anything:file-analyzer`
- `description`: `Analyze batch <batchIndex>/<totalBatches>`
- `prompt`: described below

Iterate the batches with jq to get each batch's data:

```bash
echo "$SCAN" | jq -c '.batches[]'
```

For each batch, build the agent prompt. Substitute the batch-specific values into this template:

> **Inputs:**
> - projectRoot: `<PROJECT_DIR>`
> - projectName: `<PROJECT_NAME>`
> - batchIndex: `<batch.batchIndex>`
> - totalBatches: `<total>`
> - outputPath: `<RAW_DIR>/<PROJECT_NAME>/file-summaries/batch-<batchIndex>.json`
>
> **Files to analyze** (read each one and produce a `FileSummary`):
> ```json
> <batch.files>
> ```
>
> **Intra-batch imports** (project-internal imports between files in this batch):
> ```json
> <batch.importData>
> ```
>
> **Cross-batch imports** (files outside this batch that are referenced — for context, do not re-analyze):
> ```json
> <batch.crossBatchImports>
> ```
>
> Write a JSON array of `FileSummary` objects to `outputPath`. Follow the schema and rules in your agent definition.

As each batch's subagent completes, mark its sub-task `completed`. After all batches complete, mark "Phase 2" as `completed`. Report: `Phase 2 complete. <FILE_COUNT> files analyzed.`

---

## Phase 3 — CLUSTER & GENERATE SKELETON

Mark "Phase 3" as `in_progress`. Report: `[Phase 3/5] Clustering concepts and generating vault skeleton...`

```bash
GEN=$(node "$PLUGIN_ROOT/skills/vault/run-generate.mjs" \
  "$RAW_DIR" "$VAULT_DIR" "$PROJECT_NAME")
```

Extract counts:

```bash
PAGE_COUNT=$(echo "$GEN" | jq -r '.pagesWritten')
CATEGORIES=$(echo "$GEN" | jq -r '.categories | join(", ")')
USER_FILES=$(echo "$GEN" | jq -r '.userFiles | length')
```

If `$USER_FILES` is greater than 0, report: `Note: <USER_FILES> static file(s) from raw/ will be included.`

Report: `<PAGE_COUNT> pages planned across categories: <CATEGORIES>`

Mark "Phase 3" as `completed`.

---

## Phase 4 — WRITE PAGES

Mark "Phase 4" as `in_progress`. Report: `[Phase 4/5] Writing vault pages...`

For each category in `$GEN.categories`, add a sub-task under "Phase 4" so the user can track progress per category (e.g. "Phase 4: write 02-Architecture (3 pages)").

Load the locale guide and the type templates. If the user asked for a language that isn't bundled, fall back to English and warn them:

```bash
LOCALE_FILE="$PLUGIN_ROOT/locales/$VAULT_LANG.md"
if [ ! -f "$LOCALE_FILE" ]; then
  echo "Note: no locale guide for '$VAULT_LANG' at $LOCALE_FILE — falling back to English." >&2
  VAULT_LANG="en"
  LOCALE_FILE="$PLUGIN_ROOT/locales/en.md"
fi
LOCALE_GUIDE=$(cat "$LOCALE_FILE")

# Load all type templates (map page type → template content)
TPL_FLOW=$(cat "$PLUGIN_ROOT/templates/flow.md")
TPL_CONCEPT=$(cat "$PLUGIN_ROOT/templates/concept.md")
TPL_CROSS=$(cat "$PLUGIN_ROOT/templates/cross-cutting.md")
TPL_REFERENCE=$(cat "$PLUGIN_ROOT/templates/reference.md")
TPL_SERVICE=$(cat "$PLUGIN_ROOT/templates/service-overview.md")
TPL_API=$(cat "$PLUGIN_ROOT/templates/api.md")        # used by type: api_index
TPL_TOPIC=$(cat "$PLUGIN_ROOT/templates/topic.md")    # used by type: topic_index
TPL_CONFIG=$(cat "$PLUGIN_ROOT/templates/config.md")  # used by type: config_index
TPL_DATA_MODEL=$(cat "$PLUGIN_ROOT/templates/data-model.md")     # used by type: data_model_index
TPL_INTEGRATIONS=$(cat "$PLUGIN_ROOT/templates/integrations.md") # used by type: integration_index
TPL_JOBS=$(cat "$PLUGIN_ROOT/templates/jobs.md")                 # used by type: job_index
TPL_PERMISSIONS=$(cat "$PLUGIN_ROOT/templates/permissions.md")   # used by type: permission_index
```

For each category in `$GEN.categories`, dispatch one `vault-anything:page-writer` subagent **via the Agent tool**. Run all categories concurrently — in a single message with multiple Agent tool calls.

For each category, get the pages that belong to it:

```bash
echo "$GEN" | jq -c --arg CAT "$CATEGORY" '.pages[] | select(.category == $CAT)'
```

Build the agent prompt with these substitutions. Include only the templates for page types that actually appear in this category's pages (most categories use exactly one type — flows use `flow`, architecture uses `concept`, etc.):

> **Inputs:**
> - category: `<CATEGORY>`
> - vaultDir: `<VAULT_DIR>/<CATEGORY>/`
> - outputLanguage: `<VAULT_LANG>`
>
> **Templates for the page types in this category:**
>
> For type `<type>`:
> ```
> <template content for this type, e.g. $TPL_CONCEPT>
> ```
>
> (Include one template block per unique page type present in this category's pages.)
>
> **Locale guide:**
> ```
> <LOCALE_GUIDE>
> ```
>
> **wikilinkMap** (use these page titles for [[wikilinks]]):
> ```json
> <GEN.wikilinkMap>
> ```
>
> **Pages to write** (skeleton files already exist at vaultDir — read them for context, then overwrite with finished prose):
> ```json
> <pages for this category>
> ```
>
> **User-provided static files** that contribute to this category (read these for additional context):
> ```json
> <userFiles relevant to this category, or empty array>
> ```
>
> Follow the writing rules in your agent definition and the section structure in the template for each page's type. Produce one finished markdown page per entry in `pages`.

As each category's subagent completes, mark its sub-task `completed`. After all category agents finish, mark "Phase 4" as `completed`. Report: `Phase 4 complete.`

---

## Phase 5 — REVIEW

Mark "Phase 5" as `in_progress`. Report: `[Phase 5/5] Running quality checks...`

```bash
REVIEW=$(node "$PLUGIN_ROOT/skills/vault/run-review.mjs" "$VAULT_DIR" "$RAW_DIR")

SCORE=$(echo    "$REVIEW" | jq -r '.qualityScore')
ISSUES=$(echo   "$REVIEW" | jq -r '.issues | length')
WARNINGS=$(echo "$REVIEW" | jq -r '.warnings | length')
```

Report `Quality score: <SCORE>/100`.

If `$ISSUES` is greater than 0:
1. List up to 5 of them by reading `$REVIEW | jq '.issues'`.
2. Attempt automatic fixes (strip backticks, add missing front matter fields).
3. Re-run the review once to confirm.

If `$WARNINGS` is greater than 0, list the top 5 (informational only — does not block).

Mark "Phase 5" as `completed`.

---

## Final Report

Output to the user:

```
✓ Vault generated

  Project:   <PROJECT_NAME>
  Workspace: <WORKSPACE_DIR>
  Pages:     <PAGE_COUNT> across <CATEGORIES>
  Quality:   <SCORE>/100

  Open in Obsidian → <VAULT_DIR>
  Run updates     → /vault-anything:vault-update <PROJECT_DIR>
```

### Versioning suggestion

If the workspace is inside the project directory (default `<project>/vault-anything/`), suggest the user version it. Print:

```
Versioning vault-anything:
  The vault and its raw layer are designed to be committed alongside your code,
  so your team shares the same documentation. Add this single line to your
  project's .gitignore:

    vault-anything/raw/vault-review.json

  (vault-review.json changes on every run and is noise; everything else is
  meant to be committed.)
```

Only print this if (a) the workspace lives inside the project directory and
(b) the project has a `.git` directory. Skip it for separate-workspace setups.

**Multi-project case:** if the root has no `.git` of its own but `$SUBREPO_COUNT`
(from Phase 1) is greater than 0, the combined vault can't be committed to the
parent because it isn't a repo. Print this instead:

```
Versioning this multi-project vault:
  The workspace root isn't a git repo, so the combined vault has nowhere to be
  committed. Two options:
    - git init the parent directory and commit the vault there, or
    - re-run with --workspace pointing at a dedicated docs/wiki git repo.
  vault-update tracks each sub-repo's HEAD independently, so incremental
  updates work either way.
```

Files in this skill

  • SKILL.md12.9 KB
  • resolve-plugin-root.mjs2.4 KB
  • resolve-workspace.mjs1.2 KB
  • run-analyze.mjs3.9 KB
  • run-generate.mjs5.8 KB
  • run-review.mjs1.3 KB
  • run-update.mjs1 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…