oh-my-customcode 0.68.1 → 0.69.0

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/README.md CHANGED
@@ -294,15 +294,15 @@ your-project/
294
294
 
295
295
  ---
296
296
 
297
- ## Optional External Tools
297
+ ## External Tool Integrations
298
298
 
299
- oh-my-customcode works fully without any external tools. These optional integrations provide additional capabilities when installed:
299
+ RTK is automatically installed during `omcustom init` for 60-90% token savings. Other tools are optional:
300
300
 
301
- | Tool | Purpose | Install | Skill |
302
- |------|---------|---------|-------|
303
- | [RTK](https://github.com/rtk-ai/rtk) | 60-90% token savings on CLI output | `brew install rtk` | `/rtk-exec` |
304
- | [Codex CLI](https://github.com/openai/codex) | OpenAI Codex hybrid workflows | `npm i -g @openai/codex` | `/codex-exec` |
305
- | [Gemini CLI](https://github.com/google-gemini/gemini-cli) | Google Gemini hybrid workflows | `npm i -g @anthropic-ai/gemini-cli` | `/gemini-exec` |
301
+ | Tool | Purpose | Install | Status |
302
+ |------|---------|---------|--------|
303
+ | [RTK](https://github.com/rtk-ai/rtk) | 60-90% token savings on CLI output | Auto-installed via `omcustom init` | **Recommended** |
304
+ | [Codex CLI](https://github.com/openai/codex) | OpenAI Codex hybrid workflows | `npm i -g @openai/codex` | Optional |
305
+ | [Gemini CLI](https://github.com/google-gemini/gemini-cli) | Google Gemini hybrid workflows | `npm i -g @google/gemini-cli` | Optional |
306
306
 
307
307
  When installed, each tool is **auto-detected** at session start and its features become available. When not installed, all commands gracefully fall back to Claude-native alternatives.
308
308
 
package/dist/cli/index.js CHANGED
@@ -9325,7 +9325,7 @@ var init_package = __esm(() => {
9325
9325
  workspaces: [
9326
9326
  "packages/*"
9327
9327
  ],
9328
- version: "0.68.1",
9328
+ version: "0.69.0",
9329
9329
  description: "Batteries-included agent harness for Claude Code",
9330
9330
  type: "module",
9331
9331
  bin: {
@@ -24824,7 +24824,9 @@ var en_default = {
24824
24824
  interactiveNoneSelected: "No projects selected. Exiting.",
24825
24825
  interactiveUpdating: "Updating selected projects...",
24826
24826
  projectLatestSuffix: "(latest)",
24827
- newVersionAvailable: "[Info] oh-my-customcode v{{latest}} available (current: v{{current}}). Run 'npm i -g oh-my-customcode' to upgrade."
24827
+ newVersionAvailable: "[Info] oh-my-customcode v{{latest}} available (current: v{{current}}). Run 'npm i -g oh-my-customcode' to upgrade.",
24828
+ rtkMissing: "[RTK] RTK is not installed. Attempting installation...",
24829
+ rtkInstalled: "[RTK] ✓ RTK installed — 60-90% token savings activated"
24828
24830
  },
24829
24831
  list: {
24830
24832
  description: "List installed components",
@@ -24924,6 +24926,10 @@ var en_default = {
24924
24926
  framework: {
24925
24927
  pass: "Framework is up to date (v{{version}})",
24926
24928
  warn: "Framework is outdated: installed v{{installed}}, latest v{{latest}} ({{behind}} version(s) behind). Run 'omcustom update' to sync."
24929
+ },
24930
+ rtk: {
24931
+ pass: "RTK installed",
24932
+ warn: "RTK not installed — token savings unavailable"
24927
24933
  }
24928
24934
  }
24929
24935
  },
@@ -24983,6 +24989,12 @@ var en_default = {
24983
24989
  }
24984
24990
  }
24985
24991
  },
24992
+ install: {
24993
+ rtk_installing: "Installing RTK...",
24994
+ rtk_success: "RTK installed successfully",
24995
+ rtk_already: "RTK already installed",
24996
+ rtk_install_failed: "RTK installation failed"
24997
+ },
24986
24998
  init: {
24987
24999
  description: "Initialize oh-my-customcode in the current directory",
24988
25000
  starting: "Initializing oh-my-customcode...",
@@ -25209,7 +25221,9 @@ var ko_default = {
25209
25221
  interactiveNoneSelected: "선택된 프로젝트가 없습니다. 종료합니다.",
25210
25222
  interactiveUpdating: "선택된 프로젝트 업데이트 중...",
25211
25223
  projectLatestSuffix: "(최신)",
25212
- newVersionAvailable: "[정보] oh-my-customcode v{{latest}} 사용 가능 (현재: v{{current}}). 'npm i -g oh-my-customcode'를 실행하여 업그레이드하세요."
25224
+ newVersionAvailable: "[정보] oh-my-customcode v{{latest}} 사용 가능 (현재: v{{current}}). 'npm i -g oh-my-customcode'를 실행하여 업그레이드하세요.",
25225
+ rtkMissing: "[RTK] RTK가 설치되지 않았습니다. 설치를 시도합니다...",
25226
+ rtkInstalled: "[RTK] ✓ RTK 설치 완료 — 토큰 60-90% 절감 활성화"
25213
25227
  },
25214
25228
  list: {
25215
25229
  description: "설치된 컴포넌트 목록 표시",
@@ -25309,6 +25323,10 @@ var ko_default = {
25309
25323
  framework: {
25310
25324
  pass: "프레임워크가 최신 상태입니다 (v{{version}})",
25311
25325
  warn: "프레임워크가 구버전입니다: 설치됨 v{{installed}}, 최신 v{{latest}} ({{behind}}개 버전 뒤처짐). 'omcustom update'를 실행하여 동기화하세요."
25326
+ },
25327
+ rtk: {
25328
+ pass: "RTK 설치됨",
25329
+ warn: "RTK 미설치 — 토큰 절감 불가"
25312
25330
  }
25313
25331
  }
25314
25332
  },
@@ -25368,6 +25386,12 @@ var ko_default = {
25368
25386
  }
25369
25387
  }
25370
25388
  },
25389
+ install: {
25390
+ rtk_installing: "RTK 설치 중...",
25391
+ rtk_success: "RTK 설치 완료",
25392
+ rtk_already: "RTK 이미 설치됨",
25393
+ rtk_install_failed: "RTK 설치 실패"
25394
+ },
25371
25395
  init: {
25372
25396
  description: "현재 디렉토리에 oh-my-customcode 초기화",
25373
25397
  starting: "oh-my-customcode 초기화 중...",
@@ -26378,6 +26402,68 @@ async function generateAndWriteLockfileForDir(targetDir) {
26378
26402
  }
26379
26403
  }
26380
26404
 
26405
+ // src/core/rtk-installer.ts
26406
+ import { execSync as execSync3 } from "node:child_process";
26407
+ import { platform } from "node:os";
26408
+ function isRtkInstalled() {
26409
+ try {
26410
+ execSync3("which rtk", { stdio: "pipe", timeout: 3000 });
26411
+ return true;
26412
+ } catch {
26413
+ return false;
26414
+ }
26415
+ }
26416
+ function getRtkVersion() {
26417
+ try {
26418
+ return execSync3("rtk --version", { encoding: "utf-8", stdio: "pipe", timeout: 3000 }).trim();
26419
+ } catch {
26420
+ return null;
26421
+ }
26422
+ }
26423
+ function installRtk() {
26424
+ if (process.env.CI || false || false) {
26425
+ return false;
26426
+ }
26427
+ if (isRtkInstalled()) {
26428
+ info("rtk.already_installed");
26429
+ return true;
26430
+ }
26431
+ const os = platform();
26432
+ try {
26433
+ if (os === "darwin") {
26434
+ try {
26435
+ info("rtk.installing_brew");
26436
+ execSync3("brew install rtk-ai/tap/rtk", {
26437
+ stdio: "inherit",
26438
+ timeout: 120000
26439
+ });
26440
+ return true;
26441
+ } catch {
26442
+ info("rtk.installing_curl");
26443
+ execSync3("curl -fsSL https://raw.githubusercontent.com/rtk-ai/rtk/refs/heads/master/install.sh | sh", {
26444
+ stdio: "inherit",
26445
+ timeout: 120000
26446
+ });
26447
+ return isRtkInstalled();
26448
+ }
26449
+ } else if (os === "linux") {
26450
+ info("rtk.installing_curl");
26451
+ execSync3("curl -fsSL https://raw.githubusercontent.com/rtk-ai/rtk/refs/heads/master/install.sh | sh", {
26452
+ stdio: "inherit",
26453
+ timeout: 120000
26454
+ });
26455
+ return isRtkInstalled();
26456
+ } else {
26457
+ warn("rtk.unsupported_os", { os });
26458
+ return false;
26459
+ }
26460
+ } catch (err) {
26461
+ const message = err instanceof Error ? err.message : String(err);
26462
+ warn("rtk.install_failed", { error: message });
26463
+ return false;
26464
+ }
26465
+ }
26466
+
26381
26467
  // src/cli/doctor.ts
26382
26468
  async function pathExists(targetPath) {
26383
26469
  try {
@@ -26677,6 +26763,23 @@ async function checkHooks(targetDir, rootDir = ".claude") {
26677
26763
  fixable: false
26678
26764
  };
26679
26765
  }
26766
+ async function checkRtk() {
26767
+ if (!isRtkInstalled()) {
26768
+ return {
26769
+ name: "RTK",
26770
+ status: "warn",
26771
+ message: "RTK not installed — token savings unavailable (brew install rtk-ai/tap/rtk)",
26772
+ fixable: true
26773
+ };
26774
+ }
26775
+ const version = getRtkVersion();
26776
+ return {
26777
+ name: "RTK",
26778
+ status: "pass",
26779
+ message: `RTK OK (${version ?? "unknown version"})`,
26780
+ fixable: false
26781
+ };
26782
+ }
26680
26783
  async function checkContexts(targetDir, rootDir = ".claude") {
26681
26784
  const contextsDir = path.join(targetDir, rootDir, "contexts");
26682
26785
  const exists2 = await isDirectory(contextsDir);
@@ -26779,7 +26882,8 @@ async function fixSingleIssue(check, targetDir, rootDir = ".claude") {
26779
26882
  const fullPaths = check.details.map((d) => path.join(targetDir, d));
26780
26883
  const fixedCount = await fixBrokenSymlinks(targetDir, fullPaths);
26781
26884
  return fixedCount > 0;
26782
- }
26885
+ },
26886
+ RTK: async () => Promise.resolve(installRtk())
26783
26887
  };
26784
26888
  const fixer = fixMap[check.name];
26785
26889
  return fixer ? fixer() : false;
@@ -26927,7 +27031,8 @@ async function runAllChecks(targetDir, layout, packageVersion, includeUpdates) {
26927
27031
  checkGuides(targetDir),
26928
27032
  checkHooks(targetDir, layout.rootDir),
26929
27033
  checkContexts(targetDir, layout.rootDir),
26930
- checkCustomComponents(targetDir, layout.rootDir)
27034
+ checkCustomComponents(targetDir, layout.rootDir),
27035
+ checkRtk()
26931
27036
  ]);
26932
27037
  const frameworkCheck = await checkFrameworkDrift(targetDir, packageVersion);
26933
27038
  const checksWithFramework = frameworkCheck ? [...baseChecks, frameworkCheck] : baseChecks;
@@ -27575,6 +27680,19 @@ async function updateInstallConfig(targetDir, options, installedComponents) {
27575
27680
  config.installedComponents = installedComponents;
27576
27681
  await saveConfig(targetDir, config);
27577
27682
  }
27683
+ function installRtkIfNeeded(result) {
27684
+ if (!isRtkInstalled()) {
27685
+ info("install.rtk_installing");
27686
+ const rtkInstalled = installRtk();
27687
+ if (rtkInstalled) {
27688
+ info("install.rtk_success");
27689
+ } else {
27690
+ result.warnings.push("RTK installation failed — install manually: brew install rtk-ai/tap/rtk");
27691
+ }
27692
+ } else {
27693
+ info("install.rtk_already");
27694
+ }
27695
+ }
27578
27696
  async function install(options) {
27579
27697
  const result = createInstallResult(options.targetDir);
27580
27698
  try {
@@ -27612,6 +27730,7 @@ async function install(options) {
27612
27730
  } else {
27613
27731
  info("install.lockfile_generated", { files: String(lockfileResult.fileCount) });
27614
27732
  }
27733
+ installRtkIfNeeded(result);
27615
27734
  result.success = true;
27616
27735
  success("install.success");
27617
27736
  } catch (err) {
@@ -27795,7 +27914,7 @@ async function backupExistingInstallation(targetDir) {
27795
27914
 
27796
27915
  // src/core/mcp-config.ts
27797
27916
  init_fs();
27798
- import { execSync as execSync3 } from "node:child_process";
27917
+ import { execSync as execSync4 } from "node:child_process";
27799
27918
  import { writeFile } from "node:fs/promises";
27800
27919
  import { join as join8 } from "node:path";
27801
27920
  async function generateMCPConfig(targetDir) {
@@ -27807,15 +27926,15 @@ async function generateMCPConfig(targetDir) {
27807
27926
  return;
27808
27927
  }
27809
27928
  try {
27810
- execSync3("uv --version", { stdio: "pipe" });
27929
+ execSync4("uv --version", { stdio: "pipe" });
27811
27930
  } catch {
27812
27931
  warn("uv (Python package manager) not found. Install it with: curl -LsSf https://astral.sh/uv/install.sh | sh");
27813
27932
  warn("Skipping ontology-rag MCP configuration. You can set it up manually later.");
27814
27933
  return;
27815
27934
  }
27816
27935
  try {
27817
- execSync3("uv venv .venv", { cwd: targetDir, stdio: "pipe" });
27818
- execSync3('uv pip install "ontology-rag @ git+https://github.com/baekenough/oh-my-customcode.git#subdirectory=packages/ontology-rag"', { cwd: targetDir, stdio: "pipe" });
27936
+ execSync4("uv venv .venv", { cwd: targetDir, stdio: "pipe" });
27937
+ execSync4('uv pip install "ontology-rag @ git+https://github.com/baekenough/oh-my-customcode.git#subdirectory=packages/ontology-rag"', { cwd: targetDir, stdio: "pipe" });
27819
27938
  } catch (error2) {
27820
27939
  const msg = error2 instanceof Error ? error2.message : String(error2);
27821
27940
  warn(`Failed to setup ontology-rag: ${msg}`);
@@ -27858,7 +27977,7 @@ async function generateMCPConfig(targetDir) {
27858
27977
  }
27859
27978
  async function checkUvAvailable() {
27860
27979
  try {
27861
- execSync3("uv --version", { stdio: "pipe" });
27980
+ execSync4("uv --version", { stdio: "pipe" });
27862
27981
  return true;
27863
27982
  } catch {
27864
27983
  return false;
@@ -29853,8 +29972,8 @@ init_package();
29853
29972
 
29854
29973
  // src/core/updater.ts
29855
29974
  init_package();
29856
- init_fs();
29857
29975
  import { join as join14 } from "node:path";
29976
+ init_fs();
29858
29977
 
29859
29978
  // src/core/entry-merger.ts
29860
29979
  var MANAGED_START = "<!-- omcustom:start -->";
@@ -30177,6 +30296,16 @@ function compareSemver2(a, b) {
30177
30296
  }
30178
30297
  return 0;
30179
30298
  }
30299
+ function checkAndInstallRtkAfterUpdate() {
30300
+ if (!isRtkInstalled()) {
30301
+ warn("update.rtk_missing");
30302
+ console.log(i18n.t("cli.update.rtkMissing"));
30303
+ const rtkInstalled = installRtk();
30304
+ if (rtkInstalled) {
30305
+ console.log(i18n.t("cli.update.rtkInstalled"));
30306
+ }
30307
+ }
30308
+ }
30180
30309
  async function update(options) {
30181
30310
  const result = createUpdateResult();
30182
30311
  try {
@@ -30224,6 +30353,7 @@ async function update(options) {
30224
30353
  files: String(lockfileResult.fileCount)
30225
30354
  });
30226
30355
  }
30356
+ checkAndInstallRtkAfterUpdate();
30227
30357
  } catch (err) {
30228
30358
  const message = err instanceof Error ? err.message : String(err);
30229
30359
  result.error = message;