@theglitchking/semantic-memory 1.1.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,13 +6,13 @@
6
6
  },
7
7
  "metadata": {
8
8
  "description": "Single-plugin marketplace for semantic-memory — the unified memory-layer plugin. v1.1.0 absorbs brain's strengths: AGENTS.md contract artifact, hard-gated verification sessions, multi-agent skill bundler (codex/copilot/pi), and SessionStart drift detection — all backwards-compatible with v1.0.x via deprecation shims.",
9
- "version": "1.1.0"
9
+ "version": "1.1.1"
10
10
  },
11
11
  "plugins": [
12
12
  {
13
13
  "name": "semantic-memory",
14
14
  "description": "Unified memory-layer plugin for Claude Code. One MCP server, 40 tools across multi-corpus search/read/write/graph/lint/sessions/contract. v1.1.0 adds: AGENTS.md contract artifact, hard-gated verification sessions (session_start/run/finish/status), proposal-mode synthesize_note + synthesize_promote, multi-agent skill bundler (codex/copilot/pi via the new `skills` CLI), and SessionStart drift detection. Backwards-compatible with v1.0.x — every previous tool name remains callable through deprecation shims (removed in v2.0.0).",
15
- "version": "1.1.0",
15
+ "version": "1.1.1",
16
16
  "author": {
17
17
  "name": "TheGlitchKing"
18
18
  },
package/CHANGELOG.md CHANGED
@@ -2,6 +2,34 @@
2
2
 
3
3
  All notable changes to semantic-memory (formerly semantic-sidekick) will be documented here.
4
4
 
5
+ ## [1.1.1] - 2026-05-08 — Hotfix: complete the rebrand wiring
6
+
7
+ v1.1.0 published with the rebrand-to-`semantic-memory` half-finished: the npm package, marketplace entry, and tool surface all moved to the new name, but the postinstall, SessionStart reconcile, slash commands, and CLI helpers were still hardcoded to the legacy `@theglitchking/semantic-sidekick` package path. Fresh `npm install @theglitchking/semantic-memory@1.1.0` installs failed to register hooks correctly and slash commands hit ancient code from the legacy npm package (still on the registry at 0.2.x).
8
+
9
+ ### Fixed
10
+
11
+ - **Postinstall (`scripts/link-skills.js`)** — `runPostinstall` now passes `packageName: "@theglitchking/semantic-memory"`, `pluginName: "semantic-memory"`, and `hookCommand` pointing at the new node_modules path. Hooks now register correctly on fresh installs.
12
+ - **SessionStart reconcile (`hooks/reconcile.js`)** — `findLocalBin` checks the rebranded package path first, falls back to the legacy path for machines mid-migration. `isOurEntry` recognizes both old and new shapes when removing stale `.mcp.json` entries.
13
+ - **SessionStart hook (`hooks/session-start.js`)** — `runSessionStart` delegate now passes the new package name + plugin name + config file.
14
+ - **vault-context hook (`hooks/vault-context.js`)** — vault path discovery now matches `semantic-memory` server entries in `.mcp.json` (was only matching `semantic-vault` and `semantic-sidekick`). CLI bin discovery prefers the new path with legacy fallback.
15
+ - **Slash commands** — all 7 (`/healthcheck`, `/status`, `/normalize-config`, `/policy`, `/mode`, `/update`, `/relink`) now invoke `@theglitchking/semantic-memory` instead of the legacy package.
16
+ - **CLI helpers (`src/cli/index.ts`)** — `PKG_NAME`, `findLocalBin`, `runRelink`, `isLocalForm` updated. Error messages reference the new path. `registerUpdateCommands` passes the new plugin name + config file.
17
+
18
+ ### Storage paths preserved (unchanged)
19
+
20
+ - `<vault>/.semantic-sidekick-index/` — vector index location, kept for backwards-compat with existing v1.0.x indices
21
+ - `~/.semantic-sidekick/models/` — model cache location, kept for backwards-compat
22
+
23
+ These intentionally retain the legacy `semantic-sidekick` name in the path — renaming would invalidate every existing user's index and force a re-download of the embedding model. The path-name mismatch with the package name is a one-time cost; we eat it.
24
+
25
+ ### Backwards compatibility
26
+
27
+ All legacy fallbacks preserved. Users with `@theglitchking/semantic-sidekick` still installed (from v0.x or v1.0 pre-rebrand) continue to work — `findLocalBin`, `runRelink`, hook discovery, and `isOurEntry` all check both paths. The DOCS_KEY entry name in `.mcp.json` stays as `"semantic-sidekick"` for existing-user compatibility.
28
+
29
+ ### How v1.1.0 slipped through
30
+
31
+ Phase 9's automated validation ran tests against `createServer()` directly with in-memory MCP clients — it never simulated a fresh `npm install` from the published tarball. The bug only fires at install time and slash-command invocation time, both of which were on the manual-smoke-deferred list. The hotfix re-emphasizes that "manual smoke against an existing v1.0.x install" needs to happen BEFORE publish, not after.
32
+
5
33
  ## [1.1.0] - 2026-05-08 — brain-absorption
6
34
 
7
35
  Adapts four targeted strengths from `JimmyMcBride/brain` into semantic-memory: AGENTS.md contract artifact, hard-gated verification sessions, multi-agent skill bundler, distill/synthesize unification — plus a server.ts refactor that makes future additions cheap, a deprecation-shimmed tool consolidation, and an opt-in SessionStart drift-detection layer.
@@ -10,7 +10,7 @@ When the user runs `/healthcheck`:
10
10
 
11
11
  The fast-tier auto-check also runs on every `SessionStart` via `vault-context.js` — healthy installs see nothing at session start, drifted installs see a one-block warning with a pointer to this command.
12
12
 
13
- Implementation: shell out to `node ./node_modules/@theglitchking/semantic-sidekick/bin/semantic-sidekick healthcheck [--fast]` (or `npx --no @theglitchking/semantic-sidekick healthcheck [--fast]` if no local install).
13
+ Implementation: shell out to `node ./node_modules/@theglitchking/semantic-memory/bin/semantic-memory healthcheck [--fast]` (or `npx --no @theglitchking/semantic-memory healthcheck [--fast]` if no local install). Falls back to the legacy `@theglitchking/semantic-sidekick` package on machines mid-migration.
14
14
 
15
15
  Drift findings are categorized by check:
16
16
  - `mcp_json_entry` — `.mcp.json` missing the semantic-memory server entry. Fix: `/normalize-config`.
package/commands/mode.md CHANGED
@@ -1,12 +1,12 @@
1
1
  ---
2
- description: Set or query the active semantic-sidekick mode (vault-first | research | outage-silence)
2
+ description: Set or query the active semantic-memory mode (vault-first | research | outage-silence)
3
3
  argument-hint: "[research|vault-first|outage-silence|status]"
4
4
  allowed-tools: Bash(cat:*), Bash(cp:*), Bash(test:*), Bash(node:*), Read, Write
5
5
  ---
6
6
 
7
- # /mode — semantic-sidekick mode control
7
+ # /mode — semantic-memory mode control
8
8
 
9
- The user invoked `/mode $ARGUMENTS`. This is the explicit ground-truth override for the semantic-sidekick routing layer.
9
+ The user invoked `/mode $ARGUMENTS`. This is the explicit ground-truth override for the semantic-memory routing layer.
10
10
 
11
11
  ## Your job
12
12
 
@@ -3,4 +3,4 @@ description: Rewrite fragile npx-@latest entries in .mcp.json to the stable node
3
3
  allowed-tools: Bash(npx:*)
4
4
  ---
5
5
 
6
- Run `npx --no @theglitchking/semantic-sidekick normalize-config` and report the result to the user. Mention that `.mcp.json.bak` was created as a safety backup, and that the MCPs need to be toggled in `/mcp` to pick up the change.
6
+ Run `npx --no @theglitchking/semantic-memory normalize-config` and report the result to the user. Mention that `.mcp.json.bak` was created as a safety backup, and that the MCPs need to be toggled in `/mcp` to pick up the change.
@@ -1,16 +1,16 @@
1
1
  ---
2
- description: Get or set the semantic-sidekick update policy (auto | nudge | off)
2
+ description: Get or set the semantic-memory update policy (auto | nudge | off)
3
3
  allowed-tools: Bash(npx:*)
4
4
  argument-hint: "[auto|nudge|off]"
5
5
  ---
6
6
 
7
7
  Arguments: $ARGUMENTS
8
8
 
9
- - If `$ARGUMENTS` is empty, run `npx --no @theglitchking/semantic-sidekick policy` and report the current policy and config path.
10
- - If `$ARGUMENTS` is one of `auto`, `nudge`, `off`, run `npx --no @theglitchking/semantic-sidekick policy $ARGUMENTS` and confirm the new setting to the user.
9
+ - If `$ARGUMENTS` is empty, run `npx --no @theglitchking/semantic-memory policy` and report the current policy and config path.
10
+ - If `$ARGUMENTS` is one of `auto`, `nudge`, `off`, run `npx --no @theglitchking/semantic-memory policy $ARGUMENTS` and confirm the new setting to the user.
11
11
  - If `$ARGUMENTS` is anything else, tell the user the valid values are `auto`, `nudge`, `off`.
12
12
 
13
13
  Policies:
14
- - `auto` — auto-run `npm update @theglitchking/semantic-sidekick` at session start when a newer version is available.
14
+ - `auto` — auto-run `npm update @theglitchking/semantic-memory` at session start when a newer version is available.
15
15
  - `nudge` — print a one-liner when a newer version is available (default).
16
16
  - `off` — do not check for updates.
@@ -3,4 +3,4 @@ description: Re-run the skill linker — refresh symlinks from node_modules into
3
3
  allowed-tools: Bash(npx:*)
4
4
  ---
5
5
 
6
- Run `npx --no @theglitchking/semantic-sidekick relink` and report the result.
6
+ Run `npx --no @theglitchking/semantic-memory relink` and report the result.
@@ -3,4 +3,4 @@ description: Show installed version, latest available version, current update po
3
3
  allowed-tools: Bash(npx:*)
4
4
  ---
5
5
 
6
- Run `npx --no @theglitchking/semantic-sidekick status` and relay the output to the user verbatim.
6
+ Run `npx --no @theglitchking/semantic-memory status` and relay the output to the user verbatim.
@@ -1,6 +1,6 @@
1
1
  ---
2
- description: Update semantic-sidekick to the latest version (runs npm update + re-links skills)
2
+ description: Update semantic-memory to the latest version (runs npm update + re-links skills)
3
3
  allowed-tools: Bash(npx:*)
4
4
  ---
5
5
 
6
- Run `npx --no @theglitchking/semantic-sidekick update` and report the before/after versions to the user. If the project doesn't have a local install, fall back to `npx -y @theglitchking/semantic-sidekick update` and note that in your summary.
6
+ Run `npx --no @theglitchking/semantic-memory update` and report the before/after versions to the user. If the project doesn't have a local install, fall back to `npx -y @theglitchking/semantic-memory update` and note that in your summary.
package/dist/cli/index.js CHANGED
@@ -181,11 +181,16 @@ var SKILL_BUNDLER_AGENTS = ["claude", "codex", "copilot", "pi"];
181
181
  // src/cli/index.ts
182
182
  var require_ = createRequire(import.meta.url);
183
183
  var { version } = require_("../../package.json");
184
- var PKG_NAME = "@theglitchking/semantic-sidekick";
184
+ var PKG_NAME = "@theglitchking/semantic-memory";
185
+ var LEGACY_PKG_NAME = "@theglitchking/semantic-sidekick";
185
186
  function runRelink(cwd) {
186
- const linker = join2(cwd, "node_modules", "@theglitchking", "semantic-sidekick", "scripts", "link-skills.js");
187
- const script = existsSync2(linker) ? linker : resolve2(process.cwd(), "scripts", "link-skills.js");
188
- if (!existsSync2(script)) {
187
+ const candidates = [
188
+ join2(cwd, "node_modules", "@theglitchking", "semantic-memory", "scripts", "link-skills.js"),
189
+ join2(cwd, "node_modules", "@theglitchking", "semantic-sidekick", "scripts", "link-skills.js"),
190
+ resolve2(process.cwd(), "scripts", "link-skills.js")
191
+ ];
192
+ const script = candidates.find((p) => existsSync2(p));
193
+ if (!script) {
189
194
  console.error("link-skills.js not found \u2014 is the package installed?");
190
195
  return;
191
196
  }
@@ -196,8 +201,14 @@ function runRelink(cwd) {
196
201
  });
197
202
  }
198
203
  function findLocalBin(cwd) {
199
- const p = join2(cwd, "node_modules", "@theglitchking", "semantic-sidekick", "bin", "semantic-sidekick");
200
- return existsSync2(p) ? p : null;
204
+ const candidates = [
205
+ join2(cwd, "node_modules", "@theglitchking", "semantic-memory", "bin", "semantic-memory"),
206
+ join2(cwd, "node_modules", "@theglitchking", "semantic-sidekick", "bin", "semantic-sidekick")
207
+ ];
208
+ for (const p of candidates) {
209
+ if (existsSync2(p)) return p;
210
+ }
211
+ return null;
201
212
  }
202
213
  function localBinArg(cwd) {
203
214
  const abs = findLocalBin(cwd);
@@ -217,7 +228,9 @@ function isNpxForm(entry) {
217
228
  if (!entry || typeof entry !== "object") return false;
218
229
  const cmd = entry.command;
219
230
  const args = Array.isArray(entry.args) ? entry.args : [];
220
- return cmd === "npx" && args.some((a) => typeof a === "string" && a.includes(PKG_NAME));
231
+ return cmd === "npx" && args.some(
232
+ (a) => typeof a === "string" && (a.includes(PKG_NAME) || a.includes(LEGACY_PKG_NAME))
233
+ );
221
234
  }
222
235
  function extractNotesPath(entry) {
223
236
  const args = Array.isArray(entry?.args) ? entry.args : [];
@@ -390,7 +403,7 @@ var TOOL_CATEGORIES = {
390
403
  function printToolList() {
391
404
  console.log("\nSemantic Pages \u2014 21 MCP Tools\n");
392
405
  console.log("Usage: These tools are available via MCP when the server is running.");
393
- console.log(" Run `semantic-sidekick tools <name>` for details on a specific tool.\n");
406
+ console.log(" Run `semantic-memory tools <name>` for details on a specific tool.\n");
394
407
  for (const [category, tools] of Object.entries(TOOL_CATEGORIES)) {
395
408
  console.log(` ${category}:`);
396
409
  for (const name of tools) {
@@ -399,13 +412,13 @@ function printToolList() {
399
412
  }
400
413
  console.log();
401
414
  }
402
- console.log("Run `semantic-sidekick tools <tool-name>` for arguments and examples.");
415
+ console.log("Run `semantic-memory tools <tool-name>` for arguments and examples.");
403
416
  }
404
417
  function printToolDetail(name) {
405
418
  const tool = TOOL_HELP[name];
406
419
  if (!tool) {
407
420
  console.error(`Unknown tool: ${name}`);
408
- console.error(`Run \`semantic-sidekick tools\` to see all available tools.`);
421
+ console.error(`Run \`semantic-memory tools\` to see all available tools.`);
409
422
  process.exit(1);
410
423
  }
411
424
  console.log(`
@@ -552,8 +565,8 @@ program.command("serve", { isDefault: true }).description("Start the MCP server
552
565
  });
553
566
  registerUpdateCommands(program, {
554
567
  packageName: PKG_NAME,
555
- pluginName: "semantic-sidekick",
556
- configFile: "semantic-sidekick.json",
568
+ pluginName: "semantic-memory",
569
+ configFile: "semantic-memory.json",
557
570
  onAfterUpdate: (cwd) => runRelink(cwd)
558
571
  });
559
572
  program.command("normalize-config").description(
@@ -573,8 +586,8 @@ program.command("normalize-config").description(
573
586
  const bin = localBinArg(cwd);
574
587
  if (!bin) {
575
588
  console.error(
576
- `no local install found at ./node_modules/@theglitchking/semantic-sidekick/bin/semantic-sidekick.
577
- run 'npm install --save @theglitchking/semantic-sidekick' first, then re-run this command.`
589
+ `no local install found at ./node_modules/@theglitchking/semantic-memory/bin/semantic-memory (or the legacy semantic-sidekick path).
590
+ run 'npm install --save @theglitchking/semantic-memory' first, then re-run this command.`
578
591
  );
579
592
  process.exit(1);
580
593
  }
@@ -627,8 +640,8 @@ program.command("healthcheck").description(
627
640
  const cwd = process.cwd();
628
641
  const bin = findLocalBin(cwd);
629
642
  if (!bin) {
630
- console.error(`no local install at ./node_modules/@theglitchking/semantic-sidekick/bin/semantic-sidekick`);
631
- console.error(`run 'npm install --save @theglitchking/semantic-sidekick' to install.`);
643
+ console.error(`no local install at ./node_modules/@theglitchking/semantic-memory/bin/semantic-memory (or legacy semantic-sidekick path)`);
644
+ console.error(`run 'npm install --save @theglitchking/semantic-memory' to install.`);
632
645
  process.exit(1);
633
646
  }
634
647
  const mcpPath = join2(cwd, ".mcp.json");
@@ -641,7 +654,7 @@ program.command("healthcheck").description(
641
654
  `\u26A0\uFE0F .mcp.json uses the fragile npx-@latest form for: ${fragile.join(", ")}`
642
655
  );
643
656
  console.warn(` Rewrite to the stable form:`);
644
- console.warn(` npx --no @theglitchking/semantic-sidekick normalize-config`);
657
+ console.warn(` npx --no @theglitchking/semantic-memory normalize-config`);
645
658
  }
646
659
  }
647
660
  const r = spawnSync("node", [bin, "--version"], { cwd, stdio: "pipe", timeout: 15e3 });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/index.ts","../../src/cli/skills.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { program } from \"commander\";\nimport { resolve, join, dirname, relative } from \"node:path\";\nimport { existsSync, readFileSync, writeFileSync, rmSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { spawnSync } from \"node:child_process\";\nimport { registerUpdateCommands } from \"@theglitchking/claude-plugin-runtime\";\nimport {\n resolveTarget,\n installSkills,\n uninstallSkills,\n listShippedSkills,\n SKILL_BUNDLER_AGENTS,\n type AgentName,\n type Scope,\n} from \"./skills.js\";\n\nconst require_ = createRequire(import.meta.url);\nconst { version } = require_(\"../../package.json\") as { version: string };\n\nconst PKG_NAME = \"@theglitchking/semantic-sidekick\";\n\nfunction runRelink(cwd: string) {\n const linker = join(cwd, \"node_modules\", \"@theglitchking\", \"semantic-sidekick\", \"scripts\", \"link-skills.js\");\n const script = existsSync(linker) ? linker : resolve(process.cwd(), \"scripts\", \"link-skills.js\");\n if (!existsSync(script)) {\n console.error(\"link-skills.js not found — is the package installed?\");\n return;\n }\n spawnSync(process.execPath, [script], {\n cwd,\n env: { ...process.env, INIT_CWD: cwd },\n stdio: \"inherit\",\n });\n}\n\nfunction findLocalBin(cwd: string): string | null {\n const p = join(cwd, \"node_modules\", \"@theglitchking\", \"semantic-sidekick\", \"bin\", \"semantic-sidekick\");\n return existsSync(p) ? p : null;\n}\n\nfunction localBinArg(cwd: string): string | null {\n const abs = findLocalBin(cwd);\n if (!abs) return null;\n const rel = relative(cwd, abs);\n return rel.startsWith(\"..\") ? abs : `./${rel}`;\n}\n\nfunction readJsonSafe(path: string): any {\n try {\n const raw = readFileSync(path, \"utf8\");\n return raw.trim() ? JSON.parse(raw) : null;\n } catch {\n return null;\n }\n}\n\n/**\n * Returns the fragile npx-form pattern we used to write in pre-0.10.0\n * SessionStart hooks, so normalize-config can detect and rewrite it.\n */\nfunction isNpxForm(entry: any): boolean {\n if (!entry || typeof entry !== \"object\") return false;\n const cmd = entry.command;\n const args = Array.isArray(entry.args) ? entry.args : [];\n return cmd === \"npx\" && args.some((a: unknown) => typeof a === \"string\" && a.includes(PKG_NAME));\n}\n\nfunction isLocalForm(entry: any): boolean {\n if (!entry || typeof entry !== \"object\") return false;\n const cmd = entry.command;\n const args = Array.isArray(entry.args) ? entry.args : [];\n return (\n cmd === \"node\" &&\n args.some((a: unknown) => typeof a === \"string\" && a.includes(\"node_modules/@theglitchking/semantic-sidekick\"))\n );\n}\n\nfunction extractNotesPath(entry: any): string | null {\n const args = Array.isArray(entry?.args) ? entry.args : [];\n const i = args.indexOf(\"--notes\");\n if (i === -1 || i + 1 >= args.length) return null;\n return String(args[i + 1]);\n}\n\nfunction extractExtraFlags(entry: any): string[] {\n const args = Array.isArray(entry?.args) ? entry.args : [];\n return args.filter((a: unknown): a is string => typeof a === \"string\" && a.startsWith(\"--\") && a !== \"--notes\");\n}\n\nconst TOOL_HELP: Record<string, { description: string; args: string; examples: string[] }> = {\n // Search\n search_semantic: {\n description: \"Vector similarity search — find notes by meaning, not just keywords\",\n args: '{ \"query\": \"string\", \"limit?\": 10 }',\n examples: [\n '{ \"query\": \"microservices architecture\", \"limit\": 5 }',\n '{ \"query\": \"how to deploy to production\" }',\n ],\n },\n search_text: {\n description: \"Full-text keyword or regex search with optional filters\",\n args: '{ \"pattern\": \"string\", \"regex?\": false, \"caseSensitive?\": false, \"pathGlob?\": \"string\", \"tagFilter?\": [\"string\"], \"limit?\": 20 }',\n examples: [\n '{ \"pattern\": \"RabbitMQ\" }',\n '{ \"pattern\": \"OAuth\\\\\\\\d\", \"regex\": true }',\n '{ \"pattern\": \"deploy\", \"pathGlob\": \"devops/**\", \"tagFilter\": [\"kubernetes\"] }',\n ],\n },\n search_graph: {\n description: \"Graph traversal — find notes connected to a concept via wikilinks and tags\",\n args: '{ \"concept\": \"string\", \"maxDepth?\": 2 }',\n examples: [\n '{ \"concept\": \"microservices\" }',\n '{ \"concept\": \"auth\", \"maxDepth\": 3 }',\n ],\n },\n search_hybrid: {\n description: \"Combined semantic + graph search — vector results re-ranked by graph proximity\",\n args: '{ \"query\": \"string\", \"limit?\": 10 }',\n examples: [\n '{ \"query\": \"event driven architecture\", \"limit\": 5 }',\n ],\n },\n\n // Read\n read_note: {\n description: \"Read the full content of a specific note by path\",\n args: '{ \"path\": \"string\" }',\n examples: [\n '{ \"path\": \"project-overview.md\" }',\n '{ \"path\": \"notes/meeting-2024-01-15.md\" }',\n ],\n },\n read_multiple_notes: {\n description: \"Batch read multiple notes in one call\",\n args: '{ \"paths\": [\"string\"] }',\n examples: [\n '{ \"paths\": [\"overview.md\", \"architecture.md\", \"deployment.md\"] }',\n ],\n },\n list_notes: {\n description: \"List all indexed notes with metadata (title, tags, link count)\",\n args: \"{}\",\n examples: [\"{}\"],\n },\n\n // Write\n create_note: {\n description: \"Create a new markdown note with optional YAML frontmatter\",\n args: '{ \"path\": \"string\", \"content\": \"string\", \"frontmatter?\": {} }',\n examples: [\n '{ \"path\": \"new-guide.md\", \"content\": \"# Guide\\\\n\\\\nContent here.\" }',\n '{ \"path\": \"tagged.md\", \"content\": \"Content.\", \"frontmatter\": { \"title\": \"Tagged Note\", \"tags\": [\"test\"] } }',\n ],\n },\n update_note: {\n description: \"Edit note content — overwrite, append, prepend, or patch by heading\",\n args: '{ \"path\": \"string\", \"content\": \"string\", \"mode\": \"overwrite|append|prepend|patch-by-heading\", \"heading?\": \"string\" }',\n examples: [\n '{ \"path\": \"guide.md\", \"content\": \"New content.\", \"mode\": \"overwrite\" }',\n '{ \"path\": \"guide.md\", \"content\": \"\\\\n## Appendix\\\\nExtra info.\", \"mode\": \"append\" }',\n '{ \"path\": \"guide.md\", \"content\": \"Updated architecture section.\", \"mode\": \"patch-by-heading\", \"heading\": \"Architecture\" }',\n ],\n },\n delete_note: {\n description: \"Delete a note permanently (requires confirm=true)\",\n args: '{ \"path\": \"string\", \"confirm\": true }',\n examples: [\n '{ \"path\": \"old-note.md\", \"confirm\": true }',\n '{ \"path\": \"old-note.md\", \"confirm\": false } // returns warning, does not delete',\n ],\n },\n move_note: {\n description: \"Move or rename a note — automatically updates wikilinks across the vault\",\n args: '{ \"from\": \"string\", \"to\": \"string\" }',\n examples: [\n '{ \"from\": \"user-service.md\", \"to\": \"auth-service.md\" }',\n '{ \"from\": \"old/note.md\", \"to\": \"new/location/note.md\" }',\n ],\n },\n\n // Metadata\n get_frontmatter: {\n description: \"Read parsed YAML frontmatter from a note as JSON\",\n args: '{ \"path\": \"string\" }',\n examples: ['{ \"path\": \"project-overview.md\" }'],\n },\n update_frontmatter: {\n description: \"Set or delete YAML frontmatter keys — pass null to delete a key\",\n args: '{ \"path\": \"string\", \"fields\": {} }',\n examples: [\n '{ \"path\": \"note.md\", \"fields\": { \"status\": \"active\", \"priority\": 1 } }',\n '{ \"path\": \"note.md\", \"fields\": { \"deprecated_field\": null } } // deletes the key',\n ],\n },\n manage_tags: {\n description: \"Add, remove, or list tags on a note (frontmatter and inline)\",\n args: '{ \"path\": \"string\", \"action\": \"add|remove|list\", \"tags?\": [\"string\"] }',\n examples: [\n '{ \"path\": \"note.md\", \"action\": \"list\" }',\n '{ \"path\": \"note.md\", \"action\": \"add\", \"tags\": [\"important\", \"reviewed\"] }',\n '{ \"path\": \"note.md\", \"action\": \"remove\", \"tags\": [\"draft\"] }',\n ],\n },\n rename_tag: {\n description: \"Rename a tag across all notes in the vault (frontmatter + inline)\",\n args: '{ \"oldTag\": \"string\", \"newTag\": \"string\" }',\n examples: ['{ \"oldTag\": \"architecture\", \"newTag\": \"arch\" }'],\n },\n\n // Graph\n backlinks: {\n description: \"Find all notes that link TO a given note via [[wikilinks]]\",\n args: '{ \"path\": \"string\" }',\n examples: ['{ \"path\": \"microservices.md\" }'],\n },\n forwardlinks: {\n description: \"Find all notes linked FROM a given note\",\n args: '{ \"path\": \"string\" }',\n examples: ['{ \"path\": \"project-overview.md\" }'],\n },\n graph_path: {\n description: \"Find the shortest path between two notes in the knowledge graph\",\n args: '{ \"from\": \"string\", \"to\": \"string\" }',\n examples: ['{ \"from\": \"project-overview.md\", \"to\": \"user-service.md\" }'],\n },\n graph_statistics: {\n description: \"Knowledge graph stats — most connected nodes, orphans, density\",\n args: \"{}\",\n examples: [\"{}\"],\n },\n\n // System\n get_stats: {\n description: \"Vault and index statistics — note count, chunks, embeddings, graph density\",\n args: \"{}\",\n examples: [\"{}\"],\n },\n reindex: {\n description: \"Force a full reindex of the vault\",\n args: \"{}\",\n examples: [\"{}\"],\n },\n};\n\nconst TOOL_CATEGORIES: Record<string, string[]> = {\n Search: [\"search_semantic\", \"search_text\", \"search_graph\", \"search_hybrid\"],\n Read: [\"read_note\", \"read_multiple_notes\", \"list_notes\"],\n Write: [\"create_note\", \"update_note\", \"delete_note\", \"move_note\"],\n Metadata: [\"get_frontmatter\", \"update_frontmatter\", \"manage_tags\", \"rename_tag\"],\n Graph: [\"backlinks\", \"forwardlinks\", \"graph_path\", \"graph_statistics\"],\n System: [\"get_stats\", \"reindex\"],\n};\n\nfunction printToolList() {\n console.log(\"\\nSemantic Pages — 21 MCP Tools\\n\");\n console.log(\"Usage: These tools are available via MCP when the server is running.\");\n console.log(\" Run `semantic-sidekick tools <name>` for details on a specific tool.\\n\");\n\n for (const [category, tools] of Object.entries(TOOL_CATEGORIES)) {\n console.log(` ${category}:`);\n for (const name of tools) {\n const tool = TOOL_HELP[name];\n console.log(` ${name.padEnd(24)} ${tool.description}`);\n }\n console.log();\n }\n\n console.log(\"Run `semantic-sidekick tools <tool-name>` for arguments and examples.\");\n}\n\nfunction printToolDetail(name: string) {\n const tool = TOOL_HELP[name];\n if (!tool) {\n console.error(`Unknown tool: ${name}`);\n console.error(`Run \\`semantic-sidekick tools\\` to see all available tools.`);\n process.exit(1);\n }\n\n console.log(`\\n ${name}`);\n console.log(` ${\"─\".repeat(name.length)}`);\n console.log(` ${tool.description}\\n`);\n console.log(` Arguments:`);\n console.log(` ${tool.args}\\n`);\n console.log(` Examples:`);\n for (const ex of tool.examples) {\n console.log(` ${ex}`);\n }\n console.log();\n}\n\nprogram\n .name(\"semantic-memory\")\n .description(\n \"Unified memory-layer MCP server for Claude Code (rebrand of semantic-sidekick at v1.0.0).\\n\" +\n \"The `semantic-sidekick` command is preserved as an alias.\\n\\n\" +\n \" Start MCP server: semantic-memory --notes ./vault\\n\" +\n \" Show vault stats: semantic-memory --notes ./vault --stats\\n\" +\n \" Force reindex: semantic-memory --notes ./vault --reindex\\n\" +\n \" List MCP tools: semantic-memory tools\\n\" +\n \" Tool details: semantic-memory tools search_semantic\"\n )\n .version(version);\n\nprogram\n .command(\"search <query>\")\n .description(\"Run a vault search and print top hits as JSON (used by activation hooks)\")\n .requiredOption(\"--notes <path>\", \"Path to markdown notes directory\")\n .option(\"--limit <n>\", \"Max results\", (v) => parseInt(v, 10), 8)\n .option(\"--text-only\", \"Skip embedder — keyword-only search (fast path, no model init)\")\n .option(\"--json\", \"Emit raw JSON (default)\", true)\n .action(async (query: string, opts) => {\n const { runSearch } = await import(\"./search.js\");\n try {\n const hits = await runSearch({\n notes: opts.notes,\n query,\n limit: opts.limit,\n textOnly: opts.textOnly,\n });\n process.stdout.write(JSON.stringify(hits, null, 2) + \"\\n\");\n process.exit(0);\n } catch (err: any) {\n console.error(`search failed: ${err.message}`);\n process.exit(1);\n }\n });\n\nprogram\n .command(\"lint\")\n .description(\"Lint the vault against vault.schema.yml (schema violations + missing provenance + stale)\")\n .requiredOption(\"--notes <path>\", \"Path to markdown notes directory\")\n .option(\"--rule <name>\", \"Limit output to one rule: schema_violations | missing_provenance | stale\")\n .option(\"--json\", \"Emit JSON instead of the human-readable report\")\n .option(\"--strict\", \"Exit non-zero on warnings too (default: exit non-zero only on errors)\")\n .action(async (opts) => {\n const { lintVault, formatLintReport } = await import(\"../core/lint.js\");\n const report = await lintVault(resolve(opts.notes));\n // Use console.log + process.exitCode (not process.exit) so Node flushes\n // stdout fully before the process ends. Early process.exit with a large\n // buffered JSON payload can truncate output.\n if (opts.json) {\n const out = opts.rule ? report.byRule[opts.rule as keyof typeof report.byRule] : report;\n console.log(JSON.stringify(out, null, 2));\n } else {\n console.log(formatLintReport(report, { rule: opts.rule }));\n }\n const bad = opts.strict ? report.counts.errors + report.counts.warnings : report.counts.errors;\n process.exitCode = bad > 0 ? 1 : 0;\n });\n\nprogram\n .command(\"log-event\")\n .description(\"Append a structured event to the vault's log.md (used by hooks and CI scripts — same shape as mcp__semantic-vault__log_event)\")\n .requiredOption(\"--notes <path>\", \"Path to markdown notes directory\")\n .requiredOption(\"--kind <name>\", \"Event category: ingest, synthesis, error, mode_change, etc.\")\n .requiredOption(\"--summary <text>\", \"One-line human summary\")\n .option(\"--payload <json>\", \"Structured payload as JSON string\")\n .action(async (opts) => {\n const { logEvent } = await import(\"../core/log.js\");\n let payload: Record<string, unknown> | undefined;\n if (opts.payload) {\n try {\n payload = JSON.parse(opts.payload);\n } catch (e: any) {\n console.error(`invalid --payload JSON: ${e.message}`);\n process.exitCode = 1;\n return;\n }\n }\n try {\n const entry = await logEvent(resolve(opts.notes), {\n kind: opts.kind,\n summary: opts.summary,\n payload,\n });\n console.log(JSON.stringify(entry));\n } catch (e: any) {\n console.error(`log-event failed: ${e.message}`);\n process.exitCode = 1;\n }\n });\n\nprogram\n .command(\"log-query\")\n .description(\"Read structured log entries from log.md — filters by kind, date range, limit\")\n .requiredOption(\"--notes <path>\", \"Path to markdown notes directory\")\n .option(\"--kind <name>\", \"Filter by kind (ingest, synthesis, error, mode_change, etc.)\")\n .option(\"--after <iso>\", \"ISO timestamp — only entries on or after\")\n .option(\"--before <iso>\", \"ISO timestamp — only entries on or before\")\n .option(\"--limit <n>\", \"Max entries (most recent)\", (v) => parseInt(v, 10))\n .action(async (opts) => {\n const { logQuery } = await import(\"../core/log.js\");\n try {\n const entries = await logQuery(resolve(opts.notes), {\n kind: opts.kind,\n after: opts.after,\n before: opts.before,\n limit: opts.limit,\n });\n console.log(JSON.stringify(entries));\n } catch (e: any) {\n console.error(`log-query failed: ${e.message}`);\n process.exitCode = 1;\n }\n });\n\nprogram\n .command(\"install-schema\")\n .description(\"Bootstrap vault.schema.yml in the vault root with the default schema\")\n .requiredOption(\"--notes <path>\", \"Path to markdown notes directory\")\n .option(\"--force\", \"Overwrite existing schema file\")\n .action(async (opts) => {\n const { installDefaultSchema } = await import(\"../core/schema.js\");\n const r = await installDefaultSchema(resolve(opts.notes), opts.force);\n console.log(r.written ? `Installed default schema: ${r.path}` : `Schema already exists: ${r.path} (use --force to overwrite)`);\n process.exit(0);\n });\n\nprogram\n .command(\"tools [name]\")\n .description(\"List all MCP tools, or show details for a specific tool\")\n .action((name?: string) => {\n if (name) {\n printToolDetail(name);\n } else {\n printToolList();\n }\n process.exit(0);\n });\n\nprogram\n .command(\"serve\", { isDefault: true })\n .description(\"Start the MCP server (default command)\")\n .requiredOption(\"--notes <path>\", \"Path to markdown notes directory\")\n .option(\"--reindex\", \"Force full reindex and exit\")\n .option(\"--stats\", \"Show vault statistics and exit\")\n .option(\"--wait-for-ready\", \"Block startup until index is fully built before serving (default: index in background; tools return 'Indexing in progress' until ready)\")\n .option(\"--read-only\", \"Suppress write tools (create_note, update_note, delete_note, move_note, update_frontmatter, manage_tags, rename_tag) — use for shared docs vaults owned by another tool\")\n .option(\"--model <name>\", \"Embedding model to use (default: all-MiniLM-L6-v2, fast; use nomic-ai/nomic-embed-text-v1.5 for higher quality)\")\n .option(\"--workers <n>\", \"Number of worker threads for parallel embedding\", parseInt)\n .option(\"--batch-size <n>\", \"Texts per ONNX forward pass (default: 8)\", parseInt)\n .option(\"--no-quantized\", \"Use full-precision model instead of quantized (slower, slightly higher quality)\")\n .option(\"--no-watch\", \"Disable file watcher\")\n .action(async (opts) => {\n const notesPath = resolve(opts.notes);\n\n if (!existsSync(notesPath)) {\n console.error(`Error: notes directory not found: ${notesPath}`);\n process.exit(1);\n }\n\n if (opts.stats) {\n const { Indexer } = await import(\"../core/indexer.js\");\n const indexer = new Indexer(notesPath);\n const docs = await indexer.indexAll();\n console.log(`Notes: ${docs.length}`);\n console.log(`Chunks: ${docs.reduce((n: number, d: any) => n + d.chunks.length, 0)}`);\n console.log(`Wikilinks: ${docs.reduce((n: number, d: any) => n + d.wikilinks.length, 0)}`);\n console.log(`Tags: ${new Set(docs.flatMap((d: any) => d.tags)).size} unique`);\n process.exit(0);\n }\n\n if (opts.reindex) {\n const { createServer } = await import(\"../mcp/server.js\");\n await createServer(notesPath, {\n watch: false,\n waitForReady: true,\n model: opts.model,\n workers: opts.workers,\n batchSize: opts.batchSize,\n quantized: opts.quantized,\n onProgress: (embedded, total) => {\n process.stderr.write(`\\rEmbedding ${embedded}/${total} chunks...`);\n },\n });\n process.stderr.write(\"\\n\");\n console.log(\"Reindex complete.\");\n process.exit(0);\n }\n\n // Default: start MCP server on stdio\n const { startServer } = await import(\"../mcp/server.js\");\n await startServer(notesPath, {\n watch: opts.watch,\n waitForReady: opts.waitForReady,\n model: opts.model,\n workers: opts.workers,\n batchSize: opts.batchSize,\n quantized: opts.quantized,\n readOnly: opts.readOnly,\n });\n });\n\nregisterUpdateCommands(program, {\n packageName: PKG_NAME,\n pluginName: \"semantic-sidekick\",\n configFile: \"semantic-sidekick.json\",\n onAfterUpdate: (cwd) => runRelink(cwd),\n});\n\nprogram\n .command(\"normalize-config\")\n .description(\n \"Rewrite fragile `npx @latest` entries in .mcp.json to the stable node-against-node_modules form (with backup and validation)\",\n )\n .option(\"--dry-run\", \"print the proposed changes but don't write\")\n .action((opts: { dryRun?: boolean }) => {\n const cwd = process.cwd();\n const mcpPath = join(cwd, \".mcp.json\");\n if (!existsSync(mcpPath)) {\n console.log(\"no .mcp.json in current directory — nothing to do\");\n process.exit(0);\n }\n const data = readJsonSafe(mcpPath);\n if (!data || typeof data !== \"object\" || !data.mcpServers || typeof data.mcpServers !== \"object\") {\n console.error(`could not parse ${mcpPath}`);\n process.exit(1);\n }\n const bin = localBinArg(cwd);\n if (!bin) {\n console.error(\n `no local install found at ./node_modules/@theglitchking/semantic-sidekick/bin/semantic-sidekick.\\n` +\n `run 'npm install --save @theglitchking/semantic-sidekick' first, then re-run this command.`,\n );\n process.exit(1);\n }\n const rewritten: string[] = [];\n for (const [key, entry] of Object.entries<any>(data.mcpServers)) {\n if (!isNpxForm(entry)) continue;\n const notes = extractNotesPath(entry) ?? \"./.claude/.vault\";\n const extra = extractExtraFlags(entry);\n data.mcpServers[key] = {\n type: \"stdio\",\n command: \"node\",\n args: [bin, \"--notes\", notes, ...extra],\n };\n rewritten.push(key);\n }\n if (rewritten.length === 0) {\n console.log(\"no npx-form entries found — .mcp.json is already in the stable form.\");\n process.exit(0);\n }\n console.log(`Rewriting ${rewritten.length} entr${rewritten.length === 1 ? \"y\" : \"ies\"}: ${rewritten.join(\", \")}`);\n if (opts.dryRun) {\n console.log(\"--- proposed .mcp.json:\");\n console.log(JSON.stringify(data, null, 2));\n console.log(\"--- (dry-run; no changes written)\");\n process.exit(0);\n }\n // Back up\n const bakPath = join(dirname(mcpPath), \".mcp.json.bak\");\n try {\n writeFileSync(bakPath, readFileSync(mcpPath, \"utf8\"));\n console.log(`backup written: ${bakPath}`);\n } catch (err: any) {\n console.error(`could not write backup: ${err.message}`);\n process.exit(1);\n }\n writeFileSync(mcpPath, JSON.stringify(data, null, 2) + \"\\n\");\n\n // Verify the local bin starts cleanly. We just run --version — fast and\n // enough to catch ERR_MODULE_NOT_FOUND type failures.\n const verify = spawnSync(\"node\", [bin, \"--version\"], { cwd, stdio: \"pipe\", timeout: 15_000 });\n if (verify.status !== 0) {\n console.error(`verification failed (exit ${verify.status}):\\n${verify.stderr?.toString() || \"\"}`);\n console.error(`rolling back from ${bakPath}`);\n writeFileSync(mcpPath, readFileSync(bakPath, \"utf8\"));\n process.exit(1);\n }\n console.log(`✓ .mcp.json normalized and verified. Toggle the MCPs in /mcp to reconnect.`);\n process.exit(0);\n });\n\nprogram\n .command(\"healthcheck\")\n .description(\n \"Verify the local install starts cleanly + run drift detection. Self-heals common npx-cache corruption (ERR_MODULE_NOT_FOUND). With --fast, skips the slow tier (full vault lint).\",\n )\n .option(\"--fast\", \"Run only the fast-tier drift checks (file-system probes). Skips the slow tier (full vault lint).\", false)\n .option(\"--json\", \"Emit structured JSON output instead of human-readable text.\", false)\n .action(async (opts) => {\n const cwd = process.cwd();\n const bin = findLocalBin(cwd);\n if (!bin) {\n console.error(`no local install at ./node_modules/@theglitchking/semantic-sidekick/bin/semantic-sidekick`);\n console.error(`run 'npm install --save @theglitchking/semantic-sidekick' to install.`);\n process.exit(1);\n }\n\n // 1. Warn if .mcp.json uses the fragile form.\n const mcpPath = join(cwd, \".mcp.json\");\n if (existsSync(mcpPath)) {\n const data = readJsonSafe(mcpPath);\n const entries = data?.mcpServers && typeof data.mcpServers === \"object\" ? Object.entries<any>(data.mcpServers) : [];\n const fragile = entries.filter(([, e]) => isNpxForm(e)).map(([k]) => k);\n if (fragile.length > 0) {\n console.warn(\n `⚠️ .mcp.json uses the fragile npx-@latest form for: ${fragile.join(\", \")}`,\n );\n console.warn(` Rewrite to the stable form:`);\n console.warn(` npx --no @theglitchking/semantic-sidekick normalize-config`);\n }\n }\n\n // 2. Smoke-test the local bin.\n const r = spawnSync(\"node\", [bin, \"--version\"], { cwd, stdio: \"pipe\", timeout: 15_000 });\n if (r.status === 0) {\n console.log(`✓ local install starts cleanly (v${r.stdout?.toString().trim()})`);\n process.exit(0);\n }\n\n const stderr = r.stderr?.toString() ?? \"\";\n\n // 3. Self-heal ERR_MODULE_NOT_FOUND in npx cache (rare but the classic\n // failure mode that triggered 0.10.0). Extract the offending npx cache\n // dir from the error message, rm -rf it, retry once.\n if (stderr.includes(\"ERR_MODULE_NOT_FOUND\")) {\n const match = stderr.match(/([\\/~][^'\"\\s]*\\/_npx\\/[^\\/'\"\\s]+)/);\n if (match) {\n const bad = match[1];\n console.warn(`detected broken npx cache at ${bad} — clearing and retrying...`);\n try { rmSync(bad, { recursive: true, force: true }); } catch {}\n const r2 = spawnSync(\"node\", [bin, \"--version\"], { cwd, stdio: \"pipe\", timeout: 15_000 });\n if (r2.status === 0) {\n console.log(`✓ cleared npx cache and verified (v${r2.stdout?.toString().trim()})`);\n process.exit(0);\n }\n console.error(`retry still failed:\\n${r2.stderr?.toString() || \"\"}`);\n } else {\n console.error(`ERR_MODULE_NOT_FOUND but could not locate offending cache path in the error.`);\n }\n }\n\n if (stderr) console.error(stderr);\n if (r.status !== 0) {\n console.error(`local install failed (exit ${r.status})`);\n process.exit(1);\n }\n });\n\n// Append drift detection to the healthcheck handler (Phase 8). Wraps the original\n// handler — the function above runs first (npx-cache self-heal), then drift detection\n// runs and prints additional findings. --fast skips the slow tier (full vault lint).\nconst driftHealthcheckActionPostprocess = async (opts: { fast?: boolean; json?: boolean }) => {\n try {\n const { runHealthcheck, formatDriftBanner } = await import(\"../core/healthcheck.js\");\n const projectRoot = process.cwd();\n // For the auto-derived vault path, prefer .claude/.vault if present\n const vaultCandidate = join(projectRoot, \".claude\", \".vault\");\n const vaultPath = existsSync(vaultCandidate) ? vaultCandidate : undefined;\n const result = await runHealthcheck({\n projectRoot,\n vaultPath,\n tier: opts.fast ? \"fast\" : \"all\",\n force: true,\n });\n if (opts.json) {\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n const banner = formatDriftBanner(result);\n if (banner) {\n console.log(\"\");\n console.log(banner);\n } else {\n console.log(\"\");\n console.log(`✓ no drift detected (${result.findings.length} checks ran in ${result.duration_ms}ms)`);\n }\n } catch (err: any) {\n console.error(`drift check threw: ${err?.message ?? err}`);\n }\n};\n\n// Wire the drift-detection postprocess. We do this by attaching to the existing\n// healthcheck command's postAction hook so the original handler still runs first.\nconst healthcheckCmd = program.commands.find((c) => c.name() === \"healthcheck\");\nif (healthcheckCmd) {\n healthcheckCmd.hook(\"postAction\", async (thisCmd) => {\n const opts = thisCmd.opts();\n await driftHealthcheckActionPostprocess({ fast: !!opts.fast, json: !!opts.json });\n });\n}\n\n// --- Skill bundler (Phase 6) ---\n\nfunction parseAgent(input: string): AgentName {\n const a = input.toLowerCase();\n if (!SKILL_BUNDLER_AGENTS.includes(a as AgentName)) {\n console.error(`Unknown agent: ${input}. Supported: ${SKILL_BUNDLER_AGENTS.join(\", \")}.`);\n process.exit(2);\n }\n return a as AgentName;\n}\n\nfunction parseScope(input: string): Scope {\n if (input !== \"global\" && input !== \"local\") {\n console.error(`Unknown scope: ${input}. Use 'global' or 'local'.`);\n process.exit(2);\n }\n return input;\n}\n\nfunction findSourceRoot(): string {\n // 1. Installed: <cwd>/node_modules/@theglitchking/semantic-sidekick or semantic-memory\n for (const pkg of [\"semantic-memory\", \"semantic-sidekick\"]) {\n const installed = join(process.cwd(), \"node_modules\", \"@theglitchking\", pkg);\n if (existsSync(installed)) return installed;\n }\n // 2. Dev: derive from the bin location (this file lives at <root>/dist/cli/index.js)\n const dev = resolve(new URL(\"../../\", import.meta.url).pathname);\n return dev;\n}\n\nconst skillsCmd = program.command(\"skills\").description(\"Install, target, or uninstall skill bundles for non-Claude agents (codex, copilot, pi). Claude installs continue to use the npm postinstall flow.\");\n\nskillsCmd\n .command(\"targets\")\n .description(\"Preview where skill bundles would be installed for one or more agents.\")\n .option(\"--agent <name...>\", \"One or more agents (default: all). Repeatable.\", undefined as any)\n .option(\"--scope <scope>\", \"global or local (default: local)\", \"local\")\n .option(\"--project <path>\", \"Project root for local-scope paths (default: cwd)\", process.cwd())\n .action((opts) => {\n const scope = parseScope(opts.scope);\n const agents: AgentName[] = (opts.agent && opts.agent.length > 0 ? opts.agent : SKILL_BUNDLER_AGENTS).map(parseAgent);\n const out = agents.map((a) => resolveTarget(a, scope, opts.project));\n console.log(JSON.stringify(out, null, 2));\n });\n\nskillsCmd\n .command(\"install\")\n .description(\"Install skill bundles into an agent's skill directory. Non-destructive by default; --force to overwrite.\")\n .requiredOption(\"--agent <name>\", \"Agent runtime (claude, codex, copilot, pi)\")\n .option(\"--scope <scope>\", \"global or local (default: local)\", \"local\")\n .option(\"--project <path>\", \"Project root for local-scope paths (default: cwd)\", process.cwd())\n .option(\"--only <names...>\", \"Restrict to specific skill names (default: all shipped)\")\n .option(\"--force\", \"Overwrite even if drift is detected against an existing manifest\", false)\n .action(async (opts) => {\n const agent = parseAgent(opts.agent);\n const scope = parseScope(opts.scope);\n if (agent === \"claude\") {\n console.error(\n \"Claude skill installs are handled by the npm postinstall (claude-plugin-runtime). \" +\n \"Run `npm install @theglitchking/semantic-memory` instead — that flow symlinks \" +\n \"skills into ~/.claude/skills/ or .claude/skills/ automatically. The skills CLI \" +\n \"is intended for non-Claude agents (codex, copilot, pi) which do not have that \" +\n \"postinstall integration.\"\n );\n process.exit(2);\n }\n const sourceRoot = findSourceRoot();\n const result = await installSkills({\n agent,\n scope,\n sourceRoot,\n projectRoot: opts.project,\n version,\n only: opts.only,\n force: opts.force === true,\n });\n console.log(JSON.stringify(result, null, 2));\n if (result.installed.length === 0 && result.reason) process.exit(1);\n });\n\nskillsCmd\n .command(\"uninstall\")\n .description(\"Remove skill bundles tracked by the semantic-memory manifest. User-written skills outside the manifest are left untouched.\")\n .requiredOption(\"--agent <name>\", \"Agent runtime (claude, codex, copilot, pi)\")\n .option(\"--scope <scope>\", \"global or local (default: local)\", \"local\")\n .option(\"--project <path>\", \"Project root for local-scope paths (default: cwd)\", process.cwd())\n .action(async (opts) => {\n const agent = parseAgent(opts.agent);\n const scope = parseScope(opts.scope);\n if (agent === \"claude\") {\n console.error(\"Claude skill uninstalls go through the npm uninstall flow. The skills CLI is for non-Claude agents.\");\n process.exit(2);\n }\n const result = await uninstallSkills({ agent, scope, projectRoot: opts.project });\n console.log(JSON.stringify(result, null, 2));\n });\n\nskillsCmd\n .command(\"list\")\n .description(\"List the skill bundles shipped with this plugin version.\")\n .action(async () => {\n const sourceRoot = findSourceRoot();\n const shipped = await listShippedSkills(sourceRoot);\n console.log(JSON.stringify(shipped.map((s) => s.name), null, 2));\n });\n\nprogram.parse();\n","import { mkdir, readFile, writeFile, copyFile, readdir, rm } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { join, basename, resolve } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { createHash } from \"node:crypto\";\n\nexport type AgentName = \"claude\" | \"codex\" | \"copilot\" | \"pi\";\nexport type Scope = \"global\" | \"local\";\n\nexport interface AgentTargetSpec {\n agent: AgentName;\n scope: Scope;\n /** Absolute resolved path where the skill bundles will land. */\n path: string;\n}\n\nexport interface SkillManifest {\n package: string;\n version: string;\n agent: AgentName;\n scope: Scope;\n installed_at: string;\n skills: { name: string; sha256: string }[];\n}\n\nexport interface InstallResult {\n agent: AgentName;\n scope: Scope;\n target_path: string;\n installed: string[];\n skipped: string[];\n reason?: string;\n manifest_path?: string;\n}\n\nconst MANIFEST_FILE = \".semantic-memory-skill-manifest.json\";\n\n/**\n * Resolve where a given (agent, scope) tuple should land. Project root is required for local\n * scope (to anchor relative paths); for global scope it's not used.\n */\nexport function resolveTarget(agent: AgentName, scope: Scope, projectRoot: string): AgentTargetSpec {\n const root = resolve(projectRoot);\n const home = homedir();\n const map: Record<AgentName, { global: string; local: string }> = {\n claude: { global: join(home, \".claude\", \"skills\"), local: join(root, \".claude\", \"skills\") },\n codex: { global: join(home, \".codex\", \"skills\"), local: join(root, \".codex\", \"skills\") },\n copilot: { global: join(home, \".copilot\", \"skills\"), local: join(root, \".github\", \"skills\") },\n pi: { global: join(home, \".pi\", \"agent\", \"skills\"), local: join(root, \".pi\", \"skills\") },\n };\n return { agent, scope, path: map[agent][scope] };\n}\n\n/**\n * Enumerate the canonical skill bundles shipped by this plugin. Each bundle is a directory\n * under `<sourceRoot>/skills/` containing at least a SKILL.md file. Entries without\n * SKILL.md are silently skipped (allows future non-skill files like `/skills/.gitkeep`).\n */\nexport async function listShippedSkills(sourceRoot: string): Promise<{ name: string; dir: string }[]> {\n const skillsDir = join(sourceRoot, \"skills\");\n if (!existsSync(skillsDir)) return [];\n const entries = await readdir(skillsDir, { withFileTypes: true });\n const out: { name: string; dir: string }[] = [];\n for (const e of entries) {\n if (!e.isDirectory()) continue;\n const dir = join(skillsDir, e.name);\n const skillFile = join(dir, \"SKILL.md\");\n if (!existsSync(skillFile)) continue;\n out.push({ name: e.name, dir });\n }\n return out;\n}\n\nasync function sha256OfFile(path: string): Promise<string> {\n const buf = await readFile(path);\n return createHash(\"sha256\").update(buf).digest(\"hex\");\n}\n\n/**\n * Copy a single skill bundle (SKILL.md plus any sibling files in the same directory) into\n * the target directory, overlaying it with the agent name. Returns the list of files written.\n *\n * The target layout is `<targetPath>/<skillName>/SKILL.md` plus mirrored siblings, so each\n * bundle is namespaced and easy to remove later.\n */\nasync function copyBundle(srcDir: string, destDir: string): Promise<string[]> {\n await mkdir(destDir, { recursive: true });\n const entries = await readdir(srcDir, { withFileTypes: true });\n const written: string[] = [];\n for (const e of entries) {\n const src = join(srcDir, e.name);\n const dest = join(destDir, e.name);\n if (e.isDirectory()) {\n const childWritten = await copyBundle(src, dest);\n written.push(...childWritten);\n continue;\n }\n if (!e.isFile()) continue;\n await copyFile(src, dest);\n written.push(dest);\n }\n return written;\n}\n\nexport interface InstallOptions {\n agent: AgentName;\n scope: Scope;\n /** Path to the package's source root (usually the repo root, where `skills/` lives). */\n sourceRoot: string;\n /** Used to anchor local-scope target paths. */\n projectRoot: string;\n /** Plugin version, recorded in the manifest. */\n version: string;\n /** Specific skills to install. When omitted, all shipped skills are installed. */\n only?: string[];\n /**\n * When false, refuse to overwrite an existing install (manifest present + sha mismatch\n * indicates upstream drift). When true, overwrite. Default false.\n */\n force?: boolean;\n}\n\n/**\n * Install all (or selected) skill bundles into an agent's skill directory.\n *\n * Behavior:\n * - Resolves the destination via resolveTarget.\n * - Reads any existing manifest. If a manifest exists, version differs from `version`,\n * AND any skill sha256 differs from the source: this is a drift event. Without\n * `force: true`, returns a refusal with reason \"drift detected\". With force, proceeds\n * and overwrites.\n * - For each shipped skill (or each in `only`), copies the bundle into\n * <target>/<skillName>/, overwriting any existing files in that subdirectory.\n * - Writes a fresh manifest at <target>/<MANIFEST_FILE> recording sha256 of each\n * SKILL.md installed, the plugin version, agent, and scope.\n */\nexport async function installSkills(opts: InstallOptions): Promise<InstallResult> {\n const target = resolveTarget(opts.agent, opts.scope, opts.projectRoot);\n const shipped = await listShippedSkills(opts.sourceRoot);\n const filter = opts.only && opts.only.length > 0 ? new Set(opts.only) : null;\n const toInstall = filter ? shipped.filter((s) => filter.has(s.name)) : shipped;\n\n if (toInstall.length === 0) {\n return {\n agent: opts.agent,\n scope: opts.scope,\n target_path: target.path,\n installed: [],\n skipped: [],\n reason: filter ? `No matching skills found (only=${[...filter].join(\",\")}).` : \"No shipped skills found at sourceRoot/skills/.\",\n };\n }\n\n const manifestPath = join(target.path, MANIFEST_FILE);\n const existing = await readManifest(manifestPath);\n\n if (existing && !opts.force) {\n const drift = await detectDrift(existing, toInstall);\n if (drift.length > 0) {\n return {\n agent: opts.agent,\n scope: opts.scope,\n target_path: target.path,\n installed: [],\n skipped: toInstall.map((s) => s.name),\n reason: `Drift detected on ${drift.length} skill(s): ${drift.join(\", \")}. Pass --force to overwrite.`,\n manifest_path: manifestPath,\n };\n }\n }\n\n await mkdir(target.path, { recursive: true });\n const installed: string[] = [];\n const skillEntries: { name: string; sha256: string }[] = [];\n for (const skill of toInstall) {\n const destDir = join(target.path, skill.name);\n await copyBundle(skill.dir, destDir);\n const skillFile = join(skill.dir, \"SKILL.md\");\n skillEntries.push({ name: skill.name, sha256: await sha256OfFile(skillFile) });\n installed.push(skill.name);\n }\n\n const manifest: SkillManifest = {\n package: \"@theglitchking/semantic-memory\",\n version: opts.version,\n agent: opts.agent,\n scope: opts.scope,\n installed_at: new Date().toISOString(),\n skills: skillEntries,\n };\n await writeFile(manifestPath, JSON.stringify(manifest, null, 2), \"utf-8\");\n\n return {\n agent: opts.agent,\n scope: opts.scope,\n target_path: target.path,\n installed,\n skipped: [],\n manifest_path: manifestPath,\n };\n}\n\nexport interface UninstallOptions {\n agent: AgentName;\n scope: Scope;\n projectRoot: string;\n}\n\nexport interface UninstallResult {\n agent: AgentName;\n scope: Scope;\n target_path: string;\n removed: string[];\n manifest_present: boolean;\n reason?: string;\n}\n\n/**\n * Remove only the skill bundles tracked in the manifest. User-written skills outside\n * the manifest are left untouched.\n */\nexport async function uninstallSkills(opts: UninstallOptions): Promise<UninstallResult> {\n const target = resolveTarget(opts.agent, opts.scope, opts.projectRoot);\n const manifestPath = join(target.path, MANIFEST_FILE);\n const manifest = await readManifest(manifestPath);\n if (!manifest) {\n return {\n agent: opts.agent,\n scope: opts.scope,\n target_path: target.path,\n removed: [],\n manifest_present: false,\n reason: \"No semantic-memory manifest found — nothing to uninstall.\",\n };\n }\n const removed: string[] = [];\n for (const skill of manifest.skills) {\n const dir = join(target.path, skill.name);\n if (existsSync(dir)) {\n await rm(dir, { recursive: true, force: true });\n removed.push(skill.name);\n }\n }\n await rm(manifestPath, { force: true });\n return {\n agent: opts.agent,\n scope: opts.scope,\n target_path: target.path,\n removed,\n manifest_present: true,\n };\n}\n\nasync function readManifest(path: string): Promise<SkillManifest | null> {\n if (!existsSync(path)) return null;\n try {\n const raw = await readFile(path, \"utf-8\");\n const parsed = JSON.parse(raw);\n if (typeof parsed?.package !== \"string\") return null;\n return parsed as SkillManifest;\n } catch {\n return null;\n }\n}\n\nasync function detectDrift(\n existing: SkillManifest,\n toInstall: { name: string; dir: string }[]\n): Promise<string[]> {\n const driftNames: string[] = [];\n const existingByName = new Map(existing.skills.map((s) => [s.name, s.sha256]));\n for (const skill of toInstall) {\n const sourceSha = await sha256OfFile(join(skill.dir, \"SKILL.md\"));\n const existingSha = existingByName.get(skill.name);\n if (existingSha !== undefined && existingSha !== sourceSha) {\n driftNames.push(skill.name);\n }\n }\n return driftNames;\n}\n\nexport const SKILL_BUNDLER_AGENTS: AgentName[] = [\"claude\", \"codex\", \"copilot\", \"pi\"];\n"],"mappings":"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","names":["resolve","join","existsSync","join","existsSync","resolve","resolve","existsSync","join"]}
1
+ {"version":3,"sources":["../../src/cli/index.ts","../../src/cli/skills.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { program } from \"commander\";\nimport { resolve, join, dirname, relative } from \"node:path\";\nimport { existsSync, readFileSync, writeFileSync, rmSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { spawnSync } from \"node:child_process\";\nimport { registerUpdateCommands } from \"@theglitchking/claude-plugin-runtime\";\nimport {\n resolveTarget,\n installSkills,\n uninstallSkills,\n listShippedSkills,\n SKILL_BUNDLER_AGENTS,\n type AgentName,\n type Scope,\n} from \"./skills.js\";\n\nconst require_ = createRequire(import.meta.url);\nconst { version } = require_(\"../../package.json\") as { version: string };\n\nconst PKG_NAME = \"@theglitchking/semantic-memory\";\nconst LEGACY_PKG_NAME = \"@theglitchking/semantic-sidekick\";\n\nfunction runRelink(cwd: string) {\n const candidates = [\n join(cwd, \"node_modules\", \"@theglitchking\", \"semantic-memory\", \"scripts\", \"link-skills.js\"),\n join(cwd, \"node_modules\", \"@theglitchking\", \"semantic-sidekick\", \"scripts\", \"link-skills.js\"),\n resolve(process.cwd(), \"scripts\", \"link-skills.js\"),\n ];\n const script = candidates.find((p) => existsSync(p));\n if (!script) {\n console.error(\"link-skills.js not found — is the package installed?\");\n return;\n }\n spawnSync(process.execPath, [script], {\n cwd,\n env: { ...process.env, INIT_CWD: cwd },\n stdio: \"inherit\",\n });\n}\n\nfunction findLocalBin(cwd: string): string | null {\n const candidates = [\n join(cwd, \"node_modules\", \"@theglitchking\", \"semantic-memory\", \"bin\", \"semantic-memory\"),\n join(cwd, \"node_modules\", \"@theglitchking\", \"semantic-sidekick\", \"bin\", \"semantic-sidekick\"),\n ];\n for (const p of candidates) {\n if (existsSync(p)) return p;\n }\n return null;\n}\n\nfunction localBinArg(cwd: string): string | null {\n const abs = findLocalBin(cwd);\n if (!abs) return null;\n const rel = relative(cwd, abs);\n return rel.startsWith(\"..\") ? abs : `./${rel}`;\n}\n\nfunction readJsonSafe(path: string): any {\n try {\n const raw = readFileSync(path, \"utf8\");\n return raw.trim() ? JSON.parse(raw) : null;\n } catch {\n return null;\n }\n}\n\n/**\n * Returns the fragile npx-form pattern we used to write in pre-0.10.0\n * SessionStart hooks, so normalize-config can detect and rewrite it.\n */\nfunction isNpxForm(entry: any): boolean {\n if (!entry || typeof entry !== \"object\") return false;\n const cmd = entry.command;\n const args = Array.isArray(entry.args) ? entry.args : [];\n return (\n cmd === \"npx\" &&\n args.some(\n (a: unknown) => typeof a === \"string\" && (a.includes(PKG_NAME) || a.includes(LEGACY_PKG_NAME))\n )\n );\n}\n\nfunction isLocalForm(entry: any): boolean {\n if (!entry || typeof entry !== \"object\") return false;\n const cmd = entry.command;\n const args = Array.isArray(entry.args) ? entry.args : [];\n return (\n cmd === \"node\" &&\n args.some(\n (a: unknown) =>\n typeof a === \"string\" &&\n (a.includes(\"node_modules/@theglitchking/semantic-memory\") ||\n a.includes(\"node_modules/@theglitchking/semantic-sidekick\"))\n )\n );\n}\n\nfunction extractNotesPath(entry: any): string | null {\n const args = Array.isArray(entry?.args) ? entry.args : [];\n const i = args.indexOf(\"--notes\");\n if (i === -1 || i + 1 >= args.length) return null;\n return String(args[i + 1]);\n}\n\nfunction extractExtraFlags(entry: any): string[] {\n const args = Array.isArray(entry?.args) ? entry.args : [];\n return args.filter((a: unknown): a is string => typeof a === \"string\" && a.startsWith(\"--\") && a !== \"--notes\");\n}\n\nconst TOOL_HELP: Record<string, { description: string; args: string; examples: string[] }> = {\n // Search\n search_semantic: {\n description: \"Vector similarity search — find notes by meaning, not just keywords\",\n args: '{ \"query\": \"string\", \"limit?\": 10 }',\n examples: [\n '{ \"query\": \"microservices architecture\", \"limit\": 5 }',\n '{ \"query\": \"how to deploy to production\" }',\n ],\n },\n search_text: {\n description: \"Full-text keyword or regex search with optional filters\",\n args: '{ \"pattern\": \"string\", \"regex?\": false, \"caseSensitive?\": false, \"pathGlob?\": \"string\", \"tagFilter?\": [\"string\"], \"limit?\": 20 }',\n examples: [\n '{ \"pattern\": \"RabbitMQ\" }',\n '{ \"pattern\": \"OAuth\\\\\\\\d\", \"regex\": true }',\n '{ \"pattern\": \"deploy\", \"pathGlob\": \"devops/**\", \"tagFilter\": [\"kubernetes\"] }',\n ],\n },\n search_graph: {\n description: \"Graph traversal — find notes connected to a concept via wikilinks and tags\",\n args: '{ \"concept\": \"string\", \"maxDepth?\": 2 }',\n examples: [\n '{ \"concept\": \"microservices\" }',\n '{ \"concept\": \"auth\", \"maxDepth\": 3 }',\n ],\n },\n search_hybrid: {\n description: \"Combined semantic + graph search — vector results re-ranked by graph proximity\",\n args: '{ \"query\": \"string\", \"limit?\": 10 }',\n examples: [\n '{ \"query\": \"event driven architecture\", \"limit\": 5 }',\n ],\n },\n\n // Read\n read_note: {\n description: \"Read the full content of a specific note by path\",\n args: '{ \"path\": \"string\" }',\n examples: [\n '{ \"path\": \"project-overview.md\" }',\n '{ \"path\": \"notes/meeting-2024-01-15.md\" }',\n ],\n },\n read_multiple_notes: {\n description: \"Batch read multiple notes in one call\",\n args: '{ \"paths\": [\"string\"] }',\n examples: [\n '{ \"paths\": [\"overview.md\", \"architecture.md\", \"deployment.md\"] }',\n ],\n },\n list_notes: {\n description: \"List all indexed notes with metadata (title, tags, link count)\",\n args: \"{}\",\n examples: [\"{}\"],\n },\n\n // Write\n create_note: {\n description: \"Create a new markdown note with optional YAML frontmatter\",\n args: '{ \"path\": \"string\", \"content\": \"string\", \"frontmatter?\": {} }',\n examples: [\n '{ \"path\": \"new-guide.md\", \"content\": \"# Guide\\\\n\\\\nContent here.\" }',\n '{ \"path\": \"tagged.md\", \"content\": \"Content.\", \"frontmatter\": { \"title\": \"Tagged Note\", \"tags\": [\"test\"] } }',\n ],\n },\n update_note: {\n description: \"Edit note content — overwrite, append, prepend, or patch by heading\",\n args: '{ \"path\": \"string\", \"content\": \"string\", \"mode\": \"overwrite|append|prepend|patch-by-heading\", \"heading?\": \"string\" }',\n examples: [\n '{ \"path\": \"guide.md\", \"content\": \"New content.\", \"mode\": \"overwrite\" }',\n '{ \"path\": \"guide.md\", \"content\": \"\\\\n## Appendix\\\\nExtra info.\", \"mode\": \"append\" }',\n '{ \"path\": \"guide.md\", \"content\": \"Updated architecture section.\", \"mode\": \"patch-by-heading\", \"heading\": \"Architecture\" }',\n ],\n },\n delete_note: {\n description: \"Delete a note permanently (requires confirm=true)\",\n args: '{ \"path\": \"string\", \"confirm\": true }',\n examples: [\n '{ \"path\": \"old-note.md\", \"confirm\": true }',\n '{ \"path\": \"old-note.md\", \"confirm\": false } // returns warning, does not delete',\n ],\n },\n move_note: {\n description: \"Move or rename a note — automatically updates wikilinks across the vault\",\n args: '{ \"from\": \"string\", \"to\": \"string\" }',\n examples: [\n '{ \"from\": \"user-service.md\", \"to\": \"auth-service.md\" }',\n '{ \"from\": \"old/note.md\", \"to\": \"new/location/note.md\" }',\n ],\n },\n\n // Metadata\n get_frontmatter: {\n description: \"Read parsed YAML frontmatter from a note as JSON\",\n args: '{ \"path\": \"string\" }',\n examples: ['{ \"path\": \"project-overview.md\" }'],\n },\n update_frontmatter: {\n description: \"Set or delete YAML frontmatter keys — pass null to delete a key\",\n args: '{ \"path\": \"string\", \"fields\": {} }',\n examples: [\n '{ \"path\": \"note.md\", \"fields\": { \"status\": \"active\", \"priority\": 1 } }',\n '{ \"path\": \"note.md\", \"fields\": { \"deprecated_field\": null } } // deletes the key',\n ],\n },\n manage_tags: {\n description: \"Add, remove, or list tags on a note (frontmatter and inline)\",\n args: '{ \"path\": \"string\", \"action\": \"add|remove|list\", \"tags?\": [\"string\"] }',\n examples: [\n '{ \"path\": \"note.md\", \"action\": \"list\" }',\n '{ \"path\": \"note.md\", \"action\": \"add\", \"tags\": [\"important\", \"reviewed\"] }',\n '{ \"path\": \"note.md\", \"action\": \"remove\", \"tags\": [\"draft\"] }',\n ],\n },\n rename_tag: {\n description: \"Rename a tag across all notes in the vault (frontmatter + inline)\",\n args: '{ \"oldTag\": \"string\", \"newTag\": \"string\" }',\n examples: ['{ \"oldTag\": \"architecture\", \"newTag\": \"arch\" }'],\n },\n\n // Graph\n backlinks: {\n description: \"Find all notes that link TO a given note via [[wikilinks]]\",\n args: '{ \"path\": \"string\" }',\n examples: ['{ \"path\": \"microservices.md\" }'],\n },\n forwardlinks: {\n description: \"Find all notes linked FROM a given note\",\n args: '{ \"path\": \"string\" }',\n examples: ['{ \"path\": \"project-overview.md\" }'],\n },\n graph_path: {\n description: \"Find the shortest path between two notes in the knowledge graph\",\n args: '{ \"from\": \"string\", \"to\": \"string\" }',\n examples: ['{ \"from\": \"project-overview.md\", \"to\": \"user-service.md\" }'],\n },\n graph_statistics: {\n description: \"Knowledge graph stats — most connected nodes, orphans, density\",\n args: \"{}\",\n examples: [\"{}\"],\n },\n\n // System\n get_stats: {\n description: \"Vault and index statistics — note count, chunks, embeddings, graph density\",\n args: \"{}\",\n examples: [\"{}\"],\n },\n reindex: {\n description: \"Force a full reindex of the vault\",\n args: \"{}\",\n examples: [\"{}\"],\n },\n};\n\nconst TOOL_CATEGORIES: Record<string, string[]> = {\n Search: [\"search_semantic\", \"search_text\", \"search_graph\", \"search_hybrid\"],\n Read: [\"read_note\", \"read_multiple_notes\", \"list_notes\"],\n Write: [\"create_note\", \"update_note\", \"delete_note\", \"move_note\"],\n Metadata: [\"get_frontmatter\", \"update_frontmatter\", \"manage_tags\", \"rename_tag\"],\n Graph: [\"backlinks\", \"forwardlinks\", \"graph_path\", \"graph_statistics\"],\n System: [\"get_stats\", \"reindex\"],\n};\n\nfunction printToolList() {\n console.log(\"\\nSemantic Pages — 21 MCP Tools\\n\");\n console.log(\"Usage: These tools are available via MCP when the server is running.\");\n console.log(\" Run `semantic-memory tools <name>` for details on a specific tool.\\n\");\n\n for (const [category, tools] of Object.entries(TOOL_CATEGORIES)) {\n console.log(` ${category}:`);\n for (const name of tools) {\n const tool = TOOL_HELP[name];\n console.log(` ${name.padEnd(24)} ${tool.description}`);\n }\n console.log();\n }\n\n console.log(\"Run `semantic-memory tools <tool-name>` for arguments and examples.\");\n}\n\nfunction printToolDetail(name: string) {\n const tool = TOOL_HELP[name];\n if (!tool) {\n console.error(`Unknown tool: ${name}`);\n console.error(`Run \\`semantic-memory tools\\` to see all available tools.`);\n process.exit(1);\n }\n\n console.log(`\\n ${name}`);\n console.log(` ${\"─\".repeat(name.length)}`);\n console.log(` ${tool.description}\\n`);\n console.log(` Arguments:`);\n console.log(` ${tool.args}\\n`);\n console.log(` Examples:`);\n for (const ex of tool.examples) {\n console.log(` ${ex}`);\n }\n console.log();\n}\n\nprogram\n .name(\"semantic-memory\")\n .description(\n \"Unified memory-layer MCP server for Claude Code (rebrand of semantic-sidekick at v1.0.0).\\n\" +\n \"The `semantic-sidekick` command is preserved as an alias.\\n\\n\" +\n \" Start MCP server: semantic-memory --notes ./vault\\n\" +\n \" Show vault stats: semantic-memory --notes ./vault --stats\\n\" +\n \" Force reindex: semantic-memory --notes ./vault --reindex\\n\" +\n \" List MCP tools: semantic-memory tools\\n\" +\n \" Tool details: semantic-memory tools search_semantic\"\n )\n .version(version);\n\nprogram\n .command(\"search <query>\")\n .description(\"Run a vault search and print top hits as JSON (used by activation hooks)\")\n .requiredOption(\"--notes <path>\", \"Path to markdown notes directory\")\n .option(\"--limit <n>\", \"Max results\", (v) => parseInt(v, 10), 8)\n .option(\"--text-only\", \"Skip embedder — keyword-only search (fast path, no model init)\")\n .option(\"--json\", \"Emit raw JSON (default)\", true)\n .action(async (query: string, opts) => {\n const { runSearch } = await import(\"./search.js\");\n try {\n const hits = await runSearch({\n notes: opts.notes,\n query,\n limit: opts.limit,\n textOnly: opts.textOnly,\n });\n process.stdout.write(JSON.stringify(hits, null, 2) + \"\\n\");\n process.exit(0);\n } catch (err: any) {\n console.error(`search failed: ${err.message}`);\n process.exit(1);\n }\n });\n\nprogram\n .command(\"lint\")\n .description(\"Lint the vault against vault.schema.yml (schema violations + missing provenance + stale)\")\n .requiredOption(\"--notes <path>\", \"Path to markdown notes directory\")\n .option(\"--rule <name>\", \"Limit output to one rule: schema_violations | missing_provenance | stale\")\n .option(\"--json\", \"Emit JSON instead of the human-readable report\")\n .option(\"--strict\", \"Exit non-zero on warnings too (default: exit non-zero only on errors)\")\n .action(async (opts) => {\n const { lintVault, formatLintReport } = await import(\"../core/lint.js\");\n const report = await lintVault(resolve(opts.notes));\n // Use console.log + process.exitCode (not process.exit) so Node flushes\n // stdout fully before the process ends. Early process.exit with a large\n // buffered JSON payload can truncate output.\n if (opts.json) {\n const out = opts.rule ? report.byRule[opts.rule as keyof typeof report.byRule] : report;\n console.log(JSON.stringify(out, null, 2));\n } else {\n console.log(formatLintReport(report, { rule: opts.rule }));\n }\n const bad = opts.strict ? report.counts.errors + report.counts.warnings : report.counts.errors;\n process.exitCode = bad > 0 ? 1 : 0;\n });\n\nprogram\n .command(\"log-event\")\n .description(\"Append a structured event to the vault's log.md (used by hooks and CI scripts — same shape as mcp__semantic-vault__log_event)\")\n .requiredOption(\"--notes <path>\", \"Path to markdown notes directory\")\n .requiredOption(\"--kind <name>\", \"Event category: ingest, synthesis, error, mode_change, etc.\")\n .requiredOption(\"--summary <text>\", \"One-line human summary\")\n .option(\"--payload <json>\", \"Structured payload as JSON string\")\n .action(async (opts) => {\n const { logEvent } = await import(\"../core/log.js\");\n let payload: Record<string, unknown> | undefined;\n if (opts.payload) {\n try {\n payload = JSON.parse(opts.payload);\n } catch (e: any) {\n console.error(`invalid --payload JSON: ${e.message}`);\n process.exitCode = 1;\n return;\n }\n }\n try {\n const entry = await logEvent(resolve(opts.notes), {\n kind: opts.kind,\n summary: opts.summary,\n payload,\n });\n console.log(JSON.stringify(entry));\n } catch (e: any) {\n console.error(`log-event failed: ${e.message}`);\n process.exitCode = 1;\n }\n });\n\nprogram\n .command(\"log-query\")\n .description(\"Read structured log entries from log.md — filters by kind, date range, limit\")\n .requiredOption(\"--notes <path>\", \"Path to markdown notes directory\")\n .option(\"--kind <name>\", \"Filter by kind (ingest, synthesis, error, mode_change, etc.)\")\n .option(\"--after <iso>\", \"ISO timestamp — only entries on or after\")\n .option(\"--before <iso>\", \"ISO timestamp — only entries on or before\")\n .option(\"--limit <n>\", \"Max entries (most recent)\", (v) => parseInt(v, 10))\n .action(async (opts) => {\n const { logQuery } = await import(\"../core/log.js\");\n try {\n const entries = await logQuery(resolve(opts.notes), {\n kind: opts.kind,\n after: opts.after,\n before: opts.before,\n limit: opts.limit,\n });\n console.log(JSON.stringify(entries));\n } catch (e: any) {\n console.error(`log-query failed: ${e.message}`);\n process.exitCode = 1;\n }\n });\n\nprogram\n .command(\"install-schema\")\n .description(\"Bootstrap vault.schema.yml in the vault root with the default schema\")\n .requiredOption(\"--notes <path>\", \"Path to markdown notes directory\")\n .option(\"--force\", \"Overwrite existing schema file\")\n .action(async (opts) => {\n const { installDefaultSchema } = await import(\"../core/schema.js\");\n const r = await installDefaultSchema(resolve(opts.notes), opts.force);\n console.log(r.written ? `Installed default schema: ${r.path}` : `Schema already exists: ${r.path} (use --force to overwrite)`);\n process.exit(0);\n });\n\nprogram\n .command(\"tools [name]\")\n .description(\"List all MCP tools, or show details for a specific tool\")\n .action((name?: string) => {\n if (name) {\n printToolDetail(name);\n } else {\n printToolList();\n }\n process.exit(0);\n });\n\nprogram\n .command(\"serve\", { isDefault: true })\n .description(\"Start the MCP server (default command)\")\n .requiredOption(\"--notes <path>\", \"Path to markdown notes directory\")\n .option(\"--reindex\", \"Force full reindex and exit\")\n .option(\"--stats\", \"Show vault statistics and exit\")\n .option(\"--wait-for-ready\", \"Block startup until index is fully built before serving (default: index in background; tools return 'Indexing in progress' until ready)\")\n .option(\"--read-only\", \"Suppress write tools (create_note, update_note, delete_note, move_note, update_frontmatter, manage_tags, rename_tag) — use for shared docs vaults owned by another tool\")\n .option(\"--model <name>\", \"Embedding model to use (default: all-MiniLM-L6-v2, fast; use nomic-ai/nomic-embed-text-v1.5 for higher quality)\")\n .option(\"--workers <n>\", \"Number of worker threads for parallel embedding\", parseInt)\n .option(\"--batch-size <n>\", \"Texts per ONNX forward pass (default: 8)\", parseInt)\n .option(\"--no-quantized\", \"Use full-precision model instead of quantized (slower, slightly higher quality)\")\n .option(\"--no-watch\", \"Disable file watcher\")\n .action(async (opts) => {\n const notesPath = resolve(opts.notes);\n\n if (!existsSync(notesPath)) {\n console.error(`Error: notes directory not found: ${notesPath}`);\n process.exit(1);\n }\n\n if (opts.stats) {\n const { Indexer } = await import(\"../core/indexer.js\");\n const indexer = new Indexer(notesPath);\n const docs = await indexer.indexAll();\n console.log(`Notes: ${docs.length}`);\n console.log(`Chunks: ${docs.reduce((n: number, d: any) => n + d.chunks.length, 0)}`);\n console.log(`Wikilinks: ${docs.reduce((n: number, d: any) => n + d.wikilinks.length, 0)}`);\n console.log(`Tags: ${new Set(docs.flatMap((d: any) => d.tags)).size} unique`);\n process.exit(0);\n }\n\n if (opts.reindex) {\n const { createServer } = await import(\"../mcp/server.js\");\n await createServer(notesPath, {\n watch: false,\n waitForReady: true,\n model: opts.model,\n workers: opts.workers,\n batchSize: opts.batchSize,\n quantized: opts.quantized,\n onProgress: (embedded, total) => {\n process.stderr.write(`\\rEmbedding ${embedded}/${total} chunks...`);\n },\n });\n process.stderr.write(\"\\n\");\n console.log(\"Reindex complete.\");\n process.exit(0);\n }\n\n // Default: start MCP server on stdio\n const { startServer } = await import(\"../mcp/server.js\");\n await startServer(notesPath, {\n watch: opts.watch,\n waitForReady: opts.waitForReady,\n model: opts.model,\n workers: opts.workers,\n batchSize: opts.batchSize,\n quantized: opts.quantized,\n readOnly: opts.readOnly,\n });\n });\n\nregisterUpdateCommands(program, {\n packageName: PKG_NAME,\n pluginName: \"semantic-memory\",\n configFile: \"semantic-memory.json\",\n onAfterUpdate: (cwd) => runRelink(cwd),\n});\n\nprogram\n .command(\"normalize-config\")\n .description(\n \"Rewrite fragile `npx @latest` entries in .mcp.json to the stable node-against-node_modules form (with backup and validation)\",\n )\n .option(\"--dry-run\", \"print the proposed changes but don't write\")\n .action((opts: { dryRun?: boolean }) => {\n const cwd = process.cwd();\n const mcpPath = join(cwd, \".mcp.json\");\n if (!existsSync(mcpPath)) {\n console.log(\"no .mcp.json in current directory — nothing to do\");\n process.exit(0);\n }\n const data = readJsonSafe(mcpPath);\n if (!data || typeof data !== \"object\" || !data.mcpServers || typeof data.mcpServers !== \"object\") {\n console.error(`could not parse ${mcpPath}`);\n process.exit(1);\n }\n const bin = localBinArg(cwd);\n if (!bin) {\n console.error(\n `no local install found at ./node_modules/@theglitchking/semantic-memory/bin/semantic-memory ` +\n `(or the legacy semantic-sidekick path).\\n` +\n `run 'npm install --save @theglitchking/semantic-memory' first, then re-run this command.`,\n );\n process.exit(1);\n }\n const rewritten: string[] = [];\n for (const [key, entry] of Object.entries<any>(data.mcpServers)) {\n if (!isNpxForm(entry)) continue;\n const notes = extractNotesPath(entry) ?? \"./.claude/.vault\";\n const extra = extractExtraFlags(entry);\n data.mcpServers[key] = {\n type: \"stdio\",\n command: \"node\",\n args: [bin, \"--notes\", notes, ...extra],\n };\n rewritten.push(key);\n }\n if (rewritten.length === 0) {\n console.log(\"no npx-form entries found — .mcp.json is already in the stable form.\");\n process.exit(0);\n }\n console.log(`Rewriting ${rewritten.length} entr${rewritten.length === 1 ? \"y\" : \"ies\"}: ${rewritten.join(\", \")}`);\n if (opts.dryRun) {\n console.log(\"--- proposed .mcp.json:\");\n console.log(JSON.stringify(data, null, 2));\n console.log(\"--- (dry-run; no changes written)\");\n process.exit(0);\n }\n // Back up\n const bakPath = join(dirname(mcpPath), \".mcp.json.bak\");\n try {\n writeFileSync(bakPath, readFileSync(mcpPath, \"utf8\"));\n console.log(`backup written: ${bakPath}`);\n } catch (err: any) {\n console.error(`could not write backup: ${err.message}`);\n process.exit(1);\n }\n writeFileSync(mcpPath, JSON.stringify(data, null, 2) + \"\\n\");\n\n // Verify the local bin starts cleanly. We just run --version — fast and\n // enough to catch ERR_MODULE_NOT_FOUND type failures.\n const verify = spawnSync(\"node\", [bin, \"--version\"], { cwd, stdio: \"pipe\", timeout: 15_000 });\n if (verify.status !== 0) {\n console.error(`verification failed (exit ${verify.status}):\\n${verify.stderr?.toString() || \"\"}`);\n console.error(`rolling back from ${bakPath}`);\n writeFileSync(mcpPath, readFileSync(bakPath, \"utf8\"));\n process.exit(1);\n }\n console.log(`✓ .mcp.json normalized and verified. Toggle the MCPs in /mcp to reconnect.`);\n process.exit(0);\n });\n\nprogram\n .command(\"healthcheck\")\n .description(\n \"Verify the local install starts cleanly + run drift detection. Self-heals common npx-cache corruption (ERR_MODULE_NOT_FOUND). With --fast, skips the slow tier (full vault lint).\",\n )\n .option(\"--fast\", \"Run only the fast-tier drift checks (file-system probes). Skips the slow tier (full vault lint).\", false)\n .option(\"--json\", \"Emit structured JSON output instead of human-readable text.\", false)\n .action(async (opts) => {\n const cwd = process.cwd();\n const bin = findLocalBin(cwd);\n if (!bin) {\n console.error(`no local install at ./node_modules/@theglitchking/semantic-memory/bin/semantic-memory (or legacy semantic-sidekick path)`);\n console.error(`run 'npm install --save @theglitchking/semantic-memory' to install.`);\n process.exit(1);\n }\n\n // 1. Warn if .mcp.json uses the fragile form.\n const mcpPath = join(cwd, \".mcp.json\");\n if (existsSync(mcpPath)) {\n const data = readJsonSafe(mcpPath);\n const entries = data?.mcpServers && typeof data.mcpServers === \"object\" ? Object.entries<any>(data.mcpServers) : [];\n const fragile = entries.filter(([, e]) => isNpxForm(e)).map(([k]) => k);\n if (fragile.length > 0) {\n console.warn(\n `⚠️ .mcp.json uses the fragile npx-@latest form for: ${fragile.join(\", \")}`,\n );\n console.warn(` Rewrite to the stable form:`);\n console.warn(` npx --no @theglitchking/semantic-memory normalize-config`);\n }\n }\n\n // 2. Smoke-test the local bin.\n const r = spawnSync(\"node\", [bin, \"--version\"], { cwd, stdio: \"pipe\", timeout: 15_000 });\n if (r.status === 0) {\n console.log(`✓ local install starts cleanly (v${r.stdout?.toString().trim()})`);\n process.exit(0);\n }\n\n const stderr = r.stderr?.toString() ?? \"\";\n\n // 3. Self-heal ERR_MODULE_NOT_FOUND in npx cache (rare but the classic\n // failure mode that triggered 0.10.0). Extract the offending npx cache\n // dir from the error message, rm -rf it, retry once.\n if (stderr.includes(\"ERR_MODULE_NOT_FOUND\")) {\n const match = stderr.match(/([\\/~][^'\"\\s]*\\/_npx\\/[^\\/'\"\\s]+)/);\n if (match) {\n const bad = match[1];\n console.warn(`detected broken npx cache at ${bad} — clearing and retrying...`);\n try { rmSync(bad, { recursive: true, force: true }); } catch {}\n const r2 = spawnSync(\"node\", [bin, \"--version\"], { cwd, stdio: \"pipe\", timeout: 15_000 });\n if (r2.status === 0) {\n console.log(`✓ cleared npx cache and verified (v${r2.stdout?.toString().trim()})`);\n process.exit(0);\n }\n console.error(`retry still failed:\\n${r2.stderr?.toString() || \"\"}`);\n } else {\n console.error(`ERR_MODULE_NOT_FOUND but could not locate offending cache path in the error.`);\n }\n }\n\n if (stderr) console.error(stderr);\n if (r.status !== 0) {\n console.error(`local install failed (exit ${r.status})`);\n process.exit(1);\n }\n });\n\n// Append drift detection to the healthcheck handler (Phase 8). Wraps the original\n// handler — the function above runs first (npx-cache self-heal), then drift detection\n// runs and prints additional findings. --fast skips the slow tier (full vault lint).\nconst driftHealthcheckActionPostprocess = async (opts: { fast?: boolean; json?: boolean }) => {\n try {\n const { runHealthcheck, formatDriftBanner } = await import(\"../core/healthcheck.js\");\n const projectRoot = process.cwd();\n // For the auto-derived vault path, prefer .claude/.vault if present\n const vaultCandidate = join(projectRoot, \".claude\", \".vault\");\n const vaultPath = existsSync(vaultCandidate) ? vaultCandidate : undefined;\n const result = await runHealthcheck({\n projectRoot,\n vaultPath,\n tier: opts.fast ? \"fast\" : \"all\",\n force: true,\n });\n if (opts.json) {\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n const banner = formatDriftBanner(result);\n if (banner) {\n console.log(\"\");\n console.log(banner);\n } else {\n console.log(\"\");\n console.log(`✓ no drift detected (${result.findings.length} checks ran in ${result.duration_ms}ms)`);\n }\n } catch (err: any) {\n console.error(`drift check threw: ${err?.message ?? err}`);\n }\n};\n\n// Wire the drift-detection postprocess. We do this by attaching to the existing\n// healthcheck command's postAction hook so the original handler still runs first.\nconst healthcheckCmd = program.commands.find((c) => c.name() === \"healthcheck\");\nif (healthcheckCmd) {\n healthcheckCmd.hook(\"postAction\", async (thisCmd) => {\n const opts = thisCmd.opts();\n await driftHealthcheckActionPostprocess({ fast: !!opts.fast, json: !!opts.json });\n });\n}\n\n// --- Skill bundler (Phase 6) ---\n\nfunction parseAgent(input: string): AgentName {\n const a = input.toLowerCase();\n if (!SKILL_BUNDLER_AGENTS.includes(a as AgentName)) {\n console.error(`Unknown agent: ${input}. Supported: ${SKILL_BUNDLER_AGENTS.join(\", \")}.`);\n process.exit(2);\n }\n return a as AgentName;\n}\n\nfunction parseScope(input: string): Scope {\n if (input !== \"global\" && input !== \"local\") {\n console.error(`Unknown scope: ${input}. Use 'global' or 'local'.`);\n process.exit(2);\n }\n return input;\n}\n\nfunction findSourceRoot(): string {\n // 1. Installed: <cwd>/node_modules/@theglitchking/semantic-sidekick or semantic-memory\n for (const pkg of [\"semantic-memory\", \"semantic-sidekick\"]) {\n const installed = join(process.cwd(), \"node_modules\", \"@theglitchking\", pkg);\n if (existsSync(installed)) return installed;\n }\n // 2. Dev: derive from the bin location (this file lives at <root>/dist/cli/index.js)\n const dev = resolve(new URL(\"../../\", import.meta.url).pathname);\n return dev;\n}\n\nconst skillsCmd = program.command(\"skills\").description(\"Install, target, or uninstall skill bundles for non-Claude agents (codex, copilot, pi). Claude installs continue to use the npm postinstall flow.\");\n\nskillsCmd\n .command(\"targets\")\n .description(\"Preview where skill bundles would be installed for one or more agents.\")\n .option(\"--agent <name...>\", \"One or more agents (default: all). Repeatable.\", undefined as any)\n .option(\"--scope <scope>\", \"global or local (default: local)\", \"local\")\n .option(\"--project <path>\", \"Project root for local-scope paths (default: cwd)\", process.cwd())\n .action((opts) => {\n const scope = parseScope(opts.scope);\n const agents: AgentName[] = (opts.agent && opts.agent.length > 0 ? opts.agent : SKILL_BUNDLER_AGENTS).map(parseAgent);\n const out = agents.map((a) => resolveTarget(a, scope, opts.project));\n console.log(JSON.stringify(out, null, 2));\n });\n\nskillsCmd\n .command(\"install\")\n .description(\"Install skill bundles into an agent's skill directory. Non-destructive by default; --force to overwrite.\")\n .requiredOption(\"--agent <name>\", \"Agent runtime (claude, codex, copilot, pi)\")\n .option(\"--scope <scope>\", \"global or local (default: local)\", \"local\")\n .option(\"--project <path>\", \"Project root for local-scope paths (default: cwd)\", process.cwd())\n .option(\"--only <names...>\", \"Restrict to specific skill names (default: all shipped)\")\n .option(\"--force\", \"Overwrite even if drift is detected against an existing manifest\", false)\n .action(async (opts) => {\n const agent = parseAgent(opts.agent);\n const scope = parseScope(opts.scope);\n if (agent === \"claude\") {\n console.error(\n \"Claude skill installs are handled by the npm postinstall (claude-plugin-runtime). \" +\n \"Run `npm install @theglitchking/semantic-memory` instead — that flow symlinks \" +\n \"skills into ~/.claude/skills/ or .claude/skills/ automatically. The skills CLI \" +\n \"is intended for non-Claude agents (codex, copilot, pi) which do not have that \" +\n \"postinstall integration.\"\n );\n process.exit(2);\n }\n const sourceRoot = findSourceRoot();\n const result = await installSkills({\n agent,\n scope,\n sourceRoot,\n projectRoot: opts.project,\n version,\n only: opts.only,\n force: opts.force === true,\n });\n console.log(JSON.stringify(result, null, 2));\n if (result.installed.length === 0 && result.reason) process.exit(1);\n });\n\nskillsCmd\n .command(\"uninstall\")\n .description(\"Remove skill bundles tracked by the semantic-memory manifest. User-written skills outside the manifest are left untouched.\")\n .requiredOption(\"--agent <name>\", \"Agent runtime (claude, codex, copilot, pi)\")\n .option(\"--scope <scope>\", \"global or local (default: local)\", \"local\")\n .option(\"--project <path>\", \"Project root for local-scope paths (default: cwd)\", process.cwd())\n .action(async (opts) => {\n const agent = parseAgent(opts.agent);\n const scope = parseScope(opts.scope);\n if (agent === \"claude\") {\n console.error(\"Claude skill uninstalls go through the npm uninstall flow. The skills CLI is for non-Claude agents.\");\n process.exit(2);\n }\n const result = await uninstallSkills({ agent, scope, projectRoot: opts.project });\n console.log(JSON.stringify(result, null, 2));\n });\n\nskillsCmd\n .command(\"list\")\n .description(\"List the skill bundles shipped with this plugin version.\")\n .action(async () => {\n const sourceRoot = findSourceRoot();\n const shipped = await listShippedSkills(sourceRoot);\n console.log(JSON.stringify(shipped.map((s) => s.name), null, 2));\n });\n\nprogram.parse();\n","import { mkdir, readFile, writeFile, copyFile, readdir, rm } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { join, basename, resolve } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { createHash } from \"node:crypto\";\n\nexport type AgentName = \"claude\" | \"codex\" | \"copilot\" | \"pi\";\nexport type Scope = \"global\" | \"local\";\n\nexport interface AgentTargetSpec {\n agent: AgentName;\n scope: Scope;\n /** Absolute resolved path where the skill bundles will land. */\n path: string;\n}\n\nexport interface SkillManifest {\n package: string;\n version: string;\n agent: AgentName;\n scope: Scope;\n installed_at: string;\n skills: { name: string; sha256: string }[];\n}\n\nexport interface InstallResult {\n agent: AgentName;\n scope: Scope;\n target_path: string;\n installed: string[];\n skipped: string[];\n reason?: string;\n manifest_path?: string;\n}\n\nconst MANIFEST_FILE = \".semantic-memory-skill-manifest.json\";\n\n/**\n * Resolve where a given (agent, scope) tuple should land. Project root is required for local\n * scope (to anchor relative paths); for global scope it's not used.\n */\nexport function resolveTarget(agent: AgentName, scope: Scope, projectRoot: string): AgentTargetSpec {\n const root = resolve(projectRoot);\n const home = homedir();\n const map: Record<AgentName, { global: string; local: string }> = {\n claude: { global: join(home, \".claude\", \"skills\"), local: join(root, \".claude\", \"skills\") },\n codex: { global: join(home, \".codex\", \"skills\"), local: join(root, \".codex\", \"skills\") },\n copilot: { global: join(home, \".copilot\", \"skills\"), local: join(root, \".github\", \"skills\") },\n pi: { global: join(home, \".pi\", \"agent\", \"skills\"), local: join(root, \".pi\", \"skills\") },\n };\n return { agent, scope, path: map[agent][scope] };\n}\n\n/**\n * Enumerate the canonical skill bundles shipped by this plugin. Each bundle is a directory\n * under `<sourceRoot>/skills/` containing at least a SKILL.md file. Entries without\n * SKILL.md are silently skipped (allows future non-skill files like `/skills/.gitkeep`).\n */\nexport async function listShippedSkills(sourceRoot: string): Promise<{ name: string; dir: string }[]> {\n const skillsDir = join(sourceRoot, \"skills\");\n if (!existsSync(skillsDir)) return [];\n const entries = await readdir(skillsDir, { withFileTypes: true });\n const out: { name: string; dir: string }[] = [];\n for (const e of entries) {\n if (!e.isDirectory()) continue;\n const dir = join(skillsDir, e.name);\n const skillFile = join(dir, \"SKILL.md\");\n if (!existsSync(skillFile)) continue;\n out.push({ name: e.name, dir });\n }\n return out;\n}\n\nasync function sha256OfFile(path: string): Promise<string> {\n const buf = await readFile(path);\n return createHash(\"sha256\").update(buf).digest(\"hex\");\n}\n\n/**\n * Copy a single skill bundle (SKILL.md plus any sibling files in the same directory) into\n * the target directory, overlaying it with the agent name. Returns the list of files written.\n *\n * The target layout is `<targetPath>/<skillName>/SKILL.md` plus mirrored siblings, so each\n * bundle is namespaced and easy to remove later.\n */\nasync function copyBundle(srcDir: string, destDir: string): Promise<string[]> {\n await mkdir(destDir, { recursive: true });\n const entries = await readdir(srcDir, { withFileTypes: true });\n const written: string[] = [];\n for (const e of entries) {\n const src = join(srcDir, e.name);\n const dest = join(destDir, e.name);\n if (e.isDirectory()) {\n const childWritten = await copyBundle(src, dest);\n written.push(...childWritten);\n continue;\n }\n if (!e.isFile()) continue;\n await copyFile(src, dest);\n written.push(dest);\n }\n return written;\n}\n\nexport interface InstallOptions {\n agent: AgentName;\n scope: Scope;\n /** Path to the package's source root (usually the repo root, where `skills/` lives). */\n sourceRoot: string;\n /** Used to anchor local-scope target paths. */\n projectRoot: string;\n /** Plugin version, recorded in the manifest. */\n version: string;\n /** Specific skills to install. When omitted, all shipped skills are installed. */\n only?: string[];\n /**\n * When false, refuse to overwrite an existing install (manifest present + sha mismatch\n * indicates upstream drift). When true, overwrite. Default false.\n */\n force?: boolean;\n}\n\n/**\n * Install all (or selected) skill bundles into an agent's skill directory.\n *\n * Behavior:\n * - Resolves the destination via resolveTarget.\n * - Reads any existing manifest. If a manifest exists, version differs from `version`,\n * AND any skill sha256 differs from the source: this is a drift event. Without\n * `force: true`, returns a refusal with reason \"drift detected\". With force, proceeds\n * and overwrites.\n * - For each shipped skill (or each in `only`), copies the bundle into\n * <target>/<skillName>/, overwriting any existing files in that subdirectory.\n * - Writes a fresh manifest at <target>/<MANIFEST_FILE> recording sha256 of each\n * SKILL.md installed, the plugin version, agent, and scope.\n */\nexport async function installSkills(opts: InstallOptions): Promise<InstallResult> {\n const target = resolveTarget(opts.agent, opts.scope, opts.projectRoot);\n const shipped = await listShippedSkills(opts.sourceRoot);\n const filter = opts.only && opts.only.length > 0 ? new Set(opts.only) : null;\n const toInstall = filter ? shipped.filter((s) => filter.has(s.name)) : shipped;\n\n if (toInstall.length === 0) {\n return {\n agent: opts.agent,\n scope: opts.scope,\n target_path: target.path,\n installed: [],\n skipped: [],\n reason: filter ? `No matching skills found (only=${[...filter].join(\",\")}).` : \"No shipped skills found at sourceRoot/skills/.\",\n };\n }\n\n const manifestPath = join(target.path, MANIFEST_FILE);\n const existing = await readManifest(manifestPath);\n\n if (existing && !opts.force) {\n const drift = await detectDrift(existing, toInstall);\n if (drift.length > 0) {\n return {\n agent: opts.agent,\n scope: opts.scope,\n target_path: target.path,\n installed: [],\n skipped: toInstall.map((s) => s.name),\n reason: `Drift detected on ${drift.length} skill(s): ${drift.join(\", \")}. Pass --force to overwrite.`,\n manifest_path: manifestPath,\n };\n }\n }\n\n await mkdir(target.path, { recursive: true });\n const installed: string[] = [];\n const skillEntries: { name: string; sha256: string }[] = [];\n for (const skill of toInstall) {\n const destDir = join(target.path, skill.name);\n await copyBundle(skill.dir, destDir);\n const skillFile = join(skill.dir, \"SKILL.md\");\n skillEntries.push({ name: skill.name, sha256: await sha256OfFile(skillFile) });\n installed.push(skill.name);\n }\n\n const manifest: SkillManifest = {\n package: \"@theglitchking/semantic-memory\",\n version: opts.version,\n agent: opts.agent,\n scope: opts.scope,\n installed_at: new Date().toISOString(),\n skills: skillEntries,\n };\n await writeFile(manifestPath, JSON.stringify(manifest, null, 2), \"utf-8\");\n\n return {\n agent: opts.agent,\n scope: opts.scope,\n target_path: target.path,\n installed,\n skipped: [],\n manifest_path: manifestPath,\n };\n}\n\nexport interface UninstallOptions {\n agent: AgentName;\n scope: Scope;\n projectRoot: string;\n}\n\nexport interface UninstallResult {\n agent: AgentName;\n scope: Scope;\n target_path: string;\n removed: string[];\n manifest_present: boolean;\n reason?: string;\n}\n\n/**\n * Remove only the skill bundles tracked in the manifest. User-written skills outside\n * the manifest are left untouched.\n */\nexport async function uninstallSkills(opts: UninstallOptions): Promise<UninstallResult> {\n const target = resolveTarget(opts.agent, opts.scope, opts.projectRoot);\n const manifestPath = join(target.path, MANIFEST_FILE);\n const manifest = await readManifest(manifestPath);\n if (!manifest) {\n return {\n agent: opts.agent,\n scope: opts.scope,\n target_path: target.path,\n removed: [],\n manifest_present: false,\n reason: \"No semantic-memory manifest found — nothing to uninstall.\",\n };\n }\n const removed: string[] = [];\n for (const skill of manifest.skills) {\n const dir = join(target.path, skill.name);\n if (existsSync(dir)) {\n await rm(dir, { recursive: true, force: true });\n removed.push(skill.name);\n }\n }\n await rm(manifestPath, { force: true });\n return {\n agent: opts.agent,\n scope: opts.scope,\n target_path: target.path,\n removed,\n manifest_present: true,\n };\n}\n\nasync function readManifest(path: string): Promise<SkillManifest | null> {\n if (!existsSync(path)) return null;\n try {\n const raw = await readFile(path, \"utf-8\");\n const parsed = JSON.parse(raw);\n if (typeof parsed?.package !== \"string\") return null;\n return parsed as SkillManifest;\n } catch {\n return null;\n }\n}\n\nasync function detectDrift(\n existing: SkillManifest,\n toInstall: { name: string; dir: string }[]\n): Promise<string[]> {\n const driftNames: string[] = [];\n const existingByName = new Map(existing.skills.map((s) => [s.name, s.sha256]));\n for (const skill of toInstall) {\n const sourceSha = await sha256OfFile(join(skill.dir, \"SKILL.md\"));\n const existingSha = existingByName.get(skill.name);\n if (existingSha !== undefined && existingSha !== sourceSha) {\n driftNames.push(skill.name);\n }\n }\n return driftNames;\n}\n\nexport const SKILL_BUNDLER_AGENTS: AgentName[] = [\"claude\", \"codex\", \"copilot\", \"pi\"];\n"],"mappings":"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","names":["resolve","join","existsSync","join","resolve","existsSync","resolve","existsSync","join"]}
@@ -1,11 +1,11 @@
1
- // Plugin-specific SessionStart reconciliation for semantic-sidekick.
1
+ // Plugin-specific SessionStart reconciliation for semantic-memory.
2
2
  //
3
3
  // Responsibilities (all conservative — the user's config always wins):
4
4
  // 1. Ensure <project>/.claude/.vault exists.
5
5
  // 2. If .mcp.json is missing a "semantic-vault" entry AND the package is
6
6
  // installed locally, add one in the node-against-node_modules form.
7
7
  // Existing entries (any shape) are preserved — if you want to rewrite
8
- // a stale entry, run `npx --no @theglitchking/semantic-sidekick
8
+ // a stale entry, run `npx --no @theglitchking/semantic-memory
9
9
  // normalize-config`.
10
10
  // 3. If hit-em-with-the-docs is enabled AND ./.documentation exists,
11
11
  // conditionally add a read-only "semantic-sidekick" entry pointed at
@@ -15,14 +15,23 @@
15
15
  // Any write is preceded by a backup to .mcp.json.bak. Never writes the
16
16
  // `npx @latest` form — that shape is fragile (npx cache corruption causes
17
17
  // ERR_MODULE_NOT_FOUND) and was the root cause of the 0.10.0 bugfix.
18
+ //
19
+ // Package-name resolution (post-1.1.1):
20
+ // Prefer the rebranded `@theglitchking/semantic-memory`. Fall back to the
21
+ // legacy `@theglitchking/semantic-sidekick` if the new package isn't
22
+ // installed — supports machines mid-migration. The DOCS_KEY entry name
23
+ // stays "semantic-sidekick" for backwards-compat with existing .mcp.json
24
+ // entries; renaming it would orphan user state without offering a
25
+ // meaningful behavioral upgrade.
18
26
 
19
27
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
20
28
  import { homedir } from "node:os";
21
29
  import { dirname, join, relative } from "node:path";
22
30
 
23
- const PKG = "@theglitchking/semantic-sidekick";
31
+ const PKG = "@theglitchking/semantic-memory";
32
+ const LEGACY_PKG = "@theglitchking/semantic-sidekick";
24
33
  const VAULT_KEY = "semantic-vault";
25
- const DOCS_KEY = "semantic-sidekick";
34
+ const DOCS_KEY = "semantic-sidekick"; // preserved for backwards-compat with existing .mcp.json entries
26
35
 
27
36
  function readJson(path, fallback = null) {
28
37
  try {
@@ -55,10 +64,24 @@ function hewtdEnabled(projectRoot) {
55
64
  return false;
56
65
  }
57
66
 
58
- /** Absolute path to the locally-installed bin script, or null. */
67
+ /**
68
+ * Absolute path to the locally-installed bin script, or null.
69
+ *
70
+ * Prefers the rebranded @theglitchking/semantic-memory package. Falls back to
71
+ * the legacy @theglitchking/semantic-sidekick install for machines that
72
+ * haven't migrated yet.
73
+ */
59
74
  export function findLocalBin(projectRoot) {
60
- const p = join(projectRoot, "node_modules", "@theglitchking", "semantic-sidekick", "bin", "semantic-sidekick");
61
- return existsSync(p) ? p : null;
75
+ const candidates = [
76
+ // Rebranded package (preferred)
77
+ join(projectRoot, "node_modules", "@theglitchking", "semantic-memory", "bin", "semantic-memory"),
78
+ // Legacy package (fallback for in-progress migrations)
79
+ join(projectRoot, "node_modules", "@theglitchking", "semantic-sidekick", "bin", "semantic-sidekick"),
80
+ ];
81
+ for (const p of candidates) {
82
+ if (existsSync(p)) return p;
83
+ }
84
+ return null;
62
85
  }
63
86
 
64
87
  /** Returns the arg form that goes into .mcp.json for this project. */
@@ -82,6 +105,7 @@ function buildEntry(binArgStr, notesPath, extraArgs = []) {
82
105
  * Detect an entry as "one of ours" so we can safely remove it when the
83
106
  * condition that created it no longer holds. Matches both shapes we've ever
84
107
  * written: the legacy npx-form and the new node-against-node_modules form.
108
+ * Both rebranded and legacy package paths are recognized.
85
109
  */
86
110
  function isOurEntry(entry, notesPath) {
87
111
  if (!entry || typeof entry !== "object") return false;
@@ -90,11 +114,16 @@ function isOurEntry(entry, notesPath) {
90
114
  const argStr = args.map((a) => String(a)).join(" ");
91
115
 
92
116
  // Legacy npx form we shipped in 0.8.0 and prior SessionStart hooks.
93
- if (cmd === "npx" && argStr.includes(PKG) && argStr.includes(notesPath)) return true;
117
+ if (cmd === "npx" && (argStr.includes(PKG) || argStr.includes(LEGACY_PKG)) && argStr.includes(notesPath)) return true;
94
118
  // Current node-against-node_modules form (0.10.0+).
95
119
  if (
96
120
  cmd === "node" &&
97
- args.some((a) => typeof a === "string" && a.includes("node_modules/@theglitchking/semantic-sidekick")) &&
121
+ args.some(
122
+ (a) =>
123
+ typeof a === "string" &&
124
+ (a.includes("node_modules/@theglitchking/semantic-memory") ||
125
+ a.includes("node_modules/@theglitchking/semantic-sidekick"))
126
+ ) &&
98
127
  argStr.includes(notesPath)
99
128
  ) {
100
129
  return true;
@@ -126,7 +155,7 @@ export function reconcile(projectRoot) {
126
155
  let raw = "";
127
156
  try { raw = readFileSync(mcpPath, "utf8"); } catch {}
128
157
  if (raw.trim()) {
129
- process.stderr.write(`semantic-sidekick hook: could not parse ${mcpPath}; leaving untouched\n`);
158
+ process.stderr.write(`semantic-memory hook: could not parse ${mcpPath}; leaving untouched\n`);
130
159
  return;
131
160
  }
132
161
  } else if (parsed && typeof parsed === "object") {
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- // semantic-sidekick SessionStart hook.
2
+ // semantic-memory SessionStart hook.
3
3
  //
4
4
  // Critical path (zero external deps): run reconcile.js to wire .mcp.json +
5
5
  // create .claude/.vault. This ALWAYS runs, even if the plugin is installed
@@ -32,7 +32,7 @@ async function main() {
32
32
  try {
33
33
  await reconcile(projectRoot);
34
34
  } catch (err) {
35
- process.stderr.write(`[semantic-sidekick] reconcile failed: ${err?.message || err}\n`);
35
+ process.stderr.write(`[semantic-memory] reconcile failed: ${err?.message || err}\n`);
36
36
  }
37
37
 
38
38
  // 2. Optional runtime-backed update check. Skip silently if the runtime
@@ -45,9 +45,9 @@ async function main() {
45
45
  // that's idempotent (reconcile writes only what's missing), so the
46
46
  // double-invocation is harmless. We return early to avoid double-emit.
47
47
  await mod.runSessionStart({
48
- packageName: "@theglitchking/semantic-sidekick",
49
- pluginName: "semantic-sidekick",
50
- configFile: "semantic-sidekick.json",
48
+ packageName: "@theglitchking/semantic-memory",
49
+ pluginName: "semantic-memory",
50
+ configFile: "semantic-memory.json",
51
51
  reconcile,
52
52
  });
53
53
  return;
@@ -57,7 +57,7 @@ async function main() {
57
57
  // resolvable. Any other error gets logged but doesn't block the session.
58
58
  const msg = String(err?.message || err);
59
59
  if (!msg.includes("Cannot find package") && !msg.includes("ERR_MODULE_NOT_FOUND")) {
60
- process.stderr.write(`[semantic-sidekick] runtime import failed: ${msg}\n`);
60
+ process.stderr.write(`[semantic-memory] runtime import failed: ${msg}\n`);
61
61
  }
62
62
  }
63
63
 
@@ -75,7 +75,7 @@ function emit(additionalContext) {
75
75
  }
76
76
 
77
77
  main().catch((err) => {
78
- process.stderr.write(`[semantic-sidekick] session-start.js fatal: ${err?.message || err}\n`);
78
+ process.stderr.write(`[semantic-memory] session-start.js fatal: ${err?.message || err}\n`);
79
79
  // Still emit — never block the session.
80
80
  emit();
81
81
  });
@@ -53,7 +53,7 @@ function findVaultPath(projectRoot) {
53
53
  const entries = data?.mcpServers || {};
54
54
  for (const [name, entry] of Object.entries(entries)) {
55
55
  if (!entry || typeof entry !== "object") continue;
56
- if (name !== "semantic-vault" && name !== "semantic-sidekick") continue;
56
+ if (name !== "semantic-vault" && name !== "semantic-sidekick" && name !== "semantic-memory") continue;
57
57
  const args = Array.isArray(entry.args) ? entry.args : [];
58
58
  const i = args.indexOf("--notes");
59
59
  if (i >= 0 && i + 1 < args.length) {
@@ -71,9 +71,15 @@ function findVaultPath(projectRoot) {
71
71
  }
72
72
 
73
73
  function findCliBin(projectRoot) {
74
- // Prefer local installed bin (when sidekick is a dependency)
75
- const installed = join(projectRoot, "node_modules", "@theglitchking", "semantic-sidekick", "bin", "semantic-sidekick");
76
- if (existsSync(installed)) return installed;
74
+ // Prefer local installed bin. Try the rebranded package first; fall back to the
75
+ // legacy semantic-sidekick path for machines mid-migration.
76
+ const candidates = [
77
+ join(projectRoot, "node_modules", "@theglitchking", "semantic-memory", "bin", "semantic-memory"),
78
+ join(projectRoot, "node_modules", "@theglitchking", "semantic-sidekick", "bin", "semantic-sidekick"),
79
+ ];
80
+ for (const p of candidates) {
81
+ if (existsSync(p)) return p;
82
+ }
77
83
  // Dev fallback: this hook lives in <repo>/hooks/, the built CLI is at <repo>/dist/cli/index.js
78
84
  const dev = resolve(new URL("../dist/cli/index.js", import.meta.url).pathname);
79
85
  if (existsSync(dev)) return dev;
@@ -130,7 +136,7 @@ export function formatContextBlock(source, query, hits) {
130
136
  if (!hits || hits.length === 0) return "";
131
137
  const lines = [];
132
138
  lines.push(`<vault-context source="${source}" query="${escapeAttr(query)}">`);
133
- lines.push(`The vault (semantic-sidekick) was proactively searched. Top hits:`);
139
+ lines.push(`The vault (semantic-memory) was proactively searched. Top hits:`);
134
140
  lines.push("");
135
141
  for (const h of hits.slice(0, 6)) {
136
142
  const score = typeof h.score === "number" ? h.score.toFixed(2) : "";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theglitchking/semantic-memory",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "Unified memory-layer plugin for Claude Code. One MCP server, multiple typed corpora (vault, code, plans, docs, research, project-map), unified cross-corpus knowledge graph, conditional tool registration, in-process drift detection, and human↔code translation. Rebrand of @theglitchking/semantic-sidekick at v1.0 — see CHANGELOG for migration.",
5
5
  "type": "module",
6
6
  "main": "./dist/core/index.js",
@@ -12,14 +12,14 @@ const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
12
12
 
13
13
  try {
14
14
  runPostinstall({
15
- packageName: "@theglitchking/semantic-sidekick",
16
- pluginName: "semantic-sidekick",
17
- configFile: "semantic-sidekick.json",
15
+ packageName: "@theglitchking/semantic-memory",
16
+ pluginName: "semantic-memory",
17
+ configFile: "semantic-memory.json",
18
18
  skillsDir: "skills",
19
19
  packageRoot,
20
20
  hookCommand:
21
- "node ./node_modules/@theglitchking/semantic-sidekick/hooks/session-start.js",
21
+ "node ./node_modules/@theglitchking/semantic-memory/hooks/session-start.js",
22
22
  });
23
23
  } catch (err) {
24
- console.warn(`[semantic-sidekick] postinstall failed: ${err?.message || err}`);
24
+ console.warn(`[semantic-memory] postinstall failed: ${err?.message || err}`);
25
25
  }