@ksm0709/context 0.0.30 → 0.0.32

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.
package/dist/cli/index.js CHANGED
@@ -2,9 +2,9 @@
2
2
  // @bun
3
3
 
4
4
  // src/cli/commands/update.ts
5
- import { resolve, join as join3 } from "path";
6
- import { existsSync as existsSync3 } from "fs";
7
- import { homedir } from "os";
5
+ import { resolve as resolve3, join as join7 } from "path";
6
+ import { existsSync as existsSync8 } from "fs";
7
+ import { homedir as homedir3 } from "os";
8
8
 
9
9
  // src/lib/scaffold.ts
10
10
  import { existsSync as existsSync2, mkdirSync, readFileSync, writeFileSync } from "fs";
@@ -27,7 +27,7 @@ function resolveContextDir(projectDir) {
27
27
  // package.json
28
28
  var package_default = {
29
29
  name: "@ksm0709/context",
30
- version: "0.0.30",
30
+ version: "0.0.32",
31
31
  author: {
32
32
  name: "TaehoKang",
33
33
  email: "ksm07091@gmail.com"
@@ -69,7 +69,7 @@ var package_default = {
69
69
  "@opencode-ai/plugin": ">=1.0.0"
70
70
  },
71
71
  dependencies: {
72
- "@ksm0709/context": "^0.0.29",
72
+ "@ksm0709/context": "^0.0.31",
73
73
  "@modelcontextprotocol/sdk": "^1.27.1",
74
74
  "jsonc-parser": "^3.0.0"
75
75
  },
@@ -449,213 +449,71 @@ function writeVersion(contextDir, version) {
449
449
  writeFileSync(join2(contextDir, ".version"), version, "utf-8");
450
450
  }
451
451
 
452
- // src/cli/commands/update.ts
453
- var KNOWN_SUBCOMMANDS = ["all", "prompt", "plugin"];
454
- function runUpdate(args) {
455
- const [subcommand, ...rest] = args;
456
- switch (subcommand) {
457
- case undefined:
458
- case "all":
459
- runUpdateAll(resolve(rest[0] ?? process.cwd()));
460
- break;
461
- case "prompt":
462
- process.stdout.write(`Prompt update is no longer supported.
463
- `);
464
- break;
465
- case "plugin":
466
- runUpdatePlugin(rest[0] ?? "latest");
467
- break;
468
- default:
469
- if (!KNOWN_SUBCOMMANDS.includes(subcommand)) {
470
- runUpdateAll(resolve(subcommand));
471
- } else {
472
- process.stderr.write(`Unknown update subcommand: ${subcommand}
473
- `);
474
- process.exit(1);
475
- }
476
- break;
477
- }
478
- }
479
- function runUpdateAll(projectDir) {
480
- const updated = updateScaffold(projectDir);
481
- if (updated.length === 0) {
482
- process.stdout.write(`All scaffold files are already up to date.
483
- `);
484
- } else {
485
- process.stdout.write(`Updated ${updated.length} file(s):
486
- `);
487
- for (const f of updated) {
488
- process.stdout.write(` - ${f}
489
- `);
490
- }
491
- }
492
- }
493
- function detectPackageManager() {
494
- if (existsSync3("bun.lock") || existsSync3("bun.lockb"))
495
- return "bun";
496
- if (existsSync3("pnpm-lock.yaml"))
497
- return "pnpm";
498
- if (existsSync3("yarn.lock"))
499
- return "yarn";
500
- if (existsSync3("package-lock.json"))
501
- return "npm";
502
- return "bun";
503
- }
504
- function detectGlobalInstalls() {
505
- const installs = [];
506
- const bunGlobalBin = join3(homedir(), ".bun", "bin", "context");
507
- if (existsSync3(bunGlobalBin)) {
508
- installs.push({ pm: "bun", label: "bun global", installCmd: ["bun", "install", "-g"] });
509
- }
510
- const spawnSync = globalThis.Bun?.spawnSync;
511
- if (spawnSync) {
512
- const whichResult = spawnSync(["which", "context"]);
513
- if (whichResult.exitCode === 0) {
514
- const binPath = whichResult.stdout.toString().trim();
515
- if (binPath && !binPath.includes(".bun") && !binPath.includes("node_modules")) {
516
- installs.push({ pm: "npm", label: "npm global", installCmd: ["npm", "install", "-g"] });
517
- }
518
- }
519
- }
520
- return installs;
521
- }
522
- function runUpdatePlugin(version) {
523
- const pkg = `@ksm0709/context@${version}`;
524
- const spawnSync = globalThis.Bun?.spawnSync;
525
- if (!spawnSync) {
526
- process.stderr.write(`Bun runtime required for plugin updates.
527
- `);
528
- process.exit(1);
529
- return;
530
- }
531
- const globalInstalls = detectGlobalInstalls();
532
- for (const { label, installCmd } of globalInstalls) {
533
- process.stdout.write(`Updating ${label} ${pkg}...
534
- `);
535
- const result = spawnSync([...installCmd, pkg]);
536
- if (result.exitCode !== 0) {
537
- process.stderr.write(`Failed to update ${label}: ${result.stderr.toString()}
538
- `);
539
- process.exit(1);
540
- return;
541
- }
542
- process.stdout.write(`Successfully updated ${label} ${pkg}.
543
- `);
544
- }
545
- const pm = detectPackageManager();
546
- process.stdout.write(`Updating local ${pkg} using ${pm}...
547
- `);
548
- const localResult = spawnSync([pm, "add", pkg]);
549
- if (localResult.exitCode !== 0) {
550
- process.stderr.write(`Failed to update local: ${localResult.stderr.toString()}
551
- `);
552
- process.exit(1);
553
- return;
554
- }
555
- process.stdout.write(`Successfully updated local ${pkg}.
556
- `);
557
- }
558
-
559
- // src/cli/commands/migrate.ts
560
- import { resolve as resolve2, join as join4 } from "path";
561
- import { existsSync as existsSync4, cpSync, rmSync, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
562
- var LEGACY_CONTEXT_DIR = ".opencode/context";
563
- var NEW_CONTEXT_DIR = ".context";
564
- function runMigrate(args) {
565
- const keepFlag = args.includes("--keep");
566
- const pathArg = args.find((a) => !a.startsWith("--"));
567
- const projectDir = resolve2(pathArg ?? process.cwd());
568
- const legacyDir = join4(projectDir, LEGACY_CONTEXT_DIR);
569
- const newDir = join4(projectDir, NEW_CONTEXT_DIR);
570
- if (!existsSync4(legacyDir)) {
571
- process.stdout.write(`Nothing to migrate.
572
- `);
573
- return;
574
- }
575
- if (existsSync4(newDir)) {
576
- process.stderr.write(`Target .context/ already exists. Aborting.
577
- `);
578
- process.exit(1);
579
- return;
580
- }
581
- cpSync(legacyDir, newDir, { recursive: true });
582
- updateConfigPaths(newDir);
583
- if (!keepFlag) {
584
- rmSync(legacyDir, { recursive: true, force: true });
585
- }
586
- process.stdout.write(`Migrated .opencode/context/ \u2192 .context/
587
- `);
588
- }
589
- function updateConfigPaths(contextDir) {
590
- const configPath = join4(contextDir, "config.jsonc");
591
- if (!existsSync4(configPath))
592
- return;
593
- try {
594
- const content = readFileSync2(configPath, "utf-8");
595
- const updated = content.replaceAll(".opencode/context/", "");
596
- if (updated !== content) {
597
- writeFileSync2(configPath, updated, "utf-8");
598
- }
599
- } catch {}
600
- }
601
-
602
452
  // src/cli/commands/install.ts
603
- import { join as join8, resolve as resolve4, dirname as dirname5 } from "path";
604
- import { existsSync as existsSync9, mkdirSync as mkdirSync5, copyFileSync } from "fs";
453
+ import { join as join6, resolve as resolve2, dirname as dirname5 } from "path";
454
+ import { existsSync as existsSync7, mkdirSync as mkdirSync5, copyFileSync } from "fs";
605
455
  import { fileURLToPath as fileURLToPath2 } from "url";
606
456
  import { createRequire as createRequire2 } from "module";
607
- import { execSync } from "child_process";
457
+ import { execSync as execSync2 } from "child_process";
608
458
 
609
459
  // src/omx/registry.ts
610
- import { join as join6, dirname as dirname2 } from "path";
611
- import { existsSync as existsSync6, readFileSync as readFileSync3, writeFileSync as writeFileSync3, mkdirSync as mkdirSync2 } from "fs";
612
- import { homedir as homedir2 } from "os";
460
+ import { join as join4, dirname as dirname2 } from "path";
461
+ import { existsSync as existsSync4, readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
462
+ import { execSync } from "child_process";
463
+ import { homedir } from "os";
613
464
 
614
465
  // src/shared/mcp-path.ts
615
466
  import { fileURLToPath } from "url";
616
- import { dirname, join as join5, resolve as resolve3 } from "path";
617
- import { existsSync as existsSync5 } from "fs";
467
+ import { dirname, join as join3, resolve } from "path";
468
+ import { existsSync as existsSync3 } from "fs";
618
469
  import { createRequire } from "module";
619
470
  function resolveMcpPath() {
620
471
  try {
621
472
  const req = createRequire(import.meta.url);
622
473
  const pkgJsonPath = req.resolve("@ksm0709/context/package.json");
623
474
  const pkgRoot = dirname(pkgJsonPath);
624
- const distMcp = join5(pkgRoot, "dist", "mcp.js");
625
- if (existsSync5(distMcp))
475
+ const distMcp = join3(pkgRoot, "dist", "mcp.js");
476
+ if (existsSync3(distMcp))
626
477
  return distMcp;
627
478
  } catch {}
628
479
  const currentFile = fileURLToPath(import.meta.url);
629
480
  const currentDir = dirname(currentFile);
630
- const distMcpPath = resolve3(currentDir, "..", "mcp.js");
631
- if (existsSync5(distMcpPath))
481
+ const distMcpPath = resolve(currentDir, "..", "mcp.js");
482
+ if (existsSync3(distMcpPath))
632
483
  return distMcpPath;
633
- const srcMcpPath = resolve3(currentDir, "..", "mcp.ts");
634
- if (existsSync5(srcMcpPath))
484
+ const srcMcpPath = resolve(currentDir, "..", "mcp.ts");
485
+ if (existsSync3(srcMcpPath))
635
486
  return srcMcpPath;
636
487
  return distMcpPath;
637
488
  }
638
489
 
639
490
  // src/omx/registry.ts
491
+ function resolveBunPath() {
492
+ try {
493
+ return execSync("which bun", { encoding: "utf-8", stdio: "pipe" }).trim();
494
+ } catch {
495
+ return "bun";
496
+ }
497
+ }
640
498
  function getRegistryPaths() {
641
499
  return [
642
- join6(homedir2(), ".omx", "mcp-registry.json"),
643
- join6(homedir2(), ".omc", "mcp-registry.json")
500
+ join4(homedir(), ".omx", "mcp-registry.json"),
501
+ join4(homedir(), ".omc", "mcp-registry.json")
644
502
  ];
645
503
  }
646
504
  function ensureMcpRegistered(sdkLog) {
647
505
  const registryPaths = getRegistryPaths();
648
506
  let targetPath = registryPaths[0];
649
507
  for (const p of registryPaths) {
650
- if (existsSync6(p)) {
508
+ if (existsSync4(p)) {
651
509
  targetPath = p;
652
510
  break;
653
511
  }
654
512
  }
655
513
  let registry = {};
656
- if (existsSync6(targetPath)) {
514
+ if (existsSync4(targetPath)) {
657
515
  try {
658
- const content = readFileSync3(targetPath, "utf-8");
516
+ const content = readFileSync2(targetPath, "utf-8");
659
517
  registry = JSON.parse(content);
660
518
  } catch (e) {
661
519
  if (sdkLog) {
@@ -665,26 +523,28 @@ function ensureMcpRegistered(sdkLog) {
665
523
  }
666
524
  }
667
525
  const mcpPath = resolveMcpPath();
526
+ const bunPath = resolveBunPath();
668
527
  const expectedConfig = {
669
- command: "bun",
670
- args: [mcpPath]
528
+ command: bunPath,
529
+ args: [mcpPath],
530
+ enabled: true
671
531
  };
672
- const currentConfig = registry["context_mcp"];
532
+ const currentConfig = registry["context-mcp"];
673
533
  let changed = false;
674
- if ("context-mcp" in registry) {
675
- delete registry["context-mcp"];
534
+ if ("context_mcp" in registry) {
535
+ delete registry["context_mcp"];
676
536
  changed = true;
677
537
  }
678
- if (!currentConfig || currentConfig.command !== expectedConfig.command || !Array.isArray(currentConfig.args) || currentConfig.args[0] !== expectedConfig.args[0]) {
679
- registry["context_mcp"] = expectedConfig;
538
+ if (!currentConfig || currentConfig.command !== expectedConfig.command || !Array.isArray(currentConfig.args) || currentConfig.args[0] !== expectedConfig.args[0] || currentConfig.enabled !== true) {
539
+ registry["context-mcp"] = expectedConfig;
680
540
  changed = true;
681
541
  }
682
542
  if (changed) {
683
543
  try {
684
544
  mkdirSync2(dirname2(targetPath), { recursive: true });
685
- writeFileSync3(targetPath, JSON.stringify(registry, null, 2), "utf-8");
545
+ writeFileSync2(targetPath, JSON.stringify(registry, null, 2), "utf-8");
686
546
  if (sdkLog) {
687
- sdkLog(`[INFO] Registered context_mcp in ${targetPath}`);
547
+ sdkLog(`[INFO] Registered context-mcp in ${targetPath}`);
688
548
  }
689
549
  return true;
690
550
  } catch (e) {
@@ -698,7 +558,7 @@ function ensureMcpRegistered(sdkLog) {
698
558
  }
699
559
 
700
560
  // src/shared/agents-md.ts
701
- import { existsSync as existsSync7, mkdirSync as mkdirSync3, readFileSync as readFileSync4, renameSync, writeFileSync as writeFileSync4 } from "fs";
561
+ import { existsSync as existsSync5, mkdirSync as mkdirSync3, readFileSync as readFileSync3, renameSync, writeFileSync as writeFileSync3 } from "fs";
702
562
  import { dirname as dirname3 } from "path";
703
563
  var START_MARKER = "<!-- context:start -->";
704
564
  var END_MARKER = "<!-- context:end -->";
@@ -736,16 +596,16 @@ function replaceMarkerBlock(existingContent, content) {
736
596
  }
737
597
  function writeFileAtomically(filePath, content) {
738
598
  const tempPath = `${filePath}.tmp`;
739
- writeFileSync4(tempPath, content, "utf-8");
599
+ writeFileSync3(tempPath, content, "utf-8");
740
600
  renameSync(tempPath, filePath);
741
601
  }
742
602
  function injectIntoAgentsMd(agentsMdPath, content) {
743
603
  mkdirSync3(dirname3(agentsMdPath), { recursive: true });
744
- if (!existsSync7(agentsMdPath)) {
604
+ if (!existsSync5(agentsMdPath)) {
745
605
  writeFileAtomically(agentsMdPath, renderMarkerBlock(content, true));
746
606
  return;
747
607
  }
748
- const existingContent = readFileSync4(agentsMdPath, "utf-8");
608
+ const existingContent = readFileSync3(agentsMdPath, "utf-8");
749
609
  const nextContent = existingContent.includes(START_MARKER) && existingContent.includes(END_MARKER) ? replaceMarkerBlock(existingContent, content) : appendMarkerBlock(existingContent, content);
750
610
  writeFileAtomically(agentsMdPath, nextContent);
751
611
  }
@@ -788,9 +648,9 @@ var STATIC_KNOWLEDGE_CONTEXT = `## Knowledge Context
788
648
  - \uD544\uC694\uD55C \uC778\uC790: daily_note_update_proof, knowledge_note_proof, quality_check_output, checkpoint_commit_hashes, scope_review_notes`;
789
649
 
790
650
  // src/shared/claude-settings.ts
791
- import { existsSync as existsSync8, readFileSync as readFileSync5, writeFileSync as writeFileSync5, renameSync as renameSync2, mkdirSync as mkdirSync4 } from "fs";
792
- import { dirname as dirname4, join as join7 } from "path";
793
- import { homedir as homedir3 } from "os";
651
+ import { existsSync as existsSync6, readFileSync as readFileSync4, writeFileSync as writeFileSync4, renameSync as renameSync2, mkdirSync as mkdirSync4 } from "fs";
652
+ import { dirname as dirname4, join as join5 } from "path";
653
+ import { homedir as homedir2 } from "os";
794
654
 
795
655
  // node_modules/jsonc-parser/lib/esm/impl/scanner.js
796
656
  function createScanner(text, ignoreTrivia = false) {
@@ -2116,22 +1976,22 @@ function applyEdits(text, edits) {
2116
1976
  }
2117
1977
 
2118
1978
  // src/shared/claude-settings.ts
2119
- var settingsPath = join7(homedir3(), ".claude", "settings.json");
1979
+ var settingsPath = join5(homedir2(), ".claude", "settings.json");
2120
1980
  function readClaudeSettings() {
2121
- if (!existsSync8(settingsPath)) {
1981
+ if (!existsSync6(settingsPath)) {
2122
1982
  return {};
2123
1983
  }
2124
- const content = readFileSync5(settingsPath, "utf8");
1984
+ const content = readFileSync4(settingsPath, "utf8");
2125
1985
  return parse2(content) ?? {};
2126
1986
  }
2127
1987
  function writeClaudeSettings(settings) {
2128
1988
  const dir = dirname4(settingsPath);
2129
- if (!existsSync8(dir)) {
1989
+ if (!existsSync6(dir)) {
2130
1990
  mkdirSync4(dir, { recursive: true });
2131
1991
  }
2132
1992
  let content;
2133
- if (existsSync8(settingsPath)) {
2134
- content = readFileSync5(settingsPath, "utf8");
1993
+ if (existsSync6(settingsPath)) {
1994
+ content = readFileSync4(settingsPath, "utf8");
2135
1995
  for (const [key, value] of Object.entries(settings)) {
2136
1996
  const edits = modify(content, [key], value, {});
2137
1997
  content = applyEdits(content, edits);
@@ -2147,17 +2007,9 @@ function writeClaudeSettings(settings) {
2147
2007
  content = JSON.stringify(settings, null, 2);
2148
2008
  }
2149
2009
  const tmp = settingsPath + ".tmp";
2150
- writeFileSync5(tmp, content, "utf8");
2010
+ writeFileSync4(tmp, content, "utf8");
2151
2011
  renameSync2(tmp, settingsPath);
2152
2012
  }
2153
- function registerMcpServer(name, entry) {
2154
- const settings = readClaudeSettings();
2155
- if (!settings.mcpServers) {
2156
- settings.mcpServers = {};
2157
- }
2158
- settings.mcpServers[name] = entry;
2159
- writeClaudeSettings(settings);
2160
- }
2161
2013
  function removeMcpServer(name) {
2162
2014
  const settings = readClaudeSettings();
2163
2015
  if (settings.mcpServers) {
@@ -2196,9 +2048,9 @@ function registerHook(event, rule) {
2196
2048
  function resolveOmxSource() {
2197
2049
  try {
2198
2050
  const cliDir = dirname5(fileURLToPath2(import.meta.url));
2199
- const pkgRoot = resolve4(cliDir, "..", "..");
2200
- const source = join8(pkgRoot, "dist", "omx", "index.mjs");
2201
- if (existsSync9(source))
2051
+ const pkgRoot = resolve2(cliDir, "..", "..");
2052
+ const source = join6(pkgRoot, "dist", "omx", "index.mjs");
2053
+ if (existsSync7(source))
2202
2054
  return source;
2203
2055
  } catch {}
2204
2056
  try {
@@ -2209,15 +2061,15 @@ function resolveOmxSource() {
2209
2061
  }
2210
2062
  }
2211
2063
  function installOmx(projectDir, sourcePath) {
2212
- if (!existsSync9(sourcePath)) {
2064
+ if (!existsSync7(sourcePath)) {
2213
2065
  process.stderr.write(`Could not find OMX plugin source file: ${sourcePath}
2214
2066
  `);
2215
2067
  process.exit(1);
2216
2068
  return;
2217
2069
  }
2218
- const targetDir = join8(projectDir, ".omx", "hooks");
2070
+ const targetDir = join6(projectDir, ".omx", "hooks");
2219
2071
  mkdirSync5(targetDir, { recursive: true });
2220
- copyFileSync(sourcePath, join8(targetDir, "context.mjs"));
2072
+ copyFileSync(sourcePath, join6(targetDir, "context.mjs"));
2221
2073
  process.stdout.write(`Installed context plugin to .omx/hooks/context.mjs
2222
2074
  `);
2223
2075
  if (ensureMcpRegistered()) {
@@ -2227,15 +2079,25 @@ function installOmx(projectDir, sourcePath) {
2227
2079
  }
2228
2080
  function installOmc(projectDir) {
2229
2081
  scaffoldIfNeeded(projectDir);
2230
- injectIntoAgentsMd(join8(projectDir, "AGENTS.md"), STATIC_KNOWLEDGE_CONTEXT);
2082
+ injectIntoAgentsMd(join6(projectDir, "AGENTS.md"), STATIC_KNOWLEDGE_CONTEXT);
2231
2083
  let bunPath = "bun";
2232
2084
  try {
2233
- bunPath = execSync("which bun", { encoding: "utf-8" }).trim();
2085
+ bunPath = execSync2("which bun", { encoding: "utf-8" }).trim();
2234
2086
  } catch {}
2235
2087
  const mcpPath = resolveMcpPath();
2236
- const hookBasePath = join8(dirname5(mcpPath), "omc") + "/";
2088
+ const hookBasePath = join6(dirname5(mcpPath), "omc") + "/";
2237
2089
  removeMcpServer("context_mcp");
2238
- registerMcpServer("context-mcp", { command: bunPath, args: [mcpPath], enabled: true });
2090
+ removeMcpServer("context-mcp");
2091
+ try {
2092
+ try {
2093
+ execSync2("claude mcp remove -s user context-mcp", { encoding: "utf-8", stdio: "pipe" });
2094
+ } catch {}
2095
+ execSync2(`claude mcp add -s user context-mcp -- ${bunPath} ${mcpPath}`, { encoding: "utf-8", stdio: "pipe" });
2096
+ } catch (e) {
2097
+ process.stderr.write(`Warning: Failed to register MCP via Claude CLI: ${e instanceof Error ? e.message : String(e)}
2098
+ ` + `You can manually run: claude mcp add -s user context-mcp -- ${bunPath} ${mcpPath}
2099
+ `);
2100
+ }
2239
2101
  registerHook("SessionStart", {
2240
2102
  matcher: "startup",
2241
2103
  hooks: [
@@ -2290,6 +2152,186 @@ function runInstall(args) {
2290
2152
  }
2291
2153
  }
2292
2154
 
2155
+ // src/cli/commands/update.ts
2156
+ var KNOWN_SUBCOMMANDS = ["all", "prompt", "plugin"];
2157
+ function runUpdate(args) {
2158
+ const [subcommand, ...rest] = args;
2159
+ switch (subcommand) {
2160
+ case undefined:
2161
+ case "all":
2162
+ runUpdateAll(resolve3(rest[0] ?? process.cwd()));
2163
+ break;
2164
+ case "prompt":
2165
+ process.stdout.write(`Prompt update is no longer supported.
2166
+ `);
2167
+ break;
2168
+ case "plugin":
2169
+ runUpdatePlugin(rest[0] ?? "latest");
2170
+ break;
2171
+ default:
2172
+ if (!KNOWN_SUBCOMMANDS.includes(subcommand)) {
2173
+ runUpdateAll(resolve3(subcommand));
2174
+ } else {
2175
+ process.stderr.write(`Unknown update subcommand: ${subcommand}
2176
+ `);
2177
+ process.exit(1);
2178
+ }
2179
+ break;
2180
+ }
2181
+ }
2182
+ function isOmxInstalled(projectDir) {
2183
+ return existsSync8(join7(projectDir, ".omx", "hooks", "context.mjs"));
2184
+ }
2185
+ function isOmcInstalled() {
2186
+ try {
2187
+ const settings = readClaudeSettings();
2188
+ return settings.mcpServers != null && "context-mcp" in settings.mcpServers;
2189
+ } catch {
2190
+ return false;
2191
+ }
2192
+ }
2193
+ function runUpdateAll(projectDir) {
2194
+ const updated = updateScaffold(projectDir);
2195
+ if (updated.length === 0) {
2196
+ process.stdout.write(`All scaffold files are already up to date.
2197
+ `);
2198
+ } else {
2199
+ process.stdout.write(`Updated ${updated.length} file(s):
2200
+ `);
2201
+ for (const f of updated) {
2202
+ process.stdout.write(` - ${f}
2203
+ `);
2204
+ }
2205
+ }
2206
+ if (isOmcInstalled()) {
2207
+ process.stdout.write(`
2208
+ Re-installing omc hooks and settings...
2209
+ `);
2210
+ installOmc(projectDir);
2211
+ }
2212
+ if (isOmxInstalled(projectDir)) {
2213
+ const source = resolveOmxSource();
2214
+ if (source) {
2215
+ process.stdout.write(`
2216
+ Re-installing omx plugin...
2217
+ `);
2218
+ installOmx(projectDir, source);
2219
+ } else {
2220
+ process.stderr.write(`
2221
+ Warning: could not resolve omx source; skipping omx reinstall.
2222
+ `);
2223
+ }
2224
+ }
2225
+ }
2226
+ function detectPackageManager() {
2227
+ if (existsSync8("bun.lock") || existsSync8("bun.lockb"))
2228
+ return "bun";
2229
+ if (existsSync8("pnpm-lock.yaml"))
2230
+ return "pnpm";
2231
+ if (existsSync8("yarn.lock"))
2232
+ return "yarn";
2233
+ if (existsSync8("package-lock.json"))
2234
+ return "npm";
2235
+ return "bun";
2236
+ }
2237
+ function detectGlobalInstalls() {
2238
+ const installs = [];
2239
+ const bunGlobalBin = join7(homedir3(), ".bun", "bin", "context");
2240
+ if (existsSync8(bunGlobalBin)) {
2241
+ installs.push({ pm: "bun", label: "bun global", installCmd: ["bun", "install", "-g"] });
2242
+ }
2243
+ const spawnSync = globalThis.Bun?.spawnSync;
2244
+ if (spawnSync) {
2245
+ const whichResult = spawnSync(["which", "context"]);
2246
+ if (whichResult.exitCode === 0) {
2247
+ const binPath = whichResult.stdout.toString().trim();
2248
+ if (binPath && !binPath.includes(".bun") && !binPath.includes("node_modules")) {
2249
+ installs.push({ pm: "npm", label: "npm global", installCmd: ["npm", "install", "-g"] });
2250
+ }
2251
+ }
2252
+ }
2253
+ return installs;
2254
+ }
2255
+ function runUpdatePlugin(version) {
2256
+ const pkg = `@ksm0709/context@${version}`;
2257
+ const spawnSync = globalThis.Bun?.spawnSync;
2258
+ if (!spawnSync) {
2259
+ process.stderr.write(`Bun runtime required for plugin updates.
2260
+ `);
2261
+ process.exit(1);
2262
+ return;
2263
+ }
2264
+ const globalInstalls = detectGlobalInstalls();
2265
+ for (const { label, installCmd } of globalInstalls) {
2266
+ process.stdout.write(`Updating ${label} ${pkg}...
2267
+ `);
2268
+ const result = spawnSync([...installCmd, pkg]);
2269
+ if (result.exitCode !== 0) {
2270
+ process.stderr.write(`Failed to update ${label}: ${result.stderr.toString()}
2271
+ `);
2272
+ process.exit(1);
2273
+ return;
2274
+ }
2275
+ process.stdout.write(`Successfully updated ${label} ${pkg}.
2276
+ `);
2277
+ }
2278
+ const pm = detectPackageManager();
2279
+ process.stdout.write(`Updating local ${pkg} using ${pm}...
2280
+ `);
2281
+ const localResult = spawnSync([pm, "add", pkg]);
2282
+ if (localResult.exitCode !== 0) {
2283
+ process.stderr.write(`Failed to update local: ${localResult.stderr.toString()}
2284
+ `);
2285
+ process.exit(1);
2286
+ return;
2287
+ }
2288
+ process.stdout.write(`Successfully updated local ${pkg}.
2289
+ `);
2290
+ }
2291
+
2292
+ // src/cli/commands/migrate.ts
2293
+ import { resolve as resolve4, join as join8 } from "path";
2294
+ import { existsSync as existsSync9, cpSync, rmSync, readFileSync as readFileSync5, writeFileSync as writeFileSync5 } from "fs";
2295
+ var LEGACY_CONTEXT_DIR = ".opencode/context";
2296
+ var NEW_CONTEXT_DIR = ".context";
2297
+ function runMigrate(args) {
2298
+ const keepFlag = args.includes("--keep");
2299
+ const pathArg = args.find((a) => !a.startsWith("--"));
2300
+ const projectDir = resolve4(pathArg ?? process.cwd());
2301
+ const legacyDir = join8(projectDir, LEGACY_CONTEXT_DIR);
2302
+ const newDir = join8(projectDir, NEW_CONTEXT_DIR);
2303
+ if (!existsSync9(legacyDir)) {
2304
+ process.stdout.write(`Nothing to migrate.
2305
+ `);
2306
+ return;
2307
+ }
2308
+ if (existsSync9(newDir)) {
2309
+ process.stderr.write(`Target .context/ already exists. Aborting.
2310
+ `);
2311
+ process.exit(1);
2312
+ return;
2313
+ }
2314
+ cpSync(legacyDir, newDir, { recursive: true });
2315
+ updateConfigPaths(newDir);
2316
+ if (!keepFlag) {
2317
+ rmSync(legacyDir, { recursive: true, force: true });
2318
+ }
2319
+ process.stdout.write(`Migrated .opencode/context/ \u2192 .context/
2320
+ `);
2321
+ }
2322
+ function updateConfigPaths(contextDir) {
2323
+ const configPath = join8(contextDir, "config.jsonc");
2324
+ if (!existsSync9(configPath))
2325
+ return;
2326
+ try {
2327
+ const content = readFileSync5(configPath, "utf-8");
2328
+ const updated = content.replaceAll(".opencode/context/", "");
2329
+ if (updated !== content) {
2330
+ writeFileSync5(configPath, updated, "utf-8");
2331
+ }
2332
+ } catch {}
2333
+ }
2334
+
2293
2335
  // src/cli/index.ts
2294
2336
  var PLUGIN_VERSION2 = package_default.version;
2295
2337
  function printHelp(out) {
@@ -2302,7 +2344,7 @@ function printHelp(out) {
2302
2344
  `);
2303
2345
  write(`Commands:
2304
2346
  `);
2305
- write(` update [all] [path] Force-update all scaffold files
2347
+ write(` update [all] [path] Force-update scaffold + reinstall omc/omx
2306
2348
  `);
2307
2349
  write(` update prompt [path] Force-update prompt files only
2308
2350
  `);
@@ -2311,6 +2353,8 @@ function printHelp(out) {
2311
2353
  write(` migrate [path] [--keep] Migrate .opencode/context/ \u2192 .context/
2312
2354
  `);
2313
2355
  write(` install omx Install OMX hook plugin to .omx/hooks/
2356
+ `);
2357
+ write(` install omc Install OMC hooks/MCP to Claude settings
2314
2358
  `);
2315
2359
  write(`
2316
2360
  `);
package/dist/index.js CHANGED
@@ -25,7 +25,7 @@ import { join as join2 } from "path";
25
25
  // package.json
26
26
  var package_default = {
27
27
  name: "@ksm0709/context",
28
- version: "0.0.30",
28
+ version: "0.0.32",
29
29
  author: {
30
30
  name: "TaehoKang",
31
31
  email: "ksm07091@gmail.com"
@@ -67,7 +67,7 @@ var package_default = {
67
67
  "@opencode-ai/plugin": ">=1.0.0"
68
68
  },
69
69
  dependencies: {
70
- "@ksm0709/context": "^0.0.29",
70
+ "@ksm0709/context": "^0.0.31",
71
71
  "@modelcontextprotocol/sdk": "^1.27.1",
72
72
  "jsonc-parser": "^3.0.0"
73
73
  },
package/dist/mcp.js CHANGED
@@ -32651,7 +32651,7 @@ function startMcpServer() {
32651
32651
  description: "Search .md files in docs/ and .context/ directories for a keyword or regex",
32652
32652
  inputSchema: {
32653
32653
  query: exports_external.string().describe("The keyword or regex to search for"),
32654
- limit: exports_external.number().optional().default(50).describe("Maximum number of results to return")
32654
+ limit: exports_external.number().optional().describe("Maximum number of results to return (default: 50)")
32655
32655
  }
32656
32656
  }, async ({ query, limit = 50 }) => {
32657
32657
  const searchDirs = ["docs", ".context"];
@@ -32819,11 +32819,14 @@ Snippet: ${r.snippet}`).join(`
32819
32819
  server.registerTool("read_daily_note", {
32820
32820
  description: "Read a daily note from N days ago",
32821
32821
  inputSchema: {
32822
- days_before: exports_external.number().optional().default(0).describe("Number of days ago (0 for today)"),
32823
- offset: exports_external.number().optional().default(0).describe("Line number to start reading from (0-indexed)"),
32824
- lines: exports_external.number().optional().default(100).describe("Number of lines to read")
32825
- }
32826
- }, async ({ days_before, offset, lines }) => {
32822
+ days_before: exports_external.number().optional().describe("Number of days ago (0 for today, default: 0)"),
32823
+ offset: exports_external.number().optional().describe("Line number to start reading from (0-indexed, default: 0)"),
32824
+ lines: exports_external.number().optional().describe("Number of lines to read (default: 100)")
32825
+ }
32826
+ }, async ({ days_before: _days_before, offset: _offset, lines: _lines }) => {
32827
+ const days_before = _days_before ?? 0;
32828
+ const offset = _offset ?? 0;
32829
+ const lines = _lines ?? 100;
32827
32830
  try {
32828
32831
  const date6 = new Date;
32829
32832
  date6.setDate(date6.getDate() - days_before);
@@ -33015,11 +33018,11 @@ ${tags.map((t) => ` - ${t}`).join(`
33015
33018
  server.registerTool("submit_turn_complete", {
33016
33019
  description: "Mark the current turn as complete after verifying all required steps",
33017
33020
  inputSchema: {
33018
- daily_note_update_proof: exports_external.string().min(5).optional().describe("Provide the file path of the updated daily note, or explicitly write 'skipped' if no update was needed."),
33019
- knowledge_note_proof: exports_external.string().min(5).optional().describe("Provide the file path of the created knowledge note, or explicitly write 'skipped' if no note was created."),
33020
- quality_check_output: exports_external.string().min(20).describe("Provide the last 5 lines of the `mise run lint && mise run test` execution output to prove quality checks passed."),
33021
- checkpoint_commit_hashes: exports_external.string().min(7).describe("Provide the output of `git log -1 --oneline` or an explanation if the task was too small for checkpoints."),
33022
- scope_review_notes: exports_external.string().min(10).describe("Provide a brief sentence confirming the scope check and that the work did not exceed the intended boundaries.")
33021
+ daily_note_update_proof: exports_external.string().optional().describe("Provide the file path of the updated daily note, or explicitly write 'skipped' if no update was needed."),
33022
+ knowledge_note_proof: exports_external.string().optional().describe("Provide the file path of the created knowledge note, or explicitly write 'skipped' if no note was created."),
33023
+ quality_check_output: exports_external.string().describe("Provide the last 5 lines of the `mise run lint && mise run test` execution output to prove quality checks passed."),
33024
+ checkpoint_commit_hashes: exports_external.string().describe("Provide the output of `git log -1 --oneline` or an explanation if the task was too small for checkpoints."),
33025
+ scope_review_notes: exports_external.string().describe("Provide a brief sentence confirming the scope check and that the work did not exceed the intended boundaries.")
33023
33026
  }
33024
33027
  }, async ({
33025
33028
  daily_note_update_proof,
@@ -33105,6 +33108,10 @@ ${tags.map((t) => ` - ${t}`).join(`
33105
33108
  return response;
33106
33109
  });
33107
33110
  }
33111
+ const rawServer = server.server;
33112
+ if (rawServer._capabilities?.tools) {
33113
+ rawServer._capabilities.tools = {};
33114
+ }
33108
33115
  const transport = new StdioServerTransport;
33109
33116
  server.connect(transport);
33110
33117
  return server;
@@ -20,7 +20,7 @@ function resolveContextDir(projectDir) {
20
20
  // package.json
21
21
  var package_default = {
22
22
  name: "@ksm0709/context",
23
- version: "0.0.30",
23
+ version: "0.0.32",
24
24
  author: {
25
25
  name: "TaehoKang",
26
26
  email: "ksm07091@gmail.com"
@@ -62,7 +62,7 @@ var package_default = {
62
62
  "@opencode-ai/plugin": ">=1.0.0"
63
63
  },
64
64
  dependencies: {
65
- "@ksm0709/context": "^0.0.29",
65
+ "@ksm0709/context": "^0.0.31",
66
66
  "@modelcontextprotocol/sdk": "^1.27.1",
67
67
  "jsonc-parser": "^3.0.0"
68
68
  },
@@ -105,7 +105,7 @@ import { join as join3 } from "node:path";
105
105
  // package.json
106
106
  var package_default = {
107
107
  name: "@ksm0709/context",
108
- version: "0.0.30",
108
+ version: "0.0.32",
109
109
  author: {
110
110
  name: "TaehoKang",
111
111
  email: "ksm07091@gmail.com"
@@ -147,7 +147,7 @@ var package_default = {
147
147
  "@opencode-ai/plugin": ">=1.0.0"
148
148
  },
149
149
  dependencies: {
150
- "@ksm0709/context": "^0.0.29",
150
+ "@ksm0709/context": "^0.0.31",
151
151
  "@modelcontextprotocol/sdk": "^1.27.1",
152
152
  "jsonc-parser": "^3.0.0"
153
153
  },
@@ -595,6 +595,7 @@ var STATIC_KNOWLEDGE_CONTEXT = `## Knowledge Context
595
595
  // src/omx/registry.ts
596
596
  import { join as join5, dirname as dirname3 } from "node:path";
597
597
  import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3 } from "node:fs";
598
+ import { execSync } from "node:child_process";
598
599
  import { homedir } from "node:os";
599
600
 
600
601
  // src/shared/mcp-path.ts
@@ -623,6 +624,13 @@ function resolveMcpPath() {
623
624
  }
624
625
 
625
626
  // src/omx/registry.ts
627
+ function resolveBunPath() {
628
+ try {
629
+ return execSync("which bun", { encoding: "utf-8", stdio: "pipe" }).trim();
630
+ } catch {
631
+ return "bun";
632
+ }
633
+ }
626
634
  function getRegistryPaths() {
627
635
  return [
628
636
  join5(homedir(), ".omx", "mcp-registry.json"),
@@ -651,18 +659,20 @@ function ensureMcpRegistered(sdkLog) {
651
659
  }
652
660
  }
653
661
  const mcpPath = resolveMcpPath();
662
+ const bunPath = resolveBunPath();
654
663
  const expectedConfig = {
655
- command: "bun",
656
- args: [mcpPath]
664
+ command: bunPath,
665
+ args: [mcpPath],
666
+ enabled: true
657
667
  };
658
- const currentConfig = registry["context_mcp"];
668
+ const currentConfig = registry["context-mcp"];
659
669
  let changed = false;
660
- if ("context-mcp" in registry) {
661
- delete registry["context-mcp"];
670
+ if ("context_mcp" in registry) {
671
+ delete registry["context_mcp"];
662
672
  changed = true;
663
673
  }
664
- if (!currentConfig || currentConfig.command !== expectedConfig.command || !Array.isArray(currentConfig.args) || currentConfig.args[0] !== expectedConfig.args[0]) {
665
- registry["context_mcp"] = expectedConfig;
674
+ if (!currentConfig || currentConfig.command !== expectedConfig.command || !Array.isArray(currentConfig.args) || currentConfig.args[0] !== expectedConfig.args[0] || currentConfig.enabled !== true) {
675
+ registry["context-mcp"] = expectedConfig;
666
676
  changed = true;
667
677
  }
668
678
  if (changed) {
@@ -670,7 +680,7 @@ function ensureMcpRegistered(sdkLog) {
670
680
  mkdirSync3(dirname3(targetPath), { recursive: true });
671
681
  writeFileSync3(targetPath, JSON.stringify(registry, null, 2), "utf-8");
672
682
  if (sdkLog) {
673
- sdkLog(`[INFO] Registered context_mcp in ${targetPath}`);
683
+ sdkLog(`[INFO] Registered context-mcp in ${targetPath}`);
674
684
  }
675
685
  return true;
676
686
  } catch (e) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ksm0709/context",
3
- "version": "0.0.30",
3
+ "version": "0.0.32",
4
4
  "author": {
5
5
  "name": "TaehoKang",
6
6
  "email": "ksm07091@gmail.com"
@@ -42,7 +42,7 @@
42
42
  "@opencode-ai/plugin": ">=1.0.0"
43
43
  },
44
44
  "dependencies": {
45
- "@ksm0709/context": "^0.0.29",
45
+ "@ksm0709/context": "^0.0.31",
46
46
  "@modelcontextprotocol/sdk": "^1.27.1",
47
47
  "jsonc-parser": "^3.0.0"
48
48
  },