oh-my-customcode 0.12.0 → 0.12.2
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 +4 -8
- package/dist/cli/index.js +382 -308
- package/dist/index.js +99 -260
- package/package.json +2 -4
- package/templates/.codex/agents/arch-documenter.md +0 -33
- package/templates/.codex/agents/arch-speckit-agent.md +0 -47
- package/templates/.codex/agents/be-express-expert.md +0 -30
- package/templates/.codex/agents/be-fastapi-expert.md +0 -43
- package/templates/.codex/agents/be-go-backend-expert.md +0 -43
- package/templates/.codex/agents/be-nestjs-expert.md +0 -28
- package/templates/.codex/agents/be-springboot-expert.md +0 -40
- package/templates/.codex/agents/db-postgres-expert.md +0 -36
- package/templates/.codex/agents/db-redis-expert.md +0 -36
- package/templates/.codex/agents/db-supabase-expert.md +0 -35
- package/templates/.codex/agents/de-airflow-expert.md +0 -34
- package/templates/.codex/agents/de-dbt-expert.md +0 -34
- package/templates/.codex/agents/de-kafka-expert.md +0 -81
- package/templates/.codex/agents/de-pipeline-expert.md +0 -32
- package/templates/.codex/agents/de-snowflake-expert.md +0 -36
- package/templates/.codex/agents/de-spark-expert.md +0 -36
- package/templates/.codex/agents/fe-svelte-agent.md +0 -29
- package/templates/.codex/agents/fe-vercel-agent.md +0 -37
- package/templates/.codex/agents/fe-vuejs-agent.md +0 -30
- package/templates/.codex/agents/infra-aws-expert.md +0 -47
- package/templates/.codex/agents/infra-docker-expert.md +0 -47
- package/templates/.codex/agents/lang-golang-expert.md +0 -43
- package/templates/.codex/agents/lang-java21-expert.md +0 -39
- package/templates/.codex/agents/lang-kotlin-expert.md +0 -43
- package/templates/.codex/agents/lang-python-expert.md +0 -43
- package/templates/.codex/agents/lang-rust-expert.md +0 -43
- package/templates/.codex/agents/lang-typescript-expert.md +0 -43
- package/templates/.codex/agents/mgr-claude-code-bible.md +0 -61
- package/templates/.codex/agents/mgr-creator.md +0 -39
- package/templates/.codex/agents/mgr-gitnerd.md +0 -45
- package/templates/.codex/agents/mgr-sauron.md +0 -161
- package/templates/.codex/agents/mgr-supplier.md +0 -35
- package/templates/.codex/agents/mgr-sync-checker.md +0 -38
- package/templates/.codex/agents/mgr-updater.md +0 -33
- package/templates/.codex/agents/qa-engineer.md +0 -32
- package/templates/.codex/agents/qa-planner.md +0 -73
- package/templates/.codex/agents/qa-writer.md +0 -27
- package/templates/.codex/agents/sys-memory-keeper.md +0 -43
- package/templates/.codex/agents/sys-naggy.md +0 -37
- package/templates/.codex/agents/tool-bun-expert.md +0 -26
- package/templates/.codex/agents/tool-npm-expert.md +0 -30
- package/templates/.codex/agents/tool-optimizer.md +0 -34
- package/templates/.codex/codex-native-hash.txt +0 -1
- package/templates/.codex/contexts/dev.md +0 -20
- package/templates/.codex/contexts/ecomode.md +0 -63
- package/templates/.codex/contexts/index.yaml +0 -41
- package/templates/.codex/contexts/research.md +0 -28
- package/templates/.codex/contexts/review.md +0 -23
- package/templates/.codex/hooks/hooks.json +0 -151
- package/templates/.codex/install-hooks.sh +0 -100
- package/templates/.codex/rules/MAY-optimization.md +0 -29
- package/templates/.codex/rules/MUST-agent-design.md +0 -57
- package/templates/.codex/rules/MUST-agent-identification.md +0 -29
- package/templates/.codex/rules/MUST-continuous-improvement.md +0 -25
- package/templates/.codex/rules/MUST-intent-transparency.md +0 -42
- package/templates/.codex/rules/MUST-language-policy.md +0 -27
- package/templates/.codex/rules/MUST-orchestrator-coordination.md +0 -128
- package/templates/.codex/rules/MUST-parallel-execution.md +0 -97
- package/templates/.codex/rules/MUST-permissions.md +0 -30
- package/templates/.codex/rules/MUST-safety.md +0 -23
- package/templates/.codex/rules/MUST-sync-verification.md +0 -125
- package/templates/.codex/rules/MUST-tool-identification.md +0 -82
- package/templates/.codex/rules/SHOULD-agent-teams.md +0 -39
- package/templates/.codex/rules/SHOULD-ecomode.md +0 -37
- package/templates/.codex/rules/SHOULD-error-handling.md +0 -33
- package/templates/.codex/rules/SHOULD-hud-statusline.md +0 -32
- package/templates/.codex/rules/SHOULD-interaction.md +0 -34
- package/templates/.codex/rules/SHOULD-memory-integration.md +0 -39
- package/templates/.codex/rules/index.yaml +0 -141
- package/templates/.codex/skills/airflow-best-practices/SKILL.md +0 -56
- package/templates/.codex/skills/audit-agents/SKILL.md +0 -116
- package/templates/.codex/skills/aws-best-practices/SKILL.md +0 -280
- package/templates/.codex/skills/claude-code-bible/SKILL.md +0 -180
- package/templates/.codex/skills/claude-code-bible/scripts/fetch-docs.js +0 -244
- package/templates/.codex/skills/create-agent/SKILL.md +0 -91
- package/templates/.codex/skills/dbt-best-practices/SKILL.md +0 -54
- package/templates/.codex/skills/de-lead-routing/SKILL.md +0 -243
- package/templates/.codex/skills/dev-lead-routing/SKILL.md +0 -94
- package/templates/.codex/skills/dev-refactor/SKILL.md +0 -123
- package/templates/.codex/skills/dev-review/SKILL.md +0 -81
- package/templates/.codex/skills/docker-best-practices/SKILL.md +0 -275
- package/templates/.codex/skills/fastapi-best-practices/SKILL.md +0 -270
- package/templates/.codex/skills/fix-refs/SKILL.md +0 -107
- package/templates/.codex/skills/go-backend-best-practices/SKILL.md +0 -338
- package/templates/.codex/skills/go-best-practices/CLAUDE.md +0 -9
- package/templates/.codex/skills/go-best-practices/SKILL.md +0 -203
- package/templates/.codex/skills/help/SKILL.md +0 -125
- package/templates/.codex/skills/intent-detection/SKILL.md +0 -215
- package/templates/.codex/skills/intent-detection/patterns/agent-triggers.yaml +0 -349
- package/templates/.codex/skills/kafka-best-practices/SKILL.md +0 -52
- package/templates/.codex/skills/kotlin-best-practices/SKILL.md +0 -256
- package/templates/.codex/skills/lists/SKILL.md +0 -78
- package/templates/.codex/skills/memory-management/SKILL.md +0 -195
- package/templates/.codex/skills/memory-recall/SKILL.md +0 -152
- package/templates/.codex/skills/memory-save/SKILL.md +0 -126
- package/templates/.codex/skills/monitoring-setup/SKILL.md +0 -115
- package/templates/.codex/skills/npm-audit/SKILL.md +0 -72
- package/templates/.codex/skills/npm-publish/SKILL.md +0 -63
- package/templates/.codex/skills/npm-version/SKILL.md +0 -75
- package/templates/.codex/skills/optimize-analyze/SKILL.md +0 -55
- package/templates/.codex/skills/optimize-bundle/SKILL.md +0 -67
- package/templates/.codex/skills/optimize-report/SKILL.md +0 -74
- package/templates/.codex/skills/pipeline-architecture-patterns/SKILL.md +0 -83
- package/templates/.codex/skills/postgres-best-practices/SKILL.md +0 -66
- package/templates/.codex/skills/python-best-practices/SKILL.md +0 -222
- package/templates/.codex/skills/qa-lead-routing/SKILL.md +0 -290
- package/templates/.codex/skills/react-best-practices/SKILL.md +0 -101
- package/templates/.codex/skills/redis-best-practices/SKILL.md +0 -83
- package/templates/.codex/skills/result-aggregation/SKILL.md +0 -164
- package/templates/.codex/skills/rust-best-practices/SKILL.md +0 -267
- package/templates/.codex/skills/sauron-watch/SKILL.md +0 -144
- package/templates/.codex/skills/secretary-routing/SKILL.md +0 -203
- package/templates/.codex/skills/snowflake-best-practices/SKILL.md +0 -65
- package/templates/.codex/skills/spark-best-practices/SKILL.md +0 -52
- package/templates/.codex/skills/springboot-best-practices/SKILL.md +0 -218
- package/templates/.codex/skills/status/SKILL.md +0 -153
- package/templates/.codex/skills/supabase-postgres-best-practices/SKILL.md +0 -99
- package/templates/.codex/skills/typescript-best-practices/SKILL.md +0 -321
- package/templates/.codex/skills/update-docs/SKILL.md +0 -140
- package/templates/.codex/skills/update-external/SKILL.md +0 -149
- package/templates/.codex/skills/vercel-deploy/SKILL.md +0 -73
- package/templates/.codex/skills/web-design-guidelines/SKILL.md +0 -118
- package/templates/.codex/skills/writing-clearly-and-concisely/SKILL.md +0 -64
- package/templates/.codex/uninstall-hooks.sh +0 -52
- package/templates/AGENTS.md.en +0 -39
- package/templates/AGENTS.md.ko +0 -39
- package/templates/manifest.codex.json +0 -43
package/dist/cli/index.js
CHANGED
|
@@ -9153,7 +9153,7 @@ function checkOutdated(tools) {
|
|
|
9153
9153
|
} catch {}
|
|
9154
9154
|
}
|
|
9155
9155
|
async function runPreflightCheck(options = {}) {
|
|
9156
|
-
const { skip = false, tools: toolNames = ["claude-code"
|
|
9156
|
+
const { skip = false, tools: toolNames = ["claude-code"], timeout = 5000 } = options;
|
|
9157
9157
|
if (skip) {
|
|
9158
9158
|
return {
|
|
9159
9159
|
tools: [],
|
|
@@ -9241,6 +9241,13 @@ function formatPreflightWarnings(result) {
|
|
|
9241
9241
|
`);
|
|
9242
9242
|
}
|
|
9243
9243
|
|
|
9244
|
+
// src/core/self-update.ts
|
|
9245
|
+
import { execSync as execSync2, spawnSync } from "node:child_process";
|
|
9246
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
9247
|
+
import { homedir } from "node:os";
|
|
9248
|
+
import { dirname, join } from "node:path";
|
|
9249
|
+
import { createInterface } from "node:readline/promises";
|
|
9250
|
+
|
|
9244
9251
|
// node_modules/i18next/dist/esm/i18next.js
|
|
9245
9252
|
var isString = (obj) => typeof obj === "string";
|
|
9246
9253
|
var defer = () => {
|
|
@@ -11680,10 +11687,21 @@ var en_default = {
|
|
|
11680
11687
|
homebrewNotFound: "Homebrew not found, skipping version check",
|
|
11681
11688
|
timeout: "Version check timed out, continuing..."
|
|
11682
11689
|
},
|
|
11690
|
+
selfUpdate: {
|
|
11691
|
+
checking: "Checking for oh-my-customcode updates...",
|
|
11692
|
+
available: "📦 New version available: v{{current}} → v{{latest}}",
|
|
11693
|
+
prompt: "Would you like to update oh-my-customcode first? (Y/n): ",
|
|
11694
|
+
updatingGlobal: "⬆️ Updating oh-my-customcode globally to v{{version}}...",
|
|
11695
|
+
updatingNpx: "⬆️ Launching latest version via npx (v{{version}})...",
|
|
11696
|
+
updated: "✅ Updated to v{{version}}",
|
|
11697
|
+
declined: "Continuing with current version.",
|
|
11698
|
+
failed: "Self-update failed: {{error}}",
|
|
11699
|
+
relaunchFailed: "Failed to launch latest version via npx (status: {{status}}).",
|
|
11700
|
+
continueAfterFailure: "Continuing init with current version."
|
|
11701
|
+
},
|
|
11683
11702
|
init: {
|
|
11684
11703
|
description: "Initialize oh-my-customcode in the current directory",
|
|
11685
11704
|
langOption: "Language for templates (en or ko)",
|
|
11686
|
-
providerOption: "Provider to initialize (auto, claude, codex)",
|
|
11687
11705
|
start: "Initializing oh-my-customcode...",
|
|
11688
11706
|
exists: "Existing {{rootDir}} directory found.",
|
|
11689
11707
|
backing_up: "Creating backup...",
|
|
@@ -11733,7 +11751,6 @@ var en_default = {
|
|
|
11733
11751
|
guidesOption: "Update only guides",
|
|
11734
11752
|
hooksOption: "Update only hooks",
|
|
11735
11753
|
contextsOption: "Update only contexts",
|
|
11736
|
-
providerOption: "Provider to update (auto, claude, codex)",
|
|
11737
11754
|
dryRunHeader: "Dry run - no changes will be made:",
|
|
11738
11755
|
componentUpdated: "✓ {{component}} updated",
|
|
11739
11756
|
componentSkipped: "- {{component}} skipped (no changes)",
|
|
@@ -11746,7 +11763,6 @@ var en_default = {
|
|
|
11746
11763
|
list: {
|
|
11747
11764
|
description: "List installed components",
|
|
11748
11765
|
typeArgument: "Type to list: agents, skills, guides, rules, or all",
|
|
11749
|
-
providerOption: "Provider to list (auto, claude, codex)",
|
|
11750
11766
|
scanning: "Scanning installed components...",
|
|
11751
11767
|
empty: "No {{type}} found.",
|
|
11752
11768
|
header: "{{type}} ({{count}} installed)",
|
|
@@ -11771,7 +11787,6 @@ var en_default = {
|
|
|
11771
11787
|
doctor: {
|
|
11772
11788
|
description: "Check and fix configuration issues",
|
|
11773
11789
|
fixOption: "Automatically fix issues that can be fixed",
|
|
11774
|
-
providerOption: "Provider to diagnose (auto, claude, codex)",
|
|
11775
11790
|
checking: "Running diagnostic checks...",
|
|
11776
11791
|
applyingFixes: "Applying fixes...",
|
|
11777
11792
|
fixing: "Fixing: {{name}}...",
|
|
@@ -11964,10 +11979,21 @@ var ko_default = {
|
|
|
11964
11979
|
homebrewNotFound: "Homebrew를 찾을 수 없어 버전 확인을 건너뜁니다",
|
|
11965
11980
|
timeout: "버전 확인 시간 초과, 계속 진행합니다..."
|
|
11966
11981
|
},
|
|
11982
|
+
selfUpdate: {
|
|
11983
|
+
checking: "oh-my-customcode 업데이트 확인 중...",
|
|
11984
|
+
available: "📦 새 버전 사용 가능: v{{current}} → v{{latest}}",
|
|
11985
|
+
prompt: "먼저 oh-my-customcode를 업데이트할까요? (Y/n): ",
|
|
11986
|
+
updatingGlobal: "⬆️ oh-my-customcode를 전역으로 v{{version}}로 업데이트 중...",
|
|
11987
|
+
updatingNpx: "⬆️ npx로 최신 버전(v{{version}})을 실행합니다...",
|
|
11988
|
+
updated: "✅ v{{version}}로 업데이트되었습니다",
|
|
11989
|
+
declined: "현재 버전으로 계속 진행합니다.",
|
|
11990
|
+
failed: "자체 업데이트 실패: {{error}}",
|
|
11991
|
+
relaunchFailed: "npx 최신 버전 실행 실패 (status: {{status}}).",
|
|
11992
|
+
continueAfterFailure: "현재 버전으로 init을 계속 진행합니다."
|
|
11993
|
+
},
|
|
11967
11994
|
init: {
|
|
11968
11995
|
description: "현재 디렉토리에 oh-my-customcode 초기화",
|
|
11969
11996
|
langOption: "템플릿 언어 (en 또는 ko)",
|
|
11970
|
-
providerOption: "초기화할 제공자 (auto, claude, codex)",
|
|
11971
11997
|
start: "oh-my-customcode 초기화 중...",
|
|
11972
11998
|
exists: "기존 {{rootDir}} 디렉토리가 발견되었습니다.",
|
|
11973
11999
|
backing_up: "백업을 생성합니다...",
|
|
@@ -12017,7 +12043,6 @@ var ko_default = {
|
|
|
12017
12043
|
guidesOption: "가이드만 업데이트",
|
|
12018
12044
|
hooksOption: "훅만 업데이트",
|
|
12019
12045
|
contextsOption: "컨텍스트만 업데이트",
|
|
12020
|
-
providerOption: "업데이트할 제공자 (auto, claude, codex)",
|
|
12021
12046
|
dryRunHeader: "드라이 런 - 변경사항 없음:",
|
|
12022
12047
|
componentUpdated: "✓ {{component}} 업데이트됨",
|
|
12023
12048
|
componentSkipped: "- {{component}} 건너뜀 (변경사항 없음)",
|
|
@@ -12030,7 +12055,6 @@ var ko_default = {
|
|
|
12030
12055
|
list: {
|
|
12031
12056
|
description: "설치된 컴포넌트 목록 표시",
|
|
12032
12057
|
typeArgument: "표시할 타입: agents, skills, guides, rules 또는 all",
|
|
12033
|
-
providerOption: "표시할 제공자 (auto, claude, codex)",
|
|
12034
12058
|
scanning: "설치된 컴포넌트 검색 중...",
|
|
12035
12059
|
empty: "{{type}}이(가) 없습니다.",
|
|
12036
12060
|
header: "{{type}} ({{count}}개 설치됨)",
|
|
@@ -12055,7 +12079,6 @@ var ko_default = {
|
|
|
12055
12079
|
doctor: {
|
|
12056
12080
|
description: "설정 문제 확인 및 수정",
|
|
12057
12081
|
fixOption: "자동으로 수정 가능한 문제 수정",
|
|
12058
|
-
providerOption: "진단할 제공자 (auto, claude, codex)",
|
|
12059
12082
|
checking: "진단 검사 실행 중...",
|
|
12060
12083
|
applyingFixes: "수정 사항 적용 중...",
|
|
12061
12084
|
fixing: "수정 중: {{name}}...",
|
|
@@ -12247,6 +12270,242 @@ var i18n = {
|
|
|
12247
12270
|
}
|
|
12248
12271
|
};
|
|
12249
12272
|
|
|
12273
|
+
// src/core/self-update.ts
|
|
12274
|
+
var DEFAULT_PACKAGE_NAME = "oh-my-customcode";
|
|
12275
|
+
var DEFAULT_CACHE_TTL_MS = 24 * 60 * 60 * 1000;
|
|
12276
|
+
var DEFAULT_CACHE_PATH = join(homedir(), ".oh-my-customcode", "self-update-cache.json");
|
|
12277
|
+
function normalizeVersion(version) {
|
|
12278
|
+
return version.trim().replace(/^v/i, "").split("-")[0] || "";
|
|
12279
|
+
}
|
|
12280
|
+
function compareSemver(a, b) {
|
|
12281
|
+
const left = normalizeVersion(a).split(".").map((n) => Number.parseInt(n, 10) || 0);
|
|
12282
|
+
const right = normalizeVersion(b).split(".").map((n) => Number.parseInt(n, 10) || 0);
|
|
12283
|
+
const maxLen = Math.max(left.length, right.length, 3);
|
|
12284
|
+
for (let i = 0;i < maxLen; i += 1) {
|
|
12285
|
+
const l = left[i] ?? 0;
|
|
12286
|
+
const r = right[i] ?? 0;
|
|
12287
|
+
if (l < r)
|
|
12288
|
+
return -1;
|
|
12289
|
+
if (l > r)
|
|
12290
|
+
return 1;
|
|
12291
|
+
}
|
|
12292
|
+
return 0;
|
|
12293
|
+
}
|
|
12294
|
+
function isInteractiveSession(stdin = process.stdin, stdout = process.stdout) {
|
|
12295
|
+
return Boolean(stdin.isTTY && stdout.isTTY);
|
|
12296
|
+
}
|
|
12297
|
+
function isNpxInvocation(argv = process.argv, env = process.env) {
|
|
12298
|
+
const argv1 = argv[1] || "";
|
|
12299
|
+
const npmExecPath = env.npm_execpath || "";
|
|
12300
|
+
const npmCommand = env.npm_command || "";
|
|
12301
|
+
return argv1.includes("/_npx/") || argv1.includes("\\_npx\\") || npmExecPath.includes("npx") || npmCommand === "exec" || env.npm_lifecycle_event === "npx";
|
|
12302
|
+
}
|
|
12303
|
+
function readCache(cachePath) {
|
|
12304
|
+
if (!existsSync(cachePath)) {
|
|
12305
|
+
return null;
|
|
12306
|
+
}
|
|
12307
|
+
try {
|
|
12308
|
+
const parsed = JSON.parse(readFileSync(cachePath, "utf-8"));
|
|
12309
|
+
if (!parsed.checkedAt || !parsed.latestVersion) {
|
|
12310
|
+
return null;
|
|
12311
|
+
}
|
|
12312
|
+
return {
|
|
12313
|
+
checkedAt: parsed.checkedAt,
|
|
12314
|
+
latestVersion: parsed.latestVersion
|
|
12315
|
+
};
|
|
12316
|
+
} catch {
|
|
12317
|
+
return null;
|
|
12318
|
+
}
|
|
12319
|
+
}
|
|
12320
|
+
function writeCache(cachePath, latestVersion, now) {
|
|
12321
|
+
const dir2 = dirname(cachePath);
|
|
12322
|
+
if (!existsSync(dir2)) {
|
|
12323
|
+
mkdirSync(dir2, { recursive: true });
|
|
12324
|
+
}
|
|
12325
|
+
const payload = {
|
|
12326
|
+
checkedAt: new Date(now).toISOString(),
|
|
12327
|
+
latestVersion
|
|
12328
|
+
};
|
|
12329
|
+
writeFileSync(cachePath, `${JSON.stringify(payload, null, 2)}
|
|
12330
|
+
`, "utf-8");
|
|
12331
|
+
}
|
|
12332
|
+
function isCacheFresh(cache, now, cacheTtlMs) {
|
|
12333
|
+
const checkedAt = new Date(cache.checkedAt).getTime();
|
|
12334
|
+
if (Number.isNaN(checkedAt)) {
|
|
12335
|
+
return false;
|
|
12336
|
+
}
|
|
12337
|
+
return now - checkedAt < cacheTtlMs;
|
|
12338
|
+
}
|
|
12339
|
+
function fetchLatestVersionFromNpm(packageName = DEFAULT_PACKAGE_NAME) {
|
|
12340
|
+
try {
|
|
12341
|
+
const output = execSync2(`npm view ${packageName} version --json`, {
|
|
12342
|
+
encoding: "utf-8",
|
|
12343
|
+
stdio: "pipe",
|
|
12344
|
+
timeout: 3000
|
|
12345
|
+
}).trim();
|
|
12346
|
+
if (!output) {
|
|
12347
|
+
return null;
|
|
12348
|
+
}
|
|
12349
|
+
let version;
|
|
12350
|
+
if (output.startsWith('"')) {
|
|
12351
|
+
version = JSON.parse(output);
|
|
12352
|
+
} else {
|
|
12353
|
+
version = output;
|
|
12354
|
+
}
|
|
12355
|
+
const normalized = normalizeVersion(version);
|
|
12356
|
+
return normalized || null;
|
|
12357
|
+
} catch {
|
|
12358
|
+
return null;
|
|
12359
|
+
}
|
|
12360
|
+
}
|
|
12361
|
+
function printContinuationSpacing() {
|
|
12362
|
+
console.log("");
|
|
12363
|
+
}
|
|
12364
|
+
function printContinueCurrentVersion() {
|
|
12365
|
+
console.warn(i18n.t("cli.selfUpdate.continueAfterFailure"));
|
|
12366
|
+
printContinuationSpacing();
|
|
12367
|
+
}
|
|
12368
|
+
function runNpxRelaunch(packageName, latestVersion, argv, env) {
|
|
12369
|
+
console.log(i18n.t("cli.selfUpdate.updatingNpx", { version: latestVersion }));
|
|
12370
|
+
const forwardedArgs = argv.slice(2);
|
|
12371
|
+
const child = spawnSync("npx", ["-y", `${packageName}@${latestVersion}`, ...forwardedArgs], {
|
|
12372
|
+
stdio: "inherit",
|
|
12373
|
+
env: {
|
|
12374
|
+
...env,
|
|
12375
|
+
OMCUSTOM_SKIP_SELF_UPDATE: "true"
|
|
12376
|
+
}
|
|
12377
|
+
});
|
|
12378
|
+
if ((child.status ?? 1) === 0) {
|
|
12379
|
+
process.exit(0);
|
|
12380
|
+
}
|
|
12381
|
+
const status = child.status ?? -1;
|
|
12382
|
+
console.warn(i18n.t("cli.selfUpdate.relaunchFailed", { status }));
|
|
12383
|
+
printContinueCurrentVersion();
|
|
12384
|
+
}
|
|
12385
|
+
function runGlobalUpdate(packageName, latestVersion) {
|
|
12386
|
+
try {
|
|
12387
|
+
console.log(i18n.t("cli.selfUpdate.updatingGlobal", { version: latestVersion }));
|
|
12388
|
+
execSync2(`npm install -g ${packageName}@${latestVersion}`, {
|
|
12389
|
+
stdio: "inherit",
|
|
12390
|
+
timeout: 60000
|
|
12391
|
+
});
|
|
12392
|
+
console.log(i18n.t("cli.selfUpdate.updated", { version: latestVersion }));
|
|
12393
|
+
printContinuationSpacing();
|
|
12394
|
+
} catch (error) {
|
|
12395
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
12396
|
+
console.warn(i18n.t("cli.selfUpdate.failed", { error: errorMessage }));
|
|
12397
|
+
printContinueCurrentVersion();
|
|
12398
|
+
}
|
|
12399
|
+
}
|
|
12400
|
+
function checkSelfUpdate(options) {
|
|
12401
|
+
const packageName = options.packageName || DEFAULT_PACKAGE_NAME;
|
|
12402
|
+
const cachePath = options.cachePath || DEFAULT_CACHE_PATH;
|
|
12403
|
+
const cacheTtlMs = options.cacheTtlMs ?? DEFAULT_CACHE_TTL_MS;
|
|
12404
|
+
const fetchLatestVersion = options.fetchLatestVersion || fetchLatestVersionFromNpm;
|
|
12405
|
+
const now = options.now ?? Date.now();
|
|
12406
|
+
const currentVersion = normalizeVersion(options.currentVersion);
|
|
12407
|
+
if (!currentVersion) {
|
|
12408
|
+
return {
|
|
12409
|
+
checked: false,
|
|
12410
|
+
updateAvailable: false,
|
|
12411
|
+
latestVersion: null,
|
|
12412
|
+
usedCache: false,
|
|
12413
|
+
reason: "invalid-current-version"
|
|
12414
|
+
};
|
|
12415
|
+
}
|
|
12416
|
+
let latestVersion = null;
|
|
12417
|
+
let usedCache = false;
|
|
12418
|
+
const cache = readCache(cachePath);
|
|
12419
|
+
if (cache && isCacheFresh(cache, now, cacheTtlMs)) {
|
|
12420
|
+
latestVersion = normalizeVersion(cache.latestVersion);
|
|
12421
|
+
usedCache = true;
|
|
12422
|
+
}
|
|
12423
|
+
if (!latestVersion) {
|
|
12424
|
+
latestVersion = fetchLatestVersion(packageName);
|
|
12425
|
+
if (latestVersion) {
|
|
12426
|
+
writeCache(cachePath, latestVersion, now);
|
|
12427
|
+
}
|
|
12428
|
+
}
|
|
12429
|
+
if (!latestVersion) {
|
|
12430
|
+
return {
|
|
12431
|
+
checked: false,
|
|
12432
|
+
updateAvailable: false,
|
|
12433
|
+
latestVersion: null,
|
|
12434
|
+
usedCache,
|
|
12435
|
+
reason: "lookup-failed"
|
|
12436
|
+
};
|
|
12437
|
+
}
|
|
12438
|
+
return {
|
|
12439
|
+
checked: true,
|
|
12440
|
+
updateAvailable: compareSemver(currentVersion, latestVersion) < 0,
|
|
12441
|
+
latestVersion,
|
|
12442
|
+
usedCache
|
|
12443
|
+
};
|
|
12444
|
+
}
|
|
12445
|
+
async function promptForSelfUpdate() {
|
|
12446
|
+
const rl = createInterface({
|
|
12447
|
+
input: process.stdin,
|
|
12448
|
+
output: process.stdout
|
|
12449
|
+
});
|
|
12450
|
+
try {
|
|
12451
|
+
const answer = await rl.question(i18n.t("cli.selfUpdate.prompt"));
|
|
12452
|
+
const normalized = answer.trim().toLowerCase();
|
|
12453
|
+
return normalized === "" || normalized === "y" || normalized === "yes";
|
|
12454
|
+
} finally {
|
|
12455
|
+
rl.close();
|
|
12456
|
+
}
|
|
12457
|
+
}
|
|
12458
|
+
function shouldSkipSelfUpdate(options) {
|
|
12459
|
+
const env = options.env || process.env;
|
|
12460
|
+
const argv = options.argv || process.argv;
|
|
12461
|
+
if (options.skip) {
|
|
12462
|
+
return true;
|
|
12463
|
+
}
|
|
12464
|
+
if (argv.includes("--skip-version-check")) {
|
|
12465
|
+
return true;
|
|
12466
|
+
}
|
|
12467
|
+
if (env.OMCUSTOM_SKIP_SELF_UPDATE === "true") {
|
|
12468
|
+
return true;
|
|
12469
|
+
}
|
|
12470
|
+
if (env.CI === "true" || env.GITHUB_ACTIONS === "true") {
|
|
12471
|
+
return true;
|
|
12472
|
+
}
|
|
12473
|
+
if (!isInteractiveSession()) {
|
|
12474
|
+
return true;
|
|
12475
|
+
}
|
|
12476
|
+
return false;
|
|
12477
|
+
}
|
|
12478
|
+
async function maybeHandleSelfUpdateForInit(options) {
|
|
12479
|
+
if (shouldSkipSelfUpdate(options)) {
|
|
12480
|
+
return;
|
|
12481
|
+
}
|
|
12482
|
+
const packageName = options.packageName || DEFAULT_PACKAGE_NAME;
|
|
12483
|
+
const currentVersion = normalizeVersion(options.currentVersion);
|
|
12484
|
+
const argv = options.argv || process.argv;
|
|
12485
|
+
const env = options.env || process.env;
|
|
12486
|
+
if (!currentVersion) {
|
|
12487
|
+
return;
|
|
12488
|
+
}
|
|
12489
|
+
console.log(i18n.t("cli.selfUpdate.checking"));
|
|
12490
|
+
const result = checkSelfUpdate(options);
|
|
12491
|
+
if (!result.checked || !result.updateAvailable || !result.latestVersion) {
|
|
12492
|
+
return;
|
|
12493
|
+
}
|
|
12494
|
+
const latestVersion = result.latestVersion;
|
|
12495
|
+
console.log(i18n.t("cli.selfUpdate.available", { current: currentVersion, latest: latestVersion }));
|
|
12496
|
+
const wantsUpdate = await promptForSelfUpdate();
|
|
12497
|
+
if (!wantsUpdate) {
|
|
12498
|
+
console.log(i18n.t("cli.selfUpdate.declined"));
|
|
12499
|
+
printContinuationSpacing();
|
|
12500
|
+
return;
|
|
12501
|
+
}
|
|
12502
|
+
if (isNpxInvocation(argv, env)) {
|
|
12503
|
+
runNpxRelaunch(packageName, latestVersion, argv, env);
|
|
12504
|
+
return;
|
|
12505
|
+
}
|
|
12506
|
+
runGlobalUpdate(packageName, latestVersion);
|
|
12507
|
+
}
|
|
12508
|
+
|
|
12250
12509
|
// src/cli/doctor.ts
|
|
12251
12510
|
import { constants, promises as fs } from "node:fs";
|
|
12252
12511
|
import path from "node:path";
|
|
@@ -12298,10 +12557,10 @@ var $visit = visit.visit;
|
|
|
12298
12557
|
var $visitAsync = visit.visitAsync;
|
|
12299
12558
|
|
|
12300
12559
|
// src/core/config.ts
|
|
12301
|
-
import { join as
|
|
12560
|
+
import { join as join3 } from "node:path";
|
|
12302
12561
|
|
|
12303
12562
|
// src/utils/fs.ts
|
|
12304
|
-
import { dirname, isAbsolute, join, normalize, relative, resolve, sep } from "node:path";
|
|
12563
|
+
import { dirname as dirname2, isAbsolute, join as join2, normalize, relative, resolve, sep } from "node:path";
|
|
12305
12564
|
import { fileURLToPath } from "node:url";
|
|
12306
12565
|
function validatePreserveFilePath(filePath, projectRoot) {
|
|
12307
12566
|
if (!filePath || filePath.trim() === "") {
|
|
@@ -12454,17 +12713,17 @@ async function readTextFile(path) {
|
|
|
12454
12713
|
}
|
|
12455
12714
|
async function writeTextFile(path, content) {
|
|
12456
12715
|
const fs = await import("node:fs/promises");
|
|
12457
|
-
await ensureDirectory(
|
|
12716
|
+
await ensureDirectory(dirname2(path));
|
|
12458
12717
|
await fs.writeFile(path, content, "utf-8");
|
|
12459
12718
|
}
|
|
12460
12719
|
function getPackageRoot() {
|
|
12461
12720
|
const currentFile = fileURLToPath(import.meta.url);
|
|
12462
|
-
const currentDir =
|
|
12721
|
+
const currentDir = dirname2(currentFile);
|
|
12463
12722
|
return resolve(currentDir, "..", "..");
|
|
12464
12723
|
}
|
|
12465
12724
|
function resolveTemplatePath(relativePath) {
|
|
12466
12725
|
const packageRoot = getPackageRoot();
|
|
12467
|
-
return
|
|
12726
|
+
return join2(packageRoot, "templates", relativePath);
|
|
12468
12727
|
}
|
|
12469
12728
|
async function listFiles(dir2, options = {}) {
|
|
12470
12729
|
const fs = await import("node:fs/promises");
|
|
@@ -12689,7 +12948,6 @@ function getDefaultConfig() {
|
|
|
12689
12948
|
configVersion: CURRENT_CONFIG_VERSION,
|
|
12690
12949
|
version: "0.0.0",
|
|
12691
12950
|
language: "en",
|
|
12692
|
-
provider: "auto",
|
|
12693
12951
|
installedAt: "",
|
|
12694
12952
|
lastUpdated: "",
|
|
12695
12953
|
installedComponents: [],
|
|
@@ -12716,7 +12974,7 @@ function getDefaultPreferences() {
|
|
|
12716
12974
|
};
|
|
12717
12975
|
}
|
|
12718
12976
|
function getConfigPath(targetDir) {
|
|
12719
|
-
return
|
|
12977
|
+
return join3(targetDir, CONFIG_FILE);
|
|
12720
12978
|
}
|
|
12721
12979
|
async function loadConfig(targetDir) {
|
|
12722
12980
|
const configPath = getConfigPath(targetDir);
|
|
@@ -12812,203 +13070,36 @@ function migrateConfig(config) {
|
|
|
12812
13070
|
}
|
|
12813
13071
|
|
|
12814
13072
|
// src/core/layout.ts
|
|
12815
|
-
var
|
|
12816
|
-
|
|
12817
|
-
|
|
12818
|
-
|
|
12819
|
-
|
|
12820
|
-
|
|
12821
|
-
|
|
12822
|
-
|
|
12823
|
-
|
|
12824
|
-
|
|
12825
|
-
|
|
12826
|
-
|
|
12827
|
-
|
|
12828
|
-
|
|
12829
|
-
|
|
12830
|
-
"guides"
|
|
12831
|
-
]
|
|
12832
|
-
},
|
|
12833
|
-
codex: {
|
|
12834
|
-
provider: "codex",
|
|
12835
|
-
rootDir: ".codex",
|
|
12836
|
-
entryFile: "AGENTS.md",
|
|
12837
|
-
entryTemplatePrefix: "AGENTS.md",
|
|
12838
|
-
manifestFile: "manifest.codex.json",
|
|
12839
|
-
backupDirPrefix: ".codex-backup-",
|
|
12840
|
-
directoryStructure: [
|
|
12841
|
-
".codex",
|
|
12842
|
-
".codex/rules",
|
|
12843
|
-
".codex/hooks",
|
|
12844
|
-
".codex/contexts",
|
|
12845
|
-
".codex/agents",
|
|
12846
|
-
".codex/skills",
|
|
12847
|
-
"guides"
|
|
12848
|
-
]
|
|
12849
|
-
}
|
|
13073
|
+
var CLAUDE_LAYOUT = {
|
|
13074
|
+
rootDir: ".claude",
|
|
13075
|
+
entryFile: "CLAUDE.md",
|
|
13076
|
+
entryTemplatePrefix: "CLAUDE.md",
|
|
13077
|
+
manifestFile: "manifest.json",
|
|
13078
|
+
backupDirPrefix: ".claude-backup-",
|
|
13079
|
+
directoryStructure: [
|
|
13080
|
+
".claude",
|
|
13081
|
+
".claude/rules",
|
|
13082
|
+
".claude/hooks",
|
|
13083
|
+
".claude/contexts",
|
|
13084
|
+
".claude/agents",
|
|
13085
|
+
".claude/skills",
|
|
13086
|
+
"guides"
|
|
13087
|
+
]
|
|
12850
13088
|
};
|
|
12851
|
-
function getProviderLayout(
|
|
12852
|
-
return
|
|
13089
|
+
function getProviderLayout() {
|
|
13090
|
+
return CLAUDE_LAYOUT;
|
|
12853
13091
|
}
|
|
12854
|
-
function getEntryTemplateName(
|
|
12855
|
-
|
|
12856
|
-
return `${layout.entryTemplatePrefix}.${language}`;
|
|
13092
|
+
function getEntryTemplateName(language) {
|
|
13093
|
+
return `CLAUDE.md.${language}`;
|
|
12857
13094
|
}
|
|
12858
|
-
function getComponentPath(
|
|
12859
|
-
const layout = getProviderLayout(provider);
|
|
13095
|
+
function getComponentPath(component) {
|
|
12860
13096
|
if (component === "entry-md") {
|
|
12861
|
-
return
|
|
13097
|
+
return "CLAUDE.md";
|
|
12862
13098
|
}
|
|
12863
13099
|
if (component === "guides") {
|
|
12864
13100
|
return "guides";
|
|
12865
13101
|
}
|
|
12866
|
-
return
|
|
12867
|
-
}
|
|
12868
|
-
function getDefaultProvider() {
|
|
12869
|
-
return "claude";
|
|
12870
|
-
}
|
|
12871
|
-
|
|
12872
|
-
// src/core/provider.ts
|
|
12873
|
-
import { join as join3 } from "node:path";
|
|
12874
|
-
var ENV_SIGNALS = {
|
|
12875
|
-
claude: [
|
|
12876
|
-
"ANTHROPIC_API_KEY",
|
|
12877
|
-
"CLAUDE_CODE",
|
|
12878
|
-
"CLAUDE_CODE_EFFORT_LEVEL",
|
|
12879
|
-
"CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS",
|
|
12880
|
-
"CLAUDE_CODE_ENABLE_TELEMETRY"
|
|
12881
|
-
],
|
|
12882
|
-
codex: ["OPENAI_API_KEY", "OPENAI_ORG_ID", "OPENAI_PROJECT", "CODEX_HOME", "CODEX_PROJECT"]
|
|
12883
|
-
};
|
|
12884
|
-
var PROVIDER_ENV_OVERRIDES = ["OMCUSTOM_PROVIDER", "LLM_SERVICE"];
|
|
12885
|
-
function normalizeProvider(value) {
|
|
12886
|
-
if (!value)
|
|
12887
|
-
return null;
|
|
12888
|
-
const normalized = value.toLowerCase().trim();
|
|
12889
|
-
if (normalized === "claude" || normalized === "codex" || normalized === "auto") {
|
|
12890
|
-
return normalized;
|
|
12891
|
-
}
|
|
12892
|
-
return null;
|
|
12893
|
-
}
|
|
12894
|
-
function detectFromEnv(env) {
|
|
12895
|
-
for (const key of PROVIDER_ENV_OVERRIDES) {
|
|
12896
|
-
const override = normalizeProvider(env[key]);
|
|
12897
|
-
if (override && override !== "auto") {
|
|
12898
|
-
return {
|
|
12899
|
-
provider: override,
|
|
12900
|
-
source: "override",
|
|
12901
|
-
confidence: "high",
|
|
12902
|
-
reason: `env:${key}`
|
|
12903
|
-
};
|
|
12904
|
-
}
|
|
12905
|
-
}
|
|
12906
|
-
const claudeSignals = ENV_SIGNALS.claude.filter((key) => Boolean(env[key]));
|
|
12907
|
-
const codexSignals = ENV_SIGNALS.codex.filter((key) => Boolean(env[key]));
|
|
12908
|
-
const hasClaude = claudeSignals.length > 0;
|
|
12909
|
-
const hasCodex = codexSignals.length > 0;
|
|
12910
|
-
if (hasClaude && !hasCodex) {
|
|
12911
|
-
return {
|
|
12912
|
-
provider: "claude",
|
|
12913
|
-
source: "env",
|
|
12914
|
-
confidence: "medium",
|
|
12915
|
-
reason: `env:${claudeSignals[0]}`
|
|
12916
|
-
};
|
|
12917
|
-
}
|
|
12918
|
-
if (hasCodex && !hasClaude) {
|
|
12919
|
-
return {
|
|
12920
|
-
provider: "codex",
|
|
12921
|
-
source: "env",
|
|
12922
|
-
confidence: "medium",
|
|
12923
|
-
reason: `env:${codexSignals[0]}`
|
|
12924
|
-
};
|
|
12925
|
-
}
|
|
12926
|
-
return null;
|
|
12927
|
-
}
|
|
12928
|
-
async function detectFromProject(targetDir) {
|
|
12929
|
-
const claudeMarkers = [join3(targetDir, "CLAUDE.md"), join3(targetDir, ".claude")];
|
|
12930
|
-
const codexMarkers = [join3(targetDir, "AGENTS.md"), join3(targetDir, ".codex")];
|
|
12931
|
-
const claudeFound = await Promise.all(claudeMarkers.map((path) => fileExists(path)));
|
|
12932
|
-
const codexFound = await Promise.all(codexMarkers.map((path) => fileExists(path)));
|
|
12933
|
-
const hasClaude = claudeFound.some(Boolean);
|
|
12934
|
-
const hasCodex = codexFound.some(Boolean);
|
|
12935
|
-
if (hasClaude && !hasCodex) {
|
|
12936
|
-
return {
|
|
12937
|
-
provider: "claude",
|
|
12938
|
-
source: "project",
|
|
12939
|
-
confidence: "medium",
|
|
12940
|
-
reason: "project:claude"
|
|
12941
|
-
};
|
|
12942
|
-
}
|
|
12943
|
-
if (hasCodex && !hasClaude) {
|
|
12944
|
-
return {
|
|
12945
|
-
provider: "codex",
|
|
12946
|
-
source: "project",
|
|
12947
|
-
confidence: "medium",
|
|
12948
|
-
reason: "project:codex"
|
|
12949
|
-
};
|
|
12950
|
-
}
|
|
12951
|
-
return null;
|
|
12952
|
-
}
|
|
12953
|
-
async function detectFromConfig(targetDir) {
|
|
12954
|
-
const configPath = join3(targetDir, ".omcustomrc.json");
|
|
12955
|
-
if (!await fileExists(configPath)) {
|
|
12956
|
-
return null;
|
|
12957
|
-
}
|
|
12958
|
-
try {
|
|
12959
|
-
const config = await readJsonFile(configPath);
|
|
12960
|
-
const provider = normalizeProvider(config.provider);
|
|
12961
|
-
if (provider && provider !== "auto") {
|
|
12962
|
-
return {
|
|
12963
|
-
provider,
|
|
12964
|
-
source: "config",
|
|
12965
|
-
confidence: "high",
|
|
12966
|
-
reason: "config:provider"
|
|
12967
|
-
};
|
|
12968
|
-
}
|
|
12969
|
-
} catch {}
|
|
12970
|
-
return null;
|
|
12971
|
-
}
|
|
12972
|
-
async function detectProvider(options = {}) {
|
|
12973
|
-
const env = options.env ?? process.env;
|
|
12974
|
-
const override = options.override;
|
|
12975
|
-
const normalizedOverride = normalizeProvider(override);
|
|
12976
|
-
if (normalizedOverride && normalizedOverride !== "auto") {
|
|
12977
|
-
return {
|
|
12978
|
-
provider: normalizedOverride,
|
|
12979
|
-
source: "override",
|
|
12980
|
-
confidence: "high",
|
|
12981
|
-
reason: "override:option"
|
|
12982
|
-
};
|
|
12983
|
-
}
|
|
12984
|
-
if (options.targetDir) {
|
|
12985
|
-
const fromConfig = await detectFromConfig(options.targetDir);
|
|
12986
|
-
if (fromConfig) {
|
|
12987
|
-
return fromConfig;
|
|
12988
|
-
}
|
|
12989
|
-
}
|
|
12990
|
-
if (options.targetDir && options.preferProject) {
|
|
12991
|
-
const fromProject = await detectFromProject(options.targetDir);
|
|
12992
|
-
if (fromProject) {
|
|
12993
|
-
return fromProject;
|
|
12994
|
-
}
|
|
12995
|
-
}
|
|
12996
|
-
const fromEnv = detectFromEnv(env);
|
|
12997
|
-
if (fromEnv) {
|
|
12998
|
-
return fromEnv;
|
|
12999
|
-
}
|
|
13000
|
-
if (options.targetDir && !options.preferProject) {
|
|
13001
|
-
const fromProject = await detectFromProject(options.targetDir);
|
|
13002
|
-
if (fromProject) {
|
|
13003
|
-
return fromProject;
|
|
13004
|
-
}
|
|
13005
|
-
}
|
|
13006
|
-
return {
|
|
13007
|
-
provider: getDefaultProvider(),
|
|
13008
|
-
source: "default",
|
|
13009
|
-
confidence: "low",
|
|
13010
|
-
reason: "default"
|
|
13011
|
-
};
|
|
13102
|
+
return `.claude/${component}`;
|
|
13012
13103
|
}
|
|
13013
13104
|
|
|
13014
13105
|
// src/cli/doctor.ts
|
|
@@ -13452,12 +13543,7 @@ async function doctorCommand(options = {}) {
|
|
|
13452
13543
|
const targetDir = process.cwd();
|
|
13453
13544
|
console.log(i18n.t("cli.doctor.checking"));
|
|
13454
13545
|
console.log("");
|
|
13455
|
-
const
|
|
13456
|
-
targetDir,
|
|
13457
|
-
override: options.provider,
|
|
13458
|
-
preferProject: true
|
|
13459
|
-
});
|
|
13460
|
-
const layout = getProviderLayout(detection.provider);
|
|
13546
|
+
const layout = getProviderLayout();
|
|
13461
13547
|
let checks = await Promise.all([
|
|
13462
13548
|
checkEntryDoc(targetDir, layout.entryFile),
|
|
13463
13549
|
checkRules(targetDir, layout.rootDir),
|
|
@@ -13795,21 +13881,21 @@ async function ensureTargetDirectory(targetDir) {
|
|
|
13795
13881
|
await ensureDirectory(targetDir);
|
|
13796
13882
|
}
|
|
13797
13883
|
}
|
|
13798
|
-
async function handleBackup(targetDir,
|
|
13884
|
+
async function handleBackup(targetDir, shouldBackup, result) {
|
|
13799
13885
|
if (!shouldBackup)
|
|
13800
13886
|
return;
|
|
13801
|
-
const backupPaths = await backupExistingInstallation(targetDir
|
|
13887
|
+
const backupPaths = await backupExistingInstallation(targetDir);
|
|
13802
13888
|
result.backedUpPaths.push(...backupPaths);
|
|
13803
13889
|
if (backupPaths.length > 0) {
|
|
13804
13890
|
info("install.backup", { path: backupPaths[0] });
|
|
13805
13891
|
}
|
|
13806
13892
|
}
|
|
13807
|
-
async function checkAndWarnExisting(targetDir,
|
|
13893
|
+
async function checkAndWarnExisting(targetDir, force, backup, result) {
|
|
13808
13894
|
if (force || backup)
|
|
13809
13895
|
return;
|
|
13810
|
-
const existingPaths = await checkExistingPaths(targetDir
|
|
13896
|
+
const existingPaths = await checkExistingPaths(targetDir);
|
|
13811
13897
|
if (existingPaths.length > 0) {
|
|
13812
|
-
const layout = getProviderLayout(
|
|
13898
|
+
const layout = getProviderLayout();
|
|
13813
13899
|
warn("install.exists", { rootDir: layout.rootDir });
|
|
13814
13900
|
result.warnings.push(`Existing files found: ${existingPaths.join(", ")}. Use --force to overwrite or --backup to backup first.`);
|
|
13815
13901
|
}
|
|
@@ -13820,15 +13906,15 @@ async function verifyTemplateDirectory() {
|
|
|
13820
13906
|
throw new Error(`Template directory not found: ${templateDir}`);
|
|
13821
13907
|
}
|
|
13822
13908
|
}
|
|
13823
|
-
async function installAllComponents(targetDir,
|
|
13909
|
+
async function installAllComponents(targetDir, options, result) {
|
|
13824
13910
|
const components = options.components || getAllComponents();
|
|
13825
13911
|
for (const component of components) {
|
|
13826
|
-
await installSingleComponent(targetDir,
|
|
13912
|
+
await installSingleComponent(targetDir, component, options, result);
|
|
13827
13913
|
}
|
|
13828
13914
|
}
|
|
13829
|
-
async function installSingleComponent(targetDir,
|
|
13915
|
+
async function installSingleComponent(targetDir, component, options, result) {
|
|
13830
13916
|
try {
|
|
13831
|
-
const installed = await installComponent(targetDir,
|
|
13917
|
+
const installed = await installComponent(targetDir, component, options);
|
|
13832
13918
|
if (installed) {
|
|
13833
13919
|
result.installedComponents.push(component);
|
|
13834
13920
|
} else {
|
|
@@ -13839,36 +13925,34 @@ async function installSingleComponent(targetDir, provider, component, options, r
|
|
|
13839
13925
|
result.warnings.push(`Failed to install ${component}: ${message}`);
|
|
13840
13926
|
}
|
|
13841
13927
|
}
|
|
13842
|
-
async function installEntryDocWithTracking(targetDir,
|
|
13928
|
+
async function installEntryDocWithTracking(targetDir, options, result) {
|
|
13843
13929
|
const language = options.language ?? DEFAULT_LANGUAGE2;
|
|
13844
13930
|
const overwrite = !!(options.force || options.backup);
|
|
13845
|
-
const installed = await installEntryDoc(targetDir,
|
|
13931
|
+
const installed = await installEntryDoc(targetDir, language, overwrite);
|
|
13846
13932
|
if (installed) {
|
|
13847
13933
|
result.installedComponents.push("entry-md");
|
|
13848
13934
|
} else {
|
|
13849
13935
|
result.skippedComponents.push("entry-md");
|
|
13850
13936
|
}
|
|
13851
13937
|
}
|
|
13852
|
-
async function updateInstallConfig(targetDir,
|
|
13938
|
+
async function updateInstallConfig(targetDir, options, installedComponents) {
|
|
13853
13939
|
const config = await loadConfig(targetDir);
|
|
13854
13940
|
config.language = options.language ?? DEFAULT_LANGUAGE2;
|
|
13855
|
-
config.provider = provider;
|
|
13856
13941
|
config.installedAt = new Date().toISOString();
|
|
13857
13942
|
config.installedComponents = installedComponents;
|
|
13858
13943
|
await saveConfig(targetDir, config);
|
|
13859
13944
|
}
|
|
13860
13945
|
async function install(options) {
|
|
13861
13946
|
const result = createInstallResult(options.targetDir);
|
|
13862
|
-
const provider = options.provider ?? "claude";
|
|
13863
13947
|
try {
|
|
13864
13948
|
info("install.start", { targetDir: options.targetDir });
|
|
13865
13949
|
await ensureTargetDirectory(options.targetDir);
|
|
13866
|
-
await handleBackup(options.targetDir,
|
|
13867
|
-
await checkAndWarnExisting(options.targetDir,
|
|
13950
|
+
await handleBackup(options.targetDir, !!options.backup, result);
|
|
13951
|
+
await checkAndWarnExisting(options.targetDir, !!options.force, !!options.backup, result);
|
|
13868
13952
|
await verifyTemplateDirectory();
|
|
13869
|
-
await installAllComponents(options.targetDir,
|
|
13870
|
-
await installEntryDocWithTracking(options.targetDir,
|
|
13871
|
-
await updateInstallConfig(options.targetDir,
|
|
13953
|
+
await installAllComponents(options.targetDir, options, result);
|
|
13954
|
+
await installEntryDocWithTracking(options.targetDir, options, result);
|
|
13955
|
+
await updateInstallConfig(options.targetDir, options, result.installedComponents);
|
|
13872
13956
|
result.success = true;
|
|
13873
13957
|
success("install.success");
|
|
13874
13958
|
} catch (err) {
|
|
@@ -13881,11 +13965,11 @@ async function install(options) {
|
|
|
13881
13965
|
function getAllComponents() {
|
|
13882
13966
|
return ["rules", "agents", "skills", "guides", "hooks", "contexts"];
|
|
13883
13967
|
}
|
|
13884
|
-
async function installComponent(targetDir,
|
|
13968
|
+
async function installComponent(targetDir, component, options) {
|
|
13885
13969
|
if (component === "entry-md") {
|
|
13886
13970
|
return false;
|
|
13887
13971
|
}
|
|
13888
|
-
const templatePath = getComponentPath(
|
|
13972
|
+
const templatePath = getComponentPath(component);
|
|
13889
13973
|
if (!templatePath) {
|
|
13890
13974
|
return false;
|
|
13891
13975
|
}
|
|
@@ -13913,9 +13997,9 @@ function renderGitWorkflowSection(targetDir, language) {
|
|
|
13913
13997
|
const result = detectGitWorkflow(targetDir) ?? getDefaultWorkflow();
|
|
13914
13998
|
return language === "ko" ? renderGitWorkflowKO(result) : renderGitWorkflowEN(result);
|
|
13915
13999
|
}
|
|
13916
|
-
async function installEntryDoc(targetDir,
|
|
13917
|
-
const layout = getProviderLayout(
|
|
13918
|
-
const templateFile = getEntryTemplateName(
|
|
14000
|
+
async function installEntryDoc(targetDir, language, overwrite = false) {
|
|
14001
|
+
const layout = getProviderLayout();
|
|
14002
|
+
const templateFile = getEntryTemplateName(language);
|
|
13919
14003
|
const srcPath = resolveTemplatePath(templateFile);
|
|
13920
14004
|
const destPath = join4(targetDir, layout.entryFile);
|
|
13921
14005
|
if (!await fileExists(srcPath)) {
|
|
@@ -13942,8 +14026,8 @@ async function backupExisting(sourcePath, backupDir) {
|
|
|
13942
14026
|
await rename(sourcePath, backupPath);
|
|
13943
14027
|
return backupPath;
|
|
13944
14028
|
}
|
|
13945
|
-
async function checkExistingPaths(targetDir
|
|
13946
|
-
const layout = getProviderLayout(
|
|
14029
|
+
async function checkExistingPaths(targetDir) {
|
|
14030
|
+
const layout = getProviderLayout();
|
|
13947
14031
|
const pathsToCheck = [layout.entryFile, layout.rootDir, "guides"];
|
|
13948
14032
|
const existingPaths = [];
|
|
13949
14033
|
for (const relativePath of pathsToCheck) {
|
|
@@ -13954,9 +14038,9 @@ async function checkExistingPaths(targetDir, provider) {
|
|
|
13954
14038
|
}
|
|
13955
14039
|
return existingPaths;
|
|
13956
14040
|
}
|
|
13957
|
-
async function backupExistingInstallation(targetDir
|
|
13958
|
-
const layout = getProviderLayout(
|
|
13959
|
-
const existingPaths = await checkExistingPaths(targetDir
|
|
14041
|
+
async function backupExistingInstallation(targetDir) {
|
|
14042
|
+
const layout = getProviderLayout();
|
|
14043
|
+
const existingPaths = await checkExistingPaths(targetDir);
|
|
13960
14044
|
if (existingPaths.length === 0) {
|
|
13961
14045
|
return [];
|
|
13962
14046
|
}
|
|
@@ -13979,11 +14063,11 @@ async function backupExistingInstallation(targetDir, provider) {
|
|
|
13979
14063
|
}
|
|
13980
14064
|
|
|
13981
14065
|
// src/core/mcp-config.ts
|
|
13982
|
-
import { execSync as
|
|
14066
|
+
import { execSync as execSync3 } from "node:child_process";
|
|
13983
14067
|
import { writeFile } from "node:fs/promises";
|
|
13984
14068
|
import { join as join5 } from "node:path";
|
|
13985
|
-
async function generateMCPConfig(targetDir
|
|
13986
|
-
const layout = getProviderLayout(
|
|
14069
|
+
async function generateMCPConfig(targetDir) {
|
|
14070
|
+
const layout = getProviderLayout();
|
|
13987
14071
|
const mcpConfigPath = join5(targetDir, ".mcp.json");
|
|
13988
14072
|
const ontologyDir = join5(layout.rootDir, "ontology");
|
|
13989
14073
|
const ontologyExists = await fileExists(join5(targetDir, ontologyDir));
|
|
@@ -14025,7 +14109,7 @@ async function generateMCPConfig(targetDir, provider) {
|
|
|
14025
14109
|
}
|
|
14026
14110
|
async function checkPythonAvailable() {
|
|
14027
14111
|
try {
|
|
14028
|
-
|
|
14112
|
+
execSync3("python --version", { stdio: "pipe" });
|
|
14029
14113
|
return true;
|
|
14030
14114
|
} catch {
|
|
14031
14115
|
return false;
|
|
@@ -14033,25 +14117,25 @@ async function checkPythonAvailable() {
|
|
|
14033
14117
|
}
|
|
14034
14118
|
|
|
14035
14119
|
// src/cli/init.ts
|
|
14036
|
-
async function checkExistingInstallation(targetDir
|
|
14037
|
-
const layout = getProviderLayout(
|
|
14120
|
+
async function checkExistingInstallation(targetDir) {
|
|
14121
|
+
const layout = getProviderLayout();
|
|
14038
14122
|
const rootDir = join6(targetDir, layout.rootDir);
|
|
14039
14123
|
return fileExists(rootDir);
|
|
14040
14124
|
}
|
|
14041
14125
|
var PROVIDER_SUBDIR_COMPONENTS = new Set(["rules", "hooks", "contexts", "agents", "skills"]);
|
|
14042
|
-
function componentToPath(targetDir,
|
|
14126
|
+
function componentToPath(targetDir, component) {
|
|
14043
14127
|
if (component === "entry-md") {
|
|
14044
|
-
const layout = getProviderLayout(
|
|
14128
|
+
const layout = getProviderLayout();
|
|
14045
14129
|
return join6(targetDir, layout.entryFile);
|
|
14046
14130
|
}
|
|
14047
14131
|
if (PROVIDER_SUBDIR_COMPONENTS.has(component)) {
|
|
14048
|
-
const layout = getProviderLayout(
|
|
14132
|
+
const layout = getProviderLayout();
|
|
14049
14133
|
return join6(targetDir, layout.rootDir, component);
|
|
14050
14134
|
}
|
|
14051
14135
|
return join6(targetDir, component);
|
|
14052
14136
|
}
|
|
14053
|
-
function buildInstalledPaths(targetDir,
|
|
14054
|
-
return components.map((component) => componentToPath(targetDir,
|
|
14137
|
+
function buildInstalledPaths(targetDir, components) {
|
|
14138
|
+
return components.map((component) => componentToPath(targetDir, component));
|
|
14055
14139
|
}
|
|
14056
14140
|
function logItems(items, formatter) {
|
|
14057
14141
|
for (const item of items) {
|
|
@@ -14084,10 +14168,8 @@ async function initCommand(options) {
|
|
|
14084
14168
|
const targetDir = process.cwd();
|
|
14085
14169
|
console.log(i18n.t("cli.init.start"));
|
|
14086
14170
|
try {
|
|
14087
|
-
const
|
|
14088
|
-
const
|
|
14089
|
-
const layout = getProviderLayout(provider);
|
|
14090
|
-
const exists2 = await checkExistingInstallation(targetDir, provider);
|
|
14171
|
+
const layout = getProviderLayout();
|
|
14172
|
+
const exists2 = await checkExistingInstallation(targetDir);
|
|
14091
14173
|
if (exists2) {
|
|
14092
14174
|
console.log(i18n.t("cli.init.exists", { rootDir: layout.rootDir }));
|
|
14093
14175
|
console.log(i18n.t("cli.init.backing_up"));
|
|
@@ -14096,20 +14178,19 @@ async function initCommand(options) {
|
|
|
14096
14178
|
const installResult = await install({
|
|
14097
14179
|
targetDir,
|
|
14098
14180
|
language: options.lang,
|
|
14099
|
-
provider,
|
|
14100
14181
|
force: options.force ?? false,
|
|
14101
14182
|
backup: exists2
|
|
14102
14183
|
});
|
|
14103
14184
|
if (!installResult.success) {
|
|
14104
14185
|
return createFailureResult(installResult.error || "Unknown error");
|
|
14105
14186
|
}
|
|
14106
|
-
const installedPaths = buildInstalledPaths(targetDir,
|
|
14187
|
+
const installedPaths = buildInstalledPaths(targetDir, installResult.installedComponents);
|
|
14107
14188
|
logInstallResultInfo(installResult);
|
|
14108
14189
|
logSuccessDetails(installedPaths, installResult.skippedComponents);
|
|
14109
14190
|
const pythonAvailable = await checkPythonAvailable();
|
|
14110
14191
|
if (pythonAvailable) {
|
|
14111
14192
|
try {
|
|
14112
|
-
await generateMCPConfig(targetDir
|
|
14193
|
+
await generateMCPConfig(targetDir);
|
|
14113
14194
|
} catch {
|
|
14114
14195
|
console.warn("Warning: Failed to generate MCP config. You can configure it manually.");
|
|
14115
14196
|
}
|
|
@@ -14130,7 +14211,7 @@ async function initCommand(options) {
|
|
|
14130
14211
|
}
|
|
14131
14212
|
|
|
14132
14213
|
// src/cli/list.ts
|
|
14133
|
-
import { basename as basename2, dirname as
|
|
14214
|
+
import { basename as basename2, dirname as dirname3, join as join7, relative as relative2 } from "node:path";
|
|
14134
14215
|
var ALLOWED_TOP_LEVEL_KEYS = new Set(["name", "type", "description", "version", "category"]);
|
|
14135
14216
|
function parseKeyValue(line) {
|
|
14136
14217
|
const colonIndex = line.indexOf(":");
|
|
@@ -14330,7 +14411,7 @@ async function getSkills(targetDir, rootDir = ".claude", config) {
|
|
|
14330
14411
|
const customSkillPaths = new Set(customComponents.filter((c) => c.type === "skill").map((c) => c.path));
|
|
14331
14412
|
const skillMdFiles = await listFiles(skillsDir, { recursive: true, pattern: "SKILL.md" });
|
|
14332
14413
|
const skills = await Promise.all(skillMdFiles.map(async (skillMdPath) => {
|
|
14333
|
-
const skillDir =
|
|
14414
|
+
const skillDir = dirname3(skillMdPath);
|
|
14334
14415
|
const indexYamlPath = join7(skillDir, "index.yaml");
|
|
14335
14416
|
const { description, version } = await tryReadIndexYamlMetadata(indexYamlPath);
|
|
14336
14417
|
const relativePath = relative2(targetDir, skillDir);
|
|
@@ -14530,12 +14611,7 @@ async function listCommand(type = "all", options = {}) {
|
|
|
14530
14611
|
const format = options.format || "table";
|
|
14531
14612
|
console.log(i18n.t("cli.list.scanning"));
|
|
14532
14613
|
try {
|
|
14533
|
-
const
|
|
14534
|
-
targetDir,
|
|
14535
|
-
override: options.provider,
|
|
14536
|
-
preferProject: true
|
|
14537
|
-
});
|
|
14538
|
-
const layout = getProviderLayout(detection.provider);
|
|
14614
|
+
const layout = getProviderLayout();
|
|
14539
14615
|
const config = await loadConfig(targetDir);
|
|
14540
14616
|
const components = type === "all" ? await handleListAll(targetDir, layout.rootDir, format, config) : await COMPONENT_GETTERS[type](targetDir, layout.rootDir, config);
|
|
14541
14617
|
if (type === "all" && format === "json") {
|
|
@@ -14684,14 +14760,14 @@ function createUpdateResult() {
|
|
|
14684
14760
|
warnings: []
|
|
14685
14761
|
};
|
|
14686
14762
|
}
|
|
14687
|
-
async function handleBackupIfRequested(targetDir,
|
|
14763
|
+
async function handleBackupIfRequested(targetDir, backup, result) {
|
|
14688
14764
|
if (!backup)
|
|
14689
14765
|
return;
|
|
14690
|
-
const backupPath = await backupInstallation(targetDir
|
|
14766
|
+
const backupPath = await backupInstallation(targetDir);
|
|
14691
14767
|
result.backedUpPaths.push(backupPath);
|
|
14692
14768
|
info("update.backup_created", { path: backupPath });
|
|
14693
14769
|
}
|
|
14694
|
-
async function processComponentUpdate(targetDir,
|
|
14770
|
+
async function processComponentUpdate(targetDir, component, updateCheck, customizations, options, result, config) {
|
|
14695
14771
|
const componentUpdate = updateCheck.updatableComponents.find((c) => c.name === component);
|
|
14696
14772
|
if (!componentUpdate && !options.force) {
|
|
14697
14773
|
result.skippedComponents.push(component);
|
|
@@ -14703,7 +14779,7 @@ async function processComponentUpdate(targetDir, provider, component, updateChec
|
|
|
14703
14779
|
return;
|
|
14704
14780
|
}
|
|
14705
14781
|
try {
|
|
14706
|
-
const preserved = await updateComponent(targetDir,
|
|
14782
|
+
const preserved = await updateComponent(targetDir, component, customizations, options, config);
|
|
14707
14783
|
result.updatedComponents.push(component);
|
|
14708
14784
|
result.preservedFiles.push(...preserved);
|
|
14709
14785
|
} catch (err) {
|
|
@@ -14712,13 +14788,13 @@ async function processComponentUpdate(targetDir, provider, component, updateChec
|
|
|
14712
14788
|
result.skippedComponents.push(component);
|
|
14713
14789
|
}
|
|
14714
14790
|
}
|
|
14715
|
-
async function updateAllComponents(targetDir,
|
|
14791
|
+
async function updateAllComponents(targetDir, components, updateCheck, customizations, options, result, config) {
|
|
14716
14792
|
for (const component of components) {
|
|
14717
|
-
await processComponentUpdate(targetDir,
|
|
14793
|
+
await processComponentUpdate(targetDir, component, updateCheck, customizations, options, result, config);
|
|
14718
14794
|
}
|
|
14719
14795
|
}
|
|
14720
|
-
function getEntryTemplateName2(
|
|
14721
|
-
const layout = getProviderLayout(
|
|
14796
|
+
function getEntryTemplateName2(language) {
|
|
14797
|
+
const layout = getProviderLayout();
|
|
14722
14798
|
const baseName = layout.entryFile.replace(".md", "");
|
|
14723
14799
|
return language === "ko" ? `${baseName}.md.ko` : `${baseName}.md.en`;
|
|
14724
14800
|
}
|
|
@@ -14802,10 +14878,10 @@ function resolveCustomizations(customizations, configPreserveFiles, targetDir) {
|
|
|
14802
14878
|
}
|
|
14803
14879
|
return null;
|
|
14804
14880
|
}
|
|
14805
|
-
async function updateEntryDoc(targetDir,
|
|
14806
|
-
const layout = getProviderLayout(
|
|
14881
|
+
async function updateEntryDoc(targetDir, config, options) {
|
|
14882
|
+
const layout = getProviderLayout();
|
|
14807
14883
|
const entryPath = join8(targetDir, layout.entryFile);
|
|
14808
|
-
const templateName = getEntryTemplateName2(
|
|
14884
|
+
const templateName = getEntryTemplateName2(config.language);
|
|
14809
14885
|
const templatePath = resolveTemplatePath(templateName);
|
|
14810
14886
|
if (!await fileExists(templatePath)) {
|
|
14811
14887
|
warn("update.entry_template_not_found", { template: templateName });
|
|
@@ -14842,9 +14918,8 @@ async function update(options) {
|
|
|
14842
14918
|
try {
|
|
14843
14919
|
info("update.start", { targetDir: options.targetDir });
|
|
14844
14920
|
const config = await loadConfig(options.targetDir);
|
|
14845
|
-
const provider = options.provider ?? (config.provider === "codex" ? "codex" : "claude");
|
|
14846
14921
|
result.previousVersion = config.version;
|
|
14847
|
-
const updateCheck = await checkForUpdates(options.targetDir
|
|
14922
|
+
const updateCheck = await checkForUpdates(options.targetDir);
|
|
14848
14923
|
result.newVersion = updateCheck.latestVersion;
|
|
14849
14924
|
if (!updateCheck.hasUpdates && !options.force) {
|
|
14850
14925
|
info("update.no_updates");
|
|
@@ -14852,14 +14927,14 @@ async function update(options) {
|
|
|
14852
14927
|
result.skippedComponents = options.components || getAllUpdateComponents();
|
|
14853
14928
|
return result;
|
|
14854
14929
|
}
|
|
14855
|
-
await handleBackupIfRequested(options.targetDir,
|
|
14930
|
+
await handleBackupIfRequested(options.targetDir, !!options.backup, result);
|
|
14856
14931
|
const manifestCustomizations = await resolveManifestCustomizations(options, options.targetDir);
|
|
14857
14932
|
const configPreserveFiles = resolveConfigPreserveFiles(options, config);
|
|
14858
14933
|
const customizations = resolveCustomizations(manifestCustomizations, configPreserveFiles, options.targetDir);
|
|
14859
14934
|
const components = options.components || getAllUpdateComponents();
|
|
14860
|
-
await updateAllComponents(options.targetDir,
|
|
14935
|
+
await updateAllComponents(options.targetDir, components, updateCheck, customizations, options, result, config);
|
|
14861
14936
|
if (!options.components || options.components.length === 0) {
|
|
14862
|
-
await updateEntryDoc(options.targetDir,
|
|
14937
|
+
await updateEntryDoc(options.targetDir, config, options);
|
|
14863
14938
|
}
|
|
14864
14939
|
config.version = result.newVersion;
|
|
14865
14940
|
config.lastUpdated = new Date().toISOString();
|
|
@@ -14880,13 +14955,13 @@ async function update(options) {
|
|
|
14880
14955
|
}
|
|
14881
14956
|
return result;
|
|
14882
14957
|
}
|
|
14883
|
-
async function checkForUpdates(targetDir
|
|
14958
|
+
async function checkForUpdates(targetDir) {
|
|
14884
14959
|
const config = await loadConfig(targetDir);
|
|
14885
14960
|
const currentVersion = config.version;
|
|
14886
|
-
const latestVersion = await getLatestVersion(
|
|
14961
|
+
const latestVersion = await getLatestVersion();
|
|
14887
14962
|
const updatableComponents = [];
|
|
14888
14963
|
for (const component of getAllUpdateComponents()) {
|
|
14889
|
-
const hasUpdate = await componentHasUpdate(targetDir,
|
|
14964
|
+
const hasUpdate = await componentHasUpdate(targetDir, component, config);
|
|
14890
14965
|
if (hasUpdate) {
|
|
14891
14966
|
updatableComponents.push({
|
|
14892
14967
|
name: component,
|
|
@@ -14906,8 +14981,8 @@ async function checkForUpdates(targetDir, provider = "claude") {
|
|
|
14906
14981
|
function getAllUpdateComponents() {
|
|
14907
14982
|
return ["rules", "agents", "skills", "guides", "hooks", "contexts"];
|
|
14908
14983
|
}
|
|
14909
|
-
async function getLatestVersion(
|
|
14910
|
-
const layout = getProviderLayout(
|
|
14984
|
+
async function getLatestVersion() {
|
|
14985
|
+
const layout = getProviderLayout();
|
|
14911
14986
|
const manifestPath = resolveTemplatePath(layout.manifestFile);
|
|
14912
14987
|
if (await fileExists(manifestPath)) {
|
|
14913
14988
|
const manifest = await readJsonFile(manifestPath);
|
|
@@ -14915,17 +14990,17 @@ async function getLatestVersion(provider) {
|
|
|
14915
14990
|
}
|
|
14916
14991
|
return "0.0.0";
|
|
14917
14992
|
}
|
|
14918
|
-
async function componentHasUpdate(_targetDir,
|
|
14993
|
+
async function componentHasUpdate(_targetDir, component, config) {
|
|
14919
14994
|
const installedVersion = config.componentVersions?.[component];
|
|
14920
14995
|
if (!installedVersion) {
|
|
14921
14996
|
return true;
|
|
14922
14997
|
}
|
|
14923
|
-
const latestVersion = await getLatestVersion(
|
|
14998
|
+
const latestVersion = await getLatestVersion();
|
|
14924
14999
|
return installedVersion !== latestVersion;
|
|
14925
15000
|
}
|
|
14926
|
-
async function updateComponent(targetDir,
|
|
15001
|
+
async function updateComponent(targetDir, component, customizations, options, config) {
|
|
14927
15002
|
const preservedFiles = [];
|
|
14928
|
-
const componentPath = getComponentPath2(
|
|
15003
|
+
const componentPath = getComponentPath2(component);
|
|
14929
15004
|
const srcPath = resolveTemplatePath(componentPath);
|
|
14930
15005
|
const destPath = join8(targetDir, componentPath);
|
|
14931
15006
|
const customComponents = config.customComponents || [];
|
|
@@ -14952,19 +15027,19 @@ async function updateComponent(targetDir, provider, component, customizations, o
|
|
|
14952
15027
|
});
|
|
14953
15028
|
return preservedFiles;
|
|
14954
15029
|
}
|
|
14955
|
-
function getComponentPath2(
|
|
14956
|
-
const layout = getProviderLayout(
|
|
15030
|
+
function getComponentPath2(component) {
|
|
15031
|
+
const layout = getProviderLayout();
|
|
14957
15032
|
if (component === "guides") {
|
|
14958
15033
|
return "guides";
|
|
14959
15034
|
}
|
|
14960
15035
|
return `${layout.rootDir}/${component}`;
|
|
14961
15036
|
}
|
|
14962
|
-
async function backupInstallation(targetDir
|
|
15037
|
+
async function backupInstallation(targetDir) {
|
|
14963
15038
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
14964
15039
|
const backupDir = join8(targetDir, `.omcustom-backup-${timestamp}`);
|
|
14965
15040
|
const fs2 = await import("node:fs/promises");
|
|
14966
15041
|
await ensureDirectory(backupDir);
|
|
14967
|
-
const layout = getProviderLayout(
|
|
15042
|
+
const layout = getProviderLayout();
|
|
14968
15043
|
const dirsToBackup = [layout.rootDir, "guides"];
|
|
14969
15044
|
for (const dir2 of dirsToBackup) {
|
|
14970
15045
|
const srcPath = join8(targetDir, dir2);
|
|
@@ -14991,18 +15066,12 @@ async function loadCustomizationManifest(targetDir) {
|
|
|
14991
15066
|
async function updateCommand(options = {}) {
|
|
14992
15067
|
try {
|
|
14993
15068
|
const targetDir = process.cwd();
|
|
14994
|
-
const detection = await detectProvider({
|
|
14995
|
-
targetDir,
|
|
14996
|
-
override: options.provider
|
|
14997
|
-
});
|
|
14998
|
-
const provider = detection.provider;
|
|
14999
15069
|
const components = buildComponentsList(options);
|
|
15000
15070
|
if (options.dryRun) {
|
|
15001
15071
|
console.log(i18n.t("cli.update.dryRunHeader"));
|
|
15002
15072
|
}
|
|
15003
15073
|
const updateOptions = {
|
|
15004
15074
|
targetDir,
|
|
15005
|
-
provider,
|
|
15006
15075
|
components,
|
|
15007
15076
|
force: options.force,
|
|
15008
15077
|
preserveCustomizations: true,
|
|
@@ -15077,25 +15146,30 @@ var packageJson = require2("../../package.json");
|
|
|
15077
15146
|
function createProgram() {
|
|
15078
15147
|
const program2 = new Command;
|
|
15079
15148
|
program2.name("omcustom").description(i18n.t("cli.description")).version(packageJson.version, "-v, --version", i18n.t("cli.versionOption")).option("--skip-version-check", "Skip CLI version pre-flight check");
|
|
15080
|
-
program2.command("init").description(i18n.t("cli.init.description")).option("-l, --lang <language>", i18n.t("cli.init.langOption"), "en").
|
|
15149
|
+
program2.command("init").description(i18n.t("cli.init.description")).option("-l, --lang <language>", i18n.t("cli.init.langOption"), "en").action(async (options) => {
|
|
15081
15150
|
await initCommand(options);
|
|
15082
15151
|
});
|
|
15083
|
-
program2.command("update").description(i18n.t("cli.update.description")).option("--dry-run", i18n.t("cli.update.dryRunOption")).option("--force", i18n.t("cli.update.forceOption")).option("--force-overwrite-all", i18n.t("cli.update.forceOverwriteAllOption")).option("--backup", i18n.t("cli.update.backupOption")).option("--agents", i18n.t("cli.update.agentsOption")).option("--skills", i18n.t("cli.update.skillsOption")).option("--rules", i18n.t("cli.update.rulesOption")).option("--guides", i18n.t("cli.update.guidesOption")).option("--hooks", i18n.t("cli.update.hooksOption")).option("--contexts", i18n.t("cli.update.contextsOption")).
|
|
15152
|
+
program2.command("update").description(i18n.t("cli.update.description")).option("--dry-run", i18n.t("cli.update.dryRunOption")).option("--force", i18n.t("cli.update.forceOption")).option("--force-overwrite-all", i18n.t("cli.update.forceOverwriteAllOption")).option("--backup", i18n.t("cli.update.backupOption")).option("--agents", i18n.t("cli.update.agentsOption")).option("--skills", i18n.t("cli.update.skillsOption")).option("--rules", i18n.t("cli.update.rulesOption")).option("--guides", i18n.t("cli.update.guidesOption")).option("--hooks", i18n.t("cli.update.hooksOption")).option("--contexts", i18n.t("cli.update.contextsOption")).action(async (options) => {
|
|
15084
15153
|
await updateCommand(options);
|
|
15085
15154
|
});
|
|
15086
|
-
program2.command("list").description(i18n.t("cli.list.description")).argument("[type]", i18n.t("cli.list.typeArgument"), "all").option("-f, --format <format>", "Output format: table, json, or simple", "table").option("--verbose", "Show detailed information").
|
|
15155
|
+
program2.command("list").description(i18n.t("cli.list.description")).argument("[type]", i18n.t("cli.list.typeArgument"), "all").option("-f, --format <format>", "Output format: table, json, or simple", "table").option("--verbose", "Show detailed information").action(async (type, options) => {
|
|
15087
15156
|
await listCommand(type, {
|
|
15088
15157
|
format: options.format,
|
|
15089
|
-
verbose: options.verbose
|
|
15090
|
-
provider: options.provider
|
|
15158
|
+
verbose: options.verbose
|
|
15091
15159
|
});
|
|
15092
15160
|
});
|
|
15093
|
-
program2.command("doctor").description(i18n.t("cli.doctor.description")).option("--fix", i18n.t("cli.doctor.fixOption")).
|
|
15161
|
+
program2.command("doctor").description(i18n.t("cli.doctor.description")).option("--fix", i18n.t("cli.doctor.fixOption")).action(async (options) => {
|
|
15094
15162
|
await doctorCommand(options);
|
|
15095
15163
|
});
|
|
15096
|
-
program2.hook("preAction", async (thisCommand) => {
|
|
15164
|
+
program2.hook("preAction", async (thisCommand, actionCommand) => {
|
|
15097
15165
|
const opts = thisCommand.optsWithGlobals();
|
|
15098
15166
|
const skipCheck = opts.skipVersionCheck || false;
|
|
15167
|
+
if (actionCommand.name() === "init") {
|
|
15168
|
+
await maybeHandleSelfUpdateForInit({
|
|
15169
|
+
currentVersion: packageJson.version,
|
|
15170
|
+
skip: skipCheck
|
|
15171
|
+
});
|
|
15172
|
+
}
|
|
15099
15173
|
const result = await runPreflightCheck({ skip: skipCheck });
|
|
15100
15174
|
if (result.hasUpdates) {
|
|
15101
15175
|
const warnings = formatPreflightWarnings(result);
|