oh-my-customcode 0.10.3 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/dist/cli/index.js +100 -26
- package/dist/index.js +10 -1
- package/package.json +1 -1
- package/templates/.claude/ontology/agents.yaml +546 -0
- package/templates/.claude/ontology/graphs/agent-skill.json +101 -0
- package/templates/.claude/ontology/graphs/full-graph.json +624 -0
- package/templates/.claude/ontology/graphs/routing.json +112 -0
- package/templates/.claude/ontology/graphs/skill-rule.json +77 -0
- package/templates/.claude/ontology/rules.yaml +251 -0
- package/templates/.claude/ontology/schema.yaml +144 -0
- package/templates/.claude/ontology/skills.yaml +538 -0
package/README.md
CHANGED
|
@@ -166,6 +166,12 @@ Event-driven automation for Claude Code lifecycle events (PreToolUse, PostToolUs
|
|
|
166
166
|
|
|
167
167
|
Shared context files for cross-agent knowledge and mode configurations.
|
|
168
168
|
|
|
169
|
+
### Packages
|
|
170
|
+
|
|
171
|
+
| Package | Version | Description |
|
|
172
|
+
|---------|---------|-------------|
|
|
173
|
+
| [ontology-rag](packages/ontology-rag/) | 0.3.0 | Ontology+RAG context engine for intelligent context loading. Reduces token usage by 75-95% through hierarchical loading, graph-based routing, and adaptive compression. |
|
|
174
|
+
|
|
169
175
|
---
|
|
170
176
|
|
|
171
177
|
## CLI Commands
|
package/dist/cli/index.js
CHANGED
|
@@ -12552,6 +12552,7 @@ var MESSAGES = {
|
|
|
12552
12552
|
"install.entry_md_skipped": "{{entry}} skipped ({{reason}})",
|
|
12553
12553
|
"update.start": "Checking for updates...",
|
|
12554
12554
|
"update.success": "Updated from {{from}} to {{to}}",
|
|
12555
|
+
"update.components_synced": "Components synced (version {{version}}): {{components}}",
|
|
12555
12556
|
"update.failed": "Update failed: {{error}}",
|
|
12556
12557
|
"update.no_updates": "Already up to date",
|
|
12557
12558
|
"update.backup_created": "Backup created at: {{path}}",
|
|
@@ -12583,6 +12584,7 @@ var MESSAGES = {
|
|
|
12583
12584
|
"install.entry_md_skipped": "{{entry}} 건너뜀 ({{reason}})",
|
|
12584
12585
|
"update.start": "업데이트 확인 중...",
|
|
12585
12586
|
"update.success": "{{from}}에서 {{to}}로 업데이트 완료",
|
|
12587
|
+
"update.components_synced": "컴포넌트 동기화 완료 (버전 {{version}}): {{components}}",
|
|
12586
12588
|
"update.failed": "업데이트 실패: {{error}}",
|
|
12587
12589
|
"update.no_updates": "이미 최신 버전입니다",
|
|
12588
12590
|
"update.backup_created": "백업 생성됨: {{path}}",
|
|
@@ -13515,7 +13517,7 @@ async function doctorCommand(options = {}) {
|
|
|
13515
13517
|
}
|
|
13516
13518
|
|
|
13517
13519
|
// src/cli/init.ts
|
|
13518
|
-
import { join as
|
|
13520
|
+
import { join as join6 } from "node:path";
|
|
13519
13521
|
|
|
13520
13522
|
// src/core/installer.ts
|
|
13521
13523
|
import { readFile as fsReadFile, writeFile as fsWriteFile, rename } from "node:fs/promises";
|
|
@@ -13976,23 +13978,77 @@ async function backupExistingInstallation(targetDir, provider) {
|
|
|
13976
13978
|
return backedUpPaths.length > 0 ? [backupDir] : [];
|
|
13977
13979
|
}
|
|
13978
13980
|
|
|
13981
|
+
// src/core/mcp-config.ts
|
|
13982
|
+
import { execSync as execSync2 } from "node:child_process";
|
|
13983
|
+
import { writeFile } from "node:fs/promises";
|
|
13984
|
+
import { join as join5 } from "node:path";
|
|
13985
|
+
async function generateMCPConfig(targetDir, provider) {
|
|
13986
|
+
const layout = getProviderLayout(provider);
|
|
13987
|
+
const mcpConfigPath = join5(targetDir, ".mcp.json");
|
|
13988
|
+
const ontologyDir = join5(layout.rootDir, "ontology");
|
|
13989
|
+
const ontologyExists = await fileExists(join5(targetDir, ontologyDir));
|
|
13990
|
+
if (!ontologyExists) {
|
|
13991
|
+
return;
|
|
13992
|
+
}
|
|
13993
|
+
const config = {
|
|
13994
|
+
mcpServers: {
|
|
13995
|
+
"ontology-rag": {
|
|
13996
|
+
type: "stdio",
|
|
13997
|
+
command: "python",
|
|
13998
|
+
args: ["-m", "ontology_rag.mcp_server"],
|
|
13999
|
+
env: {
|
|
14000
|
+
ONTOLOGY_DIR: ontologyDir
|
|
14001
|
+
}
|
|
14002
|
+
}
|
|
14003
|
+
}
|
|
14004
|
+
};
|
|
14005
|
+
const existingConfigPath = mcpConfigPath;
|
|
14006
|
+
if (await fileExists(existingConfigPath)) {
|
|
14007
|
+
try {
|
|
14008
|
+
const { readFile } = await import("node:fs/promises");
|
|
14009
|
+
const existingContent = await readFile(existingConfigPath, "utf-8");
|
|
14010
|
+
const existing = JSON.parse(existingContent);
|
|
14011
|
+
if (!existing.mcpServers?.["ontology-rag"]) {
|
|
14012
|
+
existing.mcpServers = existing.mcpServers || {};
|
|
14013
|
+
existing.mcpServers["ontology-rag"] = config.mcpServers["ontology-rag"];
|
|
14014
|
+
await writeFile(mcpConfigPath, `${JSON.stringify(existing, null, 2)}
|
|
14015
|
+
`);
|
|
14016
|
+
}
|
|
14017
|
+
} catch {
|
|
14018
|
+
await writeFile(mcpConfigPath, `${JSON.stringify(config, null, 2)}
|
|
14019
|
+
`);
|
|
14020
|
+
}
|
|
14021
|
+
} else {
|
|
14022
|
+
await writeFile(mcpConfigPath, `${JSON.stringify(config, null, 2)}
|
|
14023
|
+
`);
|
|
14024
|
+
}
|
|
14025
|
+
}
|
|
14026
|
+
async function checkPythonAvailable() {
|
|
14027
|
+
try {
|
|
14028
|
+
execSync2("python --version", { stdio: "pipe" });
|
|
14029
|
+
return true;
|
|
14030
|
+
} catch {
|
|
14031
|
+
return false;
|
|
14032
|
+
}
|
|
14033
|
+
}
|
|
14034
|
+
|
|
13979
14035
|
// src/cli/init.ts
|
|
13980
14036
|
async function checkExistingInstallation(targetDir, provider) {
|
|
13981
14037
|
const layout = getProviderLayout(provider);
|
|
13982
|
-
const rootDir =
|
|
14038
|
+
const rootDir = join6(targetDir, layout.rootDir);
|
|
13983
14039
|
return fileExists(rootDir);
|
|
13984
14040
|
}
|
|
13985
14041
|
var PROVIDER_SUBDIR_COMPONENTS = new Set(["rules", "hooks", "contexts", "agents", "skills"]);
|
|
13986
14042
|
function componentToPath(targetDir, provider, component) {
|
|
13987
14043
|
if (component === "entry-md") {
|
|
13988
14044
|
const layout = getProviderLayout(provider);
|
|
13989
|
-
return
|
|
14045
|
+
return join6(targetDir, layout.entryFile);
|
|
13990
14046
|
}
|
|
13991
14047
|
if (PROVIDER_SUBDIR_COMPONENTS.has(component)) {
|
|
13992
14048
|
const layout = getProviderLayout(provider);
|
|
13993
|
-
return
|
|
14049
|
+
return join6(targetDir, layout.rootDir, component);
|
|
13994
14050
|
}
|
|
13995
|
-
return
|
|
14051
|
+
return join6(targetDir, component);
|
|
13996
14052
|
}
|
|
13997
14053
|
function buildInstalledPaths(targetDir, provider, components) {
|
|
13998
14054
|
return components.map((component) => componentToPath(targetDir, provider, component));
|
|
@@ -14050,6 +14106,17 @@ async function initCommand(options) {
|
|
|
14050
14106
|
const installedPaths = buildInstalledPaths(targetDir, provider, installResult.installedComponents);
|
|
14051
14107
|
logInstallResultInfo(installResult);
|
|
14052
14108
|
logSuccessDetails(installedPaths, installResult.skippedComponents);
|
|
14109
|
+
const pythonAvailable = await checkPythonAvailable();
|
|
14110
|
+
if (pythonAvailable) {
|
|
14111
|
+
try {
|
|
14112
|
+
await generateMCPConfig(targetDir, provider);
|
|
14113
|
+
} catch {
|
|
14114
|
+
console.warn("Warning: Failed to generate MCP config. You can configure it manually.");
|
|
14115
|
+
}
|
|
14116
|
+
} else {
|
|
14117
|
+
console.warn("Warning: Python not found. Skipping MCP server configuration.");
|
|
14118
|
+
console.warn("Install Python 3.10+ and ontology-rag to enable MCP integration.");
|
|
14119
|
+
}
|
|
14053
14120
|
return {
|
|
14054
14121
|
success: true,
|
|
14055
14122
|
message: i18n.t("cli.init.success"),
|
|
@@ -14063,7 +14130,7 @@ async function initCommand(options) {
|
|
|
14063
14130
|
}
|
|
14064
14131
|
|
|
14065
14132
|
// src/cli/list.ts
|
|
14066
|
-
import { basename as basename2, dirname as dirname2, join as
|
|
14133
|
+
import { basename as basename2, dirname as dirname2, join as join7, relative as relative2 } from "node:path";
|
|
14067
14134
|
var ALLOWED_TOP_LEVEL_KEYS = new Set(["name", "type", "description", "version", "category"]);
|
|
14068
14135
|
function parseKeyValue(line) {
|
|
14069
14136
|
const colonIndex = line.indexOf(":");
|
|
@@ -14127,12 +14194,12 @@ function extractAgentTypeFromFilename(filename) {
|
|
|
14127
14194
|
return prefixMap[prefix] || "unknown";
|
|
14128
14195
|
}
|
|
14129
14196
|
function extractSkillCategoryFromPath(skillPath, baseDir, rootDir) {
|
|
14130
|
-
const relativePath = relative2(
|
|
14197
|
+
const relativePath = relative2(join7(baseDir, rootDir, "skills"), skillPath);
|
|
14131
14198
|
const parts = relativePath.split("/").filter(Boolean);
|
|
14132
14199
|
return parts[0] || "unknown";
|
|
14133
14200
|
}
|
|
14134
14201
|
function extractGuideCategoryFromPath(guidePath, baseDir) {
|
|
14135
|
-
const relativePath = relative2(
|
|
14202
|
+
const relativePath = relative2(join7(baseDir, "guides"), guidePath);
|
|
14136
14203
|
const parts = relativePath.split("/").filter(Boolean);
|
|
14137
14204
|
return parts[0] || "unknown";
|
|
14138
14205
|
}
|
|
@@ -14226,7 +14293,7 @@ async function tryExtractMarkdownDescription(mdPath, options = {}) {
|
|
|
14226
14293
|
}
|
|
14227
14294
|
}
|
|
14228
14295
|
async function getAgents(targetDir, rootDir = ".claude", config) {
|
|
14229
|
-
const agentsDir =
|
|
14296
|
+
const agentsDir = join7(targetDir, rootDir, "agents");
|
|
14230
14297
|
if (!await fileExists(agentsDir))
|
|
14231
14298
|
return [];
|
|
14232
14299
|
try {
|
|
@@ -14254,7 +14321,7 @@ async function getAgents(targetDir, rootDir = ".claude", config) {
|
|
|
14254
14321
|
}
|
|
14255
14322
|
}
|
|
14256
14323
|
async function getSkills(targetDir, rootDir = ".claude", config) {
|
|
14257
|
-
const skillsDir =
|
|
14324
|
+
const skillsDir = join7(targetDir, rootDir, "skills");
|
|
14258
14325
|
if (!await fileExists(skillsDir))
|
|
14259
14326
|
return [];
|
|
14260
14327
|
try {
|
|
@@ -14264,7 +14331,7 @@ async function getSkills(targetDir, rootDir = ".claude", config) {
|
|
|
14264
14331
|
const skillMdFiles = await listFiles(skillsDir, { recursive: true, pattern: "SKILL.md" });
|
|
14265
14332
|
const skills = await Promise.all(skillMdFiles.map(async (skillMdPath) => {
|
|
14266
14333
|
const skillDir = dirname2(skillMdPath);
|
|
14267
|
-
const indexYamlPath =
|
|
14334
|
+
const indexYamlPath = join7(skillDir, "index.yaml");
|
|
14268
14335
|
const { description, version } = await tryReadIndexYamlMetadata(indexYamlPath);
|
|
14269
14336
|
const relativePath = relative2(targetDir, skillDir);
|
|
14270
14337
|
return {
|
|
@@ -14283,7 +14350,7 @@ async function getSkills(targetDir, rootDir = ".claude", config) {
|
|
|
14283
14350
|
}
|
|
14284
14351
|
}
|
|
14285
14352
|
async function getGuides(targetDir, config) {
|
|
14286
|
-
const guidesDir =
|
|
14353
|
+
const guidesDir = join7(targetDir, "guides");
|
|
14287
14354
|
if (!await fileExists(guidesDir))
|
|
14288
14355
|
return [];
|
|
14289
14356
|
try {
|
|
@@ -14310,7 +14377,7 @@ async function getGuides(targetDir, config) {
|
|
|
14310
14377
|
}
|
|
14311
14378
|
var RULE_PRIORITY_ORDER = { MUST: 0, SHOULD: 1, MAY: 2 };
|
|
14312
14379
|
async function getRules(targetDir, rootDir = ".claude", config) {
|
|
14313
|
-
const rulesDir =
|
|
14380
|
+
const rulesDir = join7(targetDir, rootDir, "rules");
|
|
14314
14381
|
if (!await fileExists(rulesDir))
|
|
14315
14382
|
return [];
|
|
14316
14383
|
try {
|
|
@@ -14382,7 +14449,7 @@ function formatAsJson(components) {
|
|
|
14382
14449
|
console.log(JSON.stringify(components, null, 2));
|
|
14383
14450
|
}
|
|
14384
14451
|
async function getHooks(targetDir, rootDir = ".claude") {
|
|
14385
|
-
const hooksDir =
|
|
14452
|
+
const hooksDir = join7(targetDir, rootDir, "hooks");
|
|
14386
14453
|
if (!await fileExists(hooksDir))
|
|
14387
14454
|
return [];
|
|
14388
14455
|
try {
|
|
@@ -14400,7 +14467,7 @@ async function getHooks(targetDir, rootDir = ".claude") {
|
|
|
14400
14467
|
}
|
|
14401
14468
|
}
|
|
14402
14469
|
async function getContexts(targetDir, rootDir = ".claude") {
|
|
14403
|
-
const contextsDir =
|
|
14470
|
+
const contextsDir = join7(targetDir, rootDir, "contexts");
|
|
14404
14471
|
if (!await fileExists(contextsDir))
|
|
14405
14472
|
return [];
|
|
14406
14473
|
try {
|
|
@@ -14485,7 +14552,7 @@ async function listCommand(type = "all", options = {}) {
|
|
|
14485
14552
|
}
|
|
14486
14553
|
|
|
14487
14554
|
// src/core/updater.ts
|
|
14488
|
-
import { join as
|
|
14555
|
+
import { join as join8 } from "node:path";
|
|
14489
14556
|
|
|
14490
14557
|
// src/core/entry-merger.ts
|
|
14491
14558
|
var MANAGED_START = "<!-- omcustom:start -->";
|
|
@@ -14737,7 +14804,7 @@ function resolveCustomizations(customizations, configPreserveFiles, targetDir) {
|
|
|
14737
14804
|
}
|
|
14738
14805
|
async function updateEntryDoc(targetDir, provider, config, options) {
|
|
14739
14806
|
const layout = getProviderLayout(provider);
|
|
14740
|
-
const entryPath =
|
|
14807
|
+
const entryPath = join8(targetDir, layout.entryFile);
|
|
14741
14808
|
const templateName = getEntryTemplateName2(provider, config.language);
|
|
14742
14809
|
const templatePath = resolveTemplatePath(templateName);
|
|
14743
14810
|
if (!await fileExists(templatePath)) {
|
|
@@ -14798,7 +14865,14 @@ async function update(options) {
|
|
|
14798
14865
|
config.lastUpdated = new Date().toISOString();
|
|
14799
14866
|
await saveConfig(options.targetDir, config);
|
|
14800
14867
|
result.success = true;
|
|
14801
|
-
|
|
14868
|
+
if (result.previousVersion !== result.newVersion) {
|
|
14869
|
+
success("update.success", { from: result.previousVersion, to: result.newVersion });
|
|
14870
|
+
} else if (result.updatedComponents.length > 0) {
|
|
14871
|
+
success("update.components_synced", {
|
|
14872
|
+
version: result.newVersion,
|
|
14873
|
+
components: result.updatedComponents.join(", ")
|
|
14874
|
+
});
|
|
14875
|
+
}
|
|
14802
14876
|
} catch (err) {
|
|
14803
14877
|
const message = err instanceof Error ? err.message : String(err);
|
|
14804
14878
|
result.error = message;
|
|
@@ -14853,7 +14927,7 @@ async function updateComponent(targetDir, provider, component, customizations, o
|
|
|
14853
14927
|
const preservedFiles = [];
|
|
14854
14928
|
const componentPath = getComponentPath2(provider, component);
|
|
14855
14929
|
const srcPath = resolveTemplatePath(componentPath);
|
|
14856
|
-
const destPath =
|
|
14930
|
+
const destPath = join8(targetDir, componentPath);
|
|
14857
14931
|
const customComponents = config.customComponents || [];
|
|
14858
14932
|
const skipPaths = [];
|
|
14859
14933
|
if (customizations && !options.forceOverwriteAll) {
|
|
@@ -14867,7 +14941,7 @@ async function updateComponent(targetDir, provider, component, customizations, o
|
|
|
14867
14941
|
}
|
|
14868
14942
|
}
|
|
14869
14943
|
const path2 = await import("node:path");
|
|
14870
|
-
const normalizedSkipPaths = skipPaths.map((p) => path2.relative(destPath,
|
|
14944
|
+
const normalizedSkipPaths = skipPaths.map((p) => path2.relative(destPath, join8(targetDir, p)));
|
|
14871
14945
|
await copyDirectory(srcPath, destPath, {
|
|
14872
14946
|
overwrite: true,
|
|
14873
14947
|
skipPaths: normalizedSkipPaths.length > 0 ? normalizedSkipPaths : undefined
|
|
@@ -14887,26 +14961,26 @@ function getComponentPath2(provider, component) {
|
|
|
14887
14961
|
}
|
|
14888
14962
|
async function backupInstallation(targetDir, provider) {
|
|
14889
14963
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
14890
|
-
const backupDir =
|
|
14964
|
+
const backupDir = join8(targetDir, `.omcustom-backup-${timestamp}`);
|
|
14891
14965
|
const fs2 = await import("node:fs/promises");
|
|
14892
14966
|
await ensureDirectory(backupDir);
|
|
14893
14967
|
const layout = getProviderLayout(provider);
|
|
14894
14968
|
const dirsToBackup = [layout.rootDir, "guides"];
|
|
14895
14969
|
for (const dir2 of dirsToBackup) {
|
|
14896
|
-
const srcPath =
|
|
14970
|
+
const srcPath = join8(targetDir, dir2);
|
|
14897
14971
|
if (await fileExists(srcPath)) {
|
|
14898
|
-
const destPath =
|
|
14972
|
+
const destPath = join8(backupDir, dir2);
|
|
14899
14973
|
await copyDirectory(srcPath, destPath, { overwrite: true });
|
|
14900
14974
|
}
|
|
14901
14975
|
}
|
|
14902
|
-
const entryPath =
|
|
14976
|
+
const entryPath = join8(targetDir, layout.entryFile);
|
|
14903
14977
|
if (await fileExists(entryPath)) {
|
|
14904
|
-
await fs2.copyFile(entryPath,
|
|
14978
|
+
await fs2.copyFile(entryPath, join8(backupDir, layout.entryFile));
|
|
14905
14979
|
}
|
|
14906
14980
|
return backupDir;
|
|
14907
14981
|
}
|
|
14908
14982
|
async function loadCustomizationManifest(targetDir) {
|
|
14909
|
-
const manifestPath =
|
|
14983
|
+
const manifestPath = join8(targetDir, CUSTOMIZATION_MANIFEST_FILE);
|
|
14910
14984
|
if (await fileExists(manifestPath)) {
|
|
14911
14985
|
return readJsonFile(manifestPath);
|
|
14912
14986
|
}
|
package/dist/index.js
CHANGED
|
@@ -238,6 +238,7 @@ var MESSAGES = {
|
|
|
238
238
|
"install.entry_md_skipped": "{{entry}} skipped ({{reason}})",
|
|
239
239
|
"update.start": "Checking for updates...",
|
|
240
240
|
"update.success": "Updated from {{from}} to {{to}}",
|
|
241
|
+
"update.components_synced": "Components synced (version {{version}}): {{components}}",
|
|
241
242
|
"update.failed": "Update failed: {{error}}",
|
|
242
243
|
"update.no_updates": "Already up to date",
|
|
243
244
|
"update.backup_created": "Backup created at: {{path}}",
|
|
@@ -269,6 +270,7 @@ var MESSAGES = {
|
|
|
269
270
|
"install.entry_md_skipped": "{{entry}} 건너뜀 ({{reason}})",
|
|
270
271
|
"update.start": "업데이트 확인 중...",
|
|
271
272
|
"update.success": "{{from}}에서 {{to}}로 업데이트 완료",
|
|
273
|
+
"update.components_synced": "컴포넌트 동기화 완료 (버전 {{version}}): {{components}}",
|
|
272
274
|
"update.failed": "업데이트 실패: {{error}}",
|
|
273
275
|
"update.no_updates": "이미 최신 버전입니다",
|
|
274
276
|
"update.backup_created": "백업 생성됨: {{path}}",
|
|
@@ -1508,7 +1510,14 @@ async function update(options) {
|
|
|
1508
1510
|
config.lastUpdated = new Date().toISOString();
|
|
1509
1511
|
await saveConfig(options.targetDir, config);
|
|
1510
1512
|
result.success = true;
|
|
1511
|
-
|
|
1513
|
+
if (result.previousVersion !== result.newVersion) {
|
|
1514
|
+
success("update.success", { from: result.previousVersion, to: result.newVersion });
|
|
1515
|
+
} else if (result.updatedComponents.length > 0) {
|
|
1516
|
+
success("update.components_synced", {
|
|
1517
|
+
version: result.newVersion,
|
|
1518
|
+
components: result.updatedComponents.join(", ")
|
|
1519
|
+
});
|
|
1520
|
+
}
|
|
1512
1521
|
} catch (err) {
|
|
1513
1522
|
const message = err instanceof Error ? err.message : String(err);
|
|
1514
1523
|
result.error = message;
|