From deep-wiki
Use when the user wants to regenerate derived wiki artifacts (M3-envelope-wrapped `.wiki-meta/index.json`) from the source-of-truth page frontmatter — used when the index is suspected stale, corrupted, or drifted relative to actual page files. Triggers on `/wiki-rebuild`, "rebuild wiki index", "regenerate index", "rebuild wiki", "wiki reindex", "wiki rebuild", "위키 인덱스 재생성", "위키 재빌드", "위키 인덱스 복구", "wiki 재구성". Takes no arguments; always acquires the wiki lock and emits a `rebuild` lifecycle event to `log.jsonl`.
How this skill is triggered — by the user, by Claude, or both
Slash command
/deep-wiki:wiki-rebuildThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Rebuild derived artifacts from the source-of-truth page files.
Rebuild derived artifacts from the source-of-truth page files.
이 스킬은 두 가지 경로로 호출됩니다 — 어느 쪽이든 본 SKILL §"Prerequisites" / §"Steps" 절차를 그대로 실행합니다:
/wiki-rebuild 입력 (skill 의 user-invocable: true 가 슬래시 진입을 허용).Skill({ skill: "deep-wiki:wiki-rebuild", args: "" }) 형태로 명시 invoke (cross-platform 표준 경로).두 경로 모두 args 는 비어 있으며, 동일한 본문 Steps 가 실행됩니다.
| 인자 | 의미 |
|---|---|
| (없음) | rebuild 만 수행 — 모든 페이지의 frontmatter 를 스캔하여 .wiki-meta/index.json 을 M3 envelope-wrapped 형태로 재생성 |
이 entry skill 은 wiki-schema sibling skill (4 critical invariants + 10 log actions + storage layout 규칙) 을 동작 전제로 합니다. 또한 4 개 sibling entry skill 과 wiki_root 를 공유합니다 — wiki-setup 으로 wiki_root 가 사전 초기화되어 있어야 하며, rebuild 는 wiki-ingest / wiki-query 가 작성한 페이지를 재스캔해 index 의 truth 와 일치시킵니다. 이후 wiki-lint 가 index/페이지 drift 검사를 idempotent 하게 수행할 수 있습니다.
Cross-platform self-containment: Claude Code 에서는 sibling skill (wiki-schema) 이 description 매칭으로 자동 로드되고, hooks/scripts/wrap-index-envelope.js 가 Bash 로 invoke 됩니다. 다만 Codex / Copilot CLI / Gemini CLI 등 타 플랫폼에서 Skill() 호출 시 sibling skill 의 auto-load 보장이 약할 수 있으므로, 본 SKILL §"Steps" 본문은 의도적으로 self-contained — mkdir-based lock acquisition, find-form page scan, M3 envelope wrap CLI 인터페이스, rebuild lifecycle action 의 log.jsonl entry 형식을 인라인으로 보존합니다.
Read ~/.claude/deep-wiki-config.yaml to get wiki_root. If missing, tell the user to run /wiki-setup first.
If the config contains obsidian_cli.available: true, check if the Obsidian app is running:
obsidian version 2>/dev/null
OBS_LIVE=true, read wiki_prefix from config.OBS_LIVE=false, use filesystem-only checks.set -euo pipefail
: "${WIKI_ROOT:?caller must set WIKI_ROOT to the wiki root absolute path}"
LOCK_DIR="${WIKI_ROOT}/.wiki-meta/.wiki-lock"
mkdir "$LOCK_DIR" 2>/dev/null || { echo "ERROR: Wiki is locked by another session."; exit 1; }
No trap here — round-4 Codex review #1 fix. The Claude Code Bash
tool spawns a fresh shell per bash block, so registering an EXIT
trap inside this standalone lock-acquisition block would fire as soon
as the block ends — releasing the lock BEFORE Steps 2-5 run, leaving
the rebuild to proceed unlocked and allowing concurrent ingest/rebuild
to interleave. The lock instead has the following lifecycle:
mkdir acquires the lock (no trap).rc != 0), so a helper
failure in Step 3 cleans up its own lock without leaking. On success
the lock stays held for Step 6 to release after the rebuild's other
steps complete.rmdir on the
success path.Crash recovery between Bash invocations (e.g. agent abort between Step
2 and Step 3) still leaks the lock — that is pre-existing wiki-rebuild
behaviour from the mkdir-based lock design and unchanged by M3. Manual
recovery: rmdir <wiki_root>/.wiki-meta/.wiki-lock.
Read every .md file in pages/. For each page, parse the YAML frontmatter to extract:
titletagsaliasesTimestamp format: All
tsandgenerated_atvalues MUST be UTC ISO 8601 with aZsuffix. Generate withdate -u +"%Y-%m-%dT%H:%M:%SZ". Never use local timezone offsets (e.g.+09:00) — the wiki's log is consumed by tooling that assumes a single canonical timezone.
Build a new index.json from the scanned data. v1.5.0+ wraps the page catalog
in the M3 cross-plugin envelope (cf. claude-deep-suite/docs/envelope-migration.md
§1) — the legacy {pages, generated_at} shape lives inside payload. The
envelope is added at write-time by wrap-index-envelope.js; consumers of
index.json use read-index-envelope.js to unwrap (or jq-equivalent: if
.envelope is present, treat .payload as the legacy structure; else use
the root). See "Envelope-aware read" sidebar below.
Caller contract for the bash snippet below. Required environment:
WIKI_ROOT — absolute path to the wiki root.CLAUDE_PLUGIN_ROOT — set by Claude Code at session start; helper
script locations.Step 3 — Build payload + envelope-wrap + atomic write (single bash
block). Round-3 Codex review #2 fix: payload construction and envelope
wrap MUST live in a single Bash tool invocation. The Claude Code Bash tool
spawns a fresh shell per invocation, so a PAYLOAD_TMP variable defined in
one block is unavailable to the next block (the file at that path may also
have been cleaned up via the success-gated rm -f). Combining the two
operations is the only safe form. Multi-source aggregator: every scanned
page contributes one --source-page entry (path relative to <wiki_root>,
e.g. pages/react-hooks.md); pages are markdown → recorded path-only (no
envelope detect); parent_run_id is omitted. Helper writes atomically
(temp + rename); payload temp cleanup is gated on helper success (failure
preserves it for retry, deep-work round-1 C1+C2 lessons).
set -euo pipefail
: "${WIKI_ROOT:?caller must set WIKI_ROOT to the wiki root absolute path}"
: "${CLAUDE_PLUGIN_ROOT:?caller must have CLAUDE_PLUGIN_ROOT set (Claude Code session env)}"
# Round-4 Codex review #1 + Codex adv #2 fix: register a FAILURE-ONLY
# cleanup trap inside the mutation block. On success (rc=0) the lock
# stays held for Step 6 to release. On any failure (helper exit non-zero,
# jq exit, unset variable abort) the trap releases the lock to prevent
# the stranded-lock condition R3-2 targeted, without the R3-2 mistake
# of putting the trap in Step 1's standalone block (which fires
# immediately on Step 1 block exit and kills the lock before Step 2).
PAYLOAD_TMP="${WIKI_ROOT}/.wiki-meta/index.payload.tmp.$$.$(date +%s).json"
cleanup_step3() {
local rc=$?
if [ "$rc" -ne 0 ]; then
rmdir "${WIKI_ROOT}/.wiki-meta/.wiki-lock" 2>/dev/null || true
echo "ERROR: /wiki-rebuild Step 3 failed (rc=$rc); lock released; payload preserved at $PAYLOAD_TMP" >&2
fi
return $rc
}
trap cleanup_step3 EXIT
# 3.a — Build payload. Pages array sorted alphabetically by filename
# (built from Step 2 scan; below is a structural template — caller
# substitutes actual page entries from the scan result).
cat > "$PAYLOAD_TMP" <<JSON
{
"pages": [
{
"file": "react-hooks.md",
"title": "React Hooks",
"tags": ["programming", "react"],
"aliases": ["hooks", "useState"]
}
],
"generated_at": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
}
JSON
# 3.b — Collect --source-page args from scanned pages. macOS BSD `find`
# lacks `-printf`, so we cd into ${WIKI_ROOT} inside a subshell and rely
# on the already-relative `pages` prefix. Portable to BSD (macOS) + GNU
# (Linux). The subshell isolates the cd from the outer cwd.
#
# Round-2 Opus W2-2: use `${ARR[@]+"${ARR[@]}"}` expansion so that bash
# 3.2 (default `/bin/bash` on macOS) under `set -u` does not abort when
# SOURCE_PAGE_ARGS is empty (e.g. fresh wiki with no pages). The helper
# itself accepts zero `--source-page` flags.
SOURCE_PAGE_ARGS=()
while IFS= read -r REL; do
[ -n "$REL" ] && SOURCE_PAGE_ARGS+=(--source-page "$REL")
done < <(cd "${WIKI_ROOT}" 2>/dev/null && find pages -maxdepth 1 -name '*.md' -type f 2>/dev/null | sort)
# 3.c — Envelope-wrap + atomic write. Helper writes atomically (temp +
# rename); cleanup is gated on helper success (deep-work round-1 C2).
node "${CLAUDE_PLUGIN_ROOT}/hooks/scripts/wrap-index-envelope.js" \
--payload-file "$PAYLOAD_TMP" \
--output "${WIKI_ROOT}/.wiki-meta/index.json" \
${SOURCE_PAGE_ARGS[@]+"${SOURCE_PAGE_ARGS[@]}"}
rm -f "$PAYLOAD_TMP"
# On success: trap fires with rc=0 → no rmdir; lock kept for Step 6.
# On failure: trap fires with rc!=0 → rmdir lock; payload temp preserved
# above (no rm reached). User can retry without manual lock cleanup.
Sort pages alphabetically by filename inside the payload.
Envelope-aware read (any consumer of index.json):
When reading index.json (e.g. wiki-query, wiki-lint, wiki-ingest Step 4
overlap filter), use the envelope-aware reader so v1.5.0+ envelope-wrapped
files and pre-1.5.0 legacy files both yield the legacy {pages, generated_at}
shape on stdout. The reader enforces an identity guard (producer=deep-wiki,
artifact_kind=index, schema.name=index) and rejects foreign or corrupt
envelopes (handoff §4 round-4 + round-5/7 lessons).
# Returns payload-only JSON (legacy shape) on stdout. Exit codes:
# 0 ok, 1 identity mismatch / corrupt payload, 2 IO / parse error.
INDEX_JSON=$(node "${CLAUDE_PLUGIN_ROOT}/hooks/scripts/read-index-envelope.js" \
"${WIKI_ROOT}/.wiki-meta/index.json")
# Now use jq normally: echo "$INDEX_JSON" | jq -r '.pages[].file'
If node is unavailable in the agent context, a bash-only fast-path
(deep-work round-1 W6 lesson) detects the wrapper without spawning a
per-file Node process. Note: this is a heuristic — only
read-index-envelope.js is authoritative (full identity guard + corrupt-
payload defense). The grep-based path exists for environments lacking
Node; prefer the node helper whenever available.
# Fast-path heuristic — node helper is authoritative; this exists for
# environments without node in PATH. Identity check is text-grep based
# (deep-wiki/index/producer/schema_version anchors). corrupt-payload edge
# cases (e.g. payload omitted entirely) are NOT detected here.
if grep -q '"envelope":' "${WIKI_ROOT}/.wiki-meta/index.json" && \
grep -q '"schema_version": *"1.0"' "${WIKI_ROOT}/.wiki-meta/index.json" && \
grep -q '"producer": *"deep-wiki"' "${WIKI_ROOT}/.wiki-meta/index.json" && \
grep -q '"artifact_kind": *"index"' "${WIKI_ROOT}/.wiki-meta/index.json"; then
# Envelope: extract payload via jq.
INDEX_JSON=$(jq '.payload' "${WIKI_ROOT}/.wiki-meta/index.json")
else
# Legacy: use root directly.
INDEX_JSON=$(cat "${WIKI_ROOT}/.wiki-meta/index.json")
fi
Timestamp format: All
tsandgenerated_atvalues MUST be UTC ISO 8601 with aZsuffix. Generate withdate -u +"%Y-%m-%dT%H:%M:%SZ". Never use local timezone offsets (e.g.+09:00) — the wiki's log is consumed by tooling that assumes a single canonical timezone.
{"ts":"<iso_timestamp>","action":"rebuild","source":"manual","pages_created":[],"pages_updated":[]}
After rebuilding, run an automatic health check (same as wiki-ingest auto-lint):
If OBS_LIVE, enhance checks 2 and 3 with Obsidian CLI (same as wiki-ingest auto-lint):
obsidian orphans → post-filter to <wiki_prefix>/pages/obsidian unresolved format=json → post-filter to <wiki_prefix>/pages/Wiki boundary filtering is mandatory for all vault-wide CLI results.
Auto-fix structural issues silently (prune excess versions, remove ghost index entries). Only report issues that need human judgment.
Release the lock directory. Report:
Fetches up-to-date documentation from Context7 for libraries and frameworks like React, Next.js, Prisma. Use for setup questions, API references, and code examples.
Applies a firm's KYC/AML rules grid to parsed onboarding records: assigns risk rating, checks required documents, outputs rule outcomes with citations, and routes for escalation.
Generates daily or weekly digests of activity from connected sources (chat, email, docs, tasks, CRM), highlighting action items, decisions, mentions, and project updates.
npx claudepluginhub sungmin-cho/claude-deep-suite --plugin deep-wiki