oh-my-customcode 0.12.1 → 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 +137 -336
- 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 -58
- 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 -150
- 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 -100
- package/templates/.codex/skills/claude-code-bible/scripts/fetch-docs.js +0 -272
- 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/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: [],
|
|
@@ -11663,7 +11663,7 @@ var en_default = {
|
|
|
11663
11663
|
unknownError: "An unknown error occurred"
|
|
11664
11664
|
},
|
|
11665
11665
|
cli: {
|
|
11666
|
-
description: "Batteries-included agent harness for Claude Code
|
|
11666
|
+
description: "Batteries-included agent harness for Claude Code",
|
|
11667
11667
|
versionOption: "Show version number",
|
|
11668
11668
|
usage: "Usage: omcustom <command> [options]",
|
|
11669
11669
|
commands: "Commands",
|
|
@@ -11702,7 +11702,6 @@ var en_default = {
|
|
|
11702
11702
|
init: {
|
|
11703
11703
|
description: "Initialize oh-my-customcode in the current directory",
|
|
11704
11704
|
langOption: "Language for templates (en or ko)",
|
|
11705
|
-
providerOption: "Provider to initialize (auto, claude, codex)",
|
|
11706
11705
|
start: "Initializing oh-my-customcode...",
|
|
11707
11706
|
exists: "Existing {{rootDir}} directory found.",
|
|
11708
11707
|
backing_up: "Creating backup...",
|
|
@@ -11752,7 +11751,6 @@ var en_default = {
|
|
|
11752
11751
|
guidesOption: "Update only guides",
|
|
11753
11752
|
hooksOption: "Update only hooks",
|
|
11754
11753
|
contextsOption: "Update only contexts",
|
|
11755
|
-
providerOption: "Provider to update (auto, claude, codex)",
|
|
11756
11754
|
dryRunHeader: "Dry run - no changes will be made:",
|
|
11757
11755
|
componentUpdated: "✓ {{component}} updated",
|
|
11758
11756
|
componentSkipped: "- {{component}} skipped (no changes)",
|
|
@@ -11765,7 +11763,6 @@ var en_default = {
|
|
|
11765
11763
|
list: {
|
|
11766
11764
|
description: "List installed components",
|
|
11767
11765
|
typeArgument: "Type to list: agents, skills, guides, rules, or all",
|
|
11768
|
-
providerOption: "Provider to list (auto, claude, codex)",
|
|
11769
11766
|
scanning: "Scanning installed components...",
|
|
11770
11767
|
empty: "No {{type}} found.",
|
|
11771
11768
|
header: "{{type}} ({{count}} installed)",
|
|
@@ -11790,7 +11787,6 @@ var en_default = {
|
|
|
11790
11787
|
doctor: {
|
|
11791
11788
|
description: "Check and fix configuration issues",
|
|
11792
11789
|
fixOption: "Automatically fix issues that can be fixed",
|
|
11793
|
-
providerOption: "Provider to diagnose (auto, claude, codex)",
|
|
11794
11790
|
checking: "Running diagnostic checks...",
|
|
11795
11791
|
applyingFixes: "Applying fixes...",
|
|
11796
11792
|
fixing: "Fixing: {{name}}...",
|
|
@@ -11959,7 +11955,7 @@ var ko_default = {
|
|
|
11959
11955
|
unknownError: "알 수 없는 오류가 발생했습니다"
|
|
11960
11956
|
},
|
|
11961
11957
|
cli: {
|
|
11962
|
-
description: "Claude Code
|
|
11958
|
+
description: "Claude Code를 위한 올인원 에이전트 하네스",
|
|
11963
11959
|
versionOption: "버전 번호 표시",
|
|
11964
11960
|
usage: "사용법: omcustom <명령어> [옵션]",
|
|
11965
11961
|
commands: "명령어",
|
|
@@ -11998,7 +11994,6 @@ var ko_default = {
|
|
|
11998
11994
|
init: {
|
|
11999
11995
|
description: "현재 디렉토리에 oh-my-customcode 초기화",
|
|
12000
11996
|
langOption: "템플릿 언어 (en 또는 ko)",
|
|
12001
|
-
providerOption: "초기화할 제공자 (auto, claude, codex)",
|
|
12002
11997
|
start: "oh-my-customcode 초기화 중...",
|
|
12003
11998
|
exists: "기존 {{rootDir}} 디렉토리가 발견되었습니다.",
|
|
12004
11999
|
backing_up: "백업을 생성합니다...",
|
|
@@ -12048,7 +12043,6 @@ var ko_default = {
|
|
|
12048
12043
|
guidesOption: "가이드만 업데이트",
|
|
12049
12044
|
hooksOption: "훅만 업데이트",
|
|
12050
12045
|
contextsOption: "컨텍스트만 업데이트",
|
|
12051
|
-
providerOption: "업데이트할 제공자 (auto, claude, codex)",
|
|
12052
12046
|
dryRunHeader: "드라이 런 - 변경사항 없음:",
|
|
12053
12047
|
componentUpdated: "✓ {{component}} 업데이트됨",
|
|
12054
12048
|
componentSkipped: "- {{component}} 건너뜀 (변경사항 없음)",
|
|
@@ -12061,7 +12055,6 @@ var ko_default = {
|
|
|
12061
12055
|
list: {
|
|
12062
12056
|
description: "설치된 컴포넌트 목록 표시",
|
|
12063
12057
|
typeArgument: "표시할 타입: agents, skills, guides, rules 또는 all",
|
|
12064
|
-
providerOption: "표시할 제공자 (auto, claude, codex)",
|
|
12065
12058
|
scanning: "설치된 컴포넌트 검색 중...",
|
|
12066
12059
|
empty: "{{type}}이(가) 없습니다.",
|
|
12067
12060
|
header: "{{type}} ({{count}}개 설치됨)",
|
|
@@ -12086,7 +12079,6 @@ var ko_default = {
|
|
|
12086
12079
|
doctor: {
|
|
12087
12080
|
description: "설정 문제 확인 및 수정",
|
|
12088
12081
|
fixOption: "자동으로 수정 가능한 문제 수정",
|
|
12089
|
-
providerOption: "진단할 제공자 (auto, claude, codex)",
|
|
12090
12082
|
checking: "진단 검사 실행 중...",
|
|
12091
12083
|
applyingFixes: "수정 사항 적용 중...",
|
|
12092
12084
|
fixing: "수정 중: {{name}}...",
|
|
@@ -12956,7 +12948,6 @@ function getDefaultConfig() {
|
|
|
12956
12948
|
configVersion: CURRENT_CONFIG_VERSION,
|
|
12957
12949
|
version: "0.0.0",
|
|
12958
12950
|
language: "en",
|
|
12959
|
-
provider: "auto",
|
|
12960
12951
|
installedAt: "",
|
|
12961
12952
|
lastUpdated: "",
|
|
12962
12953
|
installedComponents: [],
|
|
@@ -13079,203 +13070,36 @@ function migrateConfig(config) {
|
|
|
13079
13070
|
}
|
|
13080
13071
|
|
|
13081
13072
|
// src/core/layout.ts
|
|
13082
|
-
var
|
|
13083
|
-
|
|
13084
|
-
|
|
13085
|
-
|
|
13086
|
-
|
|
13087
|
-
|
|
13088
|
-
|
|
13089
|
-
|
|
13090
|
-
|
|
13091
|
-
|
|
13092
|
-
|
|
13093
|
-
|
|
13094
|
-
|
|
13095
|
-
|
|
13096
|
-
|
|
13097
|
-
"guides"
|
|
13098
|
-
]
|
|
13099
|
-
},
|
|
13100
|
-
codex: {
|
|
13101
|
-
provider: "codex",
|
|
13102
|
-
rootDir: ".codex",
|
|
13103
|
-
entryFile: "AGENTS.md",
|
|
13104
|
-
entryTemplatePrefix: "AGENTS.md",
|
|
13105
|
-
manifestFile: "manifest.codex.json",
|
|
13106
|
-
backupDirPrefix: ".codex-backup-",
|
|
13107
|
-
directoryStructure: [
|
|
13108
|
-
".codex",
|
|
13109
|
-
".codex/rules",
|
|
13110
|
-
".codex/hooks",
|
|
13111
|
-
".codex/contexts",
|
|
13112
|
-
".codex/agents",
|
|
13113
|
-
".codex/skills",
|
|
13114
|
-
"guides"
|
|
13115
|
-
]
|
|
13116
|
-
}
|
|
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
|
+
]
|
|
13117
13088
|
};
|
|
13118
|
-
function getProviderLayout(
|
|
13119
|
-
return
|
|
13089
|
+
function getProviderLayout() {
|
|
13090
|
+
return CLAUDE_LAYOUT;
|
|
13120
13091
|
}
|
|
13121
|
-
function getEntryTemplateName(
|
|
13122
|
-
|
|
13123
|
-
return `${layout.entryTemplatePrefix}.${language}`;
|
|
13092
|
+
function getEntryTemplateName(language) {
|
|
13093
|
+
return `CLAUDE.md.${language}`;
|
|
13124
13094
|
}
|
|
13125
|
-
function getComponentPath(
|
|
13126
|
-
const layout = getProviderLayout(provider);
|
|
13095
|
+
function getComponentPath(component) {
|
|
13127
13096
|
if (component === "entry-md") {
|
|
13128
|
-
return
|
|
13097
|
+
return "CLAUDE.md";
|
|
13129
13098
|
}
|
|
13130
13099
|
if (component === "guides") {
|
|
13131
13100
|
return "guides";
|
|
13132
13101
|
}
|
|
13133
|
-
return
|
|
13134
|
-
}
|
|
13135
|
-
function getDefaultProvider() {
|
|
13136
|
-
return "claude";
|
|
13137
|
-
}
|
|
13138
|
-
|
|
13139
|
-
// src/core/provider.ts
|
|
13140
|
-
import { join as join4 } from "node:path";
|
|
13141
|
-
var ENV_SIGNALS = {
|
|
13142
|
-
claude: [
|
|
13143
|
-
"ANTHROPIC_API_KEY",
|
|
13144
|
-
"CLAUDE_CODE",
|
|
13145
|
-
"CLAUDE_CODE_EFFORT_LEVEL",
|
|
13146
|
-
"CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS",
|
|
13147
|
-
"CLAUDE_CODE_ENABLE_TELEMETRY"
|
|
13148
|
-
],
|
|
13149
|
-
codex: ["OPENAI_API_KEY", "OPENAI_ORG_ID", "OPENAI_PROJECT", "CODEX_HOME", "CODEX_PROJECT"]
|
|
13150
|
-
};
|
|
13151
|
-
var PROVIDER_ENV_OVERRIDES = ["OMCUSTOM_PROVIDER", "LLM_SERVICE"];
|
|
13152
|
-
function normalizeProvider(value) {
|
|
13153
|
-
if (!value)
|
|
13154
|
-
return null;
|
|
13155
|
-
const normalized = value.toLowerCase().trim();
|
|
13156
|
-
if (normalized === "claude" || normalized === "codex" || normalized === "auto") {
|
|
13157
|
-
return normalized;
|
|
13158
|
-
}
|
|
13159
|
-
return null;
|
|
13160
|
-
}
|
|
13161
|
-
function detectFromEnv(env) {
|
|
13162
|
-
for (const key of PROVIDER_ENV_OVERRIDES) {
|
|
13163
|
-
const override = normalizeProvider(env[key]);
|
|
13164
|
-
if (override && override !== "auto") {
|
|
13165
|
-
return {
|
|
13166
|
-
provider: override,
|
|
13167
|
-
source: "override",
|
|
13168
|
-
confidence: "high",
|
|
13169
|
-
reason: `env:${key}`
|
|
13170
|
-
};
|
|
13171
|
-
}
|
|
13172
|
-
}
|
|
13173
|
-
const claudeSignals = ENV_SIGNALS.claude.filter((key) => Boolean(env[key]));
|
|
13174
|
-
const codexSignals = ENV_SIGNALS.codex.filter((key) => Boolean(env[key]));
|
|
13175
|
-
const hasClaude = claudeSignals.length > 0;
|
|
13176
|
-
const hasCodex = codexSignals.length > 0;
|
|
13177
|
-
if (hasClaude && !hasCodex) {
|
|
13178
|
-
return {
|
|
13179
|
-
provider: "claude",
|
|
13180
|
-
source: "env",
|
|
13181
|
-
confidence: "medium",
|
|
13182
|
-
reason: `env:${claudeSignals[0]}`
|
|
13183
|
-
};
|
|
13184
|
-
}
|
|
13185
|
-
if (hasCodex && !hasClaude) {
|
|
13186
|
-
return {
|
|
13187
|
-
provider: "codex",
|
|
13188
|
-
source: "env",
|
|
13189
|
-
confidence: "medium",
|
|
13190
|
-
reason: `env:${codexSignals[0]}`
|
|
13191
|
-
};
|
|
13192
|
-
}
|
|
13193
|
-
return null;
|
|
13194
|
-
}
|
|
13195
|
-
async function detectFromProject(targetDir) {
|
|
13196
|
-
const claudeMarkers = [join4(targetDir, "CLAUDE.md"), join4(targetDir, ".claude")];
|
|
13197
|
-
const codexMarkers = [join4(targetDir, "AGENTS.md"), join4(targetDir, ".codex")];
|
|
13198
|
-
const claudeFound = await Promise.all(claudeMarkers.map((path) => fileExists(path)));
|
|
13199
|
-
const codexFound = await Promise.all(codexMarkers.map((path) => fileExists(path)));
|
|
13200
|
-
const hasClaude = claudeFound.some(Boolean);
|
|
13201
|
-
const hasCodex = codexFound.some(Boolean);
|
|
13202
|
-
if (hasClaude && !hasCodex) {
|
|
13203
|
-
return {
|
|
13204
|
-
provider: "claude",
|
|
13205
|
-
source: "project",
|
|
13206
|
-
confidence: "medium",
|
|
13207
|
-
reason: "project:claude"
|
|
13208
|
-
};
|
|
13209
|
-
}
|
|
13210
|
-
if (hasCodex && !hasClaude) {
|
|
13211
|
-
return {
|
|
13212
|
-
provider: "codex",
|
|
13213
|
-
source: "project",
|
|
13214
|
-
confidence: "medium",
|
|
13215
|
-
reason: "project:codex"
|
|
13216
|
-
};
|
|
13217
|
-
}
|
|
13218
|
-
return null;
|
|
13219
|
-
}
|
|
13220
|
-
async function detectFromConfig(targetDir) {
|
|
13221
|
-
const configPath = join4(targetDir, ".omcustomrc.json");
|
|
13222
|
-
if (!await fileExists(configPath)) {
|
|
13223
|
-
return null;
|
|
13224
|
-
}
|
|
13225
|
-
try {
|
|
13226
|
-
const config = await readJsonFile(configPath);
|
|
13227
|
-
const provider = normalizeProvider(config.provider);
|
|
13228
|
-
if (provider && provider !== "auto") {
|
|
13229
|
-
return {
|
|
13230
|
-
provider,
|
|
13231
|
-
source: "config",
|
|
13232
|
-
confidence: "high",
|
|
13233
|
-
reason: "config:provider"
|
|
13234
|
-
};
|
|
13235
|
-
}
|
|
13236
|
-
} catch {}
|
|
13237
|
-
return null;
|
|
13238
|
-
}
|
|
13239
|
-
async function detectProvider(options = {}) {
|
|
13240
|
-
const env = options.env ?? process.env;
|
|
13241
|
-
const override = options.override;
|
|
13242
|
-
const normalizedOverride = normalizeProvider(override);
|
|
13243
|
-
if (normalizedOverride && normalizedOverride !== "auto") {
|
|
13244
|
-
return {
|
|
13245
|
-
provider: normalizedOverride,
|
|
13246
|
-
source: "override",
|
|
13247
|
-
confidence: "high",
|
|
13248
|
-
reason: "override:option"
|
|
13249
|
-
};
|
|
13250
|
-
}
|
|
13251
|
-
if (options.targetDir) {
|
|
13252
|
-
const fromConfig = await detectFromConfig(options.targetDir);
|
|
13253
|
-
if (fromConfig) {
|
|
13254
|
-
return fromConfig;
|
|
13255
|
-
}
|
|
13256
|
-
}
|
|
13257
|
-
if (options.targetDir && options.preferProject) {
|
|
13258
|
-
const fromProject = await detectFromProject(options.targetDir);
|
|
13259
|
-
if (fromProject) {
|
|
13260
|
-
return fromProject;
|
|
13261
|
-
}
|
|
13262
|
-
}
|
|
13263
|
-
const fromEnv = detectFromEnv(env);
|
|
13264
|
-
if (fromEnv) {
|
|
13265
|
-
return fromEnv;
|
|
13266
|
-
}
|
|
13267
|
-
if (options.targetDir && !options.preferProject) {
|
|
13268
|
-
const fromProject = await detectFromProject(options.targetDir);
|
|
13269
|
-
if (fromProject) {
|
|
13270
|
-
return fromProject;
|
|
13271
|
-
}
|
|
13272
|
-
}
|
|
13273
|
-
return {
|
|
13274
|
-
provider: getDefaultProvider(),
|
|
13275
|
-
source: "default",
|
|
13276
|
-
confidence: "low",
|
|
13277
|
-
reason: "default"
|
|
13278
|
-
};
|
|
13102
|
+
return `.claude/${component}`;
|
|
13279
13103
|
}
|
|
13280
13104
|
|
|
13281
13105
|
// src/cli/doctor.ts
|
|
@@ -13719,12 +13543,7 @@ async function doctorCommand(options = {}) {
|
|
|
13719
13543
|
const targetDir = process.cwd();
|
|
13720
13544
|
console.log(i18n.t("cli.doctor.checking"));
|
|
13721
13545
|
console.log("");
|
|
13722
|
-
const
|
|
13723
|
-
targetDir,
|
|
13724
|
-
override: options.provider,
|
|
13725
|
-
preferProject: true
|
|
13726
|
-
});
|
|
13727
|
-
const layout = getProviderLayout(detection.provider);
|
|
13546
|
+
const layout = getProviderLayout();
|
|
13728
13547
|
let checks = await Promise.all([
|
|
13729
13548
|
checkEntryDoc(targetDir, layout.entryFile),
|
|
13730
13549
|
checkRules(targetDir, layout.rootDir),
|
|
@@ -13784,11 +13603,11 @@ async function doctorCommand(options = {}) {
|
|
|
13784
13603
|
}
|
|
13785
13604
|
|
|
13786
13605
|
// src/cli/init.ts
|
|
13787
|
-
import { join as
|
|
13606
|
+
import { join as join6 } from "node:path";
|
|
13788
13607
|
|
|
13789
13608
|
// src/core/installer.ts
|
|
13790
13609
|
import { readFile as fsReadFile, writeFile as fsWriteFile, rename } from "node:fs/promises";
|
|
13791
|
-
import { basename, join as
|
|
13610
|
+
import { basename, join as join4 } from "node:path";
|
|
13792
13611
|
|
|
13793
13612
|
// src/core/git-workflow.ts
|
|
13794
13613
|
import { execFileSync } from "node:child_process";
|
|
@@ -14044,7 +13863,7 @@ function getDefaultWorkflow() {
|
|
|
14044
13863
|
var DEFAULT_LANGUAGE2 = "en";
|
|
14045
13864
|
function getTemplateDir() {
|
|
14046
13865
|
const packageRoot = getPackageRoot();
|
|
14047
|
-
return
|
|
13866
|
+
return join4(packageRoot, "templates");
|
|
14048
13867
|
}
|
|
14049
13868
|
function createInstallResult(targetDir) {
|
|
14050
13869
|
return {
|
|
@@ -14062,21 +13881,21 @@ async function ensureTargetDirectory(targetDir) {
|
|
|
14062
13881
|
await ensureDirectory(targetDir);
|
|
14063
13882
|
}
|
|
14064
13883
|
}
|
|
14065
|
-
async function handleBackup(targetDir,
|
|
13884
|
+
async function handleBackup(targetDir, shouldBackup, result) {
|
|
14066
13885
|
if (!shouldBackup)
|
|
14067
13886
|
return;
|
|
14068
|
-
const backupPaths = await backupExistingInstallation(targetDir
|
|
13887
|
+
const backupPaths = await backupExistingInstallation(targetDir);
|
|
14069
13888
|
result.backedUpPaths.push(...backupPaths);
|
|
14070
13889
|
if (backupPaths.length > 0) {
|
|
14071
13890
|
info("install.backup", { path: backupPaths[0] });
|
|
14072
13891
|
}
|
|
14073
13892
|
}
|
|
14074
|
-
async function checkAndWarnExisting(targetDir,
|
|
13893
|
+
async function checkAndWarnExisting(targetDir, force, backup, result) {
|
|
14075
13894
|
if (force || backup)
|
|
14076
13895
|
return;
|
|
14077
|
-
const existingPaths = await checkExistingPaths(targetDir
|
|
13896
|
+
const existingPaths = await checkExistingPaths(targetDir);
|
|
14078
13897
|
if (existingPaths.length > 0) {
|
|
14079
|
-
const layout = getProviderLayout(
|
|
13898
|
+
const layout = getProviderLayout();
|
|
14080
13899
|
warn("install.exists", { rootDir: layout.rootDir });
|
|
14081
13900
|
result.warnings.push(`Existing files found: ${existingPaths.join(", ")}. Use --force to overwrite or --backup to backup first.`);
|
|
14082
13901
|
}
|
|
@@ -14087,15 +13906,15 @@ async function verifyTemplateDirectory() {
|
|
|
14087
13906
|
throw new Error(`Template directory not found: ${templateDir}`);
|
|
14088
13907
|
}
|
|
14089
13908
|
}
|
|
14090
|
-
async function installAllComponents(targetDir,
|
|
13909
|
+
async function installAllComponents(targetDir, options, result) {
|
|
14091
13910
|
const components = options.components || getAllComponents();
|
|
14092
13911
|
for (const component of components) {
|
|
14093
|
-
await installSingleComponent(targetDir,
|
|
13912
|
+
await installSingleComponent(targetDir, component, options, result);
|
|
14094
13913
|
}
|
|
14095
13914
|
}
|
|
14096
|
-
async function installSingleComponent(targetDir,
|
|
13915
|
+
async function installSingleComponent(targetDir, component, options, result) {
|
|
14097
13916
|
try {
|
|
14098
|
-
const installed = await installComponent(targetDir,
|
|
13917
|
+
const installed = await installComponent(targetDir, component, options);
|
|
14099
13918
|
if (installed) {
|
|
14100
13919
|
result.installedComponents.push(component);
|
|
14101
13920
|
} else {
|
|
@@ -14106,36 +13925,34 @@ async function installSingleComponent(targetDir, provider, component, options, r
|
|
|
14106
13925
|
result.warnings.push(`Failed to install ${component}: ${message}`);
|
|
14107
13926
|
}
|
|
14108
13927
|
}
|
|
14109
|
-
async function installEntryDocWithTracking(targetDir,
|
|
13928
|
+
async function installEntryDocWithTracking(targetDir, options, result) {
|
|
14110
13929
|
const language = options.language ?? DEFAULT_LANGUAGE2;
|
|
14111
13930
|
const overwrite = !!(options.force || options.backup);
|
|
14112
|
-
const installed = await installEntryDoc(targetDir,
|
|
13931
|
+
const installed = await installEntryDoc(targetDir, language, overwrite);
|
|
14113
13932
|
if (installed) {
|
|
14114
13933
|
result.installedComponents.push("entry-md");
|
|
14115
13934
|
} else {
|
|
14116
13935
|
result.skippedComponents.push("entry-md");
|
|
14117
13936
|
}
|
|
14118
13937
|
}
|
|
14119
|
-
async function updateInstallConfig(targetDir,
|
|
13938
|
+
async function updateInstallConfig(targetDir, options, installedComponents) {
|
|
14120
13939
|
const config = await loadConfig(targetDir);
|
|
14121
13940
|
config.language = options.language ?? DEFAULT_LANGUAGE2;
|
|
14122
|
-
config.provider = provider;
|
|
14123
13941
|
config.installedAt = new Date().toISOString();
|
|
14124
13942
|
config.installedComponents = installedComponents;
|
|
14125
13943
|
await saveConfig(targetDir, config);
|
|
14126
13944
|
}
|
|
14127
13945
|
async function install(options) {
|
|
14128
13946
|
const result = createInstallResult(options.targetDir);
|
|
14129
|
-
const provider = options.provider ?? "claude";
|
|
14130
13947
|
try {
|
|
14131
13948
|
info("install.start", { targetDir: options.targetDir });
|
|
14132
13949
|
await ensureTargetDirectory(options.targetDir);
|
|
14133
|
-
await handleBackup(options.targetDir,
|
|
14134
|
-
await checkAndWarnExisting(options.targetDir,
|
|
13950
|
+
await handleBackup(options.targetDir, !!options.backup, result);
|
|
13951
|
+
await checkAndWarnExisting(options.targetDir, !!options.force, !!options.backup, result);
|
|
14135
13952
|
await verifyTemplateDirectory();
|
|
14136
|
-
await installAllComponents(options.targetDir,
|
|
14137
|
-
await installEntryDocWithTracking(options.targetDir,
|
|
14138
|
-
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);
|
|
14139
13956
|
result.success = true;
|
|
14140
13957
|
success("install.success");
|
|
14141
13958
|
} catch (err) {
|
|
@@ -14148,15 +13965,15 @@ async function install(options) {
|
|
|
14148
13965
|
function getAllComponents() {
|
|
14149
13966
|
return ["rules", "agents", "skills", "guides", "hooks", "contexts"];
|
|
14150
13967
|
}
|
|
14151
|
-
async function installComponent(targetDir,
|
|
13968
|
+
async function installComponent(targetDir, component, options) {
|
|
14152
13969
|
if (component === "entry-md") {
|
|
14153
13970
|
return false;
|
|
14154
13971
|
}
|
|
14155
|
-
const templatePath = getComponentPath(
|
|
13972
|
+
const templatePath = getComponentPath(component);
|
|
14156
13973
|
if (!templatePath) {
|
|
14157
13974
|
return false;
|
|
14158
13975
|
}
|
|
14159
|
-
const destPath =
|
|
13976
|
+
const destPath = join4(targetDir, templatePath);
|
|
14160
13977
|
const destExists = await fileExists(destPath);
|
|
14161
13978
|
if (destExists && !options.force && !options.backup) {
|
|
14162
13979
|
debug("install.component_skipped", { component });
|
|
@@ -14180,11 +13997,11 @@ function renderGitWorkflowSection(targetDir, language) {
|
|
|
14180
13997
|
const result = detectGitWorkflow(targetDir) ?? getDefaultWorkflow();
|
|
14181
13998
|
return language === "ko" ? renderGitWorkflowKO(result) : renderGitWorkflowEN(result);
|
|
14182
13999
|
}
|
|
14183
|
-
async function installEntryDoc(targetDir,
|
|
14184
|
-
const layout = getProviderLayout(
|
|
14185
|
-
const templateFile = getEntryTemplateName(
|
|
14000
|
+
async function installEntryDoc(targetDir, language, overwrite = false) {
|
|
14001
|
+
const layout = getProviderLayout();
|
|
14002
|
+
const templateFile = getEntryTemplateName(language);
|
|
14186
14003
|
const srcPath = resolveTemplatePath(templateFile);
|
|
14187
|
-
const destPath =
|
|
14004
|
+
const destPath = join4(targetDir, layout.entryFile);
|
|
14188
14005
|
if (!await fileExists(srcPath)) {
|
|
14189
14006
|
warn("install.entry_md_not_found", { language, path: srcPath, entry: layout.entryFile });
|
|
14190
14007
|
return false;
|
|
@@ -14205,34 +14022,34 @@ async function installEntryDoc(targetDir, provider, language, overwrite = false)
|
|
|
14205
14022
|
}
|
|
14206
14023
|
async function backupExisting(sourcePath, backupDir) {
|
|
14207
14024
|
const name = basename(sourcePath);
|
|
14208
|
-
const backupPath =
|
|
14025
|
+
const backupPath = join4(backupDir, name);
|
|
14209
14026
|
await rename(sourcePath, backupPath);
|
|
14210
14027
|
return backupPath;
|
|
14211
14028
|
}
|
|
14212
|
-
async function checkExistingPaths(targetDir
|
|
14213
|
-
const layout = getProviderLayout(
|
|
14029
|
+
async function checkExistingPaths(targetDir) {
|
|
14030
|
+
const layout = getProviderLayout();
|
|
14214
14031
|
const pathsToCheck = [layout.entryFile, layout.rootDir, "guides"];
|
|
14215
14032
|
const existingPaths = [];
|
|
14216
14033
|
for (const relativePath of pathsToCheck) {
|
|
14217
|
-
const fullPath =
|
|
14034
|
+
const fullPath = join4(targetDir, relativePath);
|
|
14218
14035
|
if (await fileExists(fullPath)) {
|
|
14219
14036
|
existingPaths.push(relativePath);
|
|
14220
14037
|
}
|
|
14221
14038
|
}
|
|
14222
14039
|
return existingPaths;
|
|
14223
14040
|
}
|
|
14224
|
-
async function backupExistingInstallation(targetDir
|
|
14225
|
-
const layout = getProviderLayout(
|
|
14226
|
-
const existingPaths = await checkExistingPaths(targetDir
|
|
14041
|
+
async function backupExistingInstallation(targetDir) {
|
|
14042
|
+
const layout = getProviderLayout();
|
|
14043
|
+
const existingPaths = await checkExistingPaths(targetDir);
|
|
14227
14044
|
if (existingPaths.length === 0) {
|
|
14228
14045
|
return [];
|
|
14229
14046
|
}
|
|
14230
14047
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
14231
|
-
const backupDir =
|
|
14048
|
+
const backupDir = join4(targetDir, `${layout.backupDirPrefix}${timestamp}`);
|
|
14232
14049
|
await ensureDirectory(backupDir);
|
|
14233
14050
|
const backedUpPaths = [];
|
|
14234
14051
|
for (const relativePath of existingPaths) {
|
|
14235
|
-
const fullPath =
|
|
14052
|
+
const fullPath = join4(targetDir, relativePath);
|
|
14236
14053
|
try {
|
|
14237
14054
|
const backupPath = await backupExisting(fullPath, backupDir);
|
|
14238
14055
|
backedUpPaths.push(backupPath);
|
|
@@ -14248,12 +14065,12 @@ async function backupExistingInstallation(targetDir, provider) {
|
|
|
14248
14065
|
// src/core/mcp-config.ts
|
|
14249
14066
|
import { execSync as execSync3 } from "node:child_process";
|
|
14250
14067
|
import { writeFile } from "node:fs/promises";
|
|
14251
|
-
import { join as
|
|
14252
|
-
async function generateMCPConfig(targetDir
|
|
14253
|
-
const layout = getProviderLayout(
|
|
14254
|
-
const mcpConfigPath =
|
|
14255
|
-
const ontologyDir =
|
|
14256
|
-
const ontologyExists = await fileExists(
|
|
14068
|
+
import { join as join5 } from "node:path";
|
|
14069
|
+
async function generateMCPConfig(targetDir) {
|
|
14070
|
+
const layout = getProviderLayout();
|
|
14071
|
+
const mcpConfigPath = join5(targetDir, ".mcp.json");
|
|
14072
|
+
const ontologyDir = join5(layout.rootDir, "ontology");
|
|
14073
|
+
const ontologyExists = await fileExists(join5(targetDir, ontologyDir));
|
|
14257
14074
|
if (!ontologyExists) {
|
|
14258
14075
|
return;
|
|
14259
14076
|
}
|
|
@@ -14300,25 +14117,25 @@ async function checkPythonAvailable() {
|
|
|
14300
14117
|
}
|
|
14301
14118
|
|
|
14302
14119
|
// src/cli/init.ts
|
|
14303
|
-
async function checkExistingInstallation(targetDir
|
|
14304
|
-
const layout = getProviderLayout(
|
|
14305
|
-
const rootDir =
|
|
14120
|
+
async function checkExistingInstallation(targetDir) {
|
|
14121
|
+
const layout = getProviderLayout();
|
|
14122
|
+
const rootDir = join6(targetDir, layout.rootDir);
|
|
14306
14123
|
return fileExists(rootDir);
|
|
14307
14124
|
}
|
|
14308
14125
|
var PROVIDER_SUBDIR_COMPONENTS = new Set(["rules", "hooks", "contexts", "agents", "skills"]);
|
|
14309
|
-
function componentToPath(targetDir,
|
|
14126
|
+
function componentToPath(targetDir, component) {
|
|
14310
14127
|
if (component === "entry-md") {
|
|
14311
|
-
const layout = getProviderLayout(
|
|
14312
|
-
return
|
|
14128
|
+
const layout = getProviderLayout();
|
|
14129
|
+
return join6(targetDir, layout.entryFile);
|
|
14313
14130
|
}
|
|
14314
14131
|
if (PROVIDER_SUBDIR_COMPONENTS.has(component)) {
|
|
14315
|
-
const layout = getProviderLayout(
|
|
14316
|
-
return
|
|
14132
|
+
const layout = getProviderLayout();
|
|
14133
|
+
return join6(targetDir, layout.rootDir, component);
|
|
14317
14134
|
}
|
|
14318
|
-
return
|
|
14135
|
+
return join6(targetDir, component);
|
|
14319
14136
|
}
|
|
14320
|
-
function buildInstalledPaths(targetDir,
|
|
14321
|
-
return components.map((component) => componentToPath(targetDir,
|
|
14137
|
+
function buildInstalledPaths(targetDir, components) {
|
|
14138
|
+
return components.map((component) => componentToPath(targetDir, component));
|
|
14322
14139
|
}
|
|
14323
14140
|
function logItems(items, formatter) {
|
|
14324
14141
|
for (const item of items) {
|
|
@@ -14351,10 +14168,8 @@ async function initCommand(options) {
|
|
|
14351
14168
|
const targetDir = process.cwd();
|
|
14352
14169
|
console.log(i18n.t("cli.init.start"));
|
|
14353
14170
|
try {
|
|
14354
|
-
const
|
|
14355
|
-
const
|
|
14356
|
-
const layout = getProviderLayout(provider);
|
|
14357
|
-
const exists2 = await checkExistingInstallation(targetDir, provider);
|
|
14171
|
+
const layout = getProviderLayout();
|
|
14172
|
+
const exists2 = await checkExistingInstallation(targetDir);
|
|
14358
14173
|
if (exists2) {
|
|
14359
14174
|
console.log(i18n.t("cli.init.exists", { rootDir: layout.rootDir }));
|
|
14360
14175
|
console.log(i18n.t("cli.init.backing_up"));
|
|
@@ -14363,20 +14178,19 @@ async function initCommand(options) {
|
|
|
14363
14178
|
const installResult = await install({
|
|
14364
14179
|
targetDir,
|
|
14365
14180
|
language: options.lang,
|
|
14366
|
-
provider,
|
|
14367
14181
|
force: options.force ?? false,
|
|
14368
14182
|
backup: exists2
|
|
14369
14183
|
});
|
|
14370
14184
|
if (!installResult.success) {
|
|
14371
14185
|
return createFailureResult(installResult.error || "Unknown error");
|
|
14372
14186
|
}
|
|
14373
|
-
const installedPaths = buildInstalledPaths(targetDir,
|
|
14187
|
+
const installedPaths = buildInstalledPaths(targetDir, installResult.installedComponents);
|
|
14374
14188
|
logInstallResultInfo(installResult);
|
|
14375
14189
|
logSuccessDetails(installedPaths, installResult.skippedComponents);
|
|
14376
14190
|
const pythonAvailable = await checkPythonAvailable();
|
|
14377
14191
|
if (pythonAvailable) {
|
|
14378
14192
|
try {
|
|
14379
|
-
await generateMCPConfig(targetDir
|
|
14193
|
+
await generateMCPConfig(targetDir);
|
|
14380
14194
|
} catch {
|
|
14381
14195
|
console.warn("Warning: Failed to generate MCP config. You can configure it manually.");
|
|
14382
14196
|
}
|
|
@@ -14397,7 +14211,7 @@ async function initCommand(options) {
|
|
|
14397
14211
|
}
|
|
14398
14212
|
|
|
14399
14213
|
// src/cli/list.ts
|
|
14400
|
-
import { basename as basename2, dirname as dirname3, join as
|
|
14214
|
+
import { basename as basename2, dirname as dirname3, join as join7, relative as relative2 } from "node:path";
|
|
14401
14215
|
var ALLOWED_TOP_LEVEL_KEYS = new Set(["name", "type", "description", "version", "category"]);
|
|
14402
14216
|
function parseKeyValue(line) {
|
|
14403
14217
|
const colonIndex = line.indexOf(":");
|
|
@@ -14461,12 +14275,12 @@ function extractAgentTypeFromFilename(filename) {
|
|
|
14461
14275
|
return prefixMap[prefix] || "unknown";
|
|
14462
14276
|
}
|
|
14463
14277
|
function extractSkillCategoryFromPath(skillPath, baseDir, rootDir) {
|
|
14464
|
-
const relativePath = relative2(
|
|
14278
|
+
const relativePath = relative2(join7(baseDir, rootDir, "skills"), skillPath);
|
|
14465
14279
|
const parts = relativePath.split("/").filter(Boolean);
|
|
14466
14280
|
return parts[0] || "unknown";
|
|
14467
14281
|
}
|
|
14468
14282
|
function extractGuideCategoryFromPath(guidePath, baseDir) {
|
|
14469
|
-
const relativePath = relative2(
|
|
14283
|
+
const relativePath = relative2(join7(baseDir, "guides"), guidePath);
|
|
14470
14284
|
const parts = relativePath.split("/").filter(Boolean);
|
|
14471
14285
|
return parts[0] || "unknown";
|
|
14472
14286
|
}
|
|
@@ -14560,7 +14374,7 @@ async function tryExtractMarkdownDescription(mdPath, options = {}) {
|
|
|
14560
14374
|
}
|
|
14561
14375
|
}
|
|
14562
14376
|
async function getAgents(targetDir, rootDir = ".claude", config) {
|
|
14563
|
-
const agentsDir =
|
|
14377
|
+
const agentsDir = join7(targetDir, rootDir, "agents");
|
|
14564
14378
|
if (!await fileExists(agentsDir))
|
|
14565
14379
|
return [];
|
|
14566
14380
|
try {
|
|
@@ -14588,7 +14402,7 @@ async function getAgents(targetDir, rootDir = ".claude", config) {
|
|
|
14588
14402
|
}
|
|
14589
14403
|
}
|
|
14590
14404
|
async function getSkills(targetDir, rootDir = ".claude", config) {
|
|
14591
|
-
const skillsDir =
|
|
14405
|
+
const skillsDir = join7(targetDir, rootDir, "skills");
|
|
14592
14406
|
if (!await fileExists(skillsDir))
|
|
14593
14407
|
return [];
|
|
14594
14408
|
try {
|
|
@@ -14598,7 +14412,7 @@ async function getSkills(targetDir, rootDir = ".claude", config) {
|
|
|
14598
14412
|
const skillMdFiles = await listFiles(skillsDir, { recursive: true, pattern: "SKILL.md" });
|
|
14599
14413
|
const skills = await Promise.all(skillMdFiles.map(async (skillMdPath) => {
|
|
14600
14414
|
const skillDir = dirname3(skillMdPath);
|
|
14601
|
-
const indexYamlPath =
|
|
14415
|
+
const indexYamlPath = join7(skillDir, "index.yaml");
|
|
14602
14416
|
const { description, version } = await tryReadIndexYamlMetadata(indexYamlPath);
|
|
14603
14417
|
const relativePath = relative2(targetDir, skillDir);
|
|
14604
14418
|
return {
|
|
@@ -14617,7 +14431,7 @@ async function getSkills(targetDir, rootDir = ".claude", config) {
|
|
|
14617
14431
|
}
|
|
14618
14432
|
}
|
|
14619
14433
|
async function getGuides(targetDir, config) {
|
|
14620
|
-
const guidesDir =
|
|
14434
|
+
const guidesDir = join7(targetDir, "guides");
|
|
14621
14435
|
if (!await fileExists(guidesDir))
|
|
14622
14436
|
return [];
|
|
14623
14437
|
try {
|
|
@@ -14644,7 +14458,7 @@ async function getGuides(targetDir, config) {
|
|
|
14644
14458
|
}
|
|
14645
14459
|
var RULE_PRIORITY_ORDER = { MUST: 0, SHOULD: 1, MAY: 2 };
|
|
14646
14460
|
async function getRules(targetDir, rootDir = ".claude", config) {
|
|
14647
|
-
const rulesDir =
|
|
14461
|
+
const rulesDir = join7(targetDir, rootDir, "rules");
|
|
14648
14462
|
if (!await fileExists(rulesDir))
|
|
14649
14463
|
return [];
|
|
14650
14464
|
try {
|
|
@@ -14716,7 +14530,7 @@ function formatAsJson(components) {
|
|
|
14716
14530
|
console.log(JSON.stringify(components, null, 2));
|
|
14717
14531
|
}
|
|
14718
14532
|
async function getHooks(targetDir, rootDir = ".claude") {
|
|
14719
|
-
const hooksDir =
|
|
14533
|
+
const hooksDir = join7(targetDir, rootDir, "hooks");
|
|
14720
14534
|
if (!await fileExists(hooksDir))
|
|
14721
14535
|
return [];
|
|
14722
14536
|
try {
|
|
@@ -14734,7 +14548,7 @@ async function getHooks(targetDir, rootDir = ".claude") {
|
|
|
14734
14548
|
}
|
|
14735
14549
|
}
|
|
14736
14550
|
async function getContexts(targetDir, rootDir = ".claude") {
|
|
14737
|
-
const contextsDir =
|
|
14551
|
+
const contextsDir = join7(targetDir, rootDir, "contexts");
|
|
14738
14552
|
if (!await fileExists(contextsDir))
|
|
14739
14553
|
return [];
|
|
14740
14554
|
try {
|
|
@@ -14797,12 +14611,7 @@ async function listCommand(type = "all", options = {}) {
|
|
|
14797
14611
|
const format = options.format || "table";
|
|
14798
14612
|
console.log(i18n.t("cli.list.scanning"));
|
|
14799
14613
|
try {
|
|
14800
|
-
const
|
|
14801
|
-
targetDir,
|
|
14802
|
-
override: options.provider,
|
|
14803
|
-
preferProject: true
|
|
14804
|
-
});
|
|
14805
|
-
const layout = getProviderLayout(detection.provider);
|
|
14614
|
+
const layout = getProviderLayout();
|
|
14806
14615
|
const config = await loadConfig(targetDir);
|
|
14807
14616
|
const components = type === "all" ? await handleListAll(targetDir, layout.rootDir, format, config) : await COMPONENT_GETTERS[type](targetDir, layout.rootDir, config);
|
|
14808
14617
|
if (type === "all" && format === "json") {
|
|
@@ -14819,7 +14628,7 @@ async function listCommand(type = "all", options = {}) {
|
|
|
14819
14628
|
}
|
|
14820
14629
|
|
|
14821
14630
|
// src/core/updater.ts
|
|
14822
|
-
import { join as
|
|
14631
|
+
import { join as join8 } from "node:path";
|
|
14823
14632
|
|
|
14824
14633
|
// src/core/entry-merger.ts
|
|
14825
14634
|
var MANAGED_START = "<!-- omcustom:start -->";
|
|
@@ -14951,14 +14760,14 @@ function createUpdateResult() {
|
|
|
14951
14760
|
warnings: []
|
|
14952
14761
|
};
|
|
14953
14762
|
}
|
|
14954
|
-
async function handleBackupIfRequested(targetDir,
|
|
14763
|
+
async function handleBackupIfRequested(targetDir, backup, result) {
|
|
14955
14764
|
if (!backup)
|
|
14956
14765
|
return;
|
|
14957
|
-
const backupPath = await backupInstallation(targetDir
|
|
14766
|
+
const backupPath = await backupInstallation(targetDir);
|
|
14958
14767
|
result.backedUpPaths.push(backupPath);
|
|
14959
14768
|
info("update.backup_created", { path: backupPath });
|
|
14960
14769
|
}
|
|
14961
|
-
async function processComponentUpdate(targetDir,
|
|
14770
|
+
async function processComponentUpdate(targetDir, component, updateCheck, customizations, options, result, config) {
|
|
14962
14771
|
const componentUpdate = updateCheck.updatableComponents.find((c) => c.name === component);
|
|
14963
14772
|
if (!componentUpdate && !options.force) {
|
|
14964
14773
|
result.skippedComponents.push(component);
|
|
@@ -14970,7 +14779,7 @@ async function processComponentUpdate(targetDir, provider, component, updateChec
|
|
|
14970
14779
|
return;
|
|
14971
14780
|
}
|
|
14972
14781
|
try {
|
|
14973
|
-
const preserved = await updateComponent(targetDir,
|
|
14782
|
+
const preserved = await updateComponent(targetDir, component, customizations, options, config);
|
|
14974
14783
|
result.updatedComponents.push(component);
|
|
14975
14784
|
result.preservedFiles.push(...preserved);
|
|
14976
14785
|
} catch (err) {
|
|
@@ -14979,13 +14788,13 @@ async function processComponentUpdate(targetDir, provider, component, updateChec
|
|
|
14979
14788
|
result.skippedComponents.push(component);
|
|
14980
14789
|
}
|
|
14981
14790
|
}
|
|
14982
|
-
async function updateAllComponents(targetDir,
|
|
14791
|
+
async function updateAllComponents(targetDir, components, updateCheck, customizations, options, result, config) {
|
|
14983
14792
|
for (const component of components) {
|
|
14984
|
-
await processComponentUpdate(targetDir,
|
|
14793
|
+
await processComponentUpdate(targetDir, component, updateCheck, customizations, options, result, config);
|
|
14985
14794
|
}
|
|
14986
14795
|
}
|
|
14987
|
-
function getEntryTemplateName2(
|
|
14988
|
-
const layout = getProviderLayout(
|
|
14796
|
+
function getEntryTemplateName2(language) {
|
|
14797
|
+
const layout = getProviderLayout();
|
|
14989
14798
|
const baseName = layout.entryFile.replace(".md", "");
|
|
14990
14799
|
return language === "ko" ? `${baseName}.md.ko` : `${baseName}.md.en`;
|
|
14991
14800
|
}
|
|
@@ -15069,10 +14878,10 @@ function resolveCustomizations(customizations, configPreserveFiles, targetDir) {
|
|
|
15069
14878
|
}
|
|
15070
14879
|
return null;
|
|
15071
14880
|
}
|
|
15072
|
-
async function updateEntryDoc(targetDir,
|
|
15073
|
-
const layout = getProviderLayout(
|
|
15074
|
-
const entryPath =
|
|
15075
|
-
const templateName = getEntryTemplateName2(
|
|
14881
|
+
async function updateEntryDoc(targetDir, config, options) {
|
|
14882
|
+
const layout = getProviderLayout();
|
|
14883
|
+
const entryPath = join8(targetDir, layout.entryFile);
|
|
14884
|
+
const templateName = getEntryTemplateName2(config.language);
|
|
15076
14885
|
const templatePath = resolveTemplatePath(templateName);
|
|
15077
14886
|
if (!await fileExists(templatePath)) {
|
|
15078
14887
|
warn("update.entry_template_not_found", { template: templateName });
|
|
@@ -15109,9 +14918,8 @@ async function update(options) {
|
|
|
15109
14918
|
try {
|
|
15110
14919
|
info("update.start", { targetDir: options.targetDir });
|
|
15111
14920
|
const config = await loadConfig(options.targetDir);
|
|
15112
|
-
const provider = options.provider ?? (config.provider === "codex" ? "codex" : "claude");
|
|
15113
14921
|
result.previousVersion = config.version;
|
|
15114
|
-
const updateCheck = await checkForUpdates(options.targetDir
|
|
14922
|
+
const updateCheck = await checkForUpdates(options.targetDir);
|
|
15115
14923
|
result.newVersion = updateCheck.latestVersion;
|
|
15116
14924
|
if (!updateCheck.hasUpdates && !options.force) {
|
|
15117
14925
|
info("update.no_updates");
|
|
@@ -15119,14 +14927,14 @@ async function update(options) {
|
|
|
15119
14927
|
result.skippedComponents = options.components || getAllUpdateComponents();
|
|
15120
14928
|
return result;
|
|
15121
14929
|
}
|
|
15122
|
-
await handleBackupIfRequested(options.targetDir,
|
|
14930
|
+
await handleBackupIfRequested(options.targetDir, !!options.backup, result);
|
|
15123
14931
|
const manifestCustomizations = await resolveManifestCustomizations(options, options.targetDir);
|
|
15124
14932
|
const configPreserveFiles = resolveConfigPreserveFiles(options, config);
|
|
15125
14933
|
const customizations = resolveCustomizations(manifestCustomizations, configPreserveFiles, options.targetDir);
|
|
15126
14934
|
const components = options.components || getAllUpdateComponents();
|
|
15127
|
-
await updateAllComponents(options.targetDir,
|
|
14935
|
+
await updateAllComponents(options.targetDir, components, updateCheck, customizations, options, result, config);
|
|
15128
14936
|
if (!options.components || options.components.length === 0) {
|
|
15129
|
-
await updateEntryDoc(options.targetDir,
|
|
14937
|
+
await updateEntryDoc(options.targetDir, config, options);
|
|
15130
14938
|
}
|
|
15131
14939
|
config.version = result.newVersion;
|
|
15132
14940
|
config.lastUpdated = new Date().toISOString();
|
|
@@ -15147,13 +14955,13 @@ async function update(options) {
|
|
|
15147
14955
|
}
|
|
15148
14956
|
return result;
|
|
15149
14957
|
}
|
|
15150
|
-
async function checkForUpdates(targetDir
|
|
14958
|
+
async function checkForUpdates(targetDir) {
|
|
15151
14959
|
const config = await loadConfig(targetDir);
|
|
15152
14960
|
const currentVersion = config.version;
|
|
15153
|
-
const latestVersion = await getLatestVersion(
|
|
14961
|
+
const latestVersion = await getLatestVersion();
|
|
15154
14962
|
const updatableComponents = [];
|
|
15155
14963
|
for (const component of getAllUpdateComponents()) {
|
|
15156
|
-
const hasUpdate = await componentHasUpdate(targetDir,
|
|
14964
|
+
const hasUpdate = await componentHasUpdate(targetDir, component, config);
|
|
15157
14965
|
if (hasUpdate) {
|
|
15158
14966
|
updatableComponents.push({
|
|
15159
14967
|
name: component,
|
|
@@ -15173,8 +14981,8 @@ async function checkForUpdates(targetDir, provider = "claude") {
|
|
|
15173
14981
|
function getAllUpdateComponents() {
|
|
15174
14982
|
return ["rules", "agents", "skills", "guides", "hooks", "contexts"];
|
|
15175
14983
|
}
|
|
15176
|
-
async function getLatestVersion(
|
|
15177
|
-
const layout = getProviderLayout(
|
|
14984
|
+
async function getLatestVersion() {
|
|
14985
|
+
const layout = getProviderLayout();
|
|
15178
14986
|
const manifestPath = resolveTemplatePath(layout.manifestFile);
|
|
15179
14987
|
if (await fileExists(manifestPath)) {
|
|
15180
14988
|
const manifest = await readJsonFile(manifestPath);
|
|
@@ -15182,19 +14990,19 @@ async function getLatestVersion(provider) {
|
|
|
15182
14990
|
}
|
|
15183
14991
|
return "0.0.0";
|
|
15184
14992
|
}
|
|
15185
|
-
async function componentHasUpdate(_targetDir,
|
|
14993
|
+
async function componentHasUpdate(_targetDir, component, config) {
|
|
15186
14994
|
const installedVersion = config.componentVersions?.[component];
|
|
15187
14995
|
if (!installedVersion) {
|
|
15188
14996
|
return true;
|
|
15189
14997
|
}
|
|
15190
|
-
const latestVersion = await getLatestVersion(
|
|
14998
|
+
const latestVersion = await getLatestVersion();
|
|
15191
14999
|
return installedVersion !== latestVersion;
|
|
15192
15000
|
}
|
|
15193
|
-
async function updateComponent(targetDir,
|
|
15001
|
+
async function updateComponent(targetDir, component, customizations, options, config) {
|
|
15194
15002
|
const preservedFiles = [];
|
|
15195
|
-
const componentPath = getComponentPath2(
|
|
15003
|
+
const componentPath = getComponentPath2(component);
|
|
15196
15004
|
const srcPath = resolveTemplatePath(componentPath);
|
|
15197
|
-
const destPath =
|
|
15005
|
+
const destPath = join8(targetDir, componentPath);
|
|
15198
15006
|
const customComponents = config.customComponents || [];
|
|
15199
15007
|
const skipPaths = [];
|
|
15200
15008
|
if (customizations && !options.forceOverwriteAll) {
|
|
@@ -15208,7 +15016,7 @@ async function updateComponent(targetDir, provider, component, customizations, o
|
|
|
15208
15016
|
}
|
|
15209
15017
|
}
|
|
15210
15018
|
const path2 = await import("node:path");
|
|
15211
|
-
const normalizedSkipPaths = skipPaths.map((p) => path2.relative(destPath,
|
|
15019
|
+
const normalizedSkipPaths = skipPaths.map((p) => path2.relative(destPath, join8(targetDir, p)));
|
|
15212
15020
|
await copyDirectory(srcPath, destPath, {
|
|
15213
15021
|
overwrite: true,
|
|
15214
15022
|
skipPaths: normalizedSkipPaths.length > 0 ? normalizedSkipPaths : undefined
|
|
@@ -15219,35 +15027,35 @@ async function updateComponent(targetDir, provider, component, customizations, o
|
|
|
15219
15027
|
});
|
|
15220
15028
|
return preservedFiles;
|
|
15221
15029
|
}
|
|
15222
|
-
function getComponentPath2(
|
|
15223
|
-
const layout = getProviderLayout(
|
|
15030
|
+
function getComponentPath2(component) {
|
|
15031
|
+
const layout = getProviderLayout();
|
|
15224
15032
|
if (component === "guides") {
|
|
15225
15033
|
return "guides";
|
|
15226
15034
|
}
|
|
15227
15035
|
return `${layout.rootDir}/${component}`;
|
|
15228
15036
|
}
|
|
15229
|
-
async function backupInstallation(targetDir
|
|
15037
|
+
async function backupInstallation(targetDir) {
|
|
15230
15038
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
15231
|
-
const backupDir =
|
|
15039
|
+
const backupDir = join8(targetDir, `.omcustom-backup-${timestamp}`);
|
|
15232
15040
|
const fs2 = await import("node:fs/promises");
|
|
15233
15041
|
await ensureDirectory(backupDir);
|
|
15234
|
-
const layout = getProviderLayout(
|
|
15042
|
+
const layout = getProviderLayout();
|
|
15235
15043
|
const dirsToBackup = [layout.rootDir, "guides"];
|
|
15236
15044
|
for (const dir2 of dirsToBackup) {
|
|
15237
|
-
const srcPath =
|
|
15045
|
+
const srcPath = join8(targetDir, dir2);
|
|
15238
15046
|
if (await fileExists(srcPath)) {
|
|
15239
|
-
const destPath =
|
|
15047
|
+
const destPath = join8(backupDir, dir2);
|
|
15240
15048
|
await copyDirectory(srcPath, destPath, { overwrite: true });
|
|
15241
15049
|
}
|
|
15242
15050
|
}
|
|
15243
|
-
const entryPath =
|
|
15051
|
+
const entryPath = join8(targetDir, layout.entryFile);
|
|
15244
15052
|
if (await fileExists(entryPath)) {
|
|
15245
|
-
await fs2.copyFile(entryPath,
|
|
15053
|
+
await fs2.copyFile(entryPath, join8(backupDir, layout.entryFile));
|
|
15246
15054
|
}
|
|
15247
15055
|
return backupDir;
|
|
15248
15056
|
}
|
|
15249
15057
|
async function loadCustomizationManifest(targetDir) {
|
|
15250
|
-
const manifestPath =
|
|
15058
|
+
const manifestPath = join8(targetDir, CUSTOMIZATION_MANIFEST_FILE);
|
|
15251
15059
|
if (await fileExists(manifestPath)) {
|
|
15252
15060
|
return readJsonFile(manifestPath);
|
|
15253
15061
|
}
|
|
@@ -15258,18 +15066,12 @@ async function loadCustomizationManifest(targetDir) {
|
|
|
15258
15066
|
async function updateCommand(options = {}) {
|
|
15259
15067
|
try {
|
|
15260
15068
|
const targetDir = process.cwd();
|
|
15261
|
-
const detection = await detectProvider({
|
|
15262
|
-
targetDir,
|
|
15263
|
-
override: options.provider
|
|
15264
|
-
});
|
|
15265
|
-
const provider = detection.provider;
|
|
15266
15069
|
const components = buildComponentsList(options);
|
|
15267
15070
|
if (options.dryRun) {
|
|
15268
15071
|
console.log(i18n.t("cli.update.dryRunHeader"));
|
|
15269
15072
|
}
|
|
15270
15073
|
const updateOptions = {
|
|
15271
15074
|
targetDir,
|
|
15272
|
-
provider,
|
|
15273
15075
|
components,
|
|
15274
15076
|
force: options.force,
|
|
15275
15077
|
preserveCustomizations: true,
|
|
@@ -15344,20 +15146,19 @@ var packageJson = require2("../../package.json");
|
|
|
15344
15146
|
function createProgram() {
|
|
15345
15147
|
const program2 = new Command;
|
|
15346
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");
|
|
15347
|
-
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) => {
|
|
15348
15150
|
await initCommand(options);
|
|
15349
15151
|
});
|
|
15350
|
-
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) => {
|
|
15351
15153
|
await updateCommand(options);
|
|
15352
15154
|
});
|
|
15353
|
-
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) => {
|
|
15354
15156
|
await listCommand(type, {
|
|
15355
15157
|
format: options.format,
|
|
15356
|
-
verbose: options.verbose
|
|
15357
|
-
provider: options.provider
|
|
15158
|
+
verbose: options.verbose
|
|
15358
15159
|
});
|
|
15359
15160
|
});
|
|
15360
|
-
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) => {
|
|
15361
15162
|
await doctorCommand(options);
|
|
15362
15163
|
});
|
|
15363
15164
|
program2.hook("preAction", async (thisCommand, actionCommand) => {
|