@omnidev-ai/core 0.10.0 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -330,11 +330,6 @@ interface CapabilityExports {
330
330
  module?: string;
331
331
  gitignore?: string[];
332
332
  }
333
- interface EnvDeclaration {
334
- required?: boolean;
335
- secret?: boolean;
336
- default?: string;
337
- }
338
333
  interface SyncConfig {
339
334
  on_sync?: string;
340
335
  }
@@ -344,7 +339,6 @@ interface CliConfig {
344
339
  interface CapabilityConfig {
345
340
  capability: CapabilityMetadata;
346
341
  exports?: CapabilityExports;
347
- env?: Record<string, EnvDeclaration | Record<string, never>>;
348
342
  mcp?: McpConfig;
349
343
  sync?: SyncConfig;
350
344
  cli?: CliConfig;
@@ -360,7 +354,7 @@ interface McpToolSchema {
360
354
  *
361
355
  * - **stdio**: Local process using stdin/stdout (default)
362
356
  * - Requires: command
363
- * - Optional: args, env, cwd
357
+ * - Optional: args, cwd
364
358
  *
365
359
  * - **http**: Remote HTTP server (recommended for remote servers)
366
360
  * - Requires: url
@@ -508,7 +502,6 @@ interface OmniConfig {
508
502
  project?: string;
509
503
  active_profile?: string;
510
504
  always_enabled_capabilities?: string[];
511
- env?: Record<string, string>;
512
505
  profiles?: Record<string, ProfileConfig>;
513
506
  providers?: {
514
507
  enabled?: Provider[];
@@ -621,14 +614,11 @@ declare function discoverCapabilities(): Promise<string[]>;
621
614
  declare function loadCapabilityConfig(capabilityPath: string): Promise<CapabilityConfig>;
622
615
  /**
623
616
  * Loads a complete capability including config, skills, rules, docs, and exports.
624
- * Validates environment requirements before loading.
625
- *
626
617
  * @param capabilityPath - Path to the capability directory
627
- * @param env - Environment variables to validate against
628
618
  * @returns Fully loaded capability
629
- * @throws Error if validation fails or loading errors occur
619
+ * @throws Error if loading errors occur
630
620
  */
631
- declare function loadCapability(capabilityPath: string, env: Record<string, string>): Promise<LoadedCapability>;
621
+ declare function loadCapability(capabilityPath: string): Promise<LoadedCapability>;
632
622
  /**
633
623
  * Registry of loaded capabilities with helper functions.
634
624
  */
@@ -921,32 +911,6 @@ declare function enableCapability(capabilityId: string): Promise<void>;
921
911
  */
922
912
  declare function disableCapability(capabilityId: string): Promise<void>;
923
913
  /**
924
- * Load environment variables from .omni/.env file and merge with process.env.
925
- * Process environment variables take precedence over file values.
926
- *
927
- * @returns Merged environment variables
928
- */
929
- declare function loadEnvironment(): Promise<Record<string, string>>;
930
- /**
931
- * Validate that all required environment variables are present.
932
- * Checks declarations from capability config and throws descriptive errors for missing vars.
933
- *
934
- * @param declarations - Environment variable declarations from capability.toml
935
- * @param env - Loaded environment variables
936
- * @param capabilityId - ID of the capability being validated
937
- * @throws Error if required environment variables are missing
938
- */
939
- declare function validateEnv(declarations: Record<string, EnvDeclaration | Record<string, never>>, env: Record<string, string | undefined>, capabilityId: string): void;
940
- /**
941
- * Check if an environment variable should be treated as a secret.
942
- * Secrets should be masked in logs and error messages.
943
- *
944
- * @param key - Environment variable name
945
- * @param declarations - Environment variable declarations from capability.toml
946
- * @returns true if the variable is marked as secret
947
- */
948
- declare function isSecretEnvVar(key: string, declarations: Record<string, EnvDeclaration | Record<string, never>>): boolean;
949
- /**
950
914
  * Load only the base config file (omni.toml) without merging local overrides.
951
915
  * Use this when you need to modify and write back to omni.toml.
952
916
  * @returns OmniConfig from omni.toml only
@@ -1251,4 +1215,4 @@ declare function generateOmniMdTemplate(): string;
1251
1215
  declare function debug(message: string, data?: unknown): void;
1252
1216
  declare const version = "0.1.0";
1253
1217
  declare function getVersion(): string;
1254
- export { writeProviderConfig, writeMcpJson, writeEnabledProviders, writeConfig, writeActiveProfileState, version, validateHooksConfig, validateHook, validateEnv, transformToOmnidev, transformToClaude, transformHooksConfig, syncMcpJson, syncAgentConfiguration, sourceToGitUrl, setProfile, setActiveProfile, saveManifest, saveLockFile, resolveEnabledCapabilities, readMcpJson, readEnabledProviders, readCapabilityIdFromPath, readActiveProfileState, patchAddToProfile, patchAddMcp, patchAddCapabilitySource, parseSourceConfig, parseProviderFlag, parseOmniConfig, parseFileSourcePath, parseCapabilityConfig, mergeHooksConfigs, mergeAndDeduplicateHooks, loadSubagents, loadSkills, loadRules, loadProviderConfig, loadProfileConfig, loadManifest, loadLockFile, loadHooksFromCapability, loadEnvironment, loadDocs, loadConfig, loadCommands, loadCapabilityHooks, loadCapabilityConfig, loadCapability, loadBaseConfig, isValidMatcherPattern, isSecretEnvVar, isProviderEnabled, isPromptHookEvent, isMatcherEvent, isHookType, isHookPrompt, isHookEvent, isHookCommand, isGitSource, isFileSourceConfig, isFileSource, installCapabilityDependencies, hasHooks, hasAnyHooks, getVersion, getSourceCapabilityPath, getLockFilePath, getHooksDirectory, getHooksConfigPath, getEventsWithHooks, getEnabledCapabilities, getActiveProviders, getActiveProfile, generateSkillTemplate, generateRuleTemplate, generateOmniMdTemplate, generateHooksTemplate, generateHookScript, generateClaudeTemplate, generateCapabilityToml, generateAgentsTemplate, findDuplicateCommands, fetchCapabilitySource, fetchAllCapabilitySources, enableProvider, enableCapability, discoverCapabilities, disableProvider, disableCapability, debug, createEmptyValidationResult, createEmptyHooksConfig, countHooks, containsOmnidevVariables, containsClaudeVariables, clearActiveProfileState, cleanupStaleResources, checkForUpdates, buildSyncBundle, buildRouteMap, buildManifestFromCapabilities, buildCommand, buildCapabilityRegistry, ValidationSeverity, VARIABLE_MAPPINGS, SyncResult, SyncOptions, SyncConfig, SyncBundle, SubagentPermissionMode, SubagentModel, SubagentHooks, SubagentHookConfig, SubagentExport, Subagent, SourceUpdateInfo, SkillExport, Skill, SessionStartMatcher, SESSION_START_MATCHERS, Rule, ResourceManifest, ProvidersState, ProviderSyncResult, ProviderManifest, ProviderInitResult, ProviderId, ProviderContext, ProviderConfig, ProviderAdapter, Provider, PromptHookEvent, ProfileConfig, PreCompactMatcher, PROMPT_HOOK_EVENTS, PRE_COMPACT_MATCHERS, OmnidevVariable, OmniConfig, NotificationMatcher, NOTIFICATION_MATCHERS, McpTransport, McpToolSchema, McpServerStdioConfig, McpServerSseConfig, McpServerHttpConfig, McpServerConfig, McpJsonConfig, McpConfig, MatcherEvent, MATCHER_EVENTS, LoadedCapability, LoadHooksResult, LoadHooksOptions, HooksDoctorResult, HooksDoctorCheck, HooksConfig, HookValidationResult, HookValidationIssue, HookValidationCode, HookType, HookPrompt, HookMatcher, HookEvent, HookCommand, Hook, HOOK_TYPES, HOOK_EVENTS, HOOKS_DIRECTORY, HOOKS_CONFIG_FILENAME, GitCapabilitySourceConfig, FileContent, FileCapabilitySourceConfig, FetchResult, EnvDeclaration, DoctorCheckStatus, DocExport, Doc, DiscoveredContent, DeduplicateOptions, DEFAULT_PROMPT_TIMEOUT, DEFAULT_COMMAND_TIMEOUT, CommandExport, Command, CliConfig, CleanupResult, ClaudeVariable, CapabilityTemplateOptions, CapabilitySourceType, CapabilitySourceConfig, CapabilitySource, CapabilityResources, CapabilityRegistry, CapabilityMetadata, CapabilityLockEntry, CapabilityHooks, CapabilityExports, CapabilityExport, CapabilityConfig, CapabilitiesLockFile, CapabilitiesConfig, COMMON_TOOL_MATCHERS };
1218
+ export { writeProviderConfig, writeMcpJson, writeEnabledProviders, writeConfig, writeActiveProfileState, version, validateHooksConfig, validateHook, transformToOmnidev, transformToClaude, transformHooksConfig, syncMcpJson, syncAgentConfiguration, sourceToGitUrl, setProfile, setActiveProfile, saveManifest, saveLockFile, resolveEnabledCapabilities, readMcpJson, readEnabledProviders, readCapabilityIdFromPath, readActiveProfileState, patchAddToProfile, patchAddMcp, patchAddCapabilitySource, parseSourceConfig, parseProviderFlag, parseOmniConfig, parseFileSourcePath, parseCapabilityConfig, mergeHooksConfigs, mergeAndDeduplicateHooks, loadSubagents, loadSkills, loadRules, loadProviderConfig, loadProfileConfig, loadManifest, loadLockFile, loadHooksFromCapability, loadDocs, loadConfig, loadCommands, loadCapabilityHooks, loadCapabilityConfig, loadCapability, loadBaseConfig, isValidMatcherPattern, isProviderEnabled, isPromptHookEvent, isMatcherEvent, isHookType, isHookPrompt, isHookEvent, isHookCommand, isGitSource, isFileSourceConfig, isFileSource, installCapabilityDependencies, hasHooks, hasAnyHooks, getVersion, getSourceCapabilityPath, getLockFilePath, getHooksDirectory, getHooksConfigPath, getEventsWithHooks, getEnabledCapabilities, getActiveProviders, getActiveProfile, generateSkillTemplate, generateRuleTemplate, generateOmniMdTemplate, generateHooksTemplate, generateHookScript, generateClaudeTemplate, generateCapabilityToml, generateAgentsTemplate, findDuplicateCommands, fetchCapabilitySource, fetchAllCapabilitySources, enableProvider, enableCapability, discoverCapabilities, disableProvider, disableCapability, debug, createEmptyValidationResult, createEmptyHooksConfig, countHooks, containsOmnidevVariables, containsClaudeVariables, clearActiveProfileState, cleanupStaleResources, checkForUpdates, buildSyncBundle, buildRouteMap, buildManifestFromCapabilities, buildCommand, buildCapabilityRegistry, ValidationSeverity, VARIABLE_MAPPINGS, SyncResult, SyncOptions, SyncConfig, SyncBundle, SubagentPermissionMode, SubagentModel, SubagentHooks, SubagentHookConfig, SubagentExport, Subagent, SourceUpdateInfo, SkillExport, Skill, SessionStartMatcher, SESSION_START_MATCHERS, Rule, ResourceManifest, ProvidersState, ProviderSyncResult, ProviderManifest, ProviderInitResult, ProviderId, ProviderContext, ProviderConfig, ProviderAdapter, Provider, PromptHookEvent, ProfileConfig, PreCompactMatcher, PROMPT_HOOK_EVENTS, PRE_COMPACT_MATCHERS, OmnidevVariable, OmniConfig, NotificationMatcher, NOTIFICATION_MATCHERS, McpTransport, McpToolSchema, McpServerStdioConfig, McpServerSseConfig, McpServerHttpConfig, McpServerConfig, McpJsonConfig, McpConfig, MatcherEvent, MATCHER_EVENTS, LoadedCapability, LoadHooksResult, LoadHooksOptions, HooksDoctorResult, HooksDoctorCheck, HooksConfig, HookValidationResult, HookValidationIssue, HookValidationCode, HookType, HookPrompt, HookMatcher, HookEvent, HookCommand, Hook, HOOK_TYPES, HOOK_EVENTS, HOOKS_DIRECTORY, HOOKS_CONFIG_FILENAME, GitCapabilitySourceConfig, FileContent, FileCapabilitySourceConfig, FetchResult, DoctorCheckStatus, DocExport, Doc, DiscoveredContent, DeduplicateOptions, DEFAULT_PROMPT_TIMEOUT, DEFAULT_COMMAND_TIMEOUT, CommandExport, Command, CliConfig, CleanupResult, ClaudeVariable, CapabilityTemplateOptions, CapabilitySourceType, CapabilitySourceConfig, CapabilitySource, CapabilityResources, CapabilityRegistry, CapabilityMetadata, CapabilityLockEntry, CapabilityHooks, CapabilityExports, CapabilityExport, CapabilityConfig, CapabilitiesLockFile, CapabilitiesConfig, COMMON_TOOL_MATCHERS };
package/dist/index.js CHANGED
@@ -118,58 +118,10 @@ async function loadDocs(capabilityPath, capabilityId) {
118
118
  return docs;
119
119
  }
120
120
  // src/capability/loader.ts
121
- import { existsSync as existsSync9, readdirSync as readdirSync6 } from "node:fs";
122
- import { readFile as readFile7 } from "node:fs/promises";
121
+ import { existsSync as existsSync8, readdirSync as readdirSync6 } from "node:fs";
122
+ import { readFile as readFile6 } from "node:fs/promises";
123
123
  import { join as join7 } from "node:path";
124
124
 
125
- // src/config/env.ts
126
- import { existsSync as existsSync3 } from "node:fs";
127
- import { readFile as readFile3 } from "node:fs/promises";
128
- var ENV_FILE = ".omni/.env";
129
- async function loadEnvironment() {
130
- const env = {};
131
- if (existsSync3(ENV_FILE)) {
132
- const content = await readFile3(ENV_FILE, "utf-8");
133
- for (const line of content.split(`
134
- `)) {
135
- const trimmed = line.trim();
136
- if (trimmed && !trimmed.startsWith("#")) {
137
- const eqIndex = trimmed.indexOf("=");
138
- if (eqIndex > 0) {
139
- const key = trimmed.slice(0, eqIndex).trim();
140
- const value = trimmed.slice(eqIndex + 1).trim();
141
- const unquotedValue = value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'") ? value.slice(1, -1) : value;
142
- env[key] = unquotedValue;
143
- }
144
- }
145
- }
146
- }
147
- const processEnv = {};
148
- for (const [key, value] of Object.entries(process.env)) {
149
- if (value !== undefined) {
150
- processEnv[key] = value;
151
- }
152
- }
153
- return { ...env, ...processEnv };
154
- }
155
- function validateEnv(declarations, env, capabilityId) {
156
- const missing = [];
157
- for (const [key, decl] of Object.entries(declarations)) {
158
- const declaration = decl;
159
- const value = env[key] ?? declaration.default;
160
- if (declaration.required && !value) {
161
- missing.push(key);
162
- }
163
- }
164
- if (missing.length > 0) {
165
- throw new Error(`Missing required environment variable${missing.length > 1 ? "s" : ""} for capability "${capabilityId}": ${missing.join(", ")}. ` + `Set ${missing.length > 1 ? "them" : "it"} in .omni/.env or as environment variable${missing.length > 1 ? "s" : ""}.`);
166
- }
167
- }
168
- function isSecretEnvVar(key, declarations) {
169
- const decl = declarations[key];
170
- return decl?.secret === true;
171
- }
172
-
173
125
  // src/config/parser.ts
174
126
  import { parse } from "smol-toml";
175
127
  function parseOmniConfig(tomlContent) {
@@ -208,7 +160,7 @@ function parseCapabilityConfig(tomlContent) {
208
160
  }
209
161
 
210
162
  // src/hooks/loader.ts
211
- import { existsSync as existsSync5, readFileSync } from "node:fs";
163
+ import { existsSync as existsSync4, readFileSync } from "node:fs";
212
164
  import { join as join3 } from "node:path";
213
165
  import { parse as parseToml } from "smol-toml";
214
166
 
@@ -274,7 +226,7 @@ var HOOKS_CONFIG_FILENAME = "hooks.toml";
274
226
  var HOOKS_DIRECTORY = "hooks";
275
227
 
276
228
  // src/hooks/validation.ts
277
- import { existsSync as existsSync4, statSync } from "node:fs";
229
+ import { existsSync as existsSync3, statSync } from "node:fs";
278
230
  import { resolve } from "node:path";
279
231
 
280
232
  // src/hooks/types.ts
@@ -590,7 +542,7 @@ function validateScriptInCommand(command, basePath, event, matcherIndex, hookInd
590
542
  const relativePath = match[1];
591
543
  if (relativePath) {
592
544
  const fullPath = resolve(basePath, relativePath);
593
- if (!existsSync4(fullPath)) {
545
+ if (!existsSync3(fullPath)) {
594
546
  issues.push({
595
547
  severity: "error",
596
548
  code: "HOOKS_SCRIPT_NOT_FOUND",
@@ -757,7 +709,7 @@ function loadHooksFromCapability(capabilityPath, options) {
757
709
  };
758
710
  const hooksDir = join3(capabilityPath, HOOKS_DIRECTORY);
759
711
  const configPath = join3(hooksDir, HOOKS_CONFIG_FILENAME);
760
- if (!existsSync5(configPath)) {
712
+ if (!existsSync4(configPath)) {
761
713
  return {
762
714
  config: createEmptyHooksConfig(),
763
715
  validation: createEmptyValidationResult(),
@@ -844,7 +796,7 @@ function loadCapabilityHooks(capabilityName, capabilityPath, options) {
844
796
  }
845
797
  function hasHooks(capabilityPath) {
846
798
  const configPath = join3(capabilityPath, HOOKS_DIRECTORY, HOOKS_CONFIG_FILENAME);
847
- return existsSync5(configPath);
799
+ return existsSync4(configPath);
848
800
  }
849
801
  function getHooksDirectory(capabilityPath) {
850
802
  return join3(capabilityPath, HOOKS_DIRECTORY);
@@ -854,12 +806,12 @@ function getHooksConfigPath(capabilityPath) {
854
806
  }
855
807
 
856
808
  // src/capability/rules.ts
857
- import { existsSync as existsSync6, readdirSync as readdirSync3 } from "node:fs";
858
- import { readFile as readFile4 } from "node:fs/promises";
809
+ import { existsSync as existsSync5, readdirSync as readdirSync3 } from "node:fs";
810
+ import { readFile as readFile3 } from "node:fs/promises";
859
811
  import { basename as basename2, join as join4 } from "node:path";
860
812
  async function loadRules(capabilityPath, capabilityId) {
861
813
  const rulesDir = join4(capabilityPath, "rules");
862
- if (!existsSync6(rulesDir)) {
814
+ if (!existsSync5(rulesDir)) {
863
815
  return [];
864
816
  }
865
817
  const rules = [];
@@ -867,7 +819,7 @@ async function loadRules(capabilityPath, capabilityId) {
867
819
  for (const entry of entries) {
868
820
  if (entry.isFile() && entry.name.endsWith(".md")) {
869
821
  const rulePath = join4(rulesDir, entry.name);
870
- const content = await readFile4(rulePath, "utf-8");
822
+ const content = await readFile3(rulePath, "utf-8");
871
823
  rules.push({
872
824
  name: basename2(entry.name, ".md"),
873
825
  content: content.trim(),
@@ -879,12 +831,12 @@ async function loadRules(capabilityPath, capabilityId) {
879
831
  }
880
832
 
881
833
  // src/capability/skills.ts
882
- import { existsSync as existsSync7, readdirSync as readdirSync4 } from "node:fs";
883
- import { readFile as readFile5 } from "node:fs/promises";
834
+ import { existsSync as existsSync6, readdirSync as readdirSync4 } from "node:fs";
835
+ import { readFile as readFile4 } from "node:fs/promises";
884
836
  import { join as join5 } from "node:path";
885
837
  async function loadSkills(capabilityPath, capabilityId) {
886
838
  const skillsDir = join5(capabilityPath, "skills");
887
- if (!existsSync7(skillsDir)) {
839
+ if (!existsSync6(skillsDir)) {
888
840
  return [];
889
841
  }
890
842
  const skills = [];
@@ -892,7 +844,7 @@ async function loadSkills(capabilityPath, capabilityId) {
892
844
  for (const entry of entries) {
893
845
  if (entry.isDirectory()) {
894
846
  const skillPath = join5(skillsDir, entry.name, "SKILL.md");
895
- if (existsSync7(skillPath)) {
847
+ if (existsSync6(skillPath)) {
896
848
  const skill = await parseSkillFile(skillPath, capabilityId);
897
849
  skills.push(skill);
898
850
  }
@@ -901,7 +853,7 @@ async function loadSkills(capabilityPath, capabilityId) {
901
853
  return skills;
902
854
  }
903
855
  async function parseSkillFile(filePath, capabilityId) {
904
- const content = await readFile5(filePath, "utf-8");
856
+ const content = await readFile4(filePath, "utf-8");
905
857
  const parsed = parseFrontmatterWithMarkdown(content);
906
858
  if (!parsed) {
907
859
  throw new Error(`Invalid SKILL.md format at ${filePath}: missing YAML frontmatter`);
@@ -920,12 +872,12 @@ async function parseSkillFile(filePath, capabilityId) {
920
872
  }
921
873
 
922
874
  // src/capability/subagents.ts
923
- import { existsSync as existsSync8, readdirSync as readdirSync5 } from "node:fs";
924
- import { readFile as readFile6 } from "node:fs/promises";
875
+ import { existsSync as existsSync7, readdirSync as readdirSync5 } from "node:fs";
876
+ import { readFile as readFile5 } from "node:fs/promises";
925
877
  import { join as join6 } from "node:path";
926
878
  async function loadSubagents(capabilityPath, capabilityId) {
927
879
  const subagentsDir = join6(capabilityPath, "subagents");
928
- if (!existsSync8(subagentsDir)) {
880
+ if (!existsSync7(subagentsDir)) {
929
881
  return [];
930
882
  }
931
883
  const subagents = [];
@@ -933,7 +885,7 @@ async function loadSubagents(capabilityPath, capabilityId) {
933
885
  for (const entry of entries) {
934
886
  if (entry.isDirectory()) {
935
887
  const subagentPath = join6(subagentsDir, entry.name, "SUBAGENT.md");
936
- if (existsSync8(subagentPath)) {
888
+ if (existsSync7(subagentPath)) {
937
889
  const subagent = await parseSubagentFile(subagentPath, capabilityId);
938
890
  subagents.push(subagent);
939
891
  }
@@ -942,7 +894,7 @@ async function loadSubagents(capabilityPath, capabilityId) {
942
894
  return subagents;
943
895
  }
944
896
  async function parseSubagentFile(filePath, capabilityId) {
945
- const content = await readFile6(filePath, "utf-8");
897
+ const content = await readFile5(filePath, "utf-8");
946
898
  const parsed = parseFrontmatterWithMarkdown(content);
947
899
  if (!parsed) {
948
900
  throw new Error(`Invalid SUBAGENT.md format at ${filePath}: missing YAML frontmatter`);
@@ -986,13 +938,13 @@ function parseCommaSeparatedList(value) {
986
938
  var CAPABILITIES_DIR = ".omni/capabilities";
987
939
  async function discoverCapabilities() {
988
940
  const capabilities = [];
989
- if (existsSync9(CAPABILITIES_DIR)) {
941
+ if (existsSync8(CAPABILITIES_DIR)) {
990
942
  const entries = readdirSync6(CAPABILITIES_DIR, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
991
943
  for (const entry of entries) {
992
944
  if (entry.isDirectory()) {
993
945
  const entryPath = join7(CAPABILITIES_DIR, entry.name);
994
946
  const configPath = join7(entryPath, "capability.toml");
995
- if (existsSync9(configPath)) {
947
+ if (existsSync8(configPath)) {
996
948
  capabilities.push(entryPath);
997
949
  }
998
950
  }
@@ -1002,13 +954,13 @@ async function discoverCapabilities() {
1002
954
  }
1003
955
  async function loadCapabilityConfig(capabilityPath) {
1004
956
  const configPath = join7(capabilityPath, "capability.toml");
1005
- const content = await readFile7(configPath, "utf-8");
957
+ const content = await readFile6(configPath, "utf-8");
1006
958
  const config = parseCapabilityConfig(content);
1007
959
  return config;
1008
960
  }
1009
961
  async function importCapabilityExports(capabilityPath) {
1010
962
  const indexPath = join7(capabilityPath, "index.ts");
1011
- if (!existsSync9(indexPath)) {
963
+ if (!existsSync8(indexPath)) {
1012
964
  return {};
1013
965
  }
1014
966
  try {
@@ -1028,10 +980,10 @@ If this is a project-specific capability, install dependencies or remove it from
1028
980
  }
1029
981
  async function loadTypeDefinitions(capabilityPath) {
1030
982
  const typesPath = join7(capabilityPath, "types.d.ts");
1031
- if (!existsSync9(typesPath)) {
983
+ if (!existsSync8(typesPath)) {
1032
984
  return;
1033
985
  }
1034
- return readFile7(typesPath, "utf-8");
986
+ return readFile6(typesPath, "utf-8");
1035
987
  }
1036
988
  function convertSkillExports(skillExports, capabilityId) {
1037
989
  return skillExports.map((skillExport) => {
@@ -1208,12 +1160,9 @@ function convertCommandExports(commandExports, capabilityId) {
1208
1160
  return result;
1209
1161
  });
1210
1162
  }
1211
- async function loadCapability(capabilityPath, env) {
1163
+ async function loadCapability(capabilityPath) {
1212
1164
  const config = await loadCapabilityConfig(capabilityPath);
1213
1165
  const id = config.capability.id;
1214
- if (config.env) {
1215
- validateEnv(config.env, env, id);
1216
- }
1217
1166
  const exports = await importCapabilityExports(capabilityPath);
1218
1167
  const exportsAny = exports;
1219
1168
  const skills = "skills" in exports && Array.isArray(exportsAny.skills) ? convertSkillExports(exportsAny.skills, id) : await loadSkills(capabilityPath, id);
@@ -1248,13 +1197,12 @@ async function loadCapability(capabilityPath, env) {
1248
1197
  return result;
1249
1198
  }
1250
1199
  // src/config/config.ts
1251
- import { existsSync as existsSync10 } from "node:fs";
1252
- import { readFile as readFile8, writeFile } from "node:fs/promises";
1200
+ import { existsSync as existsSync9 } from "node:fs";
1201
+ import { readFile as readFile7, writeFile } from "node:fs/promises";
1253
1202
  var CONFIG_PATH = "omni.toml";
1254
1203
  var LOCAL_CONFIG = "omni.local.toml";
1255
1204
  function mergeConfigs(base, override) {
1256
1205
  const merged = { ...base, ...override };
1257
- merged.env = { ...base.env, ...override.env };
1258
1206
  merged.profiles = { ...base.profiles };
1259
1207
  for (const [name, profile] of Object.entries(override.profiles || {})) {
1260
1208
  merged.profiles[name] = {
@@ -1268,8 +1216,8 @@ function mergeConfigs(base, override) {
1268
1216
  return merged;
1269
1217
  }
1270
1218
  async function loadBaseConfig() {
1271
- if (existsSync10(CONFIG_PATH)) {
1272
- const content = await readFile8(CONFIG_PATH, "utf-8");
1219
+ if (existsSync9(CONFIG_PATH)) {
1220
+ const content = await readFile7(CONFIG_PATH, "utf-8");
1273
1221
  return parseOmniConfig(content);
1274
1222
  }
1275
1223
  return {};
@@ -1277,8 +1225,8 @@ async function loadBaseConfig() {
1277
1225
  async function loadConfig() {
1278
1226
  const baseConfig = await loadBaseConfig();
1279
1227
  let localConfig = {};
1280
- if (existsSync10(LOCAL_CONFIG)) {
1281
- const content = await readFile8(LOCAL_CONFIG, "utf-8");
1228
+ if (existsSync9(LOCAL_CONFIG)) {
1229
+ const content = await readFile7(LOCAL_CONFIG, "utf-8");
1282
1230
  localConfig = parseOmniConfig(content);
1283
1231
  }
1284
1232
  return mergeConfigs(baseConfig, localConfig);
@@ -1289,22 +1237,6 @@ async function writeConfig(config) {
1289
1237
  }
1290
1238
  function generateConfigToml(config) {
1291
1239
  const lines = [];
1292
- lines.push("# =============================================================================");
1293
- lines.push("# OmniDev Configuration");
1294
- lines.push("# =============================================================================");
1295
- lines.push("# This file defines your project's capabilities, profiles, and settings.");
1296
- lines.push("#");
1297
- lines.push("# Files:");
1298
- lines.push("# • omni.toml - Main config (commit to share with team)");
1299
- lines.push("# • omni.local.toml - Local overrides (add to .gitignore)");
1300
- lines.push("# • omni.lock.toml - Version lock file (commit for reproducibility)");
1301
- lines.push("#");
1302
- lines.push("# Quick start:");
1303
- lines.push("# 1. Add capability sources to [capabilities.sources]");
1304
- lines.push("# 2. Reference them in your profiles");
1305
- lines.push("# 3. Run: omnidev sync");
1306
- lines.push("# 4. Switch profiles: omnidev profile use <name>");
1307
- lines.push("");
1308
1240
  if (config.providers?.enabled && config.providers.enabled.length > 0) {
1309
1241
  lines.push("# AI providers to enable (claude, codex, or both)");
1310
1242
  lines.push("[providers]");
@@ -1312,23 +1244,6 @@ function generateConfigToml(config) {
1312
1244
  lines.push("");
1313
1245
  }
1314
1246
  lines.push("# =============================================================================");
1315
- lines.push("# Environment Variables");
1316
- lines.push("# =============================================================================");
1317
- lines.push("# Global environment variables available to all capabilities.");
1318
- lines.push("# Use ${VAR_NAME} syntax to reference shell environment variables.");
1319
- lines.push("#");
1320
- if (config.env && Object.keys(config.env).length > 0) {
1321
- lines.push("[env]");
1322
- for (const [key, value] of Object.entries(config.env)) {
1323
- lines.push(`${key} = "${value}"`);
1324
- }
1325
- } else {
1326
- lines.push("# [env]");
1327
- lines.push('# DATABASE_URL = "${DATABASE_URL}"');
1328
- lines.push('# API_KEY = "${MY_API_KEY}"');
1329
- }
1330
- lines.push("");
1331
- lines.push("# =============================================================================");
1332
1247
  lines.push("# Capability Sources");
1333
1248
  lines.push("# =============================================================================");
1334
1249
  lines.push("# Fetch capabilities from Git repositories. On sync, these are");
@@ -1408,10 +1323,8 @@ function generateConfigToml(config) {
1408
1323
  lines.push(`url = "${mcpConfig.url}"`);
1409
1324
  }
1410
1325
  if (mcpConfig.env && Object.keys(mcpConfig.env).length > 0) {
1411
- lines.push(`[mcps.${name}.env]`);
1412
- for (const [key, value] of Object.entries(mcpConfig.env)) {
1413
- lines.push(`${key} = "${value}"`);
1414
- }
1326
+ const entries = Object.entries(mcpConfig.env).map(([key, value]) => `${key} = "${value}"`);
1327
+ lines.push(`env = { ${entries.join(", ")} }`);
1415
1328
  }
1416
1329
  if (mcpConfig.headers && Object.keys(mcpConfig.headers).length > 0) {
1417
1330
  lines.push(`[mcps.${name}.headers]`);
@@ -1431,8 +1344,7 @@ function generateConfigToml(config) {
1431
1344
  lines.push('# command = "node"');
1432
1345
  lines.push('# args = ["./servers/database.js"]');
1433
1346
  lines.push('# cwd = "./mcp-servers"');
1434
- lines.push("# [mcps.database.env]");
1435
- lines.push('# DB_URL = "${DATABASE_URL}"');
1347
+ lines.push('# env = { DB_URL = "${DATABASE_URL}" }');
1436
1348
  lines.push("");
1437
1349
  }
1438
1350
  lines.push("# =============================================================================");
@@ -1471,16 +1383,16 @@ function generateConfigToml(config) {
1471
1383
  }
1472
1384
 
1473
1385
  // src/state/active-profile.ts
1474
- import { existsSync as existsSync11, mkdirSync } from "node:fs";
1475
- import { readFile as readFile9, unlink, writeFile as writeFile2 } from "node:fs/promises";
1386
+ import { existsSync as existsSync10, mkdirSync } from "node:fs";
1387
+ import { readFile as readFile8, unlink, writeFile as writeFile2 } from "node:fs/promises";
1476
1388
  var STATE_DIR = ".omni/state";
1477
1389
  var ACTIVE_PROFILE_PATH = `${STATE_DIR}/active-profile`;
1478
1390
  async function readActiveProfileState() {
1479
- if (!existsSync11(ACTIVE_PROFILE_PATH)) {
1391
+ if (!existsSync10(ACTIVE_PROFILE_PATH)) {
1480
1392
  return null;
1481
1393
  }
1482
1394
  try {
1483
- const content = await readFile9(ACTIVE_PROFILE_PATH, "utf-8");
1395
+ const content = await readFile8(ACTIVE_PROFILE_PATH, "utf-8");
1484
1396
  const trimmed = content.trim();
1485
1397
  return trimmed || null;
1486
1398
  } catch {
@@ -1492,7 +1404,7 @@ async function writeActiveProfileState(profileName) {
1492
1404
  await writeFile2(ACTIVE_PROFILE_PATH, profileName, "utf-8");
1493
1405
  }
1494
1406
  async function clearActiveProfileState() {
1495
- if (existsSync11(ACTIVE_PROFILE_PATH)) {
1407
+ if (existsSync10(ACTIVE_PROFILE_PATH)) {
1496
1408
  await unlink(ACTIVE_PROFILE_PATH);
1497
1409
  }
1498
1410
  }
@@ -1666,13 +1578,12 @@ function getEventsWithHooks(config) {
1666
1578
 
1667
1579
  // src/capability/registry.ts
1668
1580
  async function buildCapabilityRegistry() {
1669
- const env = await loadEnvironment();
1670
1581
  const enabledIds = await getEnabledCapabilities();
1671
1582
  const capabilityPaths = await discoverCapabilities();
1672
1583
  const capabilities = new Map;
1673
1584
  for (const path of capabilityPaths) {
1674
1585
  try {
1675
- const cap = await loadCapability(path, env);
1586
+ const cap = await loadCapability(path);
1676
1587
  if (enabledIds.includes(cap.id)) {
1677
1588
  capabilities.set(cap.id, cap);
1678
1589
  }
@@ -1703,9 +1614,9 @@ async function buildCapabilityRegistry() {
1703
1614
  };
1704
1615
  }
1705
1616
  // src/capability/sources.ts
1706
- import { existsSync as existsSync12 } from "node:fs";
1617
+ import { existsSync as existsSync11 } from "node:fs";
1707
1618
  import { spawn } from "node:child_process";
1708
- import { cp, mkdir, readdir, readFile as readFile10, rename, rm, stat, writeFile as writeFile3 } from "node:fs/promises";
1619
+ import { cp, mkdir, readdir, readFile as readFile9, rename, rm, stat, writeFile as writeFile3 } from "node:fs/promises";
1709
1620
  import { join as join8 } from "node:path";
1710
1621
  import { parse as parseToml2 } from "smol-toml";
1711
1622
 
@@ -1770,9 +1681,9 @@ function parseFileSourcePath(source) {
1770
1681
  }
1771
1682
  async function readCapabilityIdFromPath(capabilityPath) {
1772
1683
  const tomlPath = join8(capabilityPath, "capability.toml");
1773
- if (existsSync12(tomlPath)) {
1684
+ if (existsSync11(tomlPath)) {
1774
1685
  try {
1775
- const content = await readFile10(tomlPath, "utf-8");
1686
+ const content = await readFile9(tomlPath, "utf-8");
1776
1687
  const parsed = parseToml2(content);
1777
1688
  const capability = parsed["capability"];
1778
1689
  if (capability?.["id"] && typeof capability["id"] === "string") {
@@ -1822,11 +1733,11 @@ function getLockFilePath() {
1822
1733
  }
1823
1734
  async function loadLockFile() {
1824
1735
  const lockPath = getLockFilePath();
1825
- if (!existsSync12(lockPath)) {
1736
+ if (!existsSync11(lockPath)) {
1826
1737
  return { capabilities: {} };
1827
1738
  }
1828
1739
  try {
1829
- const content = await readFile10(lockPath, "utf-8");
1740
+ const content = await readFile9(lockPath, "utf-8");
1830
1741
  const parsed = parseToml2(content);
1831
1742
  const capabilities = parsed["capabilities"];
1832
1743
  return {
@@ -1915,16 +1826,16 @@ async function fetchRepo(repoPath, ref) {
1915
1826
  return true;
1916
1827
  }
1917
1828
  function hasCapabilityToml(dirPath) {
1918
- return existsSync12(join8(dirPath, "capability.toml"));
1829
+ return existsSync11(join8(dirPath, "capability.toml"));
1919
1830
  }
1920
1831
  async function shouldWrapDirectory(dirPath) {
1921
- if (existsSync12(join8(dirPath, ".claude-plugin", "plugin.json"))) {
1832
+ if (existsSync11(join8(dirPath, ".claude-plugin", "plugin.json"))) {
1922
1833
  return true;
1923
1834
  }
1924
1835
  const allDirs = [...SKILL_DIRS, ...AGENT_DIRS, ...COMMAND_DIRS, ...RULE_DIRS, ...DOC_DIRS];
1925
1836
  for (const dirName of allDirs) {
1926
1837
  const checkPath = join8(dirPath, dirName);
1927
- if (existsSync12(checkPath)) {
1838
+ if (existsSync11(checkPath)) {
1928
1839
  const stats = await stat(checkPath);
1929
1840
  if (stats.isDirectory()) {
1930
1841
  return true;
@@ -1936,7 +1847,7 @@ async function shouldWrapDirectory(dirPath) {
1936
1847
  async function findMatchingDirs(basePath, names) {
1937
1848
  for (const name of names) {
1938
1849
  const dirPath = join8(basePath, name);
1939
- if (existsSync12(dirPath)) {
1850
+ if (existsSync11(dirPath)) {
1940
1851
  const stats = await stat(dirPath);
1941
1852
  if (stats.isDirectory()) {
1942
1853
  return dirPath;
@@ -1947,7 +1858,7 @@ async function findMatchingDirs(basePath, names) {
1947
1858
  }
1948
1859
  async function findContentItems(dirPath, filePatterns) {
1949
1860
  const items = [];
1950
- if (!existsSync12(dirPath)) {
1861
+ if (!existsSync11(dirPath)) {
1951
1862
  return items;
1952
1863
  }
1953
1864
  const entries = (await readdir(dirPath, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name));
@@ -1955,7 +1866,7 @@ async function findContentItems(dirPath, filePatterns) {
1955
1866
  const entryPath = join8(dirPath, entry.name);
1956
1867
  if (entry.isDirectory()) {
1957
1868
  for (const pattern of filePatterns) {
1958
- if (existsSync12(join8(entryPath, pattern))) {
1869
+ if (existsSync11(join8(entryPath, pattern))) {
1959
1870
  items.push({
1960
1871
  name: entry.name,
1961
1872
  path: entryPath,
@@ -1977,11 +1888,11 @@ async function findContentItems(dirPath, filePatterns) {
1977
1888
  }
1978
1889
  async function parsePluginJson(dirPath) {
1979
1890
  const pluginJsonPath = join8(dirPath, ".claude-plugin", "plugin.json");
1980
- if (!existsSync12(pluginJsonPath)) {
1891
+ if (!existsSync11(pluginJsonPath)) {
1981
1892
  return null;
1982
1893
  }
1983
1894
  try {
1984
- const content = await readFile10(pluginJsonPath, "utf-8");
1895
+ const content = await readFile9(pluginJsonPath, "utf-8");
1985
1896
  const data = JSON.parse(content);
1986
1897
  const result = {
1987
1898
  name: data.name,
@@ -2002,11 +1913,11 @@ async function parsePluginJson(dirPath) {
2002
1913
  }
2003
1914
  async function readReadmeDescription(dirPath) {
2004
1915
  const readmePath = join8(dirPath, "README.md");
2005
- if (!existsSync12(readmePath)) {
1916
+ if (!existsSync11(readmePath)) {
2006
1917
  return null;
2007
1918
  }
2008
1919
  try {
2009
- const content = await readFile10(readmePath, "utf-8");
1920
+ const content = await readFile9(readmePath, "utf-8");
2010
1921
  const lines = content.split(`
2011
1922
  `);
2012
1923
  let description = "";
@@ -2045,7 +1956,7 @@ async function normalizeFolderNames(repoPath) {
2045
1956
  for (const { from, to } of renameMappings) {
2046
1957
  const fromPath = join8(repoPath, from);
2047
1958
  const toPath = join8(repoPath, to);
2048
- if (existsSync12(fromPath) && !existsSync12(toPath)) {
1959
+ if (existsSync11(fromPath) && !existsSync11(toPath)) {
2049
1960
  try {
2050
1961
  const stats = await stat(fromPath);
2051
1962
  if (stats.isDirectory()) {
@@ -2144,7 +2055,7 @@ async function fetchGitCapabilitySource(id, config, options) {
2144
2055
  let repoPath;
2145
2056
  if (config.path) {
2146
2057
  const tempPath = join8(OMNI_LOCAL, "_temp", `${id}-repo`);
2147
- if (existsSync12(join8(tempPath, ".git"))) {
2058
+ if (existsSync11(join8(tempPath, ".git"))) {
2148
2059
  if (!options?.silent) {
2149
2060
  console.log(` Checking ${id}...`);
2150
2061
  }
@@ -2160,17 +2071,17 @@ async function fetchGitCapabilitySource(id, config, options) {
2160
2071
  updated = true;
2161
2072
  }
2162
2073
  const sourcePath = join8(tempPath, config.path);
2163
- if (!existsSync12(sourcePath)) {
2074
+ if (!existsSync11(sourcePath)) {
2164
2075
  throw new Error(`Path not found in repository: ${config.path}`);
2165
2076
  }
2166
- if (existsSync12(targetPath)) {
2077
+ if (existsSync11(targetPath)) {
2167
2078
  await rm(targetPath, { recursive: true });
2168
2079
  }
2169
2080
  await mkdir(join8(targetPath, ".."), { recursive: true });
2170
2081
  await cp(sourcePath, targetPath, { recursive: true });
2171
2082
  repoPath = targetPath;
2172
2083
  } else {
2173
- if (existsSync12(join8(targetPath, ".git"))) {
2084
+ if (existsSync11(join8(targetPath, ".git"))) {
2174
2085
  if (!options?.silent) {
2175
2086
  console.log(` Checking ${id}...`);
2176
2087
  }
@@ -2209,9 +2120,9 @@ async function fetchGitCapabilitySource(id, config, options) {
2209
2120
  }
2210
2121
  let version = shortCommit(commit);
2211
2122
  const pkgJsonPath = join8(repoPath, "package.json");
2212
- if (existsSync12(pkgJsonPath)) {
2123
+ if (existsSync11(pkgJsonPath)) {
2213
2124
  try {
2214
- const pkgJson = JSON.parse(await readFile10(pkgJsonPath, "utf-8"));
2125
+ const pkgJson = JSON.parse(await readFile9(pkgJsonPath, "utf-8"));
2215
2126
  if (pkgJson.version) {
2216
2127
  version = pkgJson.version;
2217
2128
  }
@@ -2229,29 +2140,29 @@ async function fetchGitCapabilitySource(id, config, options) {
2229
2140
  async function fetchFileCapabilitySource(id, config, options) {
2230
2141
  const sourcePath = parseFileSourcePath(config.source);
2231
2142
  const targetPath = getSourceCapabilityPath(id);
2232
- if (!existsSync12(sourcePath)) {
2143
+ if (!existsSync11(sourcePath)) {
2233
2144
  throw new Error(`File source not found: ${sourcePath}`);
2234
2145
  }
2235
2146
  const sourceStats = await stat(sourcePath);
2236
2147
  if (!sourceStats.isDirectory()) {
2237
2148
  throw new Error(`File source must be a directory: ${sourcePath}`);
2238
2149
  }
2239
- if (!existsSync12(join8(sourcePath, "capability.toml"))) {
2150
+ if (!existsSync11(join8(sourcePath, "capability.toml"))) {
2240
2151
  throw new Error(`No capability.toml found in: ${sourcePath}`);
2241
2152
  }
2242
2153
  if (!options?.silent) {
2243
2154
  console.log(` Copying ${id} from ${sourcePath}...`);
2244
2155
  }
2245
- if (existsSync12(targetPath)) {
2156
+ if (existsSync11(targetPath)) {
2246
2157
  await rm(targetPath, { recursive: true });
2247
2158
  }
2248
2159
  await mkdir(join8(targetPath, ".."), { recursive: true });
2249
2160
  await cp(sourcePath, targetPath, { recursive: true });
2250
2161
  let version = "local";
2251
2162
  const capTomlPath = join8(targetPath, "capability.toml");
2252
- if (existsSync12(capTomlPath)) {
2163
+ if (existsSync11(capTomlPath)) {
2253
2164
  try {
2254
- const content = await readFile10(capTomlPath, "utf-8");
2165
+ const content = await readFile9(capTomlPath, "utf-8");
2255
2166
  const parsed = parseToml2(content);
2256
2167
  const capability = parsed["capability"];
2257
2168
  if (capability?.["version"] && typeof capability["version"] === "string") {
@@ -2342,12 +2253,12 @@ async function generateMcpCapabilityToml(id, mcpConfig, targetPath) {
2342
2253
  }
2343
2254
  async function isGeneratedMcpCapability(capabilityDir) {
2344
2255
  const tomlPath = join8(capabilityDir, "capability.toml");
2345
- if (!existsSync12(tomlPath)) {
2256
+ if (!existsSync11(tomlPath)) {
2346
2257
  console.warn("no capability.toml found in", capabilityDir);
2347
2258
  return false;
2348
2259
  }
2349
2260
  try {
2350
- const content = await readFile10(tomlPath, "utf-8");
2261
+ const content = await readFile9(tomlPath, "utf-8");
2351
2262
  const parsed = parseToml2(content);
2352
2263
  const capability = parsed["capability"];
2353
2264
  const metadata = capability?.["metadata"];
@@ -2358,7 +2269,7 @@ async function isGeneratedMcpCapability(capabilityDir) {
2358
2269
  }
2359
2270
  async function cleanupStaleMcpCapabilities(currentMcpIds) {
2360
2271
  const capabilitiesDir = join8(OMNI_LOCAL, "capabilities");
2361
- if (!existsSync12(capabilitiesDir)) {
2272
+ if (!existsSync11(capabilitiesDir)) {
2362
2273
  return;
2363
2274
  }
2364
2275
  const entries = await readdir(capabilitiesDir, { withFileTypes: true });
@@ -2466,7 +2377,7 @@ async function checkForUpdates(config) {
2466
2377
  continue;
2467
2378
  }
2468
2379
  const gitConfig = sourceConfig;
2469
- if (!existsSync12(join8(targetPath, ".git"))) {
2380
+ if (!existsSync11(join8(targetPath, ".git"))) {
2470
2381
  updates.push({
2471
2382
  id,
2472
2383
  source: gitConfig.source,
@@ -2502,15 +2413,15 @@ async function checkForUpdates(config) {
2502
2413
  return updates;
2503
2414
  }
2504
2415
  // src/config/provider.ts
2505
- import { existsSync as existsSync13 } from "node:fs";
2506
- import { readFile as readFile11, writeFile as writeFile4 } from "node:fs/promises";
2416
+ import { existsSync as existsSync12 } from "node:fs";
2417
+ import { readFile as readFile10, writeFile as writeFile4 } from "node:fs/promises";
2507
2418
  import { parse as parse2 } from "smol-toml";
2508
2419
  var PROVIDER_CONFIG_PATH = ".omni/provider.toml";
2509
2420
  async function loadProviderConfig() {
2510
- if (!existsSync13(PROVIDER_CONFIG_PATH)) {
2421
+ if (!existsSync12(PROVIDER_CONFIG_PATH)) {
2511
2422
  return { provider: "claude" };
2512
2423
  }
2513
- const content = await readFile11(PROVIDER_CONFIG_PATH, "utf-8");
2424
+ const content = await readFile10(PROVIDER_CONFIG_PATH, "utf-8");
2514
2425
  const parsed = parse2(content);
2515
2426
  return parsed;
2516
2427
  }
@@ -2552,14 +2463,14 @@ function parseProviderFlag(flag) {
2552
2463
  throw new Error(`Invalid provider: ${flag}. Must be 'claude', 'codex', or 'both'.`);
2553
2464
  }
2554
2465
  // src/config/toml-patcher.ts
2555
- import { existsSync as existsSync14 } from "node:fs";
2556
- import { readFile as readFile12, writeFile as writeFile5 } from "node:fs/promises";
2466
+ import { existsSync as existsSync13 } from "node:fs";
2467
+ import { readFile as readFile11, writeFile as writeFile5 } from "node:fs/promises";
2557
2468
  var CONFIG_PATH2 = "omni.toml";
2558
2469
  async function readConfigFile() {
2559
- if (!existsSync14(CONFIG_PATH2)) {
2470
+ if (!existsSync13(CONFIG_PATH2)) {
2560
2471
  return "";
2561
2472
  }
2562
- return readFile12(CONFIG_PATH2, "utf-8");
2473
+ return readFile11(CONFIG_PATH2, "utf-8");
2563
2474
  }
2564
2475
  async function writeConfigFile(content) {
2565
2476
  await writeFile5(CONFIG_PATH2, content, "utf-8");
@@ -2649,10 +2560,8 @@ function formatMcpConfig(name, config) {
2649
2560
  lines.push(`url = "${config.url}"`);
2650
2561
  }
2651
2562
  if (config.env && Object.keys(config.env).length > 0) {
2652
- lines.push(`[mcps.${name}.env]`);
2653
- for (const [key, value] of Object.entries(config.env)) {
2654
- lines.push(`${key} = "${value}"`);
2655
- }
2563
+ const entries = Object.entries(config.env).map(([key, value]) => `${key} = "${value}"`);
2564
+ lines.push(`env = { ${entries.join(", ")} }`);
2656
2565
  }
2657
2566
  if (config.headers && Object.keys(config.headers).length > 0) {
2658
2567
  lines.push(`[mcps.${name}.headers]`);
@@ -2758,15 +2667,15 @@ function escapeRegExp(str) {
2758
2667
  return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2759
2668
  }
2760
2669
  // src/mcp-json/manager.ts
2761
- import { existsSync as existsSync15 } from "node:fs";
2762
- import { readFile as readFile13, writeFile as writeFile6 } from "node:fs/promises";
2670
+ import { existsSync as existsSync14 } from "node:fs";
2671
+ import { readFile as readFile12, writeFile as writeFile6 } from "node:fs/promises";
2763
2672
  var MCP_JSON_PATH = ".mcp.json";
2764
2673
  async function readMcpJson() {
2765
- if (!existsSync15(MCP_JSON_PATH)) {
2674
+ if (!existsSync14(MCP_JSON_PATH)) {
2766
2675
  return { mcpServers: {} };
2767
2676
  }
2768
2677
  try {
2769
- const content = await readFile13(MCP_JSON_PATH, "utf-8");
2678
+ const content = await readFile12(MCP_JSON_PATH, "utf-8");
2770
2679
  const parsed = JSON.parse(content);
2771
2680
  return {
2772
2681
  mcpServers: parsed.mcpServers || {}
@@ -2845,19 +2754,19 @@ async function syncMcpJson(capabilities2, previousManifest, options = {}) {
2845
2754
  }
2846
2755
  }
2847
2756
  // src/state/manifest.ts
2848
- import { existsSync as existsSync16, mkdirSync as mkdirSync2, rmSync } from "node:fs";
2849
- import { readFile as readFile14, writeFile as writeFile7 } from "node:fs/promises";
2757
+ import { existsSync as existsSync15, mkdirSync as mkdirSync2, rmSync } from "node:fs";
2758
+ import { readFile as readFile13, writeFile as writeFile7 } from "node:fs/promises";
2850
2759
  var MANIFEST_PATH = ".omni/state/manifest.json";
2851
2760
  var CURRENT_VERSION = 1;
2852
2761
  async function loadManifest() {
2853
- if (!existsSync16(MANIFEST_PATH)) {
2762
+ if (!existsSync15(MANIFEST_PATH)) {
2854
2763
  return {
2855
2764
  version: CURRENT_VERSION,
2856
2765
  syncedAt: new Date().toISOString(),
2857
2766
  capabilities: {}
2858
2767
  };
2859
2768
  }
2860
- const content = await readFile14(MANIFEST_PATH, "utf-8");
2769
+ const content = await readFile13(MANIFEST_PATH, "utf-8");
2861
2770
  return JSON.parse(content);
2862
2771
  }
2863
2772
  async function saveManifest(manifest) {
@@ -2897,14 +2806,14 @@ async function cleanupStaleResources(previousManifest, currentCapabilityIds) {
2897
2806
  }
2898
2807
  for (const skillName of resources.skills) {
2899
2808
  const skillDir = `.claude/skills/${skillName}`;
2900
- if (existsSync16(skillDir)) {
2809
+ if (existsSync15(skillDir)) {
2901
2810
  rmSync(skillDir, { recursive: true });
2902
2811
  result.deletedSkills.push(skillName);
2903
2812
  }
2904
2813
  }
2905
2814
  for (const ruleName of resources.rules) {
2906
2815
  const rulePath = `.cursor/rules/omnidev-${ruleName}.mdc`;
2907
- if (existsSync16(rulePath)) {
2816
+ if (existsSync15(rulePath)) {
2908
2817
  rmSync(rulePath);
2909
2818
  result.deletedRules.push(ruleName);
2910
2819
  }
@@ -2913,17 +2822,17 @@ async function cleanupStaleResources(previousManifest, currentCapabilityIds) {
2913
2822
  return result;
2914
2823
  }
2915
2824
  // src/state/providers.ts
2916
- import { existsSync as existsSync17, mkdirSync as mkdirSync3 } from "node:fs";
2917
- import { readFile as readFile15, writeFile as writeFile8 } from "node:fs/promises";
2825
+ import { existsSync as existsSync16, mkdirSync as mkdirSync3 } from "node:fs";
2826
+ import { readFile as readFile14, writeFile as writeFile8 } from "node:fs/promises";
2918
2827
  var STATE_DIR2 = ".omni/state";
2919
2828
  var PROVIDERS_PATH = `${STATE_DIR2}/providers.json`;
2920
2829
  var DEFAULT_PROVIDERS = ["claude-code"];
2921
2830
  async function readEnabledProviders() {
2922
- if (!existsSync17(PROVIDERS_PATH)) {
2831
+ if (!existsSync16(PROVIDERS_PATH)) {
2923
2832
  return DEFAULT_PROVIDERS;
2924
2833
  }
2925
2834
  try {
2926
- const content = await readFile15(PROVIDERS_PATH, "utf-8");
2835
+ const content = await readFile14(PROVIDERS_PATH, "utf-8");
2927
2836
  const state = JSON.parse(content);
2928
2837
  return state.enabled.length > 0 ? state.enabled : DEFAULT_PROVIDERS;
2929
2838
  } catch {
@@ -2955,10 +2864,10 @@ async function isProviderEnabled(providerId) {
2955
2864
  import { spawn as spawn2 } from "node:child_process";
2956
2865
  import { mkdirSync as mkdirSync4 } from "node:fs";
2957
2866
  async function installCapabilityDependencies(silent) {
2958
- const { existsSync: existsSync18, readdirSync: readdirSync7 } = await import("node:fs");
2867
+ const { existsSync: existsSync17, readdirSync: readdirSync7 } = await import("node:fs");
2959
2868
  const { join: join9 } = await import("node:path");
2960
2869
  const capabilitiesDir = ".omni/capabilities";
2961
- if (!existsSync18(capabilitiesDir)) {
2870
+ if (!existsSync17(capabilitiesDir)) {
2962
2871
  return;
2963
2872
  }
2964
2873
  const entries = readdirSync7(capabilitiesDir, { withFileTypes: true });
@@ -2980,14 +2889,14 @@ async function installCapabilityDependencies(silent) {
2980
2889
  }
2981
2890
  const capabilityPath = join9(capabilitiesDir, entry.name);
2982
2891
  const packageJsonPath = join9(capabilityPath, "package.json");
2983
- if (!existsSync18(packageJsonPath)) {
2892
+ if (!existsSync17(packageJsonPath)) {
2984
2893
  continue;
2985
2894
  }
2986
2895
  if (!silent) {
2987
2896
  console.log(`Installing dependencies for ${capabilityPath}...`);
2988
2897
  }
2989
2898
  await new Promise((resolve2, reject) => {
2990
- const useNpmCi = hasNpm && existsSync18(join9(capabilityPath, "package-lock.json"));
2899
+ const useNpmCi = hasNpm && existsSync17(join9(capabilityPath, "package-lock.json"));
2991
2900
  const cmd = hasBun ? "bun" : "npm";
2992
2901
  const args = hasBun ? ["install"] : useNpmCi ? ["ci"] : ["install"];
2993
2902
  const proc = spawn2(cmd, args, {
@@ -3349,7 +3258,6 @@ export {
3349
3258
  version,
3350
3259
  validateHooksConfig,
3351
3260
  validateHook,
3352
- validateEnv,
3353
3261
  transformToOmnidev,
3354
3262
  transformToClaude,
3355
3263
  transformHooksConfig,
@@ -3383,7 +3291,6 @@ export {
3383
3291
  loadManifest,
3384
3292
  loadLockFile,
3385
3293
  loadHooksFromCapability,
3386
- loadEnvironment,
3387
3294
  loadDocs,
3388
3295
  loadConfig,
3389
3296
  loadCommands,
@@ -3392,7 +3299,6 @@ export {
3392
3299
  loadCapability,
3393
3300
  loadBaseConfig,
3394
3301
  isValidMatcherPattern,
3395
- isSecretEnvVar,
3396
3302
  isProviderEnabled,
3397
3303
  isPromptHookEvent,
3398
3304
  isMatcherEvent,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omnidev-ai/core",
3
- "version": "0.10.0",
3
+ "version": "0.10.1",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -1,7 +1,6 @@
1
1
  import { existsSync, readdirSync } from "node:fs";
2
2
  import { readFile } from "node:fs/promises";
3
3
  import { join } from "node:path";
4
- import { validateEnv } from "../config/env";
5
4
  import { parseCapabilityConfig } from "../config/parser";
6
5
  import { loadCapabilityHooks } from "../hooks/loader.js";
7
6
  import type {
@@ -339,25 +338,14 @@ function convertCommandExports(commandExports: unknown[], capabilityId: string):
339
338
 
340
339
  /**
341
340
  * Loads a complete capability including config, skills, rules, docs, and exports.
342
- * Validates environment requirements before loading.
343
- *
344
341
  * @param capabilityPath - Path to the capability directory
345
- * @param env - Environment variables to validate against
346
342
  * @returns Fully loaded capability
347
- * @throws Error if validation fails or loading errors occur
343
+ * @throws Error if loading errors occur
348
344
  */
349
- export async function loadCapability(
350
- capabilityPath: string,
351
- env: Record<string, string>,
352
- ): Promise<LoadedCapability> {
345
+ export async function loadCapability(capabilityPath: string): Promise<LoadedCapability> {
353
346
  const config = await loadCapabilityConfig(capabilityPath);
354
347
  const id = config.capability.id;
355
348
 
356
- // Validate environment
357
- if (config.env) {
358
- validateEnv(config.env, env, id);
359
- }
360
-
361
349
  // Load content - programmatic takes precedence
362
350
  const exports = await importCapabilityExports(capabilityPath);
363
351
 
@@ -1,5 +1,4 @@
1
1
  import { getEnabledCapabilities } from "../config/capabilities";
2
- import { loadEnvironment } from "../config/env";
3
2
  import { mergeHooksConfigs } from "../hooks/merger.js";
4
3
  import type { HooksConfig, CapabilityHooks, Doc, LoadedCapability, Rule, Skill } from "../types";
5
4
  import { discoverCapabilities, loadCapability } from "./loader";
@@ -27,7 +26,6 @@ export interface CapabilityRegistry {
27
26
  * @returns Capability registry with helper functions
28
27
  */
29
28
  export async function buildCapabilityRegistry(): Promise<CapabilityRegistry> {
30
- const env = await loadEnvironment();
31
29
  const enabledIds = await getEnabledCapabilities();
32
30
 
33
31
  const capabilityPaths = await discoverCapabilities();
@@ -35,7 +33,7 @@ export async function buildCapabilityRegistry(): Promise<CapabilityRegistry> {
35
33
 
36
34
  for (const path of capabilityPaths) {
37
35
  try {
38
- const cap = await loadCapability(path, env);
36
+ const cap = await loadCapability(path);
39
37
 
40
38
  // Only add if enabled
41
39
  if (enabledIds.includes(cap.id)) {
@@ -11,7 +11,6 @@ Configuration loading and parsing system using TOML format with profile-based ca
11
11
  | Task | Location | Notes |
12
12
  |------|----------|-------|
13
13
  | Config merge logic | loader.ts | Merges config.toml + config.local.toml |
14
- | Environment loading | env.ts | Loads .omni/.env, validates declarations |
15
14
  | TOML parsing | parser.ts | Uses smol-toml, validates capability.toml |
16
15
  | Provider selection | provider.ts | Loads provider.toml, parses CLI flags |
17
16
  | Profile management | profiles.ts | Active profile tracking, resolves capabilities |
@@ -23,7 +22,6 @@ Configuration loading and parsing system using TOML format with profile-based ca
23
22
  - `.omni/config.toml` - main config (project name, default profile, profiles)
24
23
  - `.omni/config.local.toml` - local overrides (gitignored)
25
24
  - `.omni/provider.toml` - provider selection (claude/codex/both)
26
- - `.omni/.env` - secrets, always gitignored
27
25
 
28
26
  **Profile-Based Capability Management:**
29
27
  - Profiles define capability sets in `[profiles.name].capabilities`
@@ -31,16 +29,7 @@ Configuration loading and parsing system using TOML format with profile-based ca
31
29
  - `always_enabled_capabilities` list merged with profile capabilities
32
30
  - Use `enableCapability()` / `disableCapability()` to update active profile
33
31
 
34
- **Environment Variable Handling:**
35
- - capability.toml `[env]` section declares requirements
36
- - `required = true` → must be present or default
37
- - `secret = true` → masked in logs/error messages
38
- - `default = "value"` → optional with fallback
39
-
40
32
  ## ANTI-PATTERNS (THIS SUBSYSTEM)
41
33
 
42
34
  - **NEVER** edit config.toml directly for capability changes - use enableCapability()/disableCapability()
43
- - **NEVER** commit .omni/.env or config.local.toml - both gitignored
44
35
  - **NEVER** parse TOML manually - use parseOmniConfig() / parseCapabilityConfig()
45
- - **NEVER** ignore validateEnv() errors - required env vars block capability load
46
- - **NEVER** assume process.env is complete - merge with .omni/.env via loadEnvironment()
@@ -15,9 +15,6 @@ const LOCAL_CONFIG = "omni.local.toml";
15
15
  function mergeConfigs(base: OmniConfig, override: OmniConfig): OmniConfig {
16
16
  const merged: OmniConfig = { ...base, ...override };
17
17
 
18
- // Deep merge env
19
- merged.env = { ...base.env, ...override.env };
20
-
21
18
  // Deep merge profiles
22
19
  merged.profiles = { ...base.profiles };
23
20
  for (const [name, profile] of Object.entries(override.profiles || {})) {
@@ -84,26 +81,6 @@ export async function writeConfig(config: OmniConfig): Promise<void> {
84
81
  function generateConfigToml(config: OmniConfig): string {
85
82
  const lines: string[] = [];
86
83
 
87
- lines.push("# =============================================================================");
88
- lines.push("# OmniDev Configuration");
89
- lines.push("# =============================================================================");
90
- lines.push("# This file defines your project's capabilities, profiles, and settings.");
91
- lines.push("#");
92
- lines.push("# Files:");
93
- lines.push("# • omni.toml - Main config (commit to share with team)");
94
- lines.push("# • omni.local.toml - Local overrides (add to .gitignore)");
95
- lines.push("# • omni.lock.toml - Version lock file (commit for reproducibility)");
96
- lines.push("#");
97
- lines.push("# Quick start:");
98
- lines.push("# 1. Add capability sources to [capabilities.sources]");
99
- lines.push("# 2. Reference them in your profiles");
100
- lines.push("# 3. Run: omnidev sync");
101
- lines.push("# 4. Switch profiles: omnidev profile use <name>");
102
- lines.push("");
103
-
104
- // Note: active_profile is stored in .omni/state/active-profile, not in config.toml
105
- // We still read it from config.toml for backwards compatibility, but don't write it here
106
-
107
84
  // Providers
108
85
  if (config.providers?.enabled && config.providers.enabled.length > 0) {
109
86
  lines.push("# AI providers to enable (claude, codex, or both)");
@@ -112,28 +89,6 @@ function generateConfigToml(config: OmniConfig): string {
112
89
  lines.push("");
113
90
  }
114
91
 
115
- // Environment variables
116
- lines.push("# =============================================================================");
117
- lines.push("# Environment Variables");
118
- lines.push("# =============================================================================");
119
- lines.push("# Global environment variables available to all capabilities.");
120
- // biome-ignore lint/suspicious/noTemplateCurlyInString: Example of env var syntax
121
- lines.push("# Use ${VAR_NAME} syntax to reference shell environment variables.");
122
- lines.push("#");
123
- if (config.env && Object.keys(config.env).length > 0) {
124
- lines.push("[env]");
125
- for (const [key, value] of Object.entries(config.env)) {
126
- lines.push(`${key} = "${value}"`);
127
- }
128
- } else {
129
- lines.push("# [env]");
130
- // biome-ignore lint/suspicious/noTemplateCurlyInString: Example of env var syntax
131
- lines.push('# DATABASE_URL = "${DATABASE_URL}"');
132
- // biome-ignore lint/suspicious/noTemplateCurlyInString: Example of env var syntax
133
- lines.push('# API_KEY = "${MY_API_KEY}"');
134
- }
135
- lines.push("");
136
-
137
92
  // Capability sources
138
93
  lines.push("# =============================================================================");
139
94
  lines.push("# Capability Sources");
@@ -235,12 +190,10 @@ function generateConfigToml(config: OmniConfig): string {
235
190
  lines.push(`url = "${mcpConfig.url}"`);
236
191
  }
237
192
 
238
- // Environment variables (sub-table)
193
+ // Environment variables (inline table)
239
194
  if (mcpConfig.env && Object.keys(mcpConfig.env).length > 0) {
240
- lines.push(`[mcps.${name}.env]`);
241
- for (const [key, value] of Object.entries(mcpConfig.env)) {
242
- lines.push(`${key} = "${value}"`);
243
- }
195
+ const entries = Object.entries(mcpConfig.env).map(([key, value]) => `${key} = "${value}"`);
196
+ lines.push(`env = { ${entries.join(", ")} }`);
244
197
  }
245
198
 
246
199
  // Headers (sub-table)
@@ -263,9 +216,8 @@ function generateConfigToml(config: OmniConfig): string {
263
216
  lines.push('# command = "node"');
264
217
  lines.push('# args = ["./servers/database.js"]');
265
218
  lines.push('# cwd = "./mcp-servers"');
266
- lines.push("# [mcps.database.env]");
267
219
  // biome-ignore lint/suspicious/noTemplateCurlyInString: Example of env var syntax
268
- lines.push('# DB_URL = "${DATABASE_URL}"');
220
+ lines.push('# env = { DB_URL = "${DATABASE_URL}" }');
269
221
  lines.push("");
270
222
  }
271
223
 
@@ -1,5 +1,4 @@
1
1
  export * from "./capabilities";
2
- export * from "./env";
3
2
  export * from "./config";
4
3
  export * from "./parser";
5
4
  export * from "./profiles";
@@ -150,12 +150,10 @@ function formatMcpConfig(name: string, config: McpConfig): string[] {
150
150
  lines.push(`url = "${config.url}"`);
151
151
  }
152
152
 
153
- // Environment variables
153
+ // Environment variables (inline table)
154
154
  if (config.env && Object.keys(config.env).length > 0) {
155
- lines.push(`[mcps.${name}.env]`);
156
- for (const [key, value] of Object.entries(config.env)) {
157
- lines.push(`${key} = "${value}"`);
158
- }
155
+ const entries = Object.entries(config.env).map(([key, value]) => `${key} = "${value}"`);
156
+ lines.push(`env = { ${entries.join(", ")} }`);
159
157
  }
160
158
 
161
159
  // Headers
@@ -48,12 +48,6 @@ export interface CapabilityExports {
48
48
  gitignore?: string[];
49
49
  }
50
50
 
51
- export interface EnvDeclaration {
52
- required?: boolean;
53
- secret?: boolean;
54
- default?: string;
55
- }
56
-
57
51
  export interface SyncConfig {
58
52
  on_sync?: string;
59
53
  }
@@ -65,7 +59,6 @@ export interface CliConfig {
65
59
  export interface CapabilityConfig {
66
60
  capability: CapabilityMetadata;
67
61
  exports?: CapabilityExports;
68
- env?: Record<string, EnvDeclaration | Record<string, never>>;
69
62
  mcp?: McpConfig;
70
63
  sync?: SyncConfig;
71
64
  cli?: CliConfig;
@@ -84,7 +77,7 @@ export interface McpToolSchema {
84
77
  *
85
78
  * - **stdio**: Local process using stdin/stdout (default)
86
79
  * - Requires: command
87
- * - Optional: args, env, cwd
80
+ * - Optional: args, cwd
88
81
  *
89
82
  * - **http**: Remote HTTP server (recommended for remote servers)
90
83
  * - Requires: url
@@ -269,7 +262,6 @@ export interface OmniConfig {
269
262
  project?: string;
270
263
  active_profile?: string;
271
264
  always_enabled_capabilities?: string[];
272
- env?: Record<string, string>;
273
265
  profiles?: Record<string, ProfileConfig>;
274
266
  providers?: {
275
267
  enabled?: Provider[];
package/src/config/env.ts DELETED
@@ -1,97 +0,0 @@
1
- import { existsSync } from "node:fs";
2
- import { readFile } from "node:fs/promises";
3
- import type { EnvDeclaration } from "../types";
4
-
5
- const ENV_FILE = ".omni/.env";
6
-
7
- /**
8
- * Load environment variables from .omni/.env file and merge with process.env.
9
- * Process environment variables take precedence over file values.
10
- *
11
- * @returns Merged environment variables
12
- */
13
- export async function loadEnvironment(): Promise<Record<string, string>> {
14
- const env: Record<string, string> = {};
15
-
16
- // Load from .omni/.env
17
- if (existsSync(ENV_FILE)) {
18
- const content = await readFile(ENV_FILE, "utf-8");
19
- for (const line of content.split("\n")) {
20
- const trimmed = line.trim();
21
- // Skip empty lines and comments
22
- if (trimmed && !trimmed.startsWith("#")) {
23
- const eqIndex = trimmed.indexOf("=");
24
- if (eqIndex > 0) {
25
- const key = trimmed.slice(0, eqIndex).trim();
26
- const value = trimmed.slice(eqIndex + 1).trim();
27
- // Remove quotes if present
28
- const unquotedValue =
29
- (value.startsWith('"') && value.endsWith('"')) ||
30
- (value.startsWith("'") && value.endsWith("'"))
31
- ? value.slice(1, -1)
32
- : value;
33
- env[key] = unquotedValue;
34
- }
35
- }
36
- }
37
- }
38
-
39
- // Process env takes precedence - filter out undefined values
40
- const processEnv: Record<string, string> = {};
41
- for (const [key, value] of Object.entries(process.env)) {
42
- if (value !== undefined) {
43
- processEnv[key] = value;
44
- }
45
- }
46
-
47
- return { ...env, ...processEnv };
48
- }
49
-
50
- /**
51
- * Validate that all required environment variables are present.
52
- * Checks declarations from capability config and throws descriptive errors for missing vars.
53
- *
54
- * @param declarations - Environment variable declarations from capability.toml
55
- * @param env - Loaded environment variables
56
- * @param capabilityId - ID of the capability being validated
57
- * @throws Error if required environment variables are missing
58
- */
59
- export function validateEnv(
60
- declarations: Record<string, EnvDeclaration | Record<string, never>>,
61
- env: Record<string, string | undefined>,
62
- capabilityId: string,
63
- ): void {
64
- const missing: string[] = [];
65
-
66
- for (const [key, decl] of Object.entries(declarations)) {
67
- const declaration = decl as EnvDeclaration;
68
- const value = env[key] ?? declaration.default;
69
-
70
- if (declaration.required && !value) {
71
- missing.push(key);
72
- }
73
- }
74
-
75
- if (missing.length > 0) {
76
- throw new Error(
77
- `Missing required environment variable${missing.length > 1 ? "s" : ""} for capability "${capabilityId}": ${missing.join(", ")}. ` +
78
- `Set ${missing.length > 1 ? "them" : "it"} in .omni/.env or as environment variable${missing.length > 1 ? "s" : ""}.`,
79
- );
80
- }
81
- }
82
-
83
- /**
84
- * Check if an environment variable should be treated as a secret.
85
- * Secrets should be masked in logs and error messages.
86
- *
87
- * @param key - Environment variable name
88
- * @param declarations - Environment variable declarations from capability.toml
89
- * @returns true if the variable is marked as secret
90
- */
91
- export function isSecretEnvVar(
92
- key: string,
93
- declarations: Record<string, EnvDeclaration | Record<string, never>>,
94
- ): boolean {
95
- const decl = declarations[key] as EnvDeclaration | undefined;
96
- return decl?.secret === true;
97
- }