@omnidev-ai/cli 0.13.4 → 0.14.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.
Files changed (2) hide show
  1. package/dist/index.js +1556 -367
  2. package/package.json +5 -2
package/dist/index.js CHANGED
@@ -64,18 +64,25 @@ function parseFrontmatterWithMarkdown(content) {
64
64
  // ../core/src/capability/commands.ts
65
65
  import { existsSync, readdirSync } from "node:fs";
66
66
  import { readFile } from "node:fs/promises";
67
- import { join as join2 } from "node:path";
67
+ import { basename, join } from "node:path";
68
68
  async function loadCommands(capabilityPath, capabilityId) {
69
- const commandsDir = join2(capabilityPath, "commands");
70
- if (!existsSync(commandsDir)) {
71
- return [];
72
- }
73
69
  const commands = [];
74
- const entries = readdirSync(commandsDir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
75
- for (const entry of entries) {
76
- if (entry.isDirectory()) {
77
- const commandPath = join2(commandsDir, entry.name, "COMMAND.md");
78
- if (existsSync(commandPath)) {
70
+ const possibleDirNames = ["commands", "command"];
71
+ for (const dirName of possibleDirNames) {
72
+ const dir = join(capabilityPath, dirName);
73
+ if (!existsSync(dir)) {
74
+ continue;
75
+ }
76
+ const entries = readdirSync(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
77
+ for (const entry of entries) {
78
+ if (entry.isDirectory()) {
79
+ const commandPath = join(dir, entry.name, "COMMAND.md");
80
+ if (existsSync(commandPath)) {
81
+ const command = await parseCommandFile(commandPath, capabilityId);
82
+ commands.push(command);
83
+ }
84
+ } else if (entry.isFile() && entry.name.endsWith(".md")) {
85
+ const commandPath = join(dir, entry.name);
79
86
  const command = await parseCommandFile(commandPath, capabilityId);
80
87
  commands.push(command);
81
88
  }
@@ -91,11 +98,13 @@ async function parseCommandFile(filePath, capabilityId) {
91
98
  }
92
99
  const frontmatter = parsed.frontmatter;
93
100
  const prompt = parsed.markdown;
94
- if (!frontmatter.name || !frontmatter.description) {
101
+ const inferredName = basename(filePath, ".md").replace(/^COMMAND$/i, "");
102
+ const name = frontmatter.name || inferredName;
103
+ if (!name || !frontmatter.description) {
95
104
  throw new Error(`Invalid COMMAND.md at ${filePath}: name and description required`);
96
105
  }
97
106
  const result = {
98
- name: frontmatter.name,
107
+ name,
99
108
  description: frontmatter.description,
100
109
  prompt: prompt.trim(),
101
110
  capabilityId
@@ -110,10 +119,10 @@ var init_commands = () => {};
110
119
  // ../core/src/capability/docs.ts
111
120
  import { existsSync as existsSync2, readdirSync as readdirSync2 } from "node:fs";
112
121
  import { readFile as readFile2 } from "node:fs/promises";
113
- import { basename, join as join3 } from "node:path";
122
+ import { basename as basename2, join as join2 } from "node:path";
114
123
  async function loadDocs(capabilityPath, capabilityId) {
115
124
  const docs = [];
116
- const definitionPath = join3(capabilityPath, "definition.md");
125
+ const definitionPath = join2(capabilityPath, "definition.md");
117
126
  if (existsSync2(definitionPath)) {
118
127
  const content = await readFile2(definitionPath, "utf-8");
119
128
  docs.push({
@@ -122,15 +131,15 @@ async function loadDocs(capabilityPath, capabilityId) {
122
131
  capabilityId
123
132
  });
124
133
  }
125
- const docsDir = join3(capabilityPath, "docs");
134
+ const docsDir = join2(capabilityPath, "docs");
126
135
  if (existsSync2(docsDir)) {
127
136
  const entries = readdirSync2(docsDir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
128
137
  for (const entry of entries) {
129
138
  if (entry.isFile() && entry.name.endsWith(".md")) {
130
- const docPath = join3(docsDir, entry.name);
139
+ const docPath = join2(docsDir, entry.name);
131
140
  const content = await readFile2(docPath, "utf-8");
132
141
  docs.push({
133
- name: basename(entry.name, ".md"),
142
+ name: basename2(entry.name, ".md"),
134
143
  content: content.trim(),
135
144
  capabilityId
136
145
  });
@@ -1057,6 +1066,151 @@ var init_parse = __esm(() => {
1057
1066
  });
1058
1067
 
1059
1068
  // ../../node_modules/.bun/smol-toml@1.6.0/node_modules/smol-toml/dist/stringify.js
1069
+ function extendedTypeOf(obj) {
1070
+ let type = typeof obj;
1071
+ if (type === "object") {
1072
+ if (Array.isArray(obj))
1073
+ return "array";
1074
+ if (obj instanceof Date)
1075
+ return "date";
1076
+ }
1077
+ return type;
1078
+ }
1079
+ function isArrayOfTables(obj) {
1080
+ for (let i = 0;i < obj.length; i++) {
1081
+ if (extendedTypeOf(obj[i]) !== "object")
1082
+ return false;
1083
+ }
1084
+ return obj.length != 0;
1085
+ }
1086
+ function formatString(s) {
1087
+ return JSON.stringify(s).replace(/\x7f/g, "\\u007f");
1088
+ }
1089
+ function stringifyValue(val, type, depth, numberAsFloat) {
1090
+ if (depth === 0) {
1091
+ throw new Error("Could not stringify the object: maximum object depth exceeded");
1092
+ }
1093
+ if (type === "number") {
1094
+ if (isNaN(val))
1095
+ return "nan";
1096
+ if (val === Infinity)
1097
+ return "inf";
1098
+ if (val === -Infinity)
1099
+ return "-inf";
1100
+ if (numberAsFloat && Number.isInteger(val))
1101
+ return val.toFixed(1);
1102
+ return val.toString();
1103
+ }
1104
+ if (type === "bigint" || type === "boolean") {
1105
+ return val.toString();
1106
+ }
1107
+ if (type === "string") {
1108
+ return formatString(val);
1109
+ }
1110
+ if (type === "date") {
1111
+ if (isNaN(val.getTime())) {
1112
+ throw new TypeError("cannot serialize invalid date");
1113
+ }
1114
+ return val.toISOString();
1115
+ }
1116
+ if (type === "object") {
1117
+ return stringifyInlineTable(val, depth, numberAsFloat);
1118
+ }
1119
+ if (type === "array") {
1120
+ return stringifyArray(val, depth, numberAsFloat);
1121
+ }
1122
+ }
1123
+ function stringifyInlineTable(obj, depth, numberAsFloat) {
1124
+ let keys = Object.keys(obj);
1125
+ if (keys.length === 0)
1126
+ return "{}";
1127
+ let res = "{ ";
1128
+ for (let i = 0;i < keys.length; i++) {
1129
+ let k = keys[i];
1130
+ if (i)
1131
+ res += ", ";
1132
+ res += BARE_KEY.test(k) ? k : formatString(k);
1133
+ res += " = ";
1134
+ res += stringifyValue(obj[k], extendedTypeOf(obj[k]), depth - 1, numberAsFloat);
1135
+ }
1136
+ return res + " }";
1137
+ }
1138
+ function stringifyArray(array, depth, numberAsFloat) {
1139
+ if (array.length === 0)
1140
+ return "[]";
1141
+ let res = "[ ";
1142
+ for (let i = 0;i < array.length; i++) {
1143
+ if (i)
1144
+ res += ", ";
1145
+ if (array[i] === null || array[i] === undefined) {
1146
+ throw new TypeError("arrays cannot contain null or undefined values");
1147
+ }
1148
+ res += stringifyValue(array[i], extendedTypeOf(array[i]), depth - 1, numberAsFloat);
1149
+ }
1150
+ return res + " ]";
1151
+ }
1152
+ function stringifyArrayTable(array, key, depth, numberAsFloat) {
1153
+ if (depth === 0) {
1154
+ throw new Error("Could not stringify the object: maximum object depth exceeded");
1155
+ }
1156
+ let res = "";
1157
+ for (let i = 0;i < array.length; i++) {
1158
+ res += `${res && `
1159
+ `}[[${key}]]
1160
+ `;
1161
+ res += stringifyTable(0, array[i], key, depth, numberAsFloat);
1162
+ }
1163
+ return res;
1164
+ }
1165
+ function stringifyTable(tableKey, obj, prefix, depth, numberAsFloat) {
1166
+ if (depth === 0) {
1167
+ throw new Error("Could not stringify the object: maximum object depth exceeded");
1168
+ }
1169
+ let preamble = "";
1170
+ let tables = "";
1171
+ let keys = Object.keys(obj);
1172
+ for (let i = 0;i < keys.length; i++) {
1173
+ let k = keys[i];
1174
+ if (obj[k] !== null && obj[k] !== undefined) {
1175
+ let type = extendedTypeOf(obj[k]);
1176
+ if (type === "symbol" || type === "function") {
1177
+ throw new TypeError(`cannot serialize values of type '${type}'`);
1178
+ }
1179
+ let key = BARE_KEY.test(k) ? k : formatString(k);
1180
+ if (type === "array" && isArrayOfTables(obj[k])) {
1181
+ tables += (tables && `
1182
+ `) + stringifyArrayTable(obj[k], prefix ? `${prefix}.${key}` : key, depth - 1, numberAsFloat);
1183
+ } else if (type === "object") {
1184
+ let tblKey = prefix ? `${prefix}.${key}` : key;
1185
+ tables += (tables && `
1186
+ `) + stringifyTable(tblKey, obj[k], tblKey, depth - 1, numberAsFloat);
1187
+ } else {
1188
+ preamble += key;
1189
+ preamble += " = ";
1190
+ preamble += stringifyValue(obj[k], type, depth, numberAsFloat);
1191
+ preamble += `
1192
+ `;
1193
+ }
1194
+ }
1195
+ }
1196
+ if (tableKey && (preamble || !tables))
1197
+ preamble = preamble ? `[${tableKey}]
1198
+ ${preamble}` : `[${tableKey}]`;
1199
+ return preamble && tables ? `${preamble}
1200
+ ${tables}` : preamble || tables;
1201
+ }
1202
+ function stringify(obj, { maxDepth = 1000, numbersAsFloat = false } = {}) {
1203
+ if (extendedTypeOf(obj) !== "object") {
1204
+ throw new TypeError("stringify can only be called with an object");
1205
+ }
1206
+ let str = stringifyTable(0, obj, "", maxDepth, numbersAsFloat);
1207
+ if (str[str.length - 1] !== `
1208
+ `)
1209
+ return str + `
1210
+ `;
1211
+ return str;
1212
+ }
1213
+ var BARE_KEY;
1060
1214
  var init_stringify = __esm(() => {
1061
1215
  /*!
1062
1216
  * Copyright (c) Squirrel Chat et al., All rights reserved.
@@ -1085,6 +1239,7 @@ var init_stringify = __esm(() => {
1085
1239
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1086
1240
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1087
1241
  */
1242
+ BARE_KEY = /^[a-z0-9-_]+$/i;
1088
1243
  });
1089
1244
 
1090
1245
  // ../../node_modules/.bun/smol-toml@1.6.0/node_modules/smol-toml/dist/index.js
@@ -1162,7 +1317,7 @@ var init_parser = __esm(() => {
1162
1317
  });
1163
1318
 
1164
1319
  // ../core/src/hooks/constants.ts
1165
- var HOOK_EVENTS, MATCHER_EVENTS, PROMPT_HOOK_EVENTS, HOOK_TYPES, COMMON_TOOL_MATCHERS, NOTIFICATION_MATCHERS, SESSION_START_MATCHERS, PRE_COMPACT_MATCHERS, DEFAULT_COMMAND_TIMEOUT = 60, DEFAULT_PROMPT_TIMEOUT = 30, VARIABLE_MAPPINGS, HOOKS_CONFIG_FILENAME = "hooks.toml", HOOKS_DIRECTORY = "hooks";
1320
+ var HOOK_EVENTS, MATCHER_EVENTS, PROMPT_HOOK_EVENTS, HOOK_TYPES, COMMON_TOOL_MATCHERS, NOTIFICATION_MATCHERS, SESSION_START_MATCHERS, PRE_COMPACT_MATCHERS, DEFAULT_COMMAND_TIMEOUT = 60, DEFAULT_PROMPT_TIMEOUT = 30, VARIABLE_MAPPINGS, HOOKS_CONFIG_FILENAME = "hooks.toml", CLAUDE_HOOKS_CONFIG_FILENAME = "hooks.json", HOOKS_DIRECTORY = "hooks";
1166
1321
  var init_constants = __esm(() => {
1167
1322
  HOOK_EVENTS = [
1168
1323
  "PreToolUse",
@@ -1698,34 +1853,369 @@ function containsOmnidevVariables(content) {
1698
1853
  }
1699
1854
  return false;
1700
1855
  }
1856
+ function resolveCapabilityRoot(content, capabilityPath) {
1857
+ let result = content;
1858
+ const variables = ["OMNIDEV_CAPABILITY_ROOT", "CLAUDE_PLUGIN_ROOT"];
1859
+ for (const varName of variables) {
1860
+ result = result.replace(new RegExp(`\\$\\{${varName}\\}`, "g"), capabilityPath);
1861
+ result = result.replace(new RegExp(`\\$${varName}(?![A-Za-z0-9_])`, "g"), capabilityPath);
1862
+ }
1863
+ return result;
1864
+ }
1865
+ function resolveCapabilityRootInConfig(config, capabilityPath) {
1866
+ const result = {};
1867
+ if (config.description !== undefined) {
1868
+ result.description = config.description;
1869
+ }
1870
+ const events = [
1871
+ "PreToolUse",
1872
+ "PostToolUse",
1873
+ "PermissionRequest",
1874
+ "UserPromptSubmit",
1875
+ "Stop",
1876
+ "SubagentStop",
1877
+ "Notification",
1878
+ "SessionStart",
1879
+ "SessionEnd",
1880
+ "PreCompact"
1881
+ ];
1882
+ for (const event of events) {
1883
+ const matchers = config[event];
1884
+ if (matchers) {
1885
+ result[event] = matchers.map((matcher) => ({
1886
+ ...matcher,
1887
+ hooks: matcher.hooks.map((hook) => {
1888
+ if (hook.type === "command") {
1889
+ return {
1890
+ ...hook,
1891
+ command: resolveCapabilityRoot(hook.command, capabilityPath)
1892
+ };
1893
+ }
1894
+ if (hook.type === "prompt") {
1895
+ return {
1896
+ ...hook,
1897
+ prompt: resolveCapabilityRoot(hook.prompt, capabilityPath)
1898
+ };
1899
+ }
1900
+ return hook;
1901
+ })
1902
+ }));
1903
+ }
1904
+ }
1905
+ return result;
1906
+ }
1701
1907
  var REVERSE_MAPPINGS;
1702
1908
  var init_variables = __esm(() => {
1703
1909
  init_constants();
1704
1910
  REVERSE_MAPPINGS = Object.fromEntries(Object.entries(VARIABLE_MAPPINGS).map(([omni, claude]) => [claude, omni]));
1705
1911
  });
1706
1912
 
1707
- // ../core/src/hooks/loader.ts
1913
+ // ../core/src/hooks/json-loader.ts
1708
1914
  import { existsSync as existsSync4, readFileSync } from "node:fs";
1709
- import { join as join4 } from "node:path";
1915
+ function loadHooksJson(configPath) {
1916
+ const unknownFieldWarnings = [];
1917
+ if (!existsSync4(configPath)) {
1918
+ return {
1919
+ config: createEmptyHooksConfig(),
1920
+ validation: createEmptyValidationResult(),
1921
+ found: false,
1922
+ configPath,
1923
+ unknownFieldWarnings: []
1924
+ };
1925
+ }
1926
+ let rawContent;
1927
+ try {
1928
+ rawContent = readFileSync(configPath, "utf-8");
1929
+ } catch (error) {
1930
+ return {
1931
+ config: createEmptyHooksConfig(),
1932
+ validation: {
1933
+ valid: false,
1934
+ errors: [
1935
+ {
1936
+ severity: "error",
1937
+ code: "HOOKS_INVALID_TOML",
1938
+ message: `Failed to read hooks.json: ${error instanceof Error ? error.message : String(error)}`,
1939
+ path: configPath
1940
+ }
1941
+ ],
1942
+ warnings: []
1943
+ },
1944
+ found: true,
1945
+ configPath,
1946
+ loadError: `Failed to read: ${error instanceof Error ? error.message : String(error)}`,
1947
+ unknownFieldWarnings: []
1948
+ };
1949
+ }
1950
+ let parsed;
1951
+ try {
1952
+ parsed = JSON.parse(rawContent);
1953
+ } catch (error) {
1954
+ return {
1955
+ config: createEmptyHooksConfig(),
1956
+ validation: {
1957
+ valid: false,
1958
+ errors: [
1959
+ {
1960
+ severity: "error",
1961
+ code: "HOOKS_INVALID_TOML",
1962
+ message: `Invalid JSON syntax: ${error instanceof Error ? error.message : String(error)}`,
1963
+ path: configPath
1964
+ }
1965
+ ],
1966
+ warnings: []
1967
+ },
1968
+ found: true,
1969
+ configPath,
1970
+ loadError: `Invalid JSON: ${error instanceof Error ? error.message : String(error)}`,
1971
+ unknownFieldWarnings: []
1972
+ };
1973
+ }
1974
+ const result = convertClaudeHooksToConfig(parsed, unknownFieldWarnings);
1975
+ return {
1976
+ config: result.config,
1977
+ validation: result.validation,
1978
+ found: true,
1979
+ configPath,
1980
+ unknownFieldWarnings
1981
+ };
1982
+ }
1983
+ function convertClaudeHooksToConfig(claudeHooks, unknownFieldWarnings) {
1984
+ const config = {};
1985
+ const errors = [];
1986
+ const warnings = [];
1987
+ if (typeof claudeHooks !== "object" || claudeHooks === null || Array.isArray(claudeHooks)) {
1988
+ errors.push({
1989
+ severity: "error",
1990
+ code: "HOOKS_INVALID_TOML",
1991
+ message: "hooks.json must be an object"
1992
+ });
1993
+ return { config: createEmptyHooksConfig(), validation: { valid: false, errors, warnings } };
1994
+ }
1995
+ for (const [eventName, matchers] of Object.entries(claudeHooks)) {
1996
+ if (!isHookEvent(eventName)) {
1997
+ unknownFieldWarnings.push(`Unknown event "${eventName}" in hooks.json. Valid events: ${HOOK_EVENTS.join(", ")}`);
1998
+ continue;
1999
+ }
2000
+ const event = eventName;
2001
+ if (!Array.isArray(matchers)) {
2002
+ errors.push({
2003
+ severity: "error",
2004
+ code: "HOOKS_INVALID_TOML",
2005
+ event,
2006
+ message: `${event} must be an array of matchers`
2007
+ });
2008
+ continue;
2009
+ }
2010
+ const convertedMatchers = [];
2011
+ for (let i = 0;i < matchers.length; i++) {
2012
+ const matcher = matchers[i];
2013
+ if (!matcher)
2014
+ continue;
2015
+ if (typeof matcher === "object" && matcher !== null) {
2016
+ for (const key of Object.keys(matcher)) {
2017
+ if (!KNOWN_MATCHER_FIELDS.has(key)) {
2018
+ unknownFieldWarnings.push(`Unknown field "${key}" in ${event}[${i}]. Known fields: ${[...KNOWN_MATCHER_FIELDS].join(", ")}`);
2019
+ }
2020
+ }
2021
+ }
2022
+ const convertedMatcher = convertMatcher(matcher, event, i, errors, unknownFieldWarnings);
2023
+ if (convertedMatcher) {
2024
+ convertedMatchers.push(convertedMatcher);
2025
+ }
2026
+ }
2027
+ if (convertedMatchers.length > 0) {
2028
+ config[event] = convertedMatchers;
2029
+ }
2030
+ }
2031
+ return {
2032
+ config,
2033
+ validation: {
2034
+ valid: errors.length === 0,
2035
+ errors,
2036
+ warnings
2037
+ }
2038
+ };
2039
+ }
2040
+ function convertMatcher(matcher, event, matcherIndex, errors, unknownFieldWarnings) {
2041
+ if (typeof matcher !== "object" || matcher === null || Array.isArray(matcher)) {
2042
+ errors.push({
2043
+ severity: "error",
2044
+ code: "HOOKS_INVALID_TOML",
2045
+ event,
2046
+ matcherIndex,
2047
+ message: `Matcher at index ${matcherIndex} must be an object`
2048
+ });
2049
+ return null;
2050
+ }
2051
+ const hooks = [];
2052
+ const hooksArray = matcher.hooks;
2053
+ if (!hooksArray) {
2054
+ errors.push({
2055
+ severity: "error",
2056
+ code: "HOOKS_INVALID_HOOKS_ARRAY",
2057
+ event,
2058
+ matcherIndex,
2059
+ message: "Matcher must have a 'hooks' array"
2060
+ });
2061
+ return null;
2062
+ }
2063
+ if (!Array.isArray(hooksArray)) {
2064
+ errors.push({
2065
+ severity: "error",
2066
+ code: "HOOKS_INVALID_HOOKS_ARRAY",
2067
+ event,
2068
+ matcherIndex,
2069
+ message: "'hooks' must be an array"
2070
+ });
2071
+ return null;
2072
+ }
2073
+ for (let i = 0;i < hooksArray.length; i++) {
2074
+ const hookEntry = hooksArray[i];
2075
+ if (!hookEntry)
2076
+ continue;
2077
+ if (typeof hookEntry === "object" && hookEntry !== null) {
2078
+ for (const key of Object.keys(hookEntry)) {
2079
+ if (!KNOWN_HOOK_FIELDS.has(key)) {
2080
+ unknownFieldWarnings.push(`Unknown field "${key}" in ${event}[${matcherIndex}].hooks[${i}]. Known fields: ${[...KNOWN_HOOK_FIELDS].join(", ")}`);
2081
+ }
2082
+ }
2083
+ }
2084
+ const hook = convertHook(hookEntry, event, matcherIndex, i, errors);
2085
+ if (hook) {
2086
+ hooks.push(hook);
2087
+ }
2088
+ }
2089
+ if (hooks.length === 0) {
2090
+ return null;
2091
+ }
2092
+ const result = { hooks };
2093
+ if (matcher.matcher !== undefined) {
2094
+ result.matcher = matcher.matcher;
2095
+ }
2096
+ return result;
2097
+ }
2098
+ function convertHook(hookEntry, event, matcherIndex, hookIndex, errors) {
2099
+ if (typeof hookEntry !== "object" || hookEntry === null || Array.isArray(hookEntry)) {
2100
+ errors.push({
2101
+ severity: "error",
2102
+ code: "HOOKS_INVALID_TOML",
2103
+ event,
2104
+ matcherIndex,
2105
+ hookIndex,
2106
+ message: "Hook must be an object"
2107
+ });
2108
+ return null;
2109
+ }
2110
+ const hookType = hookEntry.type;
2111
+ if (!hookType) {
2112
+ errors.push({
2113
+ severity: "error",
2114
+ code: "HOOKS_INVALID_TYPE",
2115
+ event,
2116
+ matcherIndex,
2117
+ hookIndex,
2118
+ message: "Hook must have a 'type' field"
2119
+ });
2120
+ return null;
2121
+ }
2122
+ if (!isHookType(hookType)) {
2123
+ errors.push({
2124
+ severity: "error",
2125
+ code: "HOOKS_INVALID_TYPE",
2126
+ event,
2127
+ matcherIndex,
2128
+ hookIndex,
2129
+ message: `Invalid hook type: "${hookType}". Must be "command" or "prompt"`
2130
+ });
2131
+ return null;
2132
+ }
2133
+ if (hookType === "command") {
2134
+ if (typeof hookEntry.command !== "string") {
2135
+ errors.push({
2136
+ severity: "error",
2137
+ code: "HOOKS_MISSING_COMMAND",
2138
+ event,
2139
+ matcherIndex,
2140
+ hookIndex,
2141
+ message: "Command hook must have a 'command' string field"
2142
+ });
2143
+ return null;
2144
+ }
2145
+ const hook = {
2146
+ type: "command",
2147
+ command: hookEntry.command
2148
+ };
2149
+ if (typeof hookEntry.timeout === "number") {
2150
+ hook.timeout = hookEntry.timeout;
2151
+ }
2152
+ return hook;
2153
+ }
2154
+ if (hookType === "prompt") {
2155
+ if (typeof hookEntry.prompt !== "string") {
2156
+ errors.push({
2157
+ severity: "error",
2158
+ code: "HOOKS_MISSING_PROMPT",
2159
+ event,
2160
+ matcherIndex,
2161
+ hookIndex,
2162
+ message: "Prompt hook must have a 'prompt' string field"
2163
+ });
2164
+ return null;
2165
+ }
2166
+ const hook = {
2167
+ type: "prompt",
2168
+ prompt: hookEntry.prompt
2169
+ };
2170
+ if (typeof hookEntry.timeout === "number") {
2171
+ hook.timeout = hookEntry.timeout;
2172
+ }
2173
+ return hook;
2174
+ }
2175
+ return null;
2176
+ }
2177
+ var KNOWN_HOOK_FIELDS, KNOWN_MATCHER_FIELDS;
2178
+ var init_json_loader = __esm(() => {
2179
+ init_constants();
2180
+ init_types();
2181
+ init_validation();
2182
+ KNOWN_HOOK_FIELDS = new Set(["type", "command", "prompt", "timeout"]);
2183
+ KNOWN_MATCHER_FIELDS = new Set(["matcher", "hooks"]);
2184
+ });
2185
+
2186
+ // ../core/src/hooks/loader.ts
2187
+ import { existsSync as existsSync5, readFileSync as readFileSync2 } from "node:fs";
2188
+ import { join as join3 } from "node:path";
1710
2189
  function loadHooksFromCapability(capabilityPath, options) {
1711
2190
  const opts = {
1712
2191
  transformVariables: true,
1713
2192
  validate: true,
1714
2193
  checkScripts: false,
2194
+ resolveCapabilityRoot: false,
1715
2195
  ...options
1716
2196
  };
1717
- const hooksDir = join4(capabilityPath, HOOKS_DIRECTORY);
1718
- const configPath = join4(hooksDir, HOOKS_CONFIG_FILENAME);
1719
- if (!existsSync4(configPath)) {
2197
+ const hooksDir = join3(capabilityPath, HOOKS_DIRECTORY);
2198
+ const tomlConfigPath = join3(hooksDir, HOOKS_CONFIG_FILENAME);
2199
+ if (existsSync5(tomlConfigPath)) {
2200
+ return loadTomlHooks(capabilityPath, tomlConfigPath, hooksDir, opts);
2201
+ }
2202
+ const hooksJsonInDir = join3(hooksDir, CLAUDE_HOOKS_CONFIG_FILENAME);
2203
+ const hooksJsonAtRoot = join3(capabilityPath, CLAUDE_HOOKS_CONFIG_FILENAME);
2204
+ const hooksJsonDirExists = existsSync5(hooksJsonInDir);
2205
+ const hooksJsonRootExists = existsSync5(hooksJsonAtRoot);
2206
+ if (!hooksJsonDirExists && !hooksJsonRootExists) {
1720
2207
  return {
1721
2208
  config: createEmptyHooksConfig(),
1722
2209
  validation: createEmptyValidationResult(),
1723
2210
  found: false
1724
2211
  };
1725
2212
  }
2213
+ return loadJsonHooksFiles(capabilityPath, hooksJsonInDir, hooksJsonAtRoot, hooksDir, opts);
2214
+ }
2215
+ function loadTomlHooks(capabilityPath, configPath, hooksDir, opts) {
1726
2216
  let rawContent;
1727
2217
  try {
1728
- rawContent = readFileSync(configPath, "utf-8");
2218
+ rawContent = readFileSync2(configPath, "utf-8");
1729
2219
  } catch (error) {
1730
2220
  return {
1731
2221
  config: createEmptyHooksConfig(),
@@ -1782,13 +2272,102 @@ function loadHooksFromCapability(capabilityPath, options) {
1782
2272
  } else {
1783
2273
  validation = createEmptyValidationResult();
1784
2274
  }
2275
+ let config = validation.valid ? parsed : createEmptyHooksConfig();
2276
+ if (opts.resolveCapabilityRoot && validation.valid) {
2277
+ config = resolveCapabilityRootInConfig(config, capabilityPath);
2278
+ }
1785
2279
  return {
1786
- config: validation.valid ? parsed : createEmptyHooksConfig(),
2280
+ config,
1787
2281
  validation,
1788
2282
  found: true,
1789
2283
  configPath
1790
2284
  };
1791
2285
  }
2286
+ function loadJsonHooksFiles(capabilityPath, hooksJsonInDir, hooksJsonAtRoot, hooksDir, opts) {
2287
+ const configs = [];
2288
+ const allErrors = [];
2289
+ const allWarnings = [];
2290
+ const unknownFieldWarnings = [];
2291
+ let foundPath;
2292
+ if (existsSync5(hooksJsonInDir)) {
2293
+ const result2 = loadHooksJson(hooksJsonInDir);
2294
+ if (result2.found) {
2295
+ foundPath = result2.configPath;
2296
+ if (result2.loadError) {
2297
+ allErrors.push(...result2.validation.errors);
2298
+ } else {
2299
+ configs.push(result2.config);
2300
+ allErrors.push(...result2.validation.errors);
2301
+ allWarnings.push(...result2.validation.warnings);
2302
+ }
2303
+ unknownFieldWarnings.push(...result2.unknownFieldWarnings);
2304
+ }
2305
+ }
2306
+ if (existsSync5(hooksJsonAtRoot)) {
2307
+ const result2 = loadHooksJson(hooksJsonAtRoot);
2308
+ if (result2.found) {
2309
+ if (!foundPath) {
2310
+ foundPath = result2.configPath;
2311
+ }
2312
+ if (result2.loadError) {
2313
+ allErrors.push(...result2.validation.errors);
2314
+ } else {
2315
+ configs.push(result2.config);
2316
+ allErrors.push(...result2.validation.errors);
2317
+ allWarnings.push(...result2.validation.warnings);
2318
+ }
2319
+ unknownFieldWarnings.push(...result2.unknownFieldWarnings);
2320
+ }
2321
+ }
2322
+ for (const warning of unknownFieldWarnings) {
2323
+ console.warn(`[hooks] Warning: ${warning}`);
2324
+ }
2325
+ let mergedConfig = createEmptyHooksConfig();
2326
+ if (configs.length > 0) {
2327
+ mergedConfig = mergeRawHooksConfigs(configs);
2328
+ }
2329
+ let validation;
2330
+ if (opts.validate && allErrors.length === 0) {
2331
+ validation = validateHooksConfig(mergedConfig, {
2332
+ basePath: hooksDir,
2333
+ checkScripts: opts.checkScripts ?? false
2334
+ });
2335
+ } else {
2336
+ validation = {
2337
+ valid: allErrors.length === 0,
2338
+ errors: allErrors,
2339
+ warnings: allWarnings
2340
+ };
2341
+ }
2342
+ if (opts.resolveCapabilityRoot && validation.valid) {
2343
+ mergedConfig = resolveCapabilityRootInConfig(mergedConfig, capabilityPath);
2344
+ }
2345
+ const result = {
2346
+ config: validation.valid ? mergedConfig : createEmptyHooksConfig(),
2347
+ validation,
2348
+ found: true
2349
+ };
2350
+ if (foundPath) {
2351
+ result.configPath = foundPath;
2352
+ }
2353
+ return result;
2354
+ }
2355
+ function mergeRawHooksConfigs(configs) {
2356
+ const result = {};
2357
+ for (const event of HOOK_EVENTS) {
2358
+ const allMatchers = [];
2359
+ for (const config of configs) {
2360
+ const matchers = config[event];
2361
+ if (matchers && matchers.length > 0) {
2362
+ allMatchers.push(...matchers);
2363
+ }
2364
+ }
2365
+ if (allMatchers.length > 0) {
2366
+ result[event] = allMatchers;
2367
+ }
2368
+ }
2369
+ return result;
2370
+ }
1792
2371
  function loadCapabilityHooks(capabilityName, capabilityPath, options) {
1793
2372
  const result = loadHooksFromCapability(capabilityPath, options);
1794
2373
  if (!result.found) {
@@ -1802,39 +2381,43 @@ function loadCapabilityHooks(capabilityName, capabilityPath, options) {
1802
2381
  };
1803
2382
  }
1804
2383
  function hasHooks(capabilityPath) {
1805
- const configPath = join4(capabilityPath, HOOKS_DIRECTORY, HOOKS_CONFIG_FILENAME);
1806
- return existsSync4(configPath);
2384
+ const tomlPath = join3(capabilityPath, HOOKS_DIRECTORY, HOOKS_CONFIG_FILENAME);
2385
+ const jsonInDir = join3(capabilityPath, HOOKS_DIRECTORY, CLAUDE_HOOKS_CONFIG_FILENAME);
2386
+ const jsonAtRoot = join3(capabilityPath, CLAUDE_HOOKS_CONFIG_FILENAME);
2387
+ return existsSync5(tomlPath) || existsSync5(jsonInDir) || existsSync5(jsonAtRoot);
1807
2388
  }
1808
2389
  function getHooksDirectory(capabilityPath) {
1809
- return join4(capabilityPath, HOOKS_DIRECTORY);
2390
+ return join3(capabilityPath, HOOKS_DIRECTORY);
1810
2391
  }
1811
2392
  function getHooksConfigPath(capabilityPath) {
1812
- return join4(capabilityPath, HOOKS_DIRECTORY, HOOKS_CONFIG_FILENAME);
2393
+ return join3(capabilityPath, HOOKS_DIRECTORY, HOOKS_CONFIG_FILENAME);
1813
2394
  }
1814
2395
  var init_loader = __esm(() => {
1815
2396
  init_dist();
1816
2397
  init_constants();
1817
2398
  init_validation();
1818
2399
  init_variables();
2400
+ init_json_loader();
2401
+ init_constants();
1819
2402
  });
1820
2403
 
1821
2404
  // ../core/src/capability/rules.ts
1822
- import { existsSync as existsSync5, readdirSync as readdirSync3 } from "node:fs";
2405
+ import { existsSync as existsSync6, readdirSync as readdirSync3 } from "node:fs";
1823
2406
  import { readFile as readFile3 } from "node:fs/promises";
1824
- import { basename as basename2, join as join5 } from "node:path";
2407
+ import { basename as basename3, join as join4 } from "node:path";
1825
2408
  async function loadRules(capabilityPath, capabilityId) {
1826
- const rulesDir = join5(capabilityPath, "rules");
1827
- if (!existsSync5(rulesDir)) {
2409
+ const rulesDir = join4(capabilityPath, "rules");
2410
+ if (!existsSync6(rulesDir)) {
1828
2411
  return [];
1829
2412
  }
1830
2413
  const rules = [];
1831
2414
  const entries = readdirSync3(rulesDir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
1832
2415
  for (const entry of entries) {
1833
2416
  if (entry.isFile() && entry.name.endsWith(".md")) {
1834
- const rulePath = join5(rulesDir, entry.name);
2417
+ const rulePath = join4(rulesDir, entry.name);
1835
2418
  const content = await readFile3(rulePath, "utf-8");
1836
2419
  rules.push({
1837
- name: basename2(entry.name, ".md"),
2420
+ name: basename3(entry.name, ".md"),
1838
2421
  content: content.trim(),
1839
2422
  capabilityId
1840
2423
  });
@@ -1845,22 +2428,25 @@ async function loadRules(capabilityPath, capabilityId) {
1845
2428
  var init_rules = () => {};
1846
2429
 
1847
2430
  // ../core/src/capability/skills.ts
1848
- import { existsSync as existsSync6, readdirSync as readdirSync4 } from "node:fs";
2431
+ import { existsSync as existsSync7, readdirSync as readdirSync4 } from "node:fs";
1849
2432
  import { readFile as readFile4 } from "node:fs/promises";
1850
- import { join as join6 } from "node:path";
2433
+ import { join as join5 } from "node:path";
1851
2434
  async function loadSkills(capabilityPath, capabilityId) {
1852
- const skillsDir = join6(capabilityPath, "skills");
1853
- if (!existsSync6(skillsDir)) {
1854
- return [];
1855
- }
1856
2435
  const skills = [];
1857
- const entries = readdirSync4(skillsDir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
1858
- for (const entry of entries) {
1859
- if (entry.isDirectory()) {
1860
- const skillPath = join6(skillsDir, entry.name, "SKILL.md");
1861
- if (existsSync6(skillPath)) {
1862
- const skill = await parseSkillFile(skillPath, capabilityId);
1863
- skills.push(skill);
2436
+ const possibleDirNames = ["skills", "skill"];
2437
+ for (const dirName of possibleDirNames) {
2438
+ const dir = join5(capabilityPath, dirName);
2439
+ if (!existsSync7(dir)) {
2440
+ continue;
2441
+ }
2442
+ const entries = readdirSync4(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
2443
+ for (const entry of entries) {
2444
+ if (entry.isDirectory()) {
2445
+ const skillPath = join5(dir, entry.name, "SKILL.md");
2446
+ if (existsSync7(skillPath)) {
2447
+ const skill = await parseSkillFile(skillPath, capabilityId);
2448
+ skills.push(skill);
2449
+ }
1864
2450
  }
1865
2451
  }
1866
2452
  }
@@ -1875,7 +2461,7 @@ async function parseSkillFile(filePath, capabilityId) {
1875
2461
  const frontmatter = parsed.frontmatter;
1876
2462
  const instructions = parsed.markdown;
1877
2463
  if (!frontmatter.name || !frontmatter.description) {
1878
- throw new Error(`Invalid SKILL.md at ${filePath}: name and description required`);
2464
+ throw new Error(`Invalid SKILL.md at ${filePath}: name and description required in frontmatter`);
1879
2465
  }
1880
2466
  return {
1881
2467
  name: frontmatter.name,
@@ -1887,20 +2473,30 @@ async function parseSkillFile(filePath, capabilityId) {
1887
2473
  var init_skills = () => {};
1888
2474
 
1889
2475
  // ../core/src/capability/subagents.ts
1890
- import { existsSync as existsSync7, readdirSync as readdirSync5 } from "node:fs";
2476
+ import { existsSync as existsSync8, readdirSync as readdirSync5 } from "node:fs";
1891
2477
  import { readFile as readFile5 } from "node:fs/promises";
1892
- import { join as join7 } from "node:path";
2478
+ import { basename as basename4, join as join6 } from "node:path";
1893
2479
  async function loadSubagents(capabilityPath, capabilityId) {
1894
- const subagentsDir = join7(capabilityPath, "subagents");
1895
- if (!existsSync7(subagentsDir)) {
1896
- return [];
1897
- }
1898
2480
  const subagents = [];
1899
- const entries = readdirSync5(subagentsDir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
1900
- for (const entry of entries) {
1901
- if (entry.isDirectory()) {
1902
- const subagentPath = join7(subagentsDir, entry.name, "SUBAGENT.md");
1903
- if (existsSync7(subagentPath)) {
2481
+ const possibleDirNames = ["subagents", "agents", "agent", "subagent"];
2482
+ for (const dirName of possibleDirNames) {
2483
+ const dir = join6(capabilityPath, dirName);
2484
+ if (!existsSync8(dir)) {
2485
+ continue;
2486
+ }
2487
+ const entries = readdirSync5(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
2488
+ for (const entry of entries) {
2489
+ if (entry.isDirectory()) {
2490
+ let subagentPath = join6(dir, entry.name, "SUBAGENT.md");
2491
+ if (!existsSync8(subagentPath)) {
2492
+ subagentPath = join6(dir, entry.name, "AGENT.md");
2493
+ }
2494
+ if (existsSync8(subagentPath)) {
2495
+ const subagent = await parseSubagentFile(subagentPath, capabilityId);
2496
+ subagents.push(subagent);
2497
+ }
2498
+ } else if (entry.isFile() && entry.name.endsWith(".md")) {
2499
+ const subagentPath = join6(dir, entry.name);
1904
2500
  const subagent = await parseSubagentFile(subagentPath, capabilityId);
1905
2501
  subagents.push(subagent);
1906
2502
  }
@@ -1916,11 +2512,13 @@ async function parseSubagentFile(filePath, capabilityId) {
1916
2512
  }
1917
2513
  const frontmatter = parsed.frontmatter;
1918
2514
  const systemPrompt = parsed.markdown;
1919
- if (!frontmatter.name || !frontmatter.description) {
2515
+ const inferredName = basename4(filePath, ".md").replace(/^SUBAGENT$/i, "").replace(/^AGENT$/i, "");
2516
+ const name = frontmatter.name || inferredName;
2517
+ if (!name || !frontmatter.description) {
1920
2518
  throw new Error(`Invalid SUBAGENT.md at ${filePath}: name and description required`);
1921
2519
  }
1922
2520
  const result = {
1923
- name: frontmatter.name,
2521
+ name,
1924
2522
  description: frontmatter.description,
1925
2523
  systemPrompt: systemPrompt.trim(),
1926
2524
  capabilityId
@@ -1951,18 +2549,18 @@ function parseCommaSeparatedList(value) {
1951
2549
  var init_subagents = () => {};
1952
2550
 
1953
2551
  // ../core/src/capability/loader.ts
1954
- import { existsSync as existsSync8, readdirSync as readdirSync6 } from "node:fs";
2552
+ import { existsSync as existsSync9, readdirSync as readdirSync6 } from "node:fs";
1955
2553
  import { readFile as readFile6 } from "node:fs/promises";
1956
- import { join as join8 } from "node:path";
2554
+ import { join as join7 } from "node:path";
1957
2555
  async function discoverCapabilities() {
1958
2556
  const capabilities = [];
1959
- if (existsSync8(CAPABILITIES_DIR)) {
2557
+ if (existsSync9(CAPABILITIES_DIR)) {
1960
2558
  const entries = readdirSync6(CAPABILITIES_DIR, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
1961
2559
  for (const entry of entries) {
1962
2560
  if (entry.isDirectory()) {
1963
- const entryPath = join8(CAPABILITIES_DIR, entry.name);
1964
- const configPath = join8(entryPath, "capability.toml");
1965
- if (existsSync8(configPath)) {
2561
+ const entryPath = join7(CAPABILITIES_DIR, entry.name);
2562
+ const configPath = join7(entryPath, "capability.toml");
2563
+ if (existsSync9(configPath)) {
1966
2564
  capabilities.push(entryPath);
1967
2565
  }
1968
2566
  }
@@ -1971,28 +2569,28 @@ async function discoverCapabilities() {
1971
2569
  return capabilities;
1972
2570
  }
1973
2571
  async function loadCapabilityConfig(capabilityPath) {
1974
- const configPath = join8(capabilityPath, "capability.toml");
2572
+ const configPath = join7(capabilityPath, "capability.toml");
1975
2573
  const content = await readFile6(configPath, "utf-8");
1976
2574
  const config = parseCapabilityConfig(content);
1977
2575
  return config;
1978
2576
  }
1979
2577
  async function importCapabilityExports(capabilityPath) {
1980
- const builtIndexPath = join8(capabilityPath, "dist", "index.js");
1981
- const jsIndexPath = join8(capabilityPath, "index.js");
1982
- const tsIndexPath = join8(capabilityPath, "index.ts");
2578
+ const builtIndexPath = join7(capabilityPath, "dist", "index.js");
2579
+ const jsIndexPath = join7(capabilityPath, "index.js");
2580
+ const tsIndexPath = join7(capabilityPath, "index.ts");
1983
2581
  let indexPath = null;
1984
- if (existsSync8(builtIndexPath)) {
2582
+ if (existsSync9(builtIndexPath)) {
1985
2583
  indexPath = builtIndexPath;
1986
- } else if (existsSync8(jsIndexPath)) {
2584
+ } else if (existsSync9(jsIndexPath)) {
1987
2585
  indexPath = jsIndexPath;
1988
- } else if (existsSync8(tsIndexPath)) {
2586
+ } else if (existsSync9(tsIndexPath)) {
1989
2587
  indexPath = tsIndexPath;
1990
2588
  }
1991
2589
  if (!indexPath) {
1992
2590
  return {};
1993
2591
  }
1994
2592
  try {
1995
- const absolutePath = join8(process.cwd(), indexPath);
2593
+ const absolutePath = join7(process.cwd(), indexPath);
1996
2594
  const module = await import(absolutePath);
1997
2595
  return module;
1998
2596
  } catch (error) {
@@ -2012,8 +2610,8 @@ If this is a project-specific capability, install dependencies or remove it from
2012
2610
  }
2013
2611
  }
2014
2612
  async function loadTypeDefinitions(capabilityPath) {
2015
- const typesPath = join8(capabilityPath, "types.d.ts");
2016
- if (!existsSync8(typesPath)) {
2613
+ const typesPath = join7(capabilityPath, "types.d.ts");
2614
+ if (!existsSync9(typesPath)) {
2017
2615
  return;
2018
2616
  }
2019
2617
  return readFile6(typesPath, "utf-8");
@@ -2206,7 +2804,7 @@ async function loadCapability(capabilityPath) {
2206
2804
  const typeDefinitionsFromExports = "typeDefinitions" in exports && typeof exportsAny.typeDefinitions === "string" ? exportsAny.typeDefinitions : undefined;
2207
2805
  const typeDefinitions = typeDefinitionsFromExports !== undefined ? typeDefinitionsFromExports : await loadTypeDefinitions(capabilityPath);
2208
2806
  const gitignore = "gitignore" in exports && Array.isArray(exportsAny.gitignore) ? exportsAny.gitignore : undefined;
2209
- const hooks = loadCapabilityHooks(id, capabilityPath);
2807
+ const hooks = loadCapabilityHooks(id, capabilityPath, { resolveCapabilityRoot: true });
2210
2808
  const result = {
2211
2809
  id,
2212
2810
  path: capabilityPath,
@@ -2241,8 +2839,8 @@ var init_loader2 = __esm(() => {
2241
2839
  });
2242
2840
 
2243
2841
  // ../core/src/config/config.ts
2244
- import { existsSync as existsSync9 } from "node:fs";
2245
- import { readFile as readFile7, writeFile as writeFile2 } from "node:fs/promises";
2842
+ import { existsSync as existsSync10 } from "node:fs";
2843
+ import { readFile as readFile7, writeFile } from "node:fs/promises";
2246
2844
  function mergeConfigs(base, override) {
2247
2845
  const merged = { ...base, ...override };
2248
2846
  merged.profiles = { ...base.profiles };
@@ -2255,10 +2853,36 @@ function mergeConfigs(base, override) {
2255
2853
  if (base.mcps || override.mcps) {
2256
2854
  merged.mcps = { ...base.mcps, ...override.mcps };
2257
2855
  }
2856
+ if (base.capabilities || override.capabilities) {
2857
+ merged.capabilities = {
2858
+ ...base.capabilities,
2859
+ ...override.capabilities,
2860
+ sources: { ...base.capabilities?.sources, ...override.capabilities?.sources },
2861
+ groups: { ...base.capabilities?.groups, ...override.capabilities?.groups },
2862
+ always_enabled: [
2863
+ ...new Set([
2864
+ ...base.capabilities?.always_enabled ?? [],
2865
+ ...override.capabilities?.always_enabled ?? []
2866
+ ])
2867
+ ],
2868
+ always_disabled: [
2869
+ ...new Set([
2870
+ ...base.capabilities?.always_disabled ?? [],
2871
+ ...override.capabilities?.always_disabled ?? []
2872
+ ])
2873
+ ]
2874
+ };
2875
+ if (merged.capabilities.always_enabled?.length === 0) {
2876
+ delete merged.capabilities.always_enabled;
2877
+ }
2878
+ if (merged.capabilities.always_disabled?.length === 0) {
2879
+ delete merged.capabilities.always_disabled;
2880
+ }
2881
+ }
2258
2882
  return merged;
2259
2883
  }
2260
2884
  async function loadBaseConfig() {
2261
- if (existsSync9(CONFIG_PATH)) {
2885
+ if (existsSync10(CONFIG_PATH)) {
2262
2886
  const content = await readFile7(CONFIG_PATH, "utf-8");
2263
2887
  return parseOmniConfig(content);
2264
2888
  }
@@ -2267,7 +2891,7 @@ async function loadBaseConfig() {
2267
2891
  async function loadConfig() {
2268
2892
  const baseConfig = await loadBaseConfig();
2269
2893
  let localConfig = {};
2270
- if (existsSync9(LOCAL_CONFIG)) {
2894
+ if (existsSync10(LOCAL_CONFIG)) {
2271
2895
  const content = await readFile7(LOCAL_CONFIG, "utf-8");
2272
2896
  localConfig = parseOmniConfig(content);
2273
2897
  }
@@ -2275,7 +2899,7 @@ async function loadConfig() {
2275
2899
  }
2276
2900
  async function writeConfig(config) {
2277
2901
  const content = generateConfigToml(config);
2278
- await writeFile2(CONFIG_PATH, content, "utf-8");
2902
+ await writeFile(CONFIG_PATH, content, "utf-8");
2279
2903
  }
2280
2904
  function generateConfigToml(config) {
2281
2905
  const lines = [];
@@ -2432,10 +3056,10 @@ var init_config = __esm(() => {
2432
3056
  });
2433
3057
 
2434
3058
  // ../core/src/state/active-profile.ts
2435
- import { existsSync as existsSync10, mkdirSync } from "node:fs";
2436
- import { readFile as readFile8, unlink, writeFile as writeFile3 } from "node:fs/promises";
3059
+ import { existsSync as existsSync11, mkdirSync } from "node:fs";
3060
+ import { readFile as readFile8, unlink, writeFile as writeFile2 } from "node:fs/promises";
2437
3061
  async function readActiveProfileState() {
2438
- if (!existsSync10(ACTIVE_PROFILE_PATH)) {
3062
+ if (!existsSync11(ACTIVE_PROFILE_PATH)) {
2439
3063
  return null;
2440
3064
  }
2441
3065
  try {
@@ -2448,10 +3072,10 @@ async function readActiveProfileState() {
2448
3072
  }
2449
3073
  async function writeActiveProfileState(profileName) {
2450
3074
  mkdirSync(STATE_DIR, { recursive: true });
2451
- await writeFile3(ACTIVE_PROFILE_PATH, profileName, "utf-8");
3075
+ await writeFile2(ACTIVE_PROFILE_PATH, profileName, "utf-8");
2452
3076
  }
2453
3077
  async function clearActiveProfileState() {
2454
- if (existsSync10(ACTIVE_PROFILE_PATH)) {
3078
+ if (existsSync11(ACTIVE_PROFILE_PATH)) {
2455
3079
  await unlink(ACTIVE_PROFILE_PATH);
2456
3080
  }
2457
3081
  }
@@ -2471,6 +3095,7 @@ function resolveEnabledCapabilities(config, profileName) {
2471
3095
  const profile = profileName ? config.profiles?.[profileName] : config.profiles?.["default"];
2472
3096
  const profileCapabilities = profile?.capabilities ?? [];
2473
3097
  const alwaysEnabled = config.capabilities?.always_enabled ?? [];
3098
+ const alwaysDisabled = config.capabilities?.always_disabled ?? [];
2474
3099
  const groups = config.capabilities?.groups ?? {};
2475
3100
  const expandCapabilities = (caps) => {
2476
3101
  return caps.flatMap((cap) => {
@@ -2488,7 +3113,9 @@ function resolveEnabledCapabilities(config, profileName) {
2488
3113
  };
2489
3114
  const expandedAlways = expandCapabilities(alwaysEnabled);
2490
3115
  const expandedProfile = expandCapabilities(profileCapabilities);
2491
- return [...new Set([...expandedAlways, ...expandedProfile])];
3116
+ const expandedDisabled = new Set(expandCapabilities(alwaysDisabled));
3117
+ const allEnabled = [...new Set([...expandedAlways, ...expandedProfile])];
3118
+ return allEnabled.filter((cap) => !expandedDisabled.has(cap));
2492
3119
  }
2493
3120
  async function loadProfileConfig(profileName) {
2494
3121
  const config = await loadConfig();
@@ -2692,10 +3319,10 @@ function getActiveProviders(config) {
2692
3319
  var init_types2 = () => {};
2693
3320
 
2694
3321
  // ../core/src/capability/sources.ts
2695
- import { existsSync as existsSync11 } from "node:fs";
3322
+ import { existsSync as existsSync12 } from "node:fs";
2696
3323
  import { spawn } from "node:child_process";
2697
- import { cp, mkdir as mkdir2, readdir, readFile as readFile9, rename, rm, stat, writeFile as writeFile4 } from "node:fs/promises";
2698
- import { join as join9 } from "node:path";
3324
+ import { cp, mkdir, readdir, readFile as readFile9, rename, rm, stat, writeFile as writeFile3 } from "node:fs/promises";
3325
+ import { join as join8 } from "node:path";
2699
3326
  import { createHash } from "node:crypto";
2700
3327
  async function spawnCapture(command, args, options) {
2701
3328
  const timeout = options?.timeout ?? 60000;
@@ -2752,8 +3379,8 @@ function parseFileSourcePath(source) {
2752
3379
  return source.slice(7);
2753
3380
  }
2754
3381
  async function readCapabilityIdFromPath(capabilityPath) {
2755
- const tomlPath = join9(capabilityPath, "capability.toml");
2756
- if (existsSync11(tomlPath)) {
3382
+ const tomlPath = join8(capabilityPath, "capability.toml");
3383
+ if (existsSync12(tomlPath)) {
2757
3384
  try {
2758
3385
  const content = await readFile9(tomlPath, "utf-8");
2759
3386
  const parsed = parse(content);
@@ -2808,14 +3435,14 @@ function sourceToGitUrl(source) {
2808
3435
  return source;
2809
3436
  }
2810
3437
  function getSourceCapabilityPath(id) {
2811
- return join9(OMNI_LOCAL, "capabilities", id);
3438
+ return join8(OMNI_LOCAL, "capabilities", id);
2812
3439
  }
2813
3440
  function getLockFilePath() {
2814
3441
  return "omni.lock.toml";
2815
3442
  }
2816
3443
  async function loadLockFile() {
2817
3444
  const lockPath = getLockFilePath();
2818
- if (!existsSync11(lockPath)) {
3445
+ if (!existsSync12(lockPath)) {
2819
3446
  return { capabilities: {} };
2820
3447
  }
2821
3448
  try {
@@ -2877,14 +3504,14 @@ function stringifyLockFile(lockFile) {
2877
3504
  }
2878
3505
  async function saveLockFile(lockFile) {
2879
3506
  const lockPath = getLockFilePath();
2880
- await mkdir2(join9(OMNI_LOCAL, "capabilities"), { recursive: true });
3507
+ await mkdir(join8(OMNI_LOCAL, "capabilities"), { recursive: true });
2881
3508
  const header = `# Auto-generated by OmniDev - DO NOT EDIT
2882
3509
  # Records installed capability versions for reproducibility
2883
3510
  # Last updated: ${new Date().toISOString()}
2884
3511
 
2885
3512
  `;
2886
3513
  const content = header + stringifyLockFile(lockFile);
2887
- await writeFile4(lockPath, content, "utf-8");
3514
+ await writeFile3(lockPath, content, "utf-8");
2888
3515
  }
2889
3516
  async function getRepoCommit(repoPath) {
2890
3517
  const { exitCode, stdout, stderr } = await spawnCapture("git", ["rev-parse", "HEAD"], {
@@ -2908,7 +3535,7 @@ async function computeContentHash(dirPath, excludePatterns = CONTENT_HASH_EXCLUD
2908
3535
  const entries = await readdir(currentPath, { withFileTypes: true });
2909
3536
  entries.sort((a, b) => a.name.localeCompare(b.name));
2910
3537
  for (const entry of entries) {
2911
- const fullPath = join9(currentPath, entry.name);
3538
+ const fullPath = join8(currentPath, entry.name);
2912
3539
  const relativePath = fullPath.slice(relativeTo.length + 1);
2913
3540
  if (excludePatterns.some((pattern) => entry.name === pattern || relativePath.startsWith(`${pattern}/`))) {
2914
3541
  continue;
@@ -2930,8 +3557,8 @@ async function computeContentHash(dirPath, excludePatterns = CONTENT_HASH_EXCLUD
2930
3557
  return hash.digest("hex");
2931
3558
  }
2932
3559
  async function detectDisplayVersion(dirPath, fallback, fallbackSource) {
2933
- const capTomlPath = join9(dirPath, "capability.toml");
2934
- if (existsSync11(capTomlPath)) {
3560
+ const capTomlPath = join8(dirPath, "capability.toml");
3561
+ if (existsSync12(capTomlPath)) {
2935
3562
  try {
2936
3563
  const content = await readFile9(capTomlPath, "utf-8");
2937
3564
  const parsed = parse(content);
@@ -2941,8 +3568,8 @@ async function detectDisplayVersion(dirPath, fallback, fallbackSource) {
2941
3568
  }
2942
3569
  } catch {}
2943
3570
  }
2944
- const pluginJsonPath = join9(dirPath, ".claude-plugin", "plugin.json");
2945
- if (existsSync11(pluginJsonPath)) {
3571
+ const pluginJsonPath = join8(dirPath, ".claude-plugin", "plugin.json");
3572
+ if (existsSync12(pluginJsonPath)) {
2946
3573
  try {
2947
3574
  const content = await readFile9(pluginJsonPath, "utf-8");
2948
3575
  const parsed = JSON.parse(content);
@@ -2951,8 +3578,8 @@ async function detectDisplayVersion(dirPath, fallback, fallbackSource) {
2951
3578
  }
2952
3579
  } catch {}
2953
3580
  }
2954
- const pkgJsonPath = join9(dirPath, "package.json");
2955
- if (existsSync11(pkgJsonPath)) {
3581
+ const pkgJsonPath = join8(dirPath, "package.json");
3582
+ if (existsSync12(pkgJsonPath)) {
2956
3583
  try {
2957
3584
  const content = await readFile9(pkgJsonPath, "utf-8");
2958
3585
  const parsed = JSON.parse(content);
@@ -2963,20 +3590,111 @@ async function detectDisplayVersion(dirPath, fallback, fallbackSource) {
2963
3590
  }
2964
3591
  return { version: fallback, source: fallbackSource };
2965
3592
  }
3593
+ async function validateGitCapability(sourceUrl, subPath) {
3594
+ const gitUrl = sourceToGitUrl(sourceUrl);
3595
+ const tempPath = join8(OMNI_LOCAL, "_temp", `_validate-${Date.now()}`);
3596
+ try {
3597
+ await mkdir(join8(tempPath, ".."), { recursive: true });
3598
+ const args = ["clone", "--depth", "1", gitUrl, tempPath];
3599
+ const { exitCode, stderr } = await spawnCapture("git", args, { timeout: 30000 });
3600
+ if (exitCode !== 0) {
3601
+ const stderrLower = stderr.toLowerCase();
3602
+ if (stderrLower.includes("not found") || stderrLower.includes("repository not found") || stderrLower.includes("does not exist")) {
3603
+ return {
3604
+ valid: false,
3605
+ hasCapabilityToml: false,
3606
+ canBeWrapped: false,
3607
+ error: "Repository not found"
3608
+ };
3609
+ }
3610
+ if (stderrLower.includes("could not resolve host")) {
3611
+ return {
3612
+ valid: false,
3613
+ hasCapabilityToml: false,
3614
+ canBeWrapped: false,
3615
+ error: "Could not resolve host - check your network connection"
3616
+ };
3617
+ }
3618
+ if (stderrLower.includes("authentication") || stderrLower.includes("permission denied")) {
3619
+ return {
3620
+ valid: false,
3621
+ hasCapabilityToml: false,
3622
+ canBeWrapped: false,
3623
+ error: "Authentication failed - repository may be private"
3624
+ };
3625
+ }
3626
+ return {
3627
+ valid: false,
3628
+ hasCapabilityToml: false,
3629
+ canBeWrapped: false,
3630
+ error: `Failed to clone repository: ${stderr.trim()}`
3631
+ };
3632
+ }
3633
+ const checkPath = subPath ? join8(tempPath, subPath) : tempPath;
3634
+ if (subPath && !existsSync12(checkPath)) {
3635
+ return {
3636
+ valid: false,
3637
+ hasCapabilityToml: false,
3638
+ canBeWrapped: false,
3639
+ error: `Path '${subPath}' not found in repository`
3640
+ };
3641
+ }
3642
+ const hasCapToml = hasCapabilityToml(checkPath);
3643
+ let capabilityId;
3644
+ if (hasCapToml) {
3645
+ const tomlPath = join8(checkPath, "capability.toml");
3646
+ try {
3647
+ const content = await readFile9(tomlPath, "utf-8");
3648
+ const parsed = parse(content);
3649
+ const capability = parsed["capability"];
3650
+ if (capability?.["id"] && typeof capability["id"] === "string") {
3651
+ capabilityId = capability["id"];
3652
+ }
3653
+ } catch {}
3654
+ const result = {
3655
+ valid: true,
3656
+ hasCapabilityToml: true,
3657
+ canBeWrapped: true
3658
+ };
3659
+ if (capabilityId) {
3660
+ result.capabilityId = capabilityId;
3661
+ }
3662
+ return result;
3663
+ }
3664
+ const canWrap = await shouldWrapDirectory(checkPath);
3665
+ if (!canWrap) {
3666
+ return {
3667
+ valid: false,
3668
+ hasCapabilityToml: false,
3669
+ canBeWrapped: false,
3670
+ error: "Repository does not contain a capability.toml and cannot be auto-wrapped (no skills, agents, commands, rules, docs, or .claude-plugin found)"
3671
+ };
3672
+ }
3673
+ return {
3674
+ valid: true,
3675
+ hasCapabilityToml: false,
3676
+ canBeWrapped: true
3677
+ };
3678
+ } finally {
3679
+ if (existsSync12(tempPath)) {
3680
+ await rm(tempPath, { recursive: true });
3681
+ }
3682
+ }
3683
+ }
2966
3684
  async function detectPinVersion(sourceUrl, subPath) {
2967
3685
  const gitUrl = sourceToGitUrl(sourceUrl);
2968
- const tempPath = join9(OMNI_LOCAL, "_temp", `_pin-detect-${Date.now()}`);
3686
+ const tempPath = join8(OMNI_LOCAL, "_temp", `_pin-detect-${Date.now()}`);
2969
3687
  try {
2970
- await mkdir2(join9(tempPath, ".."), { recursive: true });
3688
+ await mkdir(join8(tempPath, ".."), { recursive: true });
2971
3689
  const args = ["clone", "--depth", "1", gitUrl, tempPath];
2972
3690
  const { exitCode, stderr } = await spawnCapture("git", args);
2973
3691
  if (exitCode !== 0) {
2974
3692
  throw new Error(`Failed to clone ${gitUrl}: ${stderr.trim()}`);
2975
3693
  }
2976
3694
  const commit = await getRepoCommit(tempPath);
2977
- const checkPath = subPath ? join9(tempPath, subPath) : tempPath;
2978
- const capTomlPath = join9(checkPath, "capability.toml");
2979
- if (existsSync11(capTomlPath)) {
3695
+ const checkPath = subPath ? join8(tempPath, subPath) : tempPath;
3696
+ const capTomlPath = join8(checkPath, "capability.toml");
3697
+ if (existsSync12(capTomlPath)) {
2980
3698
  try {
2981
3699
  const content = await readFile9(capTomlPath, "utf-8");
2982
3700
  const parsed = parse(content);
@@ -2986,8 +3704,8 @@ async function detectPinVersion(sourceUrl, subPath) {
2986
3704
  }
2987
3705
  } catch {}
2988
3706
  }
2989
- const pluginJsonPath = join9(checkPath, ".claude-plugin", "plugin.json");
2990
- if (existsSync11(pluginJsonPath)) {
3707
+ const pluginJsonPath = join8(checkPath, ".claude-plugin", "plugin.json");
3708
+ if (existsSync12(pluginJsonPath)) {
2991
3709
  try {
2992
3710
  const content = await readFile9(pluginJsonPath, "utf-8");
2993
3711
  const parsed = JSON.parse(content);
@@ -2998,13 +3716,13 @@ async function detectPinVersion(sourceUrl, subPath) {
2998
3716
  }
2999
3717
  return commit;
3000
3718
  } finally {
3001
- if (existsSync11(tempPath)) {
3719
+ if (existsSync12(tempPath)) {
3002
3720
  await rm(tempPath, { recursive: true });
3003
3721
  }
3004
3722
  }
3005
3723
  }
3006
3724
  async function cloneRepo(gitUrl, targetPath, ref) {
3007
- await mkdir2(join9(targetPath, ".."), { recursive: true });
3725
+ await mkdir(join8(targetPath, ".."), { recursive: true });
3008
3726
  const args = ["clone", "--depth", "1"];
3009
3727
  if (ref) {
3010
3728
  args.push("--branch", ref);
@@ -3041,16 +3759,16 @@ async function fetchRepo(repoPath, ref) {
3041
3759
  return true;
3042
3760
  }
3043
3761
  function hasCapabilityToml(dirPath) {
3044
- return existsSync11(join9(dirPath, "capability.toml"));
3762
+ return existsSync12(join8(dirPath, "capability.toml"));
3045
3763
  }
3046
3764
  async function shouldWrapDirectory(dirPath) {
3047
- if (existsSync11(join9(dirPath, ".claude-plugin", "plugin.json"))) {
3765
+ if (existsSync12(join8(dirPath, ".claude-plugin", "plugin.json"))) {
3048
3766
  return true;
3049
3767
  }
3050
3768
  const allDirs = [...SKILL_DIRS, ...AGENT_DIRS, ...COMMAND_DIRS, ...RULE_DIRS, ...DOC_DIRS];
3051
3769
  for (const dirName of allDirs) {
3052
- const checkPath = join9(dirPath, dirName);
3053
- if (existsSync11(checkPath)) {
3770
+ const checkPath = join8(dirPath, dirName);
3771
+ if (existsSync12(checkPath)) {
3054
3772
  const stats = await stat(checkPath);
3055
3773
  if (stats.isDirectory()) {
3056
3774
  return true;
@@ -3061,8 +3779,8 @@ async function shouldWrapDirectory(dirPath) {
3061
3779
  }
3062
3780
  async function findMatchingDirs(basePath, names) {
3063
3781
  for (const name of names) {
3064
- const dirPath = join9(basePath, name);
3065
- if (existsSync11(dirPath)) {
3782
+ const dirPath = join8(basePath, name);
3783
+ if (existsSync12(dirPath)) {
3066
3784
  const stats = await stat(dirPath);
3067
3785
  if (stats.isDirectory()) {
3068
3786
  return dirPath;
@@ -3073,15 +3791,15 @@ async function findMatchingDirs(basePath, names) {
3073
3791
  }
3074
3792
  async function findContentItems(dirPath, filePatterns) {
3075
3793
  const items = [];
3076
- if (!existsSync11(dirPath)) {
3794
+ if (!existsSync12(dirPath)) {
3077
3795
  return items;
3078
3796
  }
3079
3797
  const entries = (await readdir(dirPath, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name));
3080
3798
  for (const entry of entries) {
3081
- const entryPath = join9(dirPath, entry.name);
3799
+ const entryPath = join8(dirPath, entry.name);
3082
3800
  if (entry.isDirectory()) {
3083
3801
  for (const pattern of filePatterns) {
3084
- if (existsSync11(join9(entryPath, pattern))) {
3802
+ if (existsSync12(join8(entryPath, pattern))) {
3085
3803
  items.push({
3086
3804
  name: entry.name,
3087
3805
  path: entryPath,
@@ -3102,8 +3820,8 @@ async function findContentItems(dirPath, filePatterns) {
3102
3820
  return items;
3103
3821
  }
3104
3822
  async function parsePluginJson(dirPath) {
3105
- const pluginJsonPath = join9(dirPath, ".claude-plugin", "plugin.json");
3106
- if (!existsSync11(pluginJsonPath)) {
3823
+ const pluginJsonPath = join8(dirPath, ".claude-plugin", "plugin.json");
3824
+ if (!existsSync12(pluginJsonPath)) {
3107
3825
  return null;
3108
3826
  }
3109
3827
  try {
@@ -3127,8 +3845,8 @@ async function parsePluginJson(dirPath) {
3127
3845
  }
3128
3846
  }
3129
3847
  async function readReadmeDescription(dirPath) {
3130
- const readmePath = join9(dirPath, "README.md");
3131
- if (!existsSync11(readmePath)) {
3848
+ const readmePath = join8(dirPath, "README.md");
3849
+ if (!existsSync12(readmePath)) {
3132
3850
  return null;
3133
3851
  }
3134
3852
  try {
@@ -3164,14 +3882,12 @@ async function normalizeFolderNames(repoPath) {
3164
3882
  const renameMappings = [
3165
3883
  { from: "skill", to: "skills" },
3166
3884
  { from: "command", to: "commands" },
3167
- { from: "rule", to: "rules" },
3168
- { from: "agent", to: "agents" },
3169
- { from: "subagent", to: "subagents" }
3885
+ { from: "rule", to: "rules" }
3170
3886
  ];
3171
3887
  for (const { from, to } of renameMappings) {
3172
- const fromPath = join9(repoPath, from);
3173
- const toPath = join9(repoPath, to);
3174
- if (existsSync11(fromPath) && !existsSync11(toPath)) {
3888
+ const fromPath = join8(repoPath, from);
3889
+ const toPath = join8(repoPath, to);
3890
+ if (existsSync12(fromPath) && !existsSync12(toPath)) {
3175
3891
  try {
3176
3892
  const stats = await stat(fromPath);
3177
3893
  if (stats.isDirectory()) {
@@ -3260,7 +3976,7 @@ repository = "${repoUrl}"
3260
3976
  wrapped = true
3261
3977
  commit = "${commit}"
3262
3978
  `;
3263
- await writeFile4(join9(repoPath, "capability.toml"), tomlContent, "utf-8");
3979
+ await writeFile3(join8(repoPath, "capability.toml"), tomlContent, "utf-8");
3264
3980
  }
3265
3981
  async function fetchGitCapabilitySource(id, config, options) {
3266
3982
  const gitUrl = sourceToGitUrl(config.source);
@@ -3270,29 +3986,29 @@ async function fetchGitCapabilitySource(id, config, options) {
3270
3986
  let repoPath;
3271
3987
  const gitRef = config.version && config.version !== "latest" ? config.version : undefined;
3272
3988
  if (config.path) {
3273
- const tempPath = join9(OMNI_LOCAL, "_temp", `${id}-repo`);
3274
- if (existsSync11(join9(tempPath, ".git"))) {
3989
+ const tempPath = join8(OMNI_LOCAL, "_temp", `${id}-repo`);
3990
+ if (existsSync12(join8(tempPath, ".git"))) {
3275
3991
  updated = await fetchRepo(tempPath, gitRef);
3276
3992
  commit = await getRepoCommit(tempPath);
3277
3993
  } else {
3278
- await mkdir2(join9(tempPath, ".."), { recursive: true });
3994
+ await mkdir(join8(tempPath, ".."), { recursive: true });
3279
3995
  await cloneRepo(gitUrl, tempPath, gitRef);
3280
3996
  commit = await getRepoCommit(tempPath);
3281
3997
  updated = true;
3282
3998
  }
3283
- const sourcePath = join9(tempPath, config.path);
3284
- if (!existsSync11(sourcePath)) {
3999
+ const sourcePath = join8(tempPath, config.path);
4000
+ if (!existsSync12(sourcePath)) {
3285
4001
  throw new Error(`Path not found in repository: ${config.path}`);
3286
4002
  }
3287
- if (existsSync11(targetPath)) {
4003
+ if (existsSync12(targetPath)) {
3288
4004
  await rm(targetPath, { recursive: true });
3289
4005
  }
3290
- await mkdir2(join9(targetPath, ".."), { recursive: true });
4006
+ await mkdir(join8(targetPath, ".."), { recursive: true });
3291
4007
  await cp(sourcePath, targetPath, { recursive: true });
3292
4008
  await rm(tempPath, { recursive: true });
3293
4009
  repoPath = targetPath;
3294
4010
  } else {
3295
- if (existsSync11(join9(targetPath, ".git"))) {
4011
+ if (existsSync12(join8(targetPath, ".git"))) {
3296
4012
  if (!options?.silent) {
3297
4013
  console.log(` Checking ${id}...`);
3298
4014
  }
@@ -3343,7 +4059,7 @@ async function fetchGitCapabilitySource(id, config, options) {
3343
4059
  async function fetchFileCapabilitySource(id, config, options) {
3344
4060
  const sourcePath = parseFileSourcePath(config.source);
3345
4061
  const targetPath = getSourceCapabilityPath(id);
3346
- if (!existsSync11(sourcePath)) {
4062
+ if (!existsSync12(sourcePath)) {
3347
4063
  throw new Error(`File source not found: ${sourcePath}`);
3348
4064
  }
3349
4065
  const sourceStats = await stat(sourcePath);
@@ -3351,7 +4067,7 @@ async function fetchFileCapabilitySource(id, config, options) {
3351
4067
  throw new Error(`File source must be a directory: ${sourcePath}`);
3352
4068
  }
3353
4069
  const contentHash = await computeContentHash(sourcePath);
3354
- const hasCapToml = existsSync11(join9(sourcePath, "capability.toml"));
4070
+ const hasCapToml = existsSync12(join8(sourcePath, "capability.toml"));
3355
4071
  let needsWrap = false;
3356
4072
  if (!hasCapToml) {
3357
4073
  needsWrap = await shouldWrapDirectory(sourcePath);
@@ -3362,10 +4078,10 @@ async function fetchFileCapabilitySource(id, config, options) {
3362
4078
  if (!options?.silent) {
3363
4079
  console.log(` Copying ${id} from ${sourcePath}...`);
3364
4080
  }
3365
- if (existsSync11(targetPath)) {
4081
+ if (existsSync12(targetPath)) {
3366
4082
  await rm(targetPath, { recursive: true });
3367
4083
  }
3368
- await mkdir2(join9(targetPath, ".."), { recursive: true });
4084
+ await mkdir(join8(targetPath, ".."), { recursive: true });
3369
4085
  await cp(sourcePath, targetPath, { recursive: true });
3370
4086
  if (needsWrap) {
3371
4087
  await normalizeFolderNames(targetPath);
@@ -3445,7 +4161,7 @@ description = "${description}"
3445
4161
  wrapped = true
3446
4162
  source = "${source}"
3447
4163
  `;
3448
- await writeFile4(join9(targetPath, "capability.toml"), tomlContent, "utf-8");
4164
+ await writeFile3(join8(targetPath, "capability.toml"), tomlContent, "utf-8");
3449
4165
  }
3450
4166
  async function fetchCapabilitySource(id, sourceConfig, options) {
3451
4167
  const config = parseSourceConfig(sourceConfig);
@@ -3518,11 +4234,11 @@ generated_from_omni_toml = true
3518
4234
  }
3519
4235
  async function generateMcpCapabilityToml(id, mcpConfig, targetPath) {
3520
4236
  const tomlContent = generateMcpCapabilityTomlContent(id, mcpConfig);
3521
- await writeFile4(join9(targetPath, "capability.toml"), tomlContent, "utf-8");
4237
+ await writeFile3(join8(targetPath, "capability.toml"), tomlContent, "utf-8");
3522
4238
  }
3523
4239
  async function isGeneratedMcpCapability(capabilityDir) {
3524
- const tomlPath = join9(capabilityDir, "capability.toml");
3525
- if (!existsSync11(tomlPath)) {
4240
+ const tomlPath = join8(capabilityDir, "capability.toml");
4241
+ if (!existsSync12(tomlPath)) {
3526
4242
  console.warn("no capability.toml found in", capabilityDir);
3527
4243
  return false;
3528
4244
  }
@@ -3537,14 +4253,14 @@ async function isGeneratedMcpCapability(capabilityDir) {
3537
4253
  }
3538
4254
  }
3539
4255
  async function cleanupStaleMcpCapabilities(currentMcpIds) {
3540
- const capabilitiesDir = join9(OMNI_LOCAL, "capabilities");
3541
- if (!existsSync11(capabilitiesDir)) {
4256
+ const capabilitiesDir = join8(OMNI_LOCAL, "capabilities");
4257
+ if (!existsSync12(capabilitiesDir)) {
3542
4258
  return;
3543
4259
  }
3544
4260
  const entries = await readdir(capabilitiesDir, { withFileTypes: true });
3545
4261
  for (const entry of entries) {
3546
4262
  if (entry.isDirectory()) {
3547
- const capDir = join9(capabilitiesDir, entry.name);
4263
+ const capDir = join8(capabilitiesDir, entry.name);
3548
4264
  const isGenerated = await isGeneratedMcpCapability(capDir);
3549
4265
  if (isGenerated && !currentMcpIds.has(entry.name)) {
3550
4266
  await rm(capDir, { recursive: true });
@@ -3557,20 +4273,20 @@ async function generateMcpCapabilities(config) {
3557
4273
  await cleanupStaleMcpCapabilities(new Set);
3558
4274
  return;
3559
4275
  }
3560
- const mcpCapabilitiesDir = join9(OMNI_LOCAL, "capabilities");
4276
+ const mcpCapabilitiesDir = join8(OMNI_LOCAL, "capabilities");
3561
4277
  const currentMcpIds = new Set;
3562
4278
  for (const [id, mcpConfig] of Object.entries(config.mcps)) {
3563
- const targetPath = join9(mcpCapabilitiesDir, id);
4279
+ const targetPath = join8(mcpCapabilitiesDir, id);
3564
4280
  currentMcpIds.add(id);
3565
- await mkdir2(targetPath, { recursive: true });
4281
+ await mkdir(targetPath, { recursive: true });
3566
4282
  await generateMcpCapabilityToml(id, mcpConfig, targetPath);
3567
4283
  }
3568
4284
  await cleanupStaleMcpCapabilities(currentMcpIds);
3569
4285
  }
3570
4286
  async function fetchAllCapabilitySources(config, options) {
3571
4287
  await generateMcpCapabilities(config);
3572
- const tempDir = join9(OMNI_LOCAL, "_temp");
3573
- if (existsSync11(tempDir)) {
4288
+ const tempDir = join8(OMNI_LOCAL, "_temp");
4289
+ if (existsSync12(tempDir)) {
3574
4290
  await rm(tempDir, { recursive: true });
3575
4291
  }
3576
4292
  const sources = config.capabilities?.sources;
@@ -3656,7 +4372,7 @@ async function checkForUpdates(config) {
3656
4372
  continue;
3657
4373
  }
3658
4374
  const gitConfig = sourceConfig;
3659
- if (!existsSync11(join9(targetPath, ".git"))) {
4375
+ if (!existsSync12(join8(targetPath, ".git"))) {
3660
4376
  updates.push({
3661
4377
  id,
3662
4378
  source: gitConfig.source,
@@ -3699,12 +4415,12 @@ function checkVersionMismatch(lockEntry, currentCommit, currentVersion) {
3699
4415
  }
3700
4416
  async function verifyIntegrity(id, lockEntry) {
3701
4417
  const capabilityPath = getSourceCapabilityPath(id);
3702
- if (!existsSync11(capabilityPath)) {
4418
+ if (!existsSync12(capabilityPath)) {
3703
4419
  return "capability directory missing";
3704
4420
  }
3705
4421
  if (lockEntry.commit) {
3706
- const gitDir = join9(capabilityPath, ".git");
3707
- if (existsSync11(gitDir)) {
4422
+ const gitDir = join8(capabilityPath, ".git");
4423
+ if (existsSync12(gitDir)) {
3708
4424
  try {
3709
4425
  const currentCommit = await getRepoCommit(capabilityPath);
3710
4426
  if (currentCommit !== lockEntry.commit) {
@@ -3769,13 +4485,14 @@ var init_hooks = __esm(() => {
3769
4485
  init_variables();
3770
4486
  init_loader();
3771
4487
  init_merger();
4488
+ init_json_loader();
3772
4489
  });
3773
4490
 
3774
4491
  // ../core/src/config/provider.ts
3775
- import { existsSync as existsSync12 } from "node:fs";
3776
- import { readFile as readFile10, writeFile as writeFile5 } from "node:fs/promises";
4492
+ import { existsSync as existsSync13 } from "node:fs";
4493
+ import { readFile as readFile10, writeFile as writeFile4 } from "node:fs/promises";
3777
4494
  async function loadProviderConfig() {
3778
- if (!existsSync12(PROVIDER_CONFIG_PATH)) {
4495
+ if (!existsSync13(PROVIDER_CONFIG_PATH)) {
3779
4496
  return { provider: "claude" };
3780
4497
  }
3781
4498
  const content = await readFile10(PROVIDER_CONFIG_PATH, "utf-8");
@@ -3805,7 +4522,7 @@ async function writeProviderConfig(config) {
3805
4522
  lines.push("# Default: Claude");
3806
4523
  lines.push('provider = "claude"');
3807
4524
  }
3808
- await writeFile5(PROVIDER_CONFIG_PATH, `${lines.join(`
4525
+ await writeFile4(PROVIDER_CONFIG_PATH, `${lines.join(`
3809
4526
  `)}
3810
4527
  `, "utf-8");
3811
4528
  }
@@ -3825,16 +4542,16 @@ var init_provider = __esm(() => {
3825
4542
  });
3826
4543
 
3827
4544
  // ../core/src/config/toml-patcher.ts
3828
- import { existsSync as existsSync13 } from "node:fs";
3829
- import { readFile as readFile11, writeFile as writeFile6 } from "node:fs/promises";
4545
+ import { existsSync as existsSync14 } from "node:fs";
4546
+ import { readFile as readFile11, writeFile as writeFile5 } from "node:fs/promises";
3830
4547
  async function readConfigFile() {
3831
- if (!existsSync13(CONFIG_PATH2)) {
4548
+ if (!existsSync14(CONFIG_PATH2)) {
3832
4549
  return "";
3833
4550
  }
3834
4551
  return readFile11(CONFIG_PATH2, "utf-8");
3835
4552
  }
3836
4553
  async function writeConfigFile(content) {
3837
- await writeFile6(CONFIG_PATH2, content, "utf-8");
4554
+ await writeFile5(CONFIG_PATH2, content, "utf-8");
3838
4555
  }
3839
4556
  function findSection(lines, sectionPattern) {
3840
4557
  return lines.findIndex((line) => sectionPattern.test(line.trim()));
@@ -4053,10 +4770,10 @@ var init_config2 = __esm(() => {
4053
4770
  });
4054
4771
 
4055
4772
  // ../core/src/mcp-json/manager.ts
4056
- import { existsSync as existsSync14 } from "node:fs";
4057
- import { readFile as readFile12, writeFile as writeFile7 } from "node:fs/promises";
4773
+ import { existsSync as existsSync15 } from "node:fs";
4774
+ import { readFile as readFile12, writeFile as writeFile6 } from "node:fs/promises";
4058
4775
  async function readMcpJson() {
4059
- if (!existsSync14(MCP_JSON_PATH)) {
4776
+ if (!existsSync15(MCP_JSON_PATH)) {
4060
4777
  return { mcpServers: {} };
4061
4778
  }
4062
4779
  try {
@@ -4070,7 +4787,7 @@ async function readMcpJson() {
4070
4787
  }
4071
4788
  }
4072
4789
  async function writeMcpJson(config2) {
4073
- await writeFile7(MCP_JSON_PATH, `${JSON.stringify(config2, null, 2)}
4790
+ await writeFile6(MCP_JSON_PATH, `${JSON.stringify(config2, null, 2)}
4074
4791
  `, "utf-8");
4075
4792
  }
4076
4793
  function buildMcpServerConfig(mcp) {
@@ -4142,10 +4859,10 @@ var init_mcp_json = __esm(() => {
4142
4859
  });
4143
4860
 
4144
4861
  // ../core/src/state/manifest.ts
4145
- import { existsSync as existsSync15, mkdirSync as mkdirSync2, rmSync } from "node:fs";
4146
- import { readFile as readFile13, writeFile as writeFile8 } from "node:fs/promises";
4862
+ import { existsSync as existsSync16, mkdirSync as mkdirSync2, rmSync } from "node:fs";
4863
+ import { readFile as readFile13, writeFile as writeFile7 } from "node:fs/promises";
4147
4864
  async function loadManifest() {
4148
- if (!existsSync15(MANIFEST_PATH)) {
4865
+ if (!existsSync16(MANIFEST_PATH)) {
4149
4866
  return {
4150
4867
  version: CURRENT_VERSION,
4151
4868
  syncedAt: new Date().toISOString(),
@@ -4157,7 +4874,7 @@ async function loadManifest() {
4157
4874
  }
4158
4875
  async function saveManifest(manifest) {
4159
4876
  mkdirSync2(".omni/state", { recursive: true });
4160
- await writeFile8(MANIFEST_PATH, `${JSON.stringify(manifest, null, 2)}
4877
+ await writeFile7(MANIFEST_PATH, `${JSON.stringify(manifest, null, 2)}
4161
4878
  `, "utf-8");
4162
4879
  }
4163
4880
  function buildManifestFromCapabilities(capabilities2) {
@@ -4192,14 +4909,14 @@ async function cleanupStaleResources(previousManifest, currentCapabilityIds) {
4192
4909
  }
4193
4910
  for (const skillName of resources.skills) {
4194
4911
  const skillDir = `.claude/skills/${skillName}`;
4195
- if (existsSync15(skillDir)) {
4912
+ if (existsSync16(skillDir)) {
4196
4913
  rmSync(skillDir, { recursive: true });
4197
4914
  result.deletedSkills.push(skillName);
4198
4915
  }
4199
4916
  }
4200
4917
  for (const ruleName of resources.rules) {
4201
4918
  const rulePath = `.cursor/rules/omnidev-${ruleName}.mdc`;
4202
- if (existsSync15(rulePath)) {
4919
+ if (existsSync16(rulePath)) {
4203
4920
  rmSync(rulePath);
4204
4921
  result.deletedRules.push(ruleName);
4205
4922
  }
@@ -4211,10 +4928,10 @@ var MANIFEST_PATH = ".omni/state/manifest.json", CURRENT_VERSION = 1;
4211
4928
  var init_manifest = () => {};
4212
4929
 
4213
4930
  // ../core/src/state/providers.ts
4214
- import { existsSync as existsSync16, mkdirSync as mkdirSync3 } from "node:fs";
4215
- import { readFile as readFile14, writeFile as writeFile9 } from "node:fs/promises";
4931
+ import { existsSync as existsSync17, mkdirSync as mkdirSync3 } from "node:fs";
4932
+ import { readFile as readFile14, writeFile as writeFile8 } from "node:fs/promises";
4216
4933
  async function readEnabledProviders() {
4217
- if (!existsSync16(PROVIDERS_PATH)) {
4934
+ if (!existsSync17(PROVIDERS_PATH)) {
4218
4935
  return DEFAULT_PROVIDERS;
4219
4936
  }
4220
4937
  try {
@@ -4228,7 +4945,7 @@ async function readEnabledProviders() {
4228
4945
  async function writeEnabledProviders(providers) {
4229
4946
  mkdirSync3(STATE_DIR2, { recursive: true });
4230
4947
  const state = { enabled: providers };
4231
- await writeFile9(PROVIDERS_PATH, `${JSON.stringify(state, null, 2)}
4948
+ await writeFile8(PROVIDERS_PATH, `${JSON.stringify(state, null, 2)}
4232
4949
  `, "utf-8");
4233
4950
  }
4234
4951
  async function enableProvider(providerId) {
@@ -4253,10 +4970,10 @@ var init_providers = __esm(() => {
4253
4970
  });
4254
4971
 
4255
4972
  // ../core/src/state/security-allows.ts
4256
- import { existsSync as existsSync17, mkdirSync as mkdirSync4 } from "node:fs";
4257
- import { readFile as readFile15, writeFile as writeFile10 } from "node:fs/promises";
4973
+ import { existsSync as existsSync18, mkdirSync as mkdirSync4 } from "node:fs";
4974
+ import { readFile as readFile15, writeFile as writeFile9 } from "node:fs/promises";
4258
4975
  async function readSecurityAllows() {
4259
- if (!existsSync17(SECURITY_PATH)) {
4976
+ if (!existsSync18(SECURITY_PATH)) {
4260
4977
  return { ...DEFAULT_STATE };
4261
4978
  }
4262
4979
  try {
@@ -4270,7 +4987,7 @@ async function readSecurityAllows() {
4270
4987
  async function writeSecurityAllows(state) {
4271
4988
  mkdirSync4(OMNI_DIR, { recursive: true });
4272
4989
  state.modifiedAt = new Date().toISOString();
4273
- await writeFile10(SECURITY_PATH, `${JSON.stringify(state, null, 2)}
4990
+ await writeFile9(SECURITY_PATH, `${JSON.stringify(state, null, 2)}
4274
4991
  `, "utf-8");
4275
4992
  }
4276
4993
  async function addSecurityAllow(capabilityId, findingType) {
@@ -4357,10 +5074,10 @@ var init_state = __esm(() => {
4357
5074
  import { spawn as spawn2 } from "node:child_process";
4358
5075
  import { mkdirSync as mkdirSync5 } from "node:fs";
4359
5076
  async function installCapabilityDependencies(silent) {
4360
- const { existsSync: existsSync18, readdirSync: readdirSync7, readFileSync: readFileSync2 } = await import("node:fs");
4361
- const { join: join10 } = await import("node:path");
5077
+ const { existsSync: existsSync19, readdirSync: readdirSync7, readFileSync: readFileSync3 } = await import("node:fs");
5078
+ const { join: join9 } = await import("node:path");
4362
5079
  const capabilitiesDir = ".omni/capabilities";
4363
- if (!existsSync18(capabilitiesDir)) {
5080
+ if (!existsSync19(capabilitiesDir)) {
4364
5081
  return;
4365
5082
  }
4366
5083
  const entries = readdirSync7(capabilitiesDir, { withFileTypes: true });
@@ -4380,13 +5097,13 @@ async function installCapabilityDependencies(silent) {
4380
5097
  if (!entry.isDirectory()) {
4381
5098
  continue;
4382
5099
  }
4383
- const capabilityPath = join10(capabilitiesDir, entry.name);
4384
- const packageJsonPath = join10(capabilityPath, "package.json");
4385
- if (!existsSync18(packageJsonPath)) {
5100
+ const capabilityPath = join9(capabilitiesDir, entry.name);
5101
+ const packageJsonPath = join9(capabilityPath, "package.json");
5102
+ if (!existsSync19(packageJsonPath)) {
4386
5103
  continue;
4387
5104
  }
4388
5105
  await new Promise((resolve2, reject) => {
4389
- const useNpmCi = hasNpm && existsSync18(join10(capabilityPath, "package-lock.json"));
5106
+ const useNpmCi = hasNpm && existsSync19(join9(capabilityPath, "package-lock.json"));
4390
5107
  const cmd = hasBun ? "bun" : "npm";
4391
5108
  const args = hasBun ? ["install"] : useNpmCi ? ["ci"] : ["install"];
4392
5109
  const proc = spawn2(cmd, args, {
@@ -4409,39 +5126,39 @@ ${stderr}`));
4409
5126
  reject(error);
4410
5127
  });
4411
5128
  });
4412
- const hasIndexTs = existsSync18(join10(capabilityPath, "index.ts"));
4413
- const hasBuiltIndex = existsSync18(join10(capabilityPath, "dist", "index.js"));
4414
- if (hasIndexTs && !hasBuiltIndex) {
4415
- let hasBuildScript = false;
4416
- try {
4417
- const pkgJson = JSON.parse(readFileSync2(packageJsonPath, "utf-8"));
4418
- hasBuildScript = Boolean(pkgJson.scripts?.build);
4419
- } catch {}
4420
- if (hasBuildScript) {
4421
- await new Promise((resolve2, reject) => {
4422
- const cmd = hasBun ? "bun" : "npm";
4423
- const args = ["run", "build"];
4424
- const proc = spawn2(cmd, args, {
4425
- cwd: capabilityPath,
4426
- stdio: "pipe"
4427
- });
4428
- let stderr = "";
4429
- proc.stderr?.on("data", (data) => {
4430
- stderr += data.toString();
4431
- });
4432
- proc.on("close", (code) => {
4433
- if (code === 0) {
4434
- resolve2();
4435
- } else {
4436
- reject(new Error(`Failed to build capability ${capabilityPath}:
5129
+ const hasIndexTs = existsSync19(join9(capabilityPath, "index.ts"));
5130
+ let hasBuildScript = false;
5131
+ try {
5132
+ const pkgJson = JSON.parse(readFileSync3(packageJsonPath, "utf-8"));
5133
+ hasBuildScript = Boolean(pkgJson.scripts?.build);
5134
+ } catch {}
5135
+ if (hasBuildScript) {
5136
+ await new Promise((resolve2, reject) => {
5137
+ const cmd = hasBun ? "bun" : "npm";
5138
+ const args = ["run", "build"];
5139
+ const proc = spawn2(cmd, args, {
5140
+ cwd: capabilityPath,
5141
+ stdio: "pipe"
5142
+ });
5143
+ let stderr = "";
5144
+ proc.stderr?.on("data", (data) => {
5145
+ stderr += data.toString();
5146
+ });
5147
+ proc.on("close", (code) => {
5148
+ if (code === 0) {
5149
+ resolve2();
5150
+ } else {
5151
+ reject(new Error(`Failed to build capability ${capabilityPath}:
4437
5152
  ${stderr}`));
4438
- }
4439
- });
4440
- proc.on("error", (error) => {
4441
- reject(error);
4442
- });
5153
+ }
5154
+ });
5155
+ proc.on("error", (error) => {
5156
+ reject(error);
4443
5157
  });
4444
- } else if (!silent) {
5158
+ });
5159
+ } else if (hasIndexTs && !silent) {
5160
+ const hasBuiltIndex = existsSync19(join9(capabilityPath, "dist", "index.js"));
5161
+ if (!hasBuiltIndex) {
4445
5162
  console.warn(`Warning: Capability at ${capabilityPath} has index.ts but no build script.
4446
5163
  Add a "build" script to package.json (e.g., "build": "tsc") to compile TypeScript.`);
4447
5164
  }
@@ -4579,9 +5296,9 @@ var init_types3 = __esm(() => {
4579
5296
  });
4580
5297
 
4581
5298
  // ../core/src/security/scanner.ts
4582
- import { existsSync as existsSync18 } from "node:fs";
5299
+ import { existsSync as existsSync19 } from "node:fs";
4583
5300
  import { lstat, readdir as readdir2, readFile as readFile16, readlink, realpath } from "node:fs/promises";
4584
- import { join as join10, relative, resolve as resolve2 } from "node:path";
5301
+ import { join as join9, relative, resolve as resolve2 } from "node:path";
4585
5302
  async function scanFileForUnicode(filePath, relativePath) {
4586
5303
  const findings = [];
4587
5304
  try {
@@ -4665,7 +5382,7 @@ async function scanFileForScripts(filePath, relativePath) {
4665
5382
  async function checkSymlink(symlinkPath, relativePath, capabilityRoot) {
4666
5383
  try {
4667
5384
  const linkTarget = await readlink(symlinkPath);
4668
- const resolvedTarget = resolve2(join10(symlinkPath, "..", linkTarget));
5385
+ const resolvedTarget = resolve2(join9(symlinkPath, "..", linkTarget));
4669
5386
  const normalizedRoot = await realpath(capabilityRoot);
4670
5387
  if (linkTarget.startsWith("/")) {
4671
5388
  return {
@@ -4700,7 +5417,7 @@ function isTextFile(filePath) {
4700
5417
  async function scanCapability(capabilityId, capabilityPath, settings = DEFAULT_SCAN_SETTINGS) {
4701
5418
  const startTime = Date.now();
4702
5419
  const findings = [];
4703
- if (!existsSync18(capabilityPath)) {
5420
+ if (!existsSync19(capabilityPath)) {
4704
5421
  return {
4705
5422
  capabilityId,
4706
5423
  path: capabilityPath,
@@ -4712,7 +5429,7 @@ async function scanCapability(capabilityId, capabilityPath, settings = DEFAULT_S
4712
5429
  async function scanDirectory(dirPath) {
4713
5430
  const entries = await readdir2(dirPath, { withFileTypes: true });
4714
5431
  for (const entry of entries) {
4715
- const fullPath = join10(dirPath, entry.name);
5432
+ const fullPath = join9(dirPath, entry.name);
4716
5433
  const relativePath = relative(capabilityPath, fullPath);
4717
5434
  if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "__pycache__") {
4718
5435
  continue;
@@ -5172,6 +5889,7 @@ __export(exports_src, {
5172
5889
  verifyIntegrity: () => verifyIntegrity,
5173
5890
  validateHooksConfig: () => validateHooksConfig,
5174
5891
  validateHook: () => validateHook,
5892
+ validateGitCapability: () => validateGitCapability,
5175
5893
  transformToOmnidev: () => transformToOmnidev,
5176
5894
  transformToClaude: () => transformToClaude,
5177
5895
  transformHooksConfig: () => transformHooksConfig,
@@ -5185,6 +5903,8 @@ __export(exports_src, {
5185
5903
  saveManifest: () => saveManifest,
5186
5904
  saveLockFile: () => saveLockFile,
5187
5905
  resolveEnabledCapabilities: () => resolveEnabledCapabilities,
5906
+ resolveCapabilityRootInConfig: () => resolveCapabilityRootInConfig,
5907
+ resolveCapabilityRoot: () => resolveCapabilityRoot,
5188
5908
  removeSecurityAllow: () => removeSecurityAllow,
5189
5909
  readSecurityAllows: () => readSecurityAllows,
5190
5910
  readMcpJson: () => readMcpJson,
@@ -5208,6 +5928,7 @@ __export(exports_src, {
5208
5928
  loadProfileConfig: () => loadProfileConfig,
5209
5929
  loadManifest: () => loadManifest,
5210
5930
  loadLockFile: () => loadLockFile,
5931
+ loadHooksJson: () => loadHooksJson,
5211
5932
  loadHooksFromCapability: () => loadHooksFromCapability,
5212
5933
  loadDocs: () => loadDocs,
5213
5934
  loadConfig: () => loadConfig,
@@ -5290,7 +6011,8 @@ __export(exports_src, {
5290
6011
  DEFAULT_SCAN_SETTINGS: () => DEFAULT_SCAN_SETTINGS,
5291
6012
  DEFAULT_PROMPT_TIMEOUT: () => DEFAULT_PROMPT_TIMEOUT,
5292
6013
  DEFAULT_COMMAND_TIMEOUT: () => DEFAULT_COMMAND_TIMEOUT,
5293
- COMMON_TOOL_MATCHERS: () => COMMON_TOOL_MATCHERS
6014
+ COMMON_TOOL_MATCHERS: () => COMMON_TOOL_MATCHERS,
6015
+ CLAUDE_HOOKS_CONFIG_FILENAME: () => CLAUDE_HOOKS_CONFIG_FILENAME
5294
6016
  });
5295
6017
  function getVersion() {
5296
6018
  return version;
@@ -5311,51 +6033,59 @@ var init_src = __esm(() => {
5311
6033
  import { run } from "@stricli/core";
5312
6034
 
5313
6035
  // src/lib/dynamic-app.ts
5314
- import { existsSync as existsSync28 } from "node:fs";
6036
+ import { existsSync as existsSync29 } from "node:fs";
5315
6037
  import { createRequire as createRequire2 } from "node:module";
5316
- import { join as join18 } from "node:path";
6038
+ import { join as join26 } from "node:path";
5317
6039
  import { buildApplication, buildRouteMap as buildRouteMap7 } from "@stricli/core";
5318
6040
 
5319
6041
  // src/commands/add.ts
5320
- import { existsSync as existsSync21 } from "node:fs";
5321
- import { basename as basename3, resolve as resolve3 } from "node:path";
6042
+ import { existsSync as existsSync22 } from "node:fs";
6043
+ import { basename as basename5, resolve as resolve3 } from "node:path";
5322
6044
 
5323
- // ../adapters/src/writers/cursor-rules.ts
5324
- import { mkdir, writeFile } from "node:fs/promises";
5325
- import { join } from "node:path";
5326
- var CursorRulesWriter = {
5327
- id: "cursor-rules",
5328
- async write(bundle, ctx) {
5329
- const rulesDir = join(ctx.projectRoot, ctx.outputPath);
5330
- await mkdir(rulesDir, { recursive: true });
5331
- const filesWritten = [];
5332
- for (const rule of bundle.rules) {
5333
- const rulePath = join(rulesDir, `omnidev-${rule.name}.mdc`);
5334
- await writeFile(rulePath, rule.content, "utf-8");
5335
- filesWritten.push(join(ctx.outputPath, `omnidev-${rule.name}.mdc`));
6045
+ // ../adapters/src/writers/generic/executor.ts
6046
+ async function executeWriters(writerConfigs, bundle, projectRoot) {
6047
+ const seen = new Set;
6048
+ const uniqueConfigs = [];
6049
+ let deduplicatedCount = 0;
6050
+ for (const config of writerConfigs) {
6051
+ const key = `${config.writer.id}:${config.outputPath}`;
6052
+ if (seen.has(key)) {
6053
+ deduplicatedCount++;
6054
+ continue;
5336
6055
  }
5337
- return {
5338
- filesWritten
5339
- };
6056
+ seen.add(key);
6057
+ uniqueConfigs.push(config);
5340
6058
  }
5341
- };
5342
- // ../adapters/src/writers/hooks.ts
6059
+ const allFilesWritten = [];
6060
+ for (const config of uniqueConfigs) {
6061
+ const result = await config.writer.write(bundle, {
6062
+ outputPath: config.outputPath,
6063
+ projectRoot
6064
+ });
6065
+ allFilesWritten.push(...result.filesWritten);
6066
+ }
6067
+ return {
6068
+ filesWritten: allFilesWritten,
6069
+ deduplicatedCount
6070
+ };
6071
+ }
6072
+ // ../adapters/src/writers/generic/hooks.ts
5343
6073
  init_src();
5344
- import { existsSync as existsSync19 } from "node:fs";
5345
- import { mkdir as mkdir3, readFile as readFile17, writeFile as writeFile11 } from "node:fs/promises";
5346
- import { dirname, join as join11 } from "node:path";
6074
+ import { existsSync as existsSync20 } from "node:fs";
6075
+ import { mkdir as mkdir2, readFile as readFile17, writeFile as writeFile10 } from "node:fs/promises";
6076
+ import { dirname, join as join10 } from "node:path";
5347
6077
  var HooksWriter = {
5348
6078
  id: "hooks",
5349
6079
  async write(bundle, ctx) {
5350
6080
  if (!bundle.hooks) {
5351
6081
  return { filesWritten: [] };
5352
6082
  }
5353
- const settingsPath = join11(ctx.projectRoot, ctx.outputPath);
6083
+ const settingsPath = join10(ctx.projectRoot, ctx.outputPath);
5354
6084
  const parentDir = dirname(settingsPath);
5355
- await mkdir3(parentDir, { recursive: true });
6085
+ await mkdir2(parentDir, { recursive: true });
5356
6086
  const claudeHooks = transformHooksConfig(bundle.hooks, "toClaude");
5357
6087
  let existingSettings = {};
5358
- if (existsSync19(settingsPath)) {
6088
+ if (existsSync20(settingsPath)) {
5359
6089
  try {
5360
6090
  const content = await readFile17(settingsPath, "utf-8");
5361
6091
  existingSettings = JSON.parse(content);
@@ -5367,28 +6097,28 @@ var HooksWriter = {
5367
6097
  ...existingSettings,
5368
6098
  hooks: claudeHooks
5369
6099
  };
5370
- await writeFile11(settingsPath, `${JSON.stringify(newSettings, null, 2)}
6100
+ await writeFile10(settingsPath, `${JSON.stringify(newSettings, null, 2)}
5371
6101
  `, "utf-8");
5372
6102
  return {
5373
6103
  filesWritten: [ctx.outputPath]
5374
6104
  };
5375
6105
  }
5376
6106
  };
5377
- // ../adapters/src/writers/instructions-md.ts
5378
- import { existsSync as existsSync20 } from "node:fs";
5379
- import { mkdir as mkdir4, readFile as readFile18, writeFile as writeFile12 } from "node:fs/promises";
5380
- import { dirname as dirname2, join as join12 } from "node:path";
6107
+ // ../adapters/src/writers/generic/instructions-md.ts
6108
+ import { existsSync as existsSync21 } from "node:fs";
6109
+ import { mkdir as mkdir3, readFile as readFile18, writeFile as writeFile11 } from "node:fs/promises";
6110
+ import { dirname as dirname2, join as join11 } from "node:path";
5381
6111
  var InstructionsMdWriter = {
5382
6112
  id: "instructions-md",
5383
6113
  async write(bundle, ctx) {
5384
- const outputFullPath = join12(ctx.projectRoot, ctx.outputPath);
6114
+ const outputFullPath = join11(ctx.projectRoot, ctx.outputPath);
5385
6115
  const parentDir = dirname2(outputFullPath);
5386
6116
  if (parentDir !== ctx.projectRoot) {
5387
- await mkdir4(parentDir, { recursive: true });
6117
+ await mkdir3(parentDir, { recursive: true });
5388
6118
  }
5389
- const omniMdPath = join12(ctx.projectRoot, "OMNI.md");
6119
+ const omniMdPath = join11(ctx.projectRoot, "OMNI.md");
5390
6120
  let omniMdContent = "";
5391
- if (existsSync20(omniMdPath)) {
6121
+ if (existsSync21(omniMdPath)) {
5392
6122
  omniMdContent = await readFile18(omniMdPath, "utf-8");
5393
6123
  }
5394
6124
  let content = omniMdContent;
@@ -5398,66 +6128,121 @@ var InstructionsMdWriter = {
5398
6128
  ${bundle.instructionsContent}
5399
6129
  `;
5400
6130
  }
5401
- await writeFile12(outputFullPath, content, "utf-8");
6131
+ await writeFile11(outputFullPath, content, "utf-8");
5402
6132
  return {
5403
6133
  filesWritten: [ctx.outputPath]
5404
6134
  };
5405
6135
  }
5406
6136
  };
5407
- // ../adapters/src/writers/skills.ts
5408
- import { mkdir as mkdir5, writeFile as writeFile13 } from "node:fs/promises";
5409
- import { join as join13 } from "node:path";
6137
+ // ../adapters/src/writers/generic/skills.ts
6138
+ import { mkdir as mkdir4, writeFile as writeFile12 } from "node:fs/promises";
6139
+ import { join as join12 } from "node:path";
5410
6140
  var SkillsWriter = {
5411
6141
  id: "skills",
5412
6142
  async write(bundle, ctx) {
5413
- const skillsDir = join13(ctx.projectRoot, ctx.outputPath);
5414
- await mkdir5(skillsDir, { recursive: true });
6143
+ const skillsDir = join12(ctx.projectRoot, ctx.outputPath);
6144
+ await mkdir4(skillsDir, { recursive: true });
5415
6145
  const filesWritten = [];
5416
6146
  for (const skill of bundle.skills) {
5417
- const skillDir = join13(skillsDir, skill.name);
5418
- await mkdir5(skillDir, { recursive: true });
5419
- const skillPath = join13(skillDir, "SKILL.md");
6147
+ const skillDir = join12(skillsDir, skill.name);
6148
+ await mkdir4(skillDir, { recursive: true });
6149
+ const skillPath = join12(skillDir, "SKILL.md");
5420
6150
  const content = `---
5421
6151
  name: ${skill.name}
5422
6152
  description: "${skill.description}"
5423
6153
  ---
5424
6154
 
5425
6155
  ${skill.instructions}`;
5426
- await writeFile13(skillPath, content, "utf-8");
5427
- filesWritten.push(join13(ctx.outputPath, skill.name, "SKILL.md"));
6156
+ await writeFile12(skillPath, content, "utf-8");
6157
+ filesWritten.push(join12(ctx.outputPath, skill.name, "SKILL.md"));
5428
6158
  }
5429
6159
  return {
5430
6160
  filesWritten
5431
6161
  };
5432
6162
  }
5433
6163
  };
5434
- // ../adapters/src/writers/executor.ts
5435
- async function executeWriters(writerConfigs, bundle, projectRoot) {
5436
- const seen = new Set;
5437
- const uniqueConfigs = [];
5438
- let deduplicatedCount = 0;
5439
- for (const config3 of writerConfigs) {
5440
- const key = `${config3.writer.id}:${config3.outputPath}`;
5441
- if (seen.has(key)) {
5442
- deduplicatedCount++;
5443
- continue;
6164
+ // ../adapters/src/writers/generic/commands-as-skills.ts
6165
+ import { mkdir as mkdir5, writeFile as writeFile13 } from "node:fs/promises";
6166
+ import { join as join13 } from "node:path";
6167
+ function generateSkillFrontmatter(command) {
6168
+ const lines = ["---"];
6169
+ lines.push(`name: ${command.name}`);
6170
+ lines.push(`description: "${command.description.replace(/"/g, "\\\"")}"`);
6171
+ if (command.allowedTools) {
6172
+ lines.push(`allowed_tools: "${command.allowedTools}"`);
6173
+ }
6174
+ lines.push("---");
6175
+ return lines.join(`
6176
+ `);
6177
+ }
6178
+ var CommandsAsSkillsWriter = {
6179
+ id: "commands-as-skills",
6180
+ async write(bundle, ctx) {
6181
+ const skillsDir = join13(ctx.projectRoot, ctx.outputPath);
6182
+ await mkdir5(skillsDir, { recursive: true });
6183
+ const filesWritten = [];
6184
+ for (const command of bundle.commands) {
6185
+ const commandSkillDir = join13(skillsDir, command.name);
6186
+ await mkdir5(commandSkillDir, { recursive: true });
6187
+ const frontmatter = generateSkillFrontmatter(command);
6188
+ const content = `${frontmatter}
6189
+
6190
+ ${command.prompt}`;
6191
+ const skillPath = join13(commandSkillDir, "SKILL.md");
6192
+ await writeFile13(skillPath, content, "utf-8");
6193
+ filesWritten.push(join13(ctx.outputPath, command.name, "SKILL.md"));
5444
6194
  }
5445
- seen.add(key);
5446
- uniqueConfigs.push(config3);
6195
+ return {
6196
+ filesWritten
6197
+ };
5447
6198
  }
5448
- const allFilesWritten = [];
5449
- for (const config3 of uniqueConfigs) {
5450
- const result = await config3.writer.write(bundle, {
5451
- outputPath: config3.outputPath,
5452
- projectRoot
5453
- });
5454
- allFilesWritten.push(...result.filesWritten);
6199
+ };
6200
+ // ../adapters/src/writers/claude/agents.ts
6201
+ import { mkdir as mkdir6, writeFile as writeFile14 } from "node:fs/promises";
6202
+ import { join as join14 } from "node:path";
6203
+ function generateFrontmatter(agent) {
6204
+ const lines = ["---"];
6205
+ lines.push(`name: ${agent.name}`);
6206
+ lines.push(`description: "${agent.description.replace(/"/g, "\\\"")}"`);
6207
+ if (agent.tools && agent.tools.length > 0) {
6208
+ lines.push(`tools: ${agent.tools.join(", ")}`);
5455
6209
  }
5456
- return {
5457
- filesWritten: allFilesWritten,
5458
- deduplicatedCount
5459
- };
6210
+ if (agent.disallowedTools && agent.disallowedTools.length > 0) {
6211
+ lines.push(`disallowedTools: ${agent.disallowedTools.join(", ")}`);
6212
+ }
6213
+ if (agent.model && agent.model !== "inherit") {
6214
+ lines.push(`model: ${agent.model}`);
6215
+ }
6216
+ if (agent.permissionMode && agent.permissionMode !== "default") {
6217
+ lines.push(`permissionMode: ${agent.permissionMode}`);
6218
+ }
6219
+ if (agent.skills && agent.skills.length > 0) {
6220
+ lines.push(`skills: ${agent.skills.join(", ")}`);
6221
+ }
6222
+ lines.push("---");
6223
+ return lines.join(`
6224
+ `);
5460
6225
  }
6226
+ var ClaudeAgentsWriter = {
6227
+ id: "claude-agents",
6228
+ async write(bundle, ctx) {
6229
+ const agentsDir = join14(ctx.projectRoot, ctx.outputPath);
6230
+ await mkdir6(agentsDir, { recursive: true });
6231
+ const filesWritten = [];
6232
+ for (const agent of bundle.subagents) {
6233
+ const frontmatter = generateFrontmatter(agent);
6234
+ const content = `${frontmatter}
6235
+
6236
+ ${agent.systemPrompt}`;
6237
+ const agentPath = join14(agentsDir, `${agent.name}.md`);
6238
+ await writeFile14(agentPath, content, "utf-8");
6239
+ filesWritten.push(join14(ctx.outputPath, `${agent.name}.md`));
6240
+ }
6241
+ return {
6242
+ filesWritten
6243
+ };
6244
+ }
6245
+ };
5461
6246
  // ../adapters/src/claude-code/index.ts
5462
6247
  var claudeCodeAdapter = {
5463
6248
  id: "claude-code",
@@ -5465,6 +6250,8 @@ var claudeCodeAdapter = {
5465
6250
  writers: [
5466
6251
  { writer: InstructionsMdWriter, outputPath: "CLAUDE.md" },
5467
6252
  { writer: SkillsWriter, outputPath: ".claude/skills/" },
6253
+ { writer: ClaudeAgentsWriter, outputPath: ".claude/agents/" },
6254
+ { writer: CommandsAsSkillsWriter, outputPath: ".claude/skills/" },
5468
6255
  { writer: HooksWriter, outputPath: ".claude/settings.json" }
5469
6256
  ],
5470
6257
  async init(_ctx) {
@@ -5483,16 +6270,97 @@ var claudeCodeAdapter = {
5483
6270
  };
5484
6271
  // ../adapters/src/codex/index.ts
5485
6272
  import { mkdirSync as mkdirSync6 } from "node:fs";
5486
- import { join as join14 } from "node:path";
6273
+ import { join as join16 } from "node:path";
6274
+
6275
+ // ../adapters/src/writers/codex/toml.ts
6276
+ init_dist();
6277
+ import { mkdir as mkdir7, writeFile as writeFile15 } from "node:fs/promises";
6278
+ import { dirname as dirname3, join as join15 } from "node:path";
6279
+ var FILE_HEADER = `# Generated by OmniDev - DO NOT EDIT
6280
+ # Run \`omnidev sync\` to regenerate
6281
+
6282
+ `;
6283
+ function buildCodexMcpConfig(id, mcp) {
6284
+ const transport = mcp.transport ?? "stdio";
6285
+ if (transport === "sse") {
6286
+ console.warn(` Warning: Skipping MCP "${id}" - SSE transport is not supported by Codex`);
6287
+ return null;
6288
+ }
6289
+ const config3 = {};
6290
+ if (transport === "http") {
6291
+ if (mcp.url) {
6292
+ config3.url = mcp.url;
6293
+ }
6294
+ if (mcp.headers && Object.keys(mcp.headers).length > 0) {
6295
+ config3.http_headers = mcp.headers;
6296
+ }
6297
+ } else {
6298
+ if (mcp.command) {
6299
+ config3.command = mcp.command;
6300
+ }
6301
+ if (mcp.args && mcp.args.length > 0) {
6302
+ config3.args = mcp.args;
6303
+ }
6304
+ if (mcp.env && Object.keys(mcp.env).length > 0) {
6305
+ config3.env = mcp.env;
6306
+ }
6307
+ if (mcp.cwd) {
6308
+ config3.cwd = mcp.cwd;
6309
+ }
6310
+ }
6311
+ return config3;
6312
+ }
6313
+ function collectMcps(bundle) {
6314
+ const mcps = new Map;
6315
+ for (const capability3 of bundle.capabilities) {
6316
+ if (capability3.config.mcp) {
6317
+ mcps.set(capability3.id, capability3.config.mcp);
6318
+ }
6319
+ }
6320
+ return mcps;
6321
+ }
6322
+ var CodexTomlWriter = {
6323
+ id: "codex-toml",
6324
+ async write(bundle, ctx) {
6325
+ const mcps = collectMcps(bundle);
6326
+ if (mcps.size === 0) {
6327
+ return { filesWritten: [] };
6328
+ }
6329
+ const configPath = join15(ctx.projectRoot, ctx.outputPath);
6330
+ const parentDir = dirname3(configPath);
6331
+ await mkdir7(parentDir, { recursive: true });
6332
+ const mcpServers = {};
6333
+ for (const [id, mcp] of mcps) {
6334
+ const converted = buildCodexMcpConfig(id, mcp);
6335
+ if (converted) {
6336
+ mcpServers[id] = converted;
6337
+ }
6338
+ }
6339
+ if (Object.keys(mcpServers).length === 0) {
6340
+ return { filesWritten: [] };
6341
+ }
6342
+ const codexConfig = {
6343
+ mcp_servers: mcpServers
6344
+ };
6345
+ const tomlContent = FILE_HEADER + stringify(codexConfig);
6346
+ await writeFile15(configPath, tomlContent, "utf-8");
6347
+ return {
6348
+ filesWritten: [ctx.outputPath]
6349
+ };
6350
+ }
6351
+ };
6352
+ // ../adapters/src/codex/index.ts
5487
6353
  var codexAdapter = {
5488
6354
  id: "codex",
5489
6355
  displayName: "Codex",
5490
6356
  writers: [
5491
6357
  { writer: InstructionsMdWriter, outputPath: "AGENTS.md" },
5492
- { writer: SkillsWriter, outputPath: ".codex/skills/" }
6358
+ { writer: SkillsWriter, outputPath: ".codex/skills/" },
6359
+ { writer: CommandsAsSkillsWriter, outputPath: ".codex/skills/" },
6360
+ { writer: CodexTomlWriter, outputPath: ".codex/config.toml" }
5493
6361
  ],
5494
6362
  async init(ctx) {
5495
- const codexDir = join14(ctx.projectRoot, ".codex");
6363
+ const codexDir = join16(ctx.projectRoot, ".codex");
5496
6364
  mkdirSync6(codexDir, { recursive: true });
5497
6365
  return {
5498
6366
  filesCreated: [".codex/"],
@@ -5509,17 +6377,186 @@ var codexAdapter = {
5509
6377
  };
5510
6378
  // ../adapters/src/cursor/index.ts
5511
6379
  import { mkdirSync as mkdirSync7 } from "node:fs";
5512
- import { join as join15 } from "node:path";
6380
+ import { join as join21 } from "node:path";
6381
+
6382
+ // ../adapters/src/writers/cursor/agents.ts
6383
+ import { mkdir as mkdir8, writeFile as writeFile16 } from "node:fs/promises";
6384
+ import { join as join17 } from "node:path";
6385
+ function mapModelToCursor(model) {
6386
+ if (!model || model === "inherit")
6387
+ return "inherit";
6388
+ const modelMap = {
6389
+ haiku: "fast",
6390
+ sonnet: "inherit",
6391
+ opus: "inherit"
6392
+ };
6393
+ return modelMap[model] ?? "inherit";
6394
+ }
6395
+ function generateFrontmatter2(agent) {
6396
+ const lines = ["---"];
6397
+ lines.push(`name: ${agent.name}`);
6398
+ lines.push(`description: "${agent.description.replace(/"/g, "\\\"")}"`);
6399
+ const model = mapModelToCursor(agent.model);
6400
+ if (model) {
6401
+ lines.push(`model: ${model}`);
6402
+ }
6403
+ if (agent.permissionMode === "plan") {
6404
+ lines.push("readonly: true");
6405
+ }
6406
+ if (agent.isBackground) {
6407
+ lines.push("is_background: true");
6408
+ }
6409
+ lines.push("---");
6410
+ return lines.join(`
6411
+ `);
6412
+ }
6413
+ var CursorAgentsWriter = {
6414
+ id: "cursor-agents",
6415
+ async write(bundle, ctx) {
6416
+ const agentsDir = join17(ctx.projectRoot, ctx.outputPath);
6417
+ await mkdir8(agentsDir, { recursive: true });
6418
+ const filesWritten = [];
6419
+ for (const agent of bundle.subagents) {
6420
+ const frontmatter = generateFrontmatter2(agent);
6421
+ const content = `${frontmatter}
6422
+
6423
+ ${agent.systemPrompt}`;
6424
+ const agentPath = join17(agentsDir, `${agent.name}.md`);
6425
+ await writeFile16(agentPath, content, "utf-8");
6426
+ filesWritten.push(join17(ctx.outputPath, `${agent.name}.md`));
6427
+ }
6428
+ return {
6429
+ filesWritten
6430
+ };
6431
+ }
6432
+ };
6433
+ // ../adapters/src/writers/cursor/commands.ts
6434
+ import { mkdir as mkdir9, writeFile as writeFile17 } from "node:fs/promises";
6435
+ import { join as join18 } from "node:path";
6436
+ var CursorCommandsWriter = {
6437
+ id: "cursor-commands",
6438
+ async write(bundle, ctx) {
6439
+ const commandsDir = join18(ctx.projectRoot, ctx.outputPath);
6440
+ await mkdir9(commandsDir, { recursive: true });
6441
+ const filesWritten = [];
6442
+ for (const command of bundle.commands) {
6443
+ const content = `# ${command.name}
6444
+
6445
+ ${command.description}
6446
+
6447
+ ${command.prompt}`;
6448
+ const commandPath = join18(commandsDir, `${command.name}.md`);
6449
+ await writeFile17(commandPath, content, "utf-8");
6450
+ filesWritten.push(join18(ctx.outputPath, `${command.name}.md`));
6451
+ }
6452
+ return {
6453
+ filesWritten
6454
+ };
6455
+ }
6456
+ };
6457
+ // ../adapters/src/writers/cursor/mcp-json.ts
6458
+ import { mkdir as mkdir10, writeFile as writeFile18 } from "node:fs/promises";
6459
+ import { dirname as dirname4, join as join19 } from "node:path";
6460
+ function buildCursorMcpConfig(mcp) {
6461
+ const transport = mcp.transport ?? "stdio";
6462
+ if (transport === "http" || transport === "sse") {
6463
+ if (!mcp.url) {
6464
+ return null;
6465
+ }
6466
+ const config4 = {
6467
+ url: mcp.url
6468
+ };
6469
+ if (mcp.headers && Object.keys(mcp.headers).length > 0) {
6470
+ config4.headers = mcp.headers;
6471
+ }
6472
+ return config4;
6473
+ }
6474
+ if (!mcp.command) {
6475
+ return null;
6476
+ }
6477
+ const config3 = {
6478
+ command: mcp.command
6479
+ };
6480
+ if (mcp.args && mcp.args.length > 0) {
6481
+ config3.args = mcp.args;
6482
+ }
6483
+ if (mcp.env && Object.keys(mcp.env).length > 0) {
6484
+ config3.env = mcp.env;
6485
+ }
6486
+ return config3;
6487
+ }
6488
+ function collectMcps2(bundle) {
6489
+ const mcps = new Map;
6490
+ for (const capability3 of bundle.capabilities) {
6491
+ if (capability3.config.mcp) {
6492
+ mcps.set(capability3.id, capability3.config.mcp);
6493
+ }
6494
+ }
6495
+ return mcps;
6496
+ }
6497
+ var CursorMcpJsonWriter = {
6498
+ id: "cursor-mcp-json",
6499
+ async write(bundle, ctx) {
6500
+ const mcps = collectMcps2(bundle);
6501
+ if (mcps.size === 0) {
6502
+ return { filesWritten: [] };
6503
+ }
6504
+ const configPath = join19(ctx.projectRoot, ctx.outputPath);
6505
+ const parentDir = dirname4(configPath);
6506
+ await mkdir10(parentDir, { recursive: true });
6507
+ const mcpServers = {};
6508
+ for (const [id, mcp] of mcps) {
6509
+ const converted = buildCursorMcpConfig(mcp);
6510
+ if (converted) {
6511
+ mcpServers[id] = converted;
6512
+ }
6513
+ }
6514
+ if (Object.keys(mcpServers).length === 0) {
6515
+ return { filesWritten: [] };
6516
+ }
6517
+ const cursorMcpJson = {
6518
+ mcpServers
6519
+ };
6520
+ await writeFile18(configPath, `${JSON.stringify(cursorMcpJson, null, 2)}
6521
+ `, "utf-8");
6522
+ return {
6523
+ filesWritten: [ctx.outputPath]
6524
+ };
6525
+ }
6526
+ };
6527
+ // ../adapters/src/writers/cursor/rules.ts
6528
+ import { mkdir as mkdir11, writeFile as writeFile19 } from "node:fs/promises";
6529
+ import { join as join20 } from "node:path";
6530
+ var CursorRulesWriter = {
6531
+ id: "cursor-rules",
6532
+ async write(bundle, ctx) {
6533
+ const rulesDir = join20(ctx.projectRoot, ctx.outputPath);
6534
+ await mkdir11(rulesDir, { recursive: true });
6535
+ const filesWritten = [];
6536
+ for (const rule of bundle.rules) {
6537
+ const rulePath = join20(rulesDir, `omnidev-${rule.name}.mdc`);
6538
+ await writeFile19(rulePath, rule.content, "utf-8");
6539
+ filesWritten.push(join20(ctx.outputPath, `omnidev-${rule.name}.mdc`));
6540
+ }
6541
+ return {
6542
+ filesWritten
6543
+ };
6544
+ }
6545
+ };
6546
+ // ../adapters/src/cursor/index.ts
5513
6547
  var cursorAdapter = {
5514
6548
  id: "cursor",
5515
6549
  displayName: "Cursor",
5516
6550
  writers: [
5517
6551
  { writer: InstructionsMdWriter, outputPath: "CLAUDE.md" },
5518
- { writer: SkillsWriter, outputPath: ".claude/skills/" },
5519
- { writer: CursorRulesWriter, outputPath: ".cursor/rules/" }
6552
+ { writer: SkillsWriter, outputPath: ".cursor/skills/" },
6553
+ { writer: CursorRulesWriter, outputPath: ".cursor/rules/" },
6554
+ { writer: CursorAgentsWriter, outputPath: ".cursor/agents/" },
6555
+ { writer: CursorCommandsWriter, outputPath: ".cursor/commands/" },
6556
+ { writer: CursorMcpJsonWriter, outputPath: ".cursor/mcp.json" }
5520
6557
  ],
5521
6558
  async init(ctx) {
5522
- const rulesDir = join15(ctx.projectRoot, ".cursor", "rules");
6559
+ const rulesDir = join21(ctx.projectRoot, ".cursor", "rules");
5523
6560
  mkdirSync7(rulesDir, { recursive: true });
5524
6561
  return {
5525
6562
  filesCreated: [".cursor/rules/"],
@@ -5536,16 +6573,153 @@ var cursorAdapter = {
5536
6573
  };
5537
6574
  // ../adapters/src/opencode/index.ts
5538
6575
  import { mkdirSync as mkdirSync8 } from "node:fs";
5539
- import { join as join16 } from "node:path";
6576
+ import { join as join24 } from "node:path";
6577
+
6578
+ // ../adapters/src/writers/opencode/agents.ts
6579
+ import { mkdir as mkdir12, writeFile as writeFile20 } from "node:fs/promises";
6580
+ import { join as join22 } from "node:path";
6581
+ function mapModelToOpenCode(model) {
6582
+ if (!model || model === "inherit")
6583
+ return;
6584
+ const modelMap = {
6585
+ sonnet: "anthropic/claude-sonnet-4",
6586
+ opus: "anthropic/claude-opus-4",
6587
+ haiku: "anthropic/claude-haiku-3-5"
6588
+ };
6589
+ return modelMap[model];
6590
+ }
6591
+ function mapPermissionsToOpenCode(permissionMode) {
6592
+ if (!permissionMode || permissionMode === "default")
6593
+ return;
6594
+ const permissionMap = {
6595
+ acceptEdits: { edit: "allow", bash: { "*": "ask" } },
6596
+ dontAsk: { edit: "allow", bash: { "*": "allow" } },
6597
+ bypassPermissions: { edit: "allow", bash: { "*": "allow" }, webfetch: "allow" },
6598
+ plan: { edit: "deny", bash: { "*": "deny" } }
6599
+ };
6600
+ return permissionMap[permissionMode];
6601
+ }
6602
+ function mapToolsToOpenCode(tools) {
6603
+ if (!tools || tools.length === 0)
6604
+ return;
6605
+ const toolsObject = {};
6606
+ for (const tool of tools) {
6607
+ toolsObject[tool.toLowerCase()] = true;
6608
+ }
6609
+ return toolsObject;
6610
+ }
6611
+ function generateFrontmatter3(agent) {
6612
+ const lines = ["---"];
6613
+ lines.push(`description: "${agent.description.replace(/"/g, "\\\"")}"`);
6614
+ const modelId = agent.modelId ?? mapModelToOpenCode(agent.model);
6615
+ if (modelId) {
6616
+ lines.push(`model: ${modelId}`);
6617
+ }
6618
+ if (agent.mode) {
6619
+ lines.push(`mode: ${agent.mode}`);
6620
+ }
6621
+ if (agent.temperature !== undefined) {
6622
+ lines.push(`temperature: ${agent.temperature}`);
6623
+ }
6624
+ if (agent.maxSteps !== undefined) {
6625
+ lines.push(`maxSteps: ${agent.maxSteps}`);
6626
+ }
6627
+ if (agent.hidden !== undefined) {
6628
+ lines.push(`hidden: ${agent.hidden}`);
6629
+ }
6630
+ const toolsObj = agent.toolPermissions ?? mapToolsToOpenCode(agent.tools);
6631
+ if (toolsObj) {
6632
+ lines.push("tools:");
6633
+ for (const [tool, enabled] of Object.entries(toolsObj)) {
6634
+ lines.push(` ${tool}: ${enabled}`);
6635
+ }
6636
+ }
6637
+ const permissions = agent.permissions ?? mapPermissionsToOpenCode(agent.permissionMode);
6638
+ if (permissions) {
6639
+ lines.push("permissions:");
6640
+ for (const [key, value] of Object.entries(permissions)) {
6641
+ if (typeof value === "object") {
6642
+ lines.push(` ${key}:`);
6643
+ for (const [subKey, subValue] of Object.entries(value)) {
6644
+ lines.push(` ${subKey}: ${subValue}`);
6645
+ }
6646
+ } else {
6647
+ lines.push(` ${key}: ${value}`);
6648
+ }
6649
+ }
6650
+ }
6651
+ lines.push("---");
6652
+ return lines.join(`
6653
+ `);
6654
+ }
6655
+ var OpenCodeAgentsWriter = {
6656
+ id: "opencode-agents",
6657
+ async write(bundle, ctx) {
6658
+ const agentsDir = join22(ctx.projectRoot, ctx.outputPath);
6659
+ await mkdir12(agentsDir, { recursive: true });
6660
+ const filesWritten = [];
6661
+ for (const agent of bundle.subagents) {
6662
+ const frontmatter = generateFrontmatter3(agent);
6663
+ const content = `${frontmatter}
6664
+
6665
+ ${agent.systemPrompt}`;
6666
+ const agentPath = join22(agentsDir, `${agent.name}.md`);
6667
+ await writeFile20(agentPath, content, "utf-8");
6668
+ filesWritten.push(join22(ctx.outputPath, `${agent.name}.md`));
6669
+ }
6670
+ return {
6671
+ filesWritten
6672
+ };
6673
+ }
6674
+ };
6675
+ // ../adapters/src/writers/opencode/commands.ts
6676
+ import { mkdir as mkdir13, writeFile as writeFile21 } from "node:fs/promises";
6677
+ import { join as join23 } from "node:path";
6678
+ function generateFrontmatter4(command) {
6679
+ const lines = ["---"];
6680
+ lines.push(`description: "${command.description.replace(/"/g, "\\\"")}"`);
6681
+ if (command.modelId) {
6682
+ lines.push(`model: ${command.modelId}`);
6683
+ }
6684
+ if (command.agent) {
6685
+ lines.push(`agent: ${command.agent}`);
6686
+ }
6687
+ lines.push("---");
6688
+ return lines.join(`
6689
+ `);
6690
+ }
6691
+ var OpenCodeCommandsWriter = {
6692
+ id: "opencode-commands",
6693
+ async write(bundle, ctx) {
6694
+ const commandsDir = join23(ctx.projectRoot, ctx.outputPath);
6695
+ await mkdir13(commandsDir, { recursive: true });
6696
+ const filesWritten = [];
6697
+ for (const command of bundle.commands) {
6698
+ const frontmatter = generateFrontmatter4(command);
6699
+ const content = `${frontmatter}
6700
+
6701
+ ${command.prompt}`;
6702
+ const commandPath = join23(commandsDir, `${command.name}.md`);
6703
+ await writeFile21(commandPath, content, "utf-8");
6704
+ filesWritten.push(join23(ctx.outputPath, `${command.name}.md`));
6705
+ }
6706
+ return {
6707
+ filesWritten
6708
+ };
6709
+ }
6710
+ };
6711
+ // ../adapters/src/opencode/index.ts
5540
6712
  var opencodeAdapter = {
5541
6713
  id: "opencode",
5542
6714
  displayName: "OpenCode",
5543
6715
  writers: [
5544
6716
  { writer: InstructionsMdWriter, outputPath: "AGENTS.md" },
5545
- { writer: SkillsWriter, outputPath: ".opencode/skills/" }
6717
+ { writer: SkillsWriter, outputPath: ".opencode/skills/" },
6718
+ { writer: OpenCodeAgentsWriter, outputPath: ".opencode/agents/" },
6719
+ { writer: OpenCodeCommandsWriter, outputPath: ".opencode/commands/" }
5546
6720
  ],
5547
6721
  async init(ctx) {
5548
- const opencodeDir = join16(ctx.projectRoot, ".opencode");
6722
+ const opencodeDir = join24(ctx.projectRoot, ".opencode");
5549
6723
  mkdirSync8(opencodeDir, { recursive: true });
5550
6724
  return {
5551
6725
  filesCreated: [".opencode/"],
@@ -5587,7 +6761,7 @@ async function inferCapabilityId(source, sourceType) {
5587
6761
  if (id) {
5588
6762
  return id;
5589
6763
  }
5590
- return basename3(resolvedPath);
6764
+ return basename5(resolvedPath);
5591
6765
  }
5592
6766
  const parts = source.replace("github:", "").split("/");
5593
6767
  if (parts.length >= 2) {
@@ -5597,7 +6771,7 @@ async function inferCapabilityId(source, sourceType) {
5597
6771
  }
5598
6772
  async function runAddCap(flags, name) {
5599
6773
  try {
5600
- if (!existsSync21("omni.toml")) {
6774
+ if (!existsSync22("omni.toml")) {
5601
6775
  console.log("✗ No config file found");
5602
6776
  console.log(" Run: omnidev init");
5603
6777
  process.exit(1);
@@ -5620,7 +6794,7 @@ async function runAddCap(flags, name) {
5620
6794
  sourceType = "local";
5621
6795
  const localPath = flags.local.startsWith("file://") ? flags.local.slice(7) : flags.local;
5622
6796
  source = `file://${localPath}`;
5623
- if (!existsSync21(localPath)) {
6797
+ if (!existsSync22(localPath)) {
5624
6798
  console.error(`✗ Local path not found: ${localPath}`);
5625
6799
  process.exit(1);
5626
6800
  }
@@ -5633,6 +6807,17 @@ async function runAddCap(flags, name) {
5633
6807
  process.exit(1);
5634
6808
  }
5635
6809
  source = `github:${flags.github}`;
6810
+ console.log(` Validating repository ${flags.github}...`);
6811
+ const validation = await validateGitCapability(source, flags.path);
6812
+ if (!validation.valid) {
6813
+ console.error(`✗ ${validation.error}`);
6814
+ process.exit(1);
6815
+ }
6816
+ if (validation.hasCapabilityToml) {
6817
+ console.log(` Found capability.toml`);
6818
+ } else {
6819
+ console.log(` Repository can be auto-wrapped as capability`);
6820
+ }
5636
6821
  } else {
5637
6822
  throw new Error("Unreachable: no source specified");
5638
6823
  }
@@ -5701,7 +6886,7 @@ async function runAddCap(flags, name) {
5701
6886
  }
5702
6887
  async function runAddMcp(flags, name) {
5703
6888
  try {
5704
- if (!existsSync21("omni.toml")) {
6889
+ if (!existsSync22("omni.toml")) {
5705
6890
  console.log("✗ No config file found");
5706
6891
  console.log(" Run: omnidev init");
5707
6892
  process.exit(1);
@@ -5832,12 +7017,16 @@ If the capability name is omitted, it will be inferred from:
5832
7017
  - For local sources: the ID in capability.toml or directory name
5833
7018
  - For GitHub sources: the repository name or last path segment
5834
7019
 
7020
+ Claude plugins (.claude-plugin/plugin.json) are automatically wrapped as OmniDev capabilities.
7021
+ Hooks defined in hooks.json are also supported and will be synced to .claude/settings.json.
7022
+
5835
7023
  Examples:
5836
7024
  omnidev add cap my-cap --github expo/skills # Uses version = "latest"
5837
7025
  omnidev add cap --github expo/skills # Infers name as "skills"
5838
7026
  omnidev add cap --github expo/skills --pin # Pins to detected version
5839
7027
  omnidev add cap --local ./capabilities/my-cap # Infers name from capability.toml
5840
- omnidev add cap custom-name --local ./capabilities/my-cap`
7028
+ omnidev add cap custom-name --local ./capabilities/my-cap
7029
+ omnidev add cap --github user/claude-plugin # Auto-wraps Claude plugins`
5841
7030
  },
5842
7031
  parameters: {
5843
7032
  flags: {
@@ -5984,9 +7173,9 @@ var addRoutes = buildRouteMap({
5984
7173
  });
5985
7174
 
5986
7175
  // src/commands/capability.ts
5987
- import { existsSync as existsSync22, mkdirSync as mkdirSync9 } from "node:fs";
5988
- import { writeFile as writeFile14 } from "node:fs/promises";
5989
- import { join as join17 } from "node:path";
7176
+ import { existsSync as existsSync23, mkdirSync as mkdirSync9 } from "node:fs";
7177
+ import { writeFile as writeFile22 } from "node:fs/promises";
7178
+ import { join as join25 } from "node:path";
5990
7179
  import { input } from "@inquirer/prompts";
5991
7180
  init_src();
5992
7181
  import { buildCommand as buildCommand2, buildRouteMap as buildRouteMap2 } from "@stricli/core";
@@ -6171,7 +7360,7 @@ node_modules/
6171
7360
  }
6172
7361
  async function runCapabilityNew(flags, capabilityId) {
6173
7362
  try {
6174
- if (!existsSync22(".omni")) {
7363
+ if (!existsSync23(".omni")) {
6175
7364
  console.error("✗ OmniDev is not initialized in this directory.");
6176
7365
  console.log("");
6177
7366
  console.log(" Run: omnidev init");
@@ -6195,28 +7384,28 @@ async function runCapabilityNew(flags, capabilityId) {
6195
7384
  default: defaultPath
6196
7385
  });
6197
7386
  }
6198
- if (existsSync22(capabilityDir)) {
7387
+ if (existsSync23(capabilityDir)) {
6199
7388
  console.error(`✗ Directory already exists at ${capabilityDir}`);
6200
7389
  process.exit(1);
6201
7390
  }
6202
7391
  const name = toTitleCase(id);
6203
7392
  mkdirSync9(capabilityDir, { recursive: true });
6204
7393
  const capabilityToml = generateCapabilityToml2({ id, name });
6205
- await writeFile14(join17(capabilityDir, "capability.toml"), capabilityToml, "utf-8");
6206
- const skillDir = join17(capabilityDir, "skills", "getting-started");
7394
+ await writeFile22(join25(capabilityDir, "capability.toml"), capabilityToml, "utf-8");
7395
+ const skillDir = join25(capabilityDir, "skills", "getting-started");
6207
7396
  mkdirSync9(skillDir, { recursive: true });
6208
- await writeFile14(join17(skillDir, "SKILL.md"), generateSkillTemplate("getting-started"), "utf-8");
6209
- const rulesDir = join17(capabilityDir, "rules");
7397
+ await writeFile22(join25(skillDir, "SKILL.md"), generateSkillTemplate("getting-started"), "utf-8");
7398
+ const rulesDir = join25(capabilityDir, "rules");
6210
7399
  mkdirSync9(rulesDir, { recursive: true });
6211
- await writeFile14(join17(rulesDir, "coding-standards.md"), generateRuleTemplate("coding-standards"), "utf-8");
6212
- const hooksDir = join17(capabilityDir, "hooks");
7400
+ await writeFile22(join25(rulesDir, "coding-standards.md"), generateRuleTemplate("coding-standards"), "utf-8");
7401
+ const hooksDir = join25(capabilityDir, "hooks");
6213
7402
  mkdirSync9(hooksDir, { recursive: true });
6214
- await writeFile14(join17(hooksDir, "hooks.toml"), generateHooksTemplate(), "utf-8");
6215
- await writeFile14(join17(hooksDir, "example-hook.sh"), generateHookScript(), "utf-8");
7403
+ await writeFile22(join25(hooksDir, "hooks.toml"), generateHooksTemplate(), "utf-8");
7404
+ await writeFile22(join25(hooksDir, "example-hook.sh"), generateHookScript(), "utf-8");
6216
7405
  if (flags.programmatic) {
6217
- await writeFile14(join17(capabilityDir, "package.json"), generatePackageJson(id), "utf-8");
6218
- await writeFile14(join17(capabilityDir, "index.ts"), generateIndexTs(id, name), "utf-8");
6219
- await writeFile14(join17(capabilityDir, ".gitignore"), generateGitignore(), "utf-8");
7406
+ await writeFile22(join25(capabilityDir, "package.json"), generatePackageJson(id), "utf-8");
7407
+ await writeFile22(join25(capabilityDir, "index.ts"), generateIndexTs(id, name), "utf-8");
7408
+ await writeFile22(join25(capabilityDir, ".gitignore"), generateGitignore(), "utf-8");
6220
7409
  }
6221
7410
  console.log(`✓ Created capability: ${name}`);
6222
7411
  console.log(` Location: ${capabilityDir}`);
@@ -6372,7 +7561,7 @@ var capabilityRoutes = buildRouteMap2({
6372
7561
  });
6373
7562
 
6374
7563
  // src/commands/doctor.ts
6375
- import { existsSync as existsSync23 } from "node:fs";
7564
+ import { existsSync as existsSync24 } from "node:fs";
6376
7565
  import { execFile } from "node:child_process";
6377
7566
  import { readFile as readFile19 } from "node:fs/promises";
6378
7567
  import { promisify } from "node:util";
@@ -6462,7 +7651,7 @@ async function checkPackageManager() {
6462
7651
  }
6463
7652
  }
6464
7653
  async function checkOmniLocalDir() {
6465
- const exists = existsSync23(".omni");
7654
+ const exists = existsSync24(".omni");
6466
7655
  if (!exists) {
6467
7656
  return {
6468
7657
  name: ".omni/ directory",
@@ -6479,7 +7668,7 @@ async function checkOmniLocalDir() {
6479
7668
  }
6480
7669
  async function checkConfig() {
6481
7670
  const configPath = "omni.toml";
6482
- if (!existsSync23(configPath)) {
7671
+ if (!existsSync24(configPath)) {
6483
7672
  return {
6484
7673
  name: "Configuration",
6485
7674
  passed: false,
@@ -6506,7 +7695,7 @@ async function checkConfig() {
6506
7695
  }
6507
7696
  async function checkRootGitignore() {
6508
7697
  const gitignorePath = ".gitignore";
6509
- if (!existsSync23(gitignorePath)) {
7698
+ if (!existsSync24(gitignorePath)) {
6510
7699
  return {
6511
7700
  name: "Root .gitignore",
6512
7701
  passed: false,
@@ -6540,7 +7729,7 @@ async function checkRootGitignore() {
6540
7729
  }
6541
7730
  async function checkCapabilitiesDir() {
6542
7731
  const capabilitiesDirPath = ".omni/capabilities";
6543
- if (!existsSync23(capabilitiesDirPath)) {
7732
+ if (!existsSync24(capabilitiesDirPath)) {
6544
7733
  return {
6545
7734
  name: "Capabilities Directory",
6546
7735
  passed: true,
@@ -6556,8 +7745,8 @@ async function checkCapabilitiesDir() {
6556
7745
 
6557
7746
  // src/commands/init.ts
6558
7747
  import { exec } from "node:child_process";
6559
- import { existsSync as existsSync24, mkdirSync as mkdirSync10 } from "node:fs";
6560
- import { readFile as readFile20, writeFile as writeFile15 } from "node:fs/promises";
7748
+ import { existsSync as existsSync25, mkdirSync as mkdirSync10 } from "node:fs";
7749
+ import { readFile as readFile20, writeFile as writeFile23 } from "node:fs/promises";
6561
7750
  import { promisify as promisify2 } from "node:util";
6562
7751
  init_src();
6563
7752
  import { buildCommand as buildCommand4 } from "@stricli/core";
@@ -6626,7 +7815,7 @@ async function runInit(_flags, providerArg) {
6626
7815
  }
6627
7816
  }
6628
7817
  await writeEnabledProviders(providerIds);
6629
- if (!existsSync24("omni.toml")) {
7818
+ if (!existsSync25("omni.toml")) {
6630
7819
  await writeConfig({
6631
7820
  profiles: {
6632
7821
  default: {
@@ -6642,8 +7831,8 @@ async function runInit(_flags, providerArg) {
6642
7831
  });
6643
7832
  await setActiveProfile("default");
6644
7833
  }
6645
- if (!existsSync24("OMNI.md")) {
6646
- await writeFile15("OMNI.md", generateOmniMdTemplate(), "utf-8");
7834
+ if (!existsSync25("OMNI.md")) {
7835
+ await writeFile23("OMNI.md", generateOmniMdTemplate(), "utf-8");
6647
7836
  }
6648
7837
  const config3 = await loadConfig();
6649
7838
  const ctx = {
@@ -6720,7 +7909,7 @@ async function addProviderFilesToGitignore(entries) {
6720
7909
  async function addToGitignore(entriesToAdd, sectionHeader) {
6721
7910
  const gitignorePath = ".gitignore";
6722
7911
  let content = "";
6723
- if (existsSync24(gitignorePath)) {
7912
+ if (existsSync25(gitignorePath)) {
6724
7913
  content = await readFile20(gitignorePath, "utf-8");
6725
7914
  }
6726
7915
  const lines = content.split(`
@@ -6736,7 +7925,7 @@ async function addToGitignore(entriesToAdd, sectionHeader) {
6736
7925
  ${missingEntries.join(`
6737
7926
  `)}
6738
7927
  `;
6739
- await writeFile15(gitignorePath, content + section, "utf-8");
7928
+ await writeFile23(gitignorePath, content + section, "utf-8");
6740
7929
  }
6741
7930
  async function getTrackedProviderFiles(files) {
6742
7931
  const tracked = [];
@@ -6752,7 +7941,7 @@ async function getTrackedProviderFiles(files) {
6752
7941
  }
6753
7942
 
6754
7943
  // src/commands/profile.ts
6755
- import { existsSync as existsSync25 } from "node:fs";
7944
+ import { existsSync as existsSync26 } from "node:fs";
6756
7945
  init_src();
6757
7946
  import { buildCommand as buildCommand5, buildRouteMap as buildRouteMap3 } from "@stricli/core";
6758
7947
  var listCommand2 = buildCommand5({
@@ -6796,7 +7985,7 @@ var profileRoutes = buildRouteMap3({
6796
7985
  });
6797
7986
  async function runProfileList() {
6798
7987
  try {
6799
- if (!existsSync25("omni.toml")) {
7988
+ if (!existsSync26("omni.toml")) {
6800
7989
  console.log("✗ No config file found");
6801
7990
  console.log(" Run: omnidev init");
6802
7991
  process.exit(1);
@@ -6836,7 +8025,7 @@ async function runProfileList() {
6836
8025
  }
6837
8026
  async function runProfileSet(profileName) {
6838
8027
  try {
6839
- if (!existsSync25("omni.toml")) {
8028
+ if (!existsSync26("omni.toml")) {
6840
8029
  console.log("✗ No config file found");
6841
8030
  console.log(" Run: omnidev init");
6842
8031
  process.exit(1);
@@ -6985,7 +8174,7 @@ var providerRoutes = buildRouteMap4({
6985
8174
 
6986
8175
  // src/commands/security.ts
6987
8176
  init_src();
6988
- import { existsSync as existsSync26 } from "node:fs";
8177
+ import { existsSync as existsSync27 } from "node:fs";
6989
8178
  import { buildCommand as buildCommand7, buildRouteMap as buildRouteMap5 } from "@stricli/core";
6990
8179
  var VALID_FINDING_TYPES = [
6991
8180
  "unicode_bidi",
@@ -7102,7 +8291,7 @@ function formatFindingsWithHints(summary) {
7102
8291
  }
7103
8292
  async function runSecurityIssues(flags = {}) {
7104
8293
  try {
7105
- if (!existsSync26("omni.toml")) {
8294
+ if (!existsSync27("omni.toml")) {
7106
8295
  console.log("No config file found");
7107
8296
  console.log(" Run: omnidev init");
7108
8297
  process.exit(1);
@@ -7357,7 +8546,7 @@ var securityRoutes = buildRouteMap5({
7357
8546
  });
7358
8547
 
7359
8548
  // src/commands/sync.ts
7360
- import { existsSync as existsSync27 } from "node:fs";
8549
+ import { existsSync as existsSync28 } from "node:fs";
7361
8550
  init_src();
7362
8551
  import { buildCommand as buildCommand8 } from "@stricli/core";
7363
8552
  var PROVIDERS_STATE_PATH = ".omni/state/providers.json";
@@ -7375,7 +8564,7 @@ async function runSync() {
7375
8564
  const config3 = await loadConfig();
7376
8565
  const activeProfile = await getActiveProfile() ?? "default";
7377
8566
  let adapters = await getEnabledAdapters();
7378
- if (!existsSync27(PROVIDERS_STATE_PATH) || adapters.length === 0) {
8567
+ if (!existsSync28(PROVIDERS_STATE_PATH) || adapters.length === 0) {
7379
8568
  console.log("No providers configured yet. Select your provider(s):");
7380
8569
  const providerIds = await promptForProviders();
7381
8570
  await writeEnabledProviders(providerIds);
@@ -7585,9 +8774,9 @@ async function buildDynamicApp() {
7585
8774
  security: securityRoutes
7586
8775
  };
7587
8776
  debug("Core routes registered", Object.keys(routes));
7588
- const configPath = join18(process.cwd(), "omni.toml");
7589
- debug("Checking for config", { configPath, exists: existsSync28(configPath), cwd: process.cwd() });
7590
- if (existsSync28(configPath)) {
8777
+ const configPath = join26(process.cwd(), "omni.toml");
8778
+ debug("Checking for config", { configPath, exists: existsSync29(configPath), cwd: process.cwd() });
8779
+ if (existsSync29(configPath)) {
7591
8780
  try {
7592
8781
  debug("Loading capability commands...");
7593
8782
  const capabilityCommands = await loadCapabilityCommands();
@@ -7662,25 +8851,25 @@ async function loadCapabilityCommands() {
7662
8851
  return commands;
7663
8852
  }
7664
8853
  async function loadCapabilityExport(capability3) {
7665
- const capabilityPath = join18(process.cwd(), capability3.path);
7666
- const builtIndexPath = join18(capabilityPath, "dist", "index.js");
7667
- const jsIndexPath = join18(capabilityPath, "index.js");
7668
- const tsIndexPath = join18(capabilityPath, "index.ts");
8854
+ const capabilityPath = join26(process.cwd(), capability3.path);
8855
+ const builtIndexPath = join26(capabilityPath, "dist", "index.js");
8856
+ const jsIndexPath = join26(capabilityPath, "index.js");
8857
+ const tsIndexPath = join26(capabilityPath, "index.ts");
7669
8858
  debug(`Checking entry points for '${capability3.id}'`, {
7670
8859
  capabilityPath,
7671
8860
  builtIndexPath,
7672
- builtExists: existsSync28(builtIndexPath),
8861
+ builtExists: existsSync29(builtIndexPath),
7673
8862
  jsIndexPath,
7674
- jsExists: existsSync28(jsIndexPath),
8863
+ jsExists: existsSync29(jsIndexPath),
7675
8864
  tsIndexPath,
7676
- tsExists: existsSync28(tsIndexPath)
8865
+ tsExists: existsSync29(tsIndexPath)
7677
8866
  });
7678
8867
  let indexPath = null;
7679
- if (existsSync28(builtIndexPath)) {
8868
+ if (existsSync29(builtIndexPath)) {
7680
8869
  indexPath = builtIndexPath;
7681
- } else if (existsSync28(jsIndexPath)) {
8870
+ } else if (existsSync29(jsIndexPath)) {
7682
8871
  indexPath = jsIndexPath;
7683
- } else if (existsSync28(tsIndexPath)) {
8872
+ } else if (existsSync29(tsIndexPath)) {
7684
8873
  indexPath = tsIndexPath;
7685
8874
  }
7686
8875
  if (!indexPath) {