| name | vault-update |
| description | Incrementally update an existing vault — detect code changes via git diff and static file changes via SHA256, then re-analyze and rewrite only affected pages |
| argument-hint | [project-dir] [--workspace <dir>] |
/vault-anything:vault-update
Incrementally updates an existing vault. Detects code changes via git diff and static-file changes via SHA256 hash, then re-analyzes and rewrites only the pages that need to change.
Arguments
| Argument | Default | Description |
|---|
project-dir | current directory | Project being updated |
--workspace | <project>/vault-anything/ | Where existing raw/ and vault/ live |
Phase 0 — Pre-flight
set -e
PLUGIN_ROOT=$(node "$CLAUDE_SKILL_DIR/../vault/resolve-plugin-root.mjs")
WORKSPACE=$(node "$PLUGIN_ROOT/skills/vault/resolve-workspace.mjs" "$@")
PROJECT_DIR=$(echo "$WORKSPACE" | jq -r '.projectDir')
PROJECT_NAME=$(echo "$WORKSPACE" | jq -r '.projectName')
RAW_DIR=$(echo "$WORKSPACE" | jq -r '.rawDir')
VAULT_DIR=$(echo "$WORKSPACE" | jq -r '.vaultDir')
EXISTS=$(echo "$WORKSPACE" | jq -r '.exists')
VAULT_LANG="en"
If $EXISTS is "false":
- Tell the user:
No vault found. Run /vault-anything:vault <project-dir> first.
- STOP.
Set up progress tracking
Before running the phases, use the TaskCreate tool to create the task list:
- Phase 1: Detect changes
- Phase 2: Re-analyze changed code files
- Phase 3: Route new static files
- Phase 4: Regenerate affected pages
- Phase 5: Review and save
Note that phases 2-4 are conditional:
- Phase 2 is skipped if there are no code changes.
- Phase 3 is skipped if there are no new static files in
raw/.
- Phase 4 is skipped if no vault pages are affected.
For each skipped phase, mark its task as cancelled (not completed) so the user can see what was skipped.
Mark each running phase in_progress when it starts, completed when it finishes.
Phase 1 — DETECT CHANGES
Mark "Phase 1" as in_progress.
PLAN=$(node "$PLUGIN_ROOT/skills/vault/run-update.mjs" \
"$PROJECT_DIR" "$RAW_DIR" "$PROJECT_NAME")
CODE_CHANGED=$(echo "$PLAN" | jq -r '.codeChanges.hasChanges')
RAW_CHANGED=$(echo "$PLAN" | jq -r '.rawChanges.hasChanges')
FULL_REANALYZE=$(echo "$PLAN" | jq -r '.codeChanges.fullReanalyze')
FULL_GENERATE=$(echo "$PLAN" | jq -r '.requiresFullGenerate')
If both $CODE_CHANGED and $RAW_CHANGED are "false":
- Mark "Phase 1" as
completed and mark phases 2-5 as cancelled.
- Report
✓ Vault is up to date. and STOP.
Otherwise, summarize the changes:
CHANGED_FILES=$(echo "$PLAN" | jq -r '.codeChanges.changedFiles | length')
ADDED=$(echo "$PLAN" | jq -r '.rawChanges.added | length')
CHANGED=$(echo "$PLAN" | jq -r '.rawChanges.changed | length')
REMOVED=$(echo "$PLAN" | jq -r '.rawChanges.removed | length')
AFFECTED=$(echo "$PLAN" | jq -r '.affectedVaultPages | length')
Report to the user:
Changes detected:
Code: <CHANGED_FILES> file(s) changed
Raw: <ADDED> new, <CHANGED> changed, <REMOVED> removed
Vault pages affected: <AFFECTED>
Ask the user to confirm before proceeding. Mark "Phase 1" as completed.
Phase 2 — RE-ANALYZE CHANGED CODE FILES
If $CODE_CHANGED is "false", mark "Phase 2" as cancelled and skip to Phase 3.
Otherwise mark "Phase 2" as in_progress.
If $FULL_REANALYZE is "true" (the saved git hash is invalid), restart by invoking /vault-anything:vault for a full rebuild, then STOP.
Otherwise, dispatch a single vault-anything:file-analyzer subagent via the Agent tool. The prompt should contain:
Task: Re-analyze only the changed files. Match by filePath and overwrite any existing summaries for those files.
Inputs:
- projectRoot:
<PROJECT_DIR>
- projectName:
<PROJECT_NAME>
- outputPath:
<RAW_DIR>/<PROJECT_NAME>/file-summaries/batch-update.json
Changed files to re-analyze:
<changedFiles from PLAN>
Follow the schema and rules in your agent definition.
Phase 3 — ROUTE NEW STATIC FILES
If .rawChanges.added | length is 0, mark "Phase 3" as cancelled and skip to Phase 4.
Otherwise mark "Phase 3" as in_progress.
For each new file in $PLAN.rawChanges.added, you need to decide which vault pages it contributes to. List the existing vault page titles for the agent:
PAGE_TITLES=$(find "$VAULT_DIR" -name "*.md" -not -name "index.md" \
-exec basename {} .md \; | jq -R . | jq -s .)
For each new file, dispatch a lightweight subagent (the general-purpose Agent works fine here) with this prompt:
Read this static document and decide which vault pages it contributes to.
File path: <RAW_DIR>/<relPath>
File content:
<read the file>
Available vault page titles:
<PAGE_TITLES>
Return JSON only: { "affectsPages": ["Page Title 1", "Page Title 2"] }
Choose at most 5 pages. If none are relevant, return { "affectsPages": [] }.
After the agent responds with affectsPages, update the manifest. Run this Node snippet, substituting the file's relPath, hash, and the affectsPages array:
node -e "
import('$PLUGIN_ROOT/packages/core/src/write-raw.mjs').then(({ readMeta, updateRawManifest }) => {
const meta = readMeta('$RAW_DIR');
updateRawManifest('$RAW_DIR', meta, '<relPath>', '<hash>', <affectsPages JSON>);
});
"
When all new files have been routed, mark "Phase 3" as completed.
Phase 4 — REGENERATE AFFECTED PAGES
Collect all pages to regenerate:
$PLAN.affectedVaultPages (pages affected by changed code or removed static files)
- Pages from the
affectsPages lists of any new/changed static files (Phase 3)
If the affected page set is empty, mark "Phase 4" as cancelled and skip to Phase 5.
Otherwise mark "Phase 4" as in_progress.
Compute the ratio of affected pages to total pages:
TOTAL=$(find "$VAULT_DIR" -name "*.md" -not -name "index.md" | wc -l)
AFFECTED_COUNT=<computed>
RATIO=$(( AFFECTED_COUNT * 100 / TOTAL ))
If $RATIO is greater than 80, or $FULL_GENERATE is "true", restart by invoking /vault-anything:vault to do a full rebuild and STOP.
Otherwise, load the locale guide and type templates. Fall back to English if the requested locale guide is missing:
LOCALE_FILE="$PLUGIN_ROOT/locales/$VAULT_LANG.md"
if [ ! -f "$LOCALE_FILE" ]; then
echo "Note: no locale guide for '$VAULT_LANG' — falling back to English." >&2
VAULT_LANG="en"
LOCALE_FILE="$PLUGIN_ROOT/locales/en.md"
fi
LOCALE_GUIDE=$(cat "$LOCALE_FILE")
PAGE_PLAN=$(cat "$RAW_DIR/$PROJECT_NAME/page-plan.json")
WIKILINK_MAP=$(echo "$PAGE_PLAN" | jq -r '.wikilinkMap')
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")
TPL_TOPIC=$(cat "$PLUGIN_ROOT/templates/topic.md")
TPL_CONFIG=$(cat "$PLUGIN_ROOT/templates/config.md")
TPL_DATA_MODEL=$(cat "$PLUGIN_ROOT/templates/data-model.md")
TPL_INTEGRATIONS=$(cat "$PLUGIN_ROOT/templates/integrations.md")
TPL_JOBS=$(cat "$PLUGIN_ROOT/templates/jobs.md")
TPL_PERMISSIONS=$(cat "$PLUGIN_ROOT/templates/permissions.md")
For each affected page, dispatch a vault-anything:page-writer subagent via the Agent tool. Run them concurrently (multiple Agent tool calls in a single message).
For each affected page, the agent prompt should contain:
Task: Rewrite this vault page with updated content.
Page path: <VAULT_DIR>/<category>/<page>.md
Page type: <type> (look up the type from the page's existing front matter)
Template for this page type:
<template content for the page's type, e.g. $TPL_CONCEPT>
Current page content (for continuity — preserve good content where possible):
<read the existing page>
Updated source summaries (from re-analyzed files relevant to this page):
<summaries for this page>
New static content contributing to this page (if any):
<content from changed/new raw files affecting this page>
Locale guide:
<LOCALE_GUIDE>
wikilinkMap: <WIKILINK_MAP>
Follow your agent definition's writing rules and the section structure in the template. Overwrite the page at vaultDir.
When all affected pages have been rewritten, mark "Phase 4" as completed.
Phase 5 — REVIEW & SAVE
Mark "Phase 5" as in_progress.
node "$PLUGIN_ROOT/skills/vault/run-review.mjs" "$VAULT_DIR" "$RAW_DIR"
Update the baseline in meta.json so the next run diffs against this state. For a single git repo this records the current commit hash; for a multi-project parent (root not a git repo) it records each sub-repo's current HEAD:
node -e "
Promise.all([
import('$PLUGIN_ROOT/packages/core/src/write-raw.mjs'),
import('$PLUGIN_ROOT/packages/core/src/diff-update.mjs'),
import('$PLUGIN_ROOT/packages/core/src/project-config.mjs'),
]).then(([raw, diff, cfg]) => {
const hash = diff.getCurrentHash('$PROJECT_DIR');
const opts = cfg.subRepoOptions(cfg.loadProjectConfig('$PROJECT_DIR'));
const subRepos = hash ? [] : diff.detectSubRepos('$PROJECT_DIR', opts);
if (hash || subRepos.length) raw.updateProjectMeta('$RAW_DIR', '$PROJECT_NAME', hash, subRepos);
});
"
Mark "Phase 5" as completed.
Report: ✓ Vault updated. <AFFECTED_COUNT> pages regenerated. Quality: <SCORE>/100