@lnai/core 0.1.0 → 0.1.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
@@ -302,12 +302,13 @@ interface InitOptions {
302
302
  rootDir: string;
303
303
  tools?: ToolId[];
304
304
  minimal?: boolean;
305
+ force?: boolean;
305
306
  }
306
307
  interface InitResult {
307
308
  created: string[];
308
309
  }
310
+ declare function initUnifiedConfig(options: InitOptions): Promise<InitResult>;
309
311
  declare function hasUnifiedConfig(rootDir: string): Promise<boolean>;
310
312
  declare function generateDefaultConfig(tools?: ToolId[]): Config;
311
- declare function initUnifiedConfig(options: InitOptions): Promise<InitResult>;
312
313
 
313
314
  export { CONFIG_DIRS, CONFIG_FILES, type ChangeResult, type Config, FileNotFoundError, type InitOptions, type InitResult, LnaiError, type MarkdownFile, type MarkdownFrontmatter, type McpServer, type OutputFile, ParseError, type PermissionLevel, type Permissions, type Plugin, PluginError, type RuleFrontmatter, type Settings, type SkillFrontmatter, type SkippedFeatureDetail, type SyncOptions, type SyncResult, TOOL_IDS, TOOL_OUTPUT_DIRS, type ToolConfig, type ToolId, UNIFIED_DIR, type UnifiedState, ValidationError, type ValidationErrorDetail, type ValidationResult, type ValidationWarningDetail, WriteError, type WriterOptions, claudeCodePlugin, computeHash, configSchema, generateDefaultConfig, hasUnifiedConfig, initUnifiedConfig, mcpServerSchema, opencodePlugin, parseFrontmatter, parseUnifiedConfig, permissionsSchema, pluginRegistry, ruleFrontmatterSchema, runSyncPipeline, settingsSchema, skillFrontmatterSchema, toolConfigSchema, toolIdSchema, updateGitignore, validateConfig, validateSettings, validateUnifiedState, writeFiles };
package/dist/index.js CHANGED
@@ -356,6 +356,26 @@ function validateUnifiedState(state) {
356
356
  skipped: []
357
357
  };
358
358
  }
359
+ function validateToolIds(tools) {
360
+ const invalidTools = tools.filter(
361
+ (t) => !TOOL_IDS.includes(t)
362
+ );
363
+ if (invalidTools.length > 0) {
364
+ return {
365
+ valid: false,
366
+ errors: [
367
+ {
368
+ path: ["tools"],
369
+ message: `Invalid tool(s): ${invalidTools.join(", ")}. Valid tools: ${TOOL_IDS.join(", ")}`,
370
+ value: invalidTools
371
+ }
372
+ ],
373
+ warnings: [],
374
+ skipped: []
375
+ };
376
+ }
377
+ return { valid: true, errors: [], warnings: [], skipped: [] };
378
+ }
359
379
  async function scanOverrideDirectory(rootDir, toolId) {
360
380
  const overrideDir = path.join(rootDir, UNIFIED_DIR, OVERRIDE_DIRS[toolId]);
361
381
  try {
@@ -821,16 +841,26 @@ function getToolsToSync(config, requestedTools) {
821
841
  }
822
842
  async function runSyncPipeline(options) {
823
843
  const { rootDir, dryRun = false, tools: requestedTools } = options;
844
+ if (requestedTools && requestedTools.length > 0) {
845
+ const toolValidation = validateToolIds(requestedTools);
846
+ if (!toolValidation.valid) {
847
+ const error = toolValidation.errors[0];
848
+ throw new ValidationError(
849
+ error?.message ?? "Invalid tools",
850
+ error?.path ?? ["tools"],
851
+ error?.value
852
+ );
853
+ }
854
+ }
824
855
  const state = await parseUnifiedConfig(rootDir);
825
856
  const unifiedValidation = validateUnifiedState(state);
826
857
  if (!unifiedValidation.valid) {
827
- return [
828
- {
829
- tool: "claudeCode",
830
- changes: [],
831
- validation: unifiedValidation
832
- }
833
- ];
858
+ const errorMessages = unifiedValidation.errors.map((e) => `${e.path.join(".")}: ${e.message}`).join("; ");
859
+ throw new ValidationError(
860
+ `Unified config validation failed: ${errorMessages}`,
861
+ ["config"],
862
+ unifiedValidation.errors
863
+ );
834
864
  }
835
865
  const toolsToSync = getToolsToSync(state.config, requestedTools);
836
866
  if (toolsToSync.length === 0) {
@@ -861,35 +891,24 @@ async function runSyncPipeline(options) {
861
891
  }
862
892
  return results;
863
893
  }
864
- async function hasUnifiedConfig(rootDir) {
865
- const aiDir = path.join(rootDir, UNIFIED_DIR);
866
- try {
867
- const stats = await fs3.stat(aiDir);
868
- return stats.isDirectory();
869
- } catch {
870
- return false;
871
- }
872
- }
873
- function generateDefaultConfig(tools) {
874
- const enabledTools = tools ?? TOOL_IDS;
875
- const toolsConfig = {};
876
- for (const toolId of TOOL_IDS) {
877
- toolsConfig[toolId] = {
878
- enabled: enabledTools.includes(toolId),
879
- versionControl: false
880
- };
881
- }
882
- return {
883
- tools: toolsConfig
884
- };
885
- }
886
894
  async function initUnifiedConfig(options) {
887
- const { rootDir, tools, minimal = false } = options;
895
+ const { rootDir, tools, minimal = false, force = false } = options;
888
896
  const aiDir = path.join(rootDir, UNIFIED_DIR);
889
897
  const created = [];
898
+ const config = generateDefaultConfig(tools);
899
+ const exists = await hasUnifiedConfig(rootDir);
900
+ if (exists && !force) {
901
+ throw new ValidationError(
902
+ `Directory ${UNIFIED_DIR}/ already exists. Use force option to overwrite.`,
903
+ [UNIFIED_DIR],
904
+ { exists: true }
905
+ );
906
+ }
907
+ if (exists) {
908
+ await fs3.rm(aiDir, { recursive: true, force: true });
909
+ }
890
910
  await fs3.mkdir(aiDir, { recursive: true });
891
911
  created.push(UNIFIED_DIR);
892
- const config = generateDefaultConfig(tools);
893
912
  const configPath = path.join(aiDir, CONFIG_FILES.config);
894
913
  await fs3.writeFile(
895
914
  configPath,
@@ -909,7 +928,36 @@ async function initUnifiedConfig(options) {
909
928
  }
910
929
  return { created };
911
930
  }
931
+ async function hasUnifiedConfig(rootDir) {
932
+ const aiDir = path.join(rootDir, UNIFIED_DIR);
933
+ try {
934
+ const stats = await fs3.stat(aiDir);
935
+ return stats.isDirectory();
936
+ } catch {
937
+ return false;
938
+ }
939
+ }
940
+ function generateDefaultConfig(tools) {
941
+ if (tools) {
942
+ const validation = validateToolIds(tools);
943
+ if (!validation.valid) {
944
+ const error = validation.errors[0];
945
+ throw new ValidationError(
946
+ error?.message ?? "Invalid tools",
947
+ error?.path ?? ["tools"],
948
+ error?.value
949
+ );
950
+ }
951
+ }
952
+ const enabledTools = tools ?? TOOL_IDS;
953
+ const toolsConfig = {};
954
+ for (const toolId of TOOL_IDS) {
955
+ toolsConfig[toolId] = {
956
+ enabled: enabledTools.includes(toolId),
957
+ versionControl: false
958
+ };
959
+ }
960
+ return { tools: toolsConfig };
961
+ }
912
962
 
913
963
  export { CONFIG_DIRS, CONFIG_FILES, FileNotFoundError, LnaiError, ParseError, PluginError, TOOL_IDS, TOOL_OUTPUT_DIRS, UNIFIED_DIR, ValidationError, WriteError, claudeCodePlugin, computeHash, configSchema, generateDefaultConfig, hasUnifiedConfig, initUnifiedConfig, mcpServerSchema, opencodePlugin, parseFrontmatter, parseUnifiedConfig, permissionsSchema, pluginRegistry, ruleFrontmatterSchema, runSyncPipeline, settingsSchema, skillFrontmatterSchema, toolConfigSchema, toolIdSchema, updateGitignore, validateConfig, validateSettings, validateUnifiedState, writeFiles };
914
- //# sourceMappingURL=index.js.map
915
- //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lnai/core",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Core library for LNAI - unified AI config management",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/constants.ts","../src/errors.ts","../src/schemas/index.ts","../src/parser/frontmatter.ts","../src/parser/index.ts","../src/validator/index.ts","../src/utils/overrides.ts","../src/plugins/claude-code/index.ts","../src/plugins/opencode/transforms.ts","../src/plugins/opencode/index.ts","../src/plugins/registry.ts","../src/plugins/index.ts","../src/writer/index.ts","../src/pipeline/index.ts","../src/init/index.ts"],"names":["path","fs","path2","fs2","fileExists","path3","path4","path5","path6","fs4"],"mappings":"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","file":"index.js","sourcesContent":["export const UNIFIED_DIR = \".ai\";\n\nexport const TOOL_IDS = [\"claudeCode\", \"opencode\"] as const;\n\nexport type ToolId = (typeof TOOL_IDS)[number];\n\nexport const CONFIG_FILES = {\n config: \"config.json\",\n settings: \"settings.json\",\n agents: \"AGENTS.md\",\n} as const;\n\nexport const CONFIG_DIRS = {\n rules: \"rules\",\n skills: \"skills\",\n subagents: \"subagents\",\n} as const;\n\nexport const TOOL_OUTPUT_DIRS: Record<ToolId, string> = {\n claudeCode: \".claude\",\n opencode: \".opencode\",\n};\n\n/** Tool-specific override directories within .ai/ */\nexport const OVERRIDE_DIRS: Record<ToolId, string> = {\n claudeCode: \".claude\",\n opencode: \".opencode\",\n};\n","export class LnaiError extends Error {\n public readonly code: string;\n\n constructor(message: string, code: string) {\n super(message);\n this.name = \"LnaiError\";\n this.code = code;\n }\n}\n\nexport class ParseError extends LnaiError {\n public readonly filePath: string;\n\n constructor(message: string, filePath: string, cause?: Error) {\n super(message, \"PARSE_ERROR\");\n this.name = \"ParseError\";\n this.filePath = filePath;\n if (cause) {\n this.cause = cause;\n }\n }\n}\n\nexport class ValidationError extends LnaiError {\n public readonly path: string[];\n public readonly value?: unknown;\n\n constructor(message: string, path: string[], value?: unknown) {\n super(message, \"VALIDATION_ERROR\");\n this.name = \"ValidationError\";\n this.path = path;\n this.value = value;\n }\n}\n\nexport class FileNotFoundError extends LnaiError {\n public readonly filePath: string;\n\n constructor(message: string, filePath: string) {\n super(message, \"FILE_NOT_FOUND\");\n this.name = \"FileNotFoundError\";\n this.filePath = filePath;\n }\n}\n\nexport class WriteError extends LnaiError {\n public readonly filePath: string;\n\n constructor(message: string, filePath: string, cause?: Error) {\n super(message, \"WRITE_ERROR\");\n this.name = \"WriteError\";\n this.filePath = filePath;\n if (cause) {\n this.cause = cause;\n }\n }\n}\n\nexport class PluginError extends LnaiError {\n public readonly pluginId: string;\n\n constructor(message: string, pluginId: string, cause?: Error) {\n super(message, \"PLUGIN_ERROR\");\n this.name = \"PluginError\";\n this.pluginId = pluginId;\n if (cause) {\n this.cause = cause;\n }\n }\n}\n","import { z } from \"zod\";\n\n/** MCP Server configuration (Claude format as source of truth) */\nexport const mcpServerSchema = z.object({\n command: z.string().optional(),\n args: z.array(z.string()).optional(),\n env: z.record(z.string(), z.string()).optional(),\n type: z.enum([\"http\", \"sse\"]).optional(),\n url: z.string().optional(),\n headers: z.record(z.string(), z.string()).optional(),\n});\n\nexport const permissionsSchema = z.object({\n allow: z.array(z.string()).optional(),\n ask: z.array(z.string()).optional(),\n deny: z.array(z.string()).optional(),\n});\n\nexport const toolConfigSchema = z.object({\n enabled: z.boolean(),\n versionControl: z.boolean().optional().default(false),\n});\n\nexport const toolIdSchema = z.enum([\"claudeCode\", \"opencode\"]);\n\n/** Settings configuration (Claude format as source of truth) */\nexport const settingsSchema = z.object({\n permissions: permissionsSchema.optional(),\n mcpServers: z.record(z.string(), mcpServerSchema).optional(),\n overrides: z\n .object({\n claudeCode: z.record(z.string(), z.unknown()).optional(),\n opencode: z.record(z.string(), z.unknown()).optional(),\n })\n .optional(),\n});\n\n/** Main config.json structure. Uses partial object to allow partial tool configs. */\nexport const configSchema = z.object({\n tools: z\n .object({\n claudeCode: toolConfigSchema,\n opencode: toolConfigSchema,\n })\n .partial()\n .optional(),\n});\n\n/** Skill frontmatter (name and description required) */\nexport const skillFrontmatterSchema = z.object({\n name: z.string(),\n description: z.string(),\n});\n\n/** Rule frontmatter (paths required) */\nexport const ruleFrontmatterSchema = z.object({\n paths: z.array(z.string()).min(1),\n});\n\nexport type McpServer = z.infer<typeof mcpServerSchema>;\nexport type Permissions = z.infer<typeof permissionsSchema>;\nexport type ToolConfig = z.infer<typeof toolConfigSchema>;\nexport type Settings = z.infer<typeof settingsSchema>;\nexport type Config = z.infer<typeof configSchema>;\nexport type SkillFrontmatter = z.infer<typeof skillFrontmatterSchema>;\nexport type RuleFrontmatter = z.infer<typeof ruleFrontmatterSchema>;\n","import matter from \"gray-matter\";\n\nexport function parseFrontmatter(content: string): {\n frontmatter: Record<string, unknown>;\n content: string;\n} {\n const parsed = matter(content);\n return {\n frontmatter: parsed.data as Record<string, unknown>,\n content: parsed.content.trim(),\n };\n}\n","import * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\n\nimport { CONFIG_DIRS, CONFIG_FILES, UNIFIED_DIR } from \"../constants\";\nimport { FileNotFoundError, ParseError } from \"../errors\";\nimport type {\n MarkdownFile,\n RuleFrontmatter,\n SkillFrontmatter,\n UnifiedState,\n} from \"../types/index\";\nimport { parseFrontmatter } from \"./frontmatter\";\n\nexport { parseFrontmatter } from \"./frontmatter\";\n\n/**\n * Parse the unified .ai/ configuration directory.\n * Reads config.json, settings.json, AGENTS.md, rules, and skills.\n */\nexport async function parseUnifiedConfig(\n rootDir: string\n): Promise<UnifiedState> {\n const aiDir = path.join(rootDir, UNIFIED_DIR);\n\n if (!(await fileExists(aiDir))) {\n throw new FileNotFoundError(\n `Unified config directory not found: ${aiDir}`,\n aiDir\n );\n }\n\n const configPath = path.join(aiDir, CONFIG_FILES.config);\n let config: UnifiedState[\"config\"];\n try {\n config = await readJsonFile<UnifiedState[\"config\"]>(configPath);\n } catch (error) {\n if (error instanceof FileNotFoundError) {\n config = { tools: {} };\n } else {\n throw error;\n }\n }\n\n const settingsPath = path.join(aiDir, CONFIG_FILES.settings);\n let settings: UnifiedState[\"settings\"] = null;\n if (await fileExists(settingsPath)) {\n settings = await readJsonFile<UnifiedState[\"settings\"]>(settingsPath);\n }\n\n const agentsPath = path.join(aiDir, CONFIG_FILES.agents);\n let agents: string | null = null;\n if (await fileExists(agentsPath)) {\n agents = await readMarkdownFile(agentsPath);\n }\n\n const rulesDir = path.join(aiDir, CONFIG_DIRS.rules);\n const rules = await readMarkdownDirectory<RuleFrontmatter>(rulesDir);\n\n const skillsDir = path.join(aiDir, CONFIG_DIRS.skills);\n const skills = await readSkillsDirectory(skillsDir);\n\n return {\n config,\n settings,\n agents,\n rules,\n skills,\n };\n}\n\nasync function fileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function readJsonFile<T>(filePath: string): Promise<T> {\n try {\n const content = await fs.readFile(filePath, \"utf-8\");\n return JSON.parse(content) as T;\n } catch (error) {\n if ((error as { code?: string }).code === \"ENOENT\") {\n throw new FileNotFoundError(`File not found: ${filePath}`, filePath);\n }\n throw new ParseError(\n `Failed to parse JSON: ${filePath}`,\n filePath,\n error as Error\n );\n }\n}\n\nasync function readMarkdownFile(filePath: string): Promise<string> {\n try {\n return await fs.readFile(filePath, \"utf-8\");\n } catch (error) {\n if ((error as { code?: string }).code === \"ENOENT\") {\n throw new FileNotFoundError(`File not found: ${filePath}`, filePath);\n }\n throw new ParseError(\n `Failed to read markdown: ${filePath}`,\n filePath,\n error as Error\n );\n }\n}\n\nasync function readMarkdownDirectory<T>(\n dirPath: string\n): Promise<MarkdownFile<T>[]> {\n const files: MarkdownFile<T>[] = [];\n\n if (!(await fileExists(dirPath))) {\n return files;\n }\n\n const entries = await fs.readdir(dirPath, { withFileTypes: true });\n\n for (const entry of entries) {\n if (entry.isFile() && entry.name.endsWith(\".md\")) {\n const filePath = path.join(dirPath, entry.name);\n const content = await readMarkdownFile(filePath);\n const parsed = parseFrontmatter(content);\n\n files.push({\n path: entry.name,\n frontmatter: parsed.frontmatter as T,\n content: parsed.content,\n });\n }\n }\n\n return files;\n}\n\nasync function readSkillsDirectory(\n dirPath: string\n): Promise<MarkdownFile<SkillFrontmatter>[]> {\n const skills: MarkdownFile<SkillFrontmatter>[] = [];\n\n if (!(await fileExists(dirPath))) {\n return skills;\n }\n\n const entries = await fs.readdir(dirPath, { withFileTypes: true });\n\n for (const entry of entries) {\n if (entry.isDirectory()) {\n const skillFile = path.join(dirPath, entry.name, \"SKILL.md\");\n if (await fileExists(skillFile)) {\n const content = await readMarkdownFile(skillFile);\n const parsed = parseFrontmatter(content);\n\n skills.push({\n path: entry.name,\n frontmatter: parsed.frontmatter as SkillFrontmatter,\n content: parsed.content,\n });\n }\n }\n }\n\n return skills;\n}\n","import type { z } from \"zod\";\n\nimport {\n configSchema,\n ruleFrontmatterSchema,\n settingsSchema,\n skillFrontmatterSchema,\n} from \"../schemas/index\";\nimport type {\n UnifiedState,\n ValidationErrorDetail,\n ValidationResult,\n} from \"../types/index\";\n\n/**\n * Convert Zod issues to ValidationErrorDetail array\n */\nfunction zodIssuesToErrors(\n issues: z.core.$ZodIssue[],\n prefix: string[] = []\n): ValidationErrorDetail[] {\n return issues.map((issue) => ({\n path: [...prefix, ...issue.path.map(String)],\n message: issue.message,\n value: undefined,\n }));\n}\n\n/**\n * Validate config.json structure using Zod\n */\nexport function validateConfig(config: unknown): ValidationResult {\n const result = configSchema.safeParse(config);\n\n if (result.success) {\n return {\n valid: true,\n errors: [],\n warnings: [],\n skipped: [],\n };\n }\n\n return {\n valid: false,\n errors: zodIssuesToErrors(result.error.issues, [\"config\"]),\n warnings: [],\n skipped: [],\n };\n}\n\n/**\n * Validate settings.json structure using Zod\n */\nexport function validateSettings(settings: unknown): ValidationResult {\n if (settings === null || settings === undefined) {\n return {\n valid: true,\n errors: [],\n warnings: [],\n skipped: [],\n };\n }\n\n const result = settingsSchema.safeParse(settings);\n\n if (result.success) {\n return {\n valid: true,\n errors: [],\n warnings: [],\n skipped: [],\n };\n }\n\n return {\n valid: false,\n errors: zodIssuesToErrors(result.error.issues, [\"settings\"]),\n warnings: [],\n skipped: [],\n };\n}\n\n/**\n * Validate skill frontmatter\n */\nfunction validateSkillFrontmatter(\n frontmatter: unknown,\n skillPath: string\n): ValidationErrorDetail[] {\n const result = skillFrontmatterSchema.safeParse(frontmatter);\n\n if (result.success) {\n return [];\n }\n\n return zodIssuesToErrors(result.error.issues, [\n \"skills\",\n skillPath,\n \"frontmatter\",\n ]);\n}\n\n/**\n * Validate rule frontmatter\n */\nfunction validateRuleFrontmatter(\n frontmatter: unknown,\n rulePath: string\n): ValidationErrorDetail[] {\n const result = ruleFrontmatterSchema.safeParse(frontmatter);\n\n if (result.success) {\n return [];\n }\n\n return zodIssuesToErrors(result.error.issues, [\n \"rules\",\n rulePath,\n \"frontmatter\",\n ]);\n}\n\n/**\n * Validate the unified configuration state\n * @param state - Parsed unified state\n * @returns Validation result\n */\nexport function validateUnifiedState(state: UnifiedState): ValidationResult {\n const errors: ValidationErrorDetail[] = [];\n const warnings: ValidationErrorDetail[] = [];\n\n // 1. Validate config.json\n const configResult = validateConfig(state.config);\n errors.push(...configResult.errors);\n\n // 2. Validate settings.json\n const settingsResult = validateSettings(state.settings);\n errors.push(...settingsResult.errors);\n\n // 3. Validate each skill's frontmatter\n for (const skill of state.skills) {\n const skillErrors = validateSkillFrontmatter(skill.frontmatter, skill.path);\n errors.push(...skillErrors);\n }\n\n // 4. Validate each rule's frontmatter\n for (const rule of state.rules) {\n const ruleErrors = validateRuleFrontmatter(rule.frontmatter, rule.path);\n errors.push(...ruleErrors);\n }\n\n // 5. Add warnings for missing optional files\n if (!state.agents) {\n warnings.push({\n path: [\"AGENTS.md\"],\n message: \"AGENTS.md not found - no main instructions will be exported\",\n });\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n skipped: [],\n };\n}\n","import * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\n\nimport deepmerge from \"deepmerge\";\n\nimport type { ToolId } from \"../constants\";\nimport { OVERRIDE_DIRS, UNIFIED_DIR } from \"../constants\";\n\n/**\n * Information about a file in the override directory\n */\nexport interface OverrideFile {\n /** Relative path from the override directory (e.g., \"commands/custom.md\") */\n relativePath: string;\n /** Absolute path to the file */\n absolutePath: string;\n}\n\n/**\n * Recursively scan an override directory for all files.\n * Returns empty array if the directory doesn't exist.\n */\nexport async function scanOverrideDirectory(\n rootDir: string,\n toolId: ToolId\n): Promise<OverrideFile[]> {\n const overrideDir = path.join(rootDir, UNIFIED_DIR, OVERRIDE_DIRS[toolId]);\n\n try {\n await fs.access(overrideDir);\n } catch {\n return [];\n }\n\n const files: OverrideFile[] = [];\n await scanDir(overrideDir, overrideDir, files);\n return files;\n}\n\nasync function scanDir(\n baseDir: string,\n currentDir: string,\n files: OverrideFile[]\n): Promise<void> {\n const entries = await fs.readdir(currentDir, { withFileTypes: true });\n\n for (const entry of entries) {\n const absolutePath = path.join(currentDir, entry.name);\n\n if (entry.isDirectory()) {\n await scanDir(baseDir, absolutePath, files);\n } else if (entry.isFile()) {\n const relativePath = path.relative(baseDir, absolutePath);\n files.push({ relativePath, absolutePath });\n }\n }\n}\n\nexport async function parseJsonFile(\n filePath: string\n): Promise<Record<string, unknown>> {\n const content = await fs.readFile(filePath, \"utf-8\");\n return JSON.parse(content) as Record<string, unknown>;\n}\n\n/**\n * Deep merge two config objects. Arrays are concatenated and deduplicated.\n */\nexport function deepMergeConfigs<T extends Record<string, unknown>>(\n base: T,\n override: Record<string, unknown>\n): T {\n return deepmerge(base, override, {\n arrayMerge: (target, source) => [...new Set([...target, ...source])],\n }) as T;\n}\n\nexport async function fileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n","import * as path from \"node:path\";\n\nimport { OVERRIDE_DIRS, TOOL_OUTPUT_DIRS, UNIFIED_DIR } from \"../../constants\";\nimport type {\n OutputFile,\n UnifiedState,\n ValidationResult,\n} from \"../../types/index\";\nimport {\n deepMergeConfigs,\n fileExists,\n scanOverrideDirectory,\n} from \"../../utils/overrides\";\nimport type { Plugin } from \"../types\";\n\n/**\n * Claude Code plugin for exporting to .claude/ format\n *\n * Output structure:\n * - .claude/CLAUDE.md (symlink -> ../.ai/AGENTS.md)\n * - .claude/rules/ (symlink -> ../.ai/rules)\n * - .claude/skills/<name>/ (symlink -> ../../.ai/skills/<name>)\n * - .claude/settings.json (generated settings merged with .ai/.claude/settings.json)\n * - .claude/<path> (symlink -> ../.ai/.claude/<path>) for other override files\n */\nexport const claudeCodePlugin: Plugin = {\n id: \"claudeCode\",\n name: \"Claude Code\",\n\n async detect(_rootDir: string): Promise<boolean> {\n // TODO: Implement in v0.2\n return false;\n },\n\n async import(_rootDir: string): Promise<Partial<UnifiedState> | null> {\n // TODO: Implement in v0.2\n return null;\n },\n\n async export(state: UnifiedState, rootDir: string): Promise<OutputFile[]> {\n const files: OutputFile[] = [];\n const outputDir = TOOL_OUTPUT_DIRS.claudeCode;\n\n if (state.agents) {\n files.push({\n path: `${outputDir}/CLAUDE.md`,\n type: \"symlink\",\n target: `../${UNIFIED_DIR}/AGENTS.md`,\n });\n }\n\n if (state.rules.length > 0) {\n files.push({\n path: `${outputDir}/rules`,\n type: \"symlink\",\n target: `../${UNIFIED_DIR}/rules`,\n });\n }\n\n for (const skill of state.skills) {\n files.push({\n path: `${outputDir}/skills/${skill.path}`,\n type: \"symlink\",\n target: `../../${UNIFIED_DIR}/skills/${skill.path}`,\n });\n }\n\n const baseSettings: Record<string, unknown> = {};\n if (state.settings?.permissions) {\n baseSettings[\"permissions\"] = state.settings.permissions;\n }\n if (state.settings?.mcpServers) {\n baseSettings[\"mcpServers\"] = state.settings.mcpServers;\n }\n\n let finalSettings = baseSettings;\n if (state.settings?.overrides?.claudeCode) {\n finalSettings = deepMergeConfigs(\n baseSettings,\n state.settings.overrides.claudeCode\n );\n }\n\n if (Object.keys(finalSettings).length > 0) {\n files.push({\n path: `${outputDir}/settings.json`,\n type: \"json\",\n content: finalSettings,\n });\n }\n\n const overrideFiles = await scanOverrideDirectory(rootDir, \"claudeCode\");\n for (const overrideFile of overrideFiles) {\n const targetPath = path.join(\n rootDir,\n outputDir,\n overrideFile.relativePath\n );\n if (await fileExists(targetPath)) {\n continue;\n }\n files.push({\n path: `${outputDir}/${overrideFile.relativePath}`,\n type: \"symlink\",\n target: `../${UNIFIED_DIR}/${OVERRIDE_DIRS.claudeCode}/${overrideFile.relativePath}`,\n });\n }\n\n return files;\n },\n\n validate(state: UnifiedState): ValidationResult {\n const warnings: { path: string[]; message: string }[] = [];\n if (!state.agents) {\n warnings.push({\n path: [\"AGENTS.md\"],\n message: \"No AGENTS.md found - .claude/CLAUDE.md will not be created\",\n });\n }\n return { valid: true, errors: [], warnings, skipped: [] };\n },\n};\n","interface OpenCodeMcpServer {\n type: \"local\" | \"remote\";\n command?: string[];\n url?: string;\n environment?: Record<string, string>;\n headers?: Record<string, string>;\n}\n\ntype OpenCodePermission = Record<\n string,\n Record<string, \"allow\" | \"ask\" | \"deny\">\n>;\n\ninterface ClaudeMcpServer {\n command?: string;\n args?: string[];\n env?: Record<string, string>;\n type?: \"http\" | \"sse\";\n url?: string;\n headers?: Record<string, string>;\n}\n\n/**\n * Transform MCP servers from Claude format to OpenCode format.\n *\n * Claude: { command: \"npx\", args: [\"-y\", \"@example/db\"], env: { \"DB_URL\": \"${DB_URL}\" } }\n * OpenCode: { type: \"local\", command: [\"npx\", \"-y\", \"@example/db\"], environment: { \"DB_URL\": \"{env:DB_URL}\" } }\n */\nexport function transformMcpToOpenCode(\n servers: Record<string, unknown> | undefined\n): Record<string, OpenCodeMcpServer> | undefined {\n if (!servers || Object.keys(servers).length === 0) {\n return undefined;\n }\n\n const result: Record<string, OpenCodeMcpServer> = {};\n\n for (const [name, serverRaw] of Object.entries(servers)) {\n const server = serverRaw as ClaudeMcpServer;\n\n if (server.type === \"http\" || server.type === \"sse\") {\n const openCodeServer: OpenCodeMcpServer = {\n type: \"remote\",\n url: server.url,\n };\n if (server.headers) {\n openCodeServer.headers = server.headers;\n }\n result[name] = openCodeServer;\n } else if (server.command) {\n const command = [server.command, ...(server.args || [])];\n const openCodeServer: OpenCodeMcpServer = {\n type: \"local\",\n command,\n };\n if (server.env) {\n openCodeServer.environment = transformEnvVars(server.env);\n }\n result[name] = openCodeServer;\n }\n }\n\n return Object.keys(result).length > 0 ? result : undefined;\n}\n\n/**\n * Transform permissions from Claude format to OpenCode format.\n *\n * Claude: { allow: [\"Bash(git:*)\"], ask: [\"Bash(npm:*)\"], deny: [\"Read(.env)\"] }\n * OpenCode: { \"bash\": { \"git *\": \"allow\", \"npm *\": \"ask\" }, \"read\": { \".env\": \"deny\" } }\n */\nexport function transformPermissionsToOpenCode(\n permissions: { allow?: string[]; ask?: string[]; deny?: string[] } | undefined\n): OpenCodePermission | undefined {\n if (!permissions) {\n return undefined;\n }\n\n const result: OpenCodePermission = {};\n\n const processRules = (\n rules: string[] | undefined,\n level: \"allow\" | \"ask\" | \"deny\"\n ) => {\n if (!rules) {\n return;\n }\n\n for (const rule of rules) {\n const parsed = parsePermissionRule(rule);\n if (!parsed) {\n continue;\n }\n\n const { tool, pattern } = parsed;\n if (!result[tool]) {\n result[tool] = {};\n }\n\n result[tool]![pattern] = level;\n }\n };\n\n // Process in priority order: allow first, then ask, then deny (highest priority overwrites)\n processRules(permissions.allow, \"allow\");\n processRules(permissions.ask, \"ask\");\n processRules(permissions.deny, \"deny\");\n\n return Object.keys(result).length > 0 ? result : undefined;\n}\n\n// --- Helper functions ---\n\n/** Transform ${VAR} or ${VAR:-default} to {env:VAR} */\nfunction transformEnvVar(value: string): string {\n return value.replace(/\\$\\{([^}:]+)(:-[^}]*)?\\}/g, \"{env:$1}\");\n}\n\nfunction transformEnvVars(env: Record<string, string>): Record<string, string> {\n const result: Record<string, string> = {};\n for (const [key, value] of Object.entries(env)) {\n result[key] = transformEnvVar(value);\n }\n return result;\n}\n\n/** Parse \"Tool(pattern)\" format, returns { tool, pattern } or null */\nfunction parsePermissionRule(\n rule: string\n): { tool: string; pattern: string } | null {\n const match = rule.match(/^(\\w+)\\(([^)]+)\\)$/);\n if (!match) {\n return null;\n }\n\n const tool = match[1];\n const pattern = match[2];\n\n if (!tool || !pattern) {\n return null;\n }\n\n const normalizedTool = tool.toLowerCase();\n\n // Convert `:*` to ` *` (word boundary)\n let normalizedPattern = pattern;\n if (normalizedPattern.includes(\":*\")) {\n normalizedPattern = normalizedPattern.replace(/:(\\*)/g, \" $1\");\n }\n\n return {\n tool: normalizedTool,\n pattern: normalizedPattern,\n };\n}\n","import * as path from \"node:path\";\n\nimport { OVERRIDE_DIRS, TOOL_OUTPUT_DIRS, UNIFIED_DIR } from \"../../constants\";\nimport type {\n OutputFile,\n UnifiedState,\n ValidationResult,\n} from \"../../types/index\";\nimport {\n deepMergeConfigs,\n fileExists,\n scanOverrideDirectory,\n} from \"../../utils/overrides\";\nimport type { Plugin } from \"../types\";\nimport {\n transformMcpToOpenCode,\n transformPermissionsToOpenCode,\n} from \"./transforms\";\n\n/**\n * OpenCode plugin for exporting to opencode.json format\n *\n * Output structure:\n * - .opencode/AGENTS.md (symlink -> ../.ai/AGENTS.md)\n * - .opencode/rules/ (symlink -> ../.ai/rules)\n * - .opencode/skills/<name>/ (symlink -> ../../.ai/skills/<name>)\n * - opencode.json (generated config merged with .ai/.opencode/opencode.json)\n * - .opencode/<path> (symlink -> ../.ai/.opencode/<path>) for other override files\n */\nexport const opencodePlugin: Plugin = {\n id: \"opencode\",\n name: \"OpenCode\",\n\n async detect(_rootDir: string): Promise<boolean> {\n // TODO: Implement in v0.2\n return false;\n },\n\n async import(_rootDir: string): Promise<Partial<UnifiedState> | null> {\n // TODO: Implement in v0.2\n return null;\n },\n\n async export(state: UnifiedState, rootDir: string): Promise<OutputFile[]> {\n const files: OutputFile[] = [];\n const outputDir = TOOL_OUTPUT_DIRS.opencode;\n\n if (state.agents) {\n files.push({\n path: `${outputDir}/AGENTS.md`,\n type: \"symlink\",\n target: `../${UNIFIED_DIR}/AGENTS.md`,\n });\n }\n\n if (state.rules.length > 0) {\n files.push({\n path: `${outputDir}/rules`,\n type: \"symlink\",\n target: `../${UNIFIED_DIR}/rules`,\n });\n }\n\n for (const skill of state.skills) {\n files.push({\n path: `${outputDir}/skills/${skill.path}`,\n type: \"symlink\",\n target: `../../${UNIFIED_DIR}/skills/${skill.path}`,\n });\n }\n\n const baseConfig: Record<string, unknown> = {\n $schema: \"https://opencode.ai/config.json\",\n };\n if (state.rules.length > 0) {\n baseConfig[\"instructions\"] = [`${outputDir}/rules/*.md`];\n }\n\n const mcp = transformMcpToOpenCode(state.settings?.mcpServers);\n if (mcp) {\n baseConfig[\"mcp\"] = mcp;\n }\n\n const permission = transformPermissionsToOpenCode(\n state.settings?.permissions\n );\n if (permission) {\n baseConfig[\"permission\"] = permission;\n }\n\n let finalConfig = baseConfig;\n if (state.settings?.overrides?.opencode) {\n finalConfig = deepMergeConfigs(\n baseConfig,\n state.settings.overrides.opencode\n );\n }\n\n files.push({\n path: \"opencode.json\",\n type: \"json\",\n content: finalConfig,\n });\n\n const overrideFiles = await scanOverrideDirectory(rootDir, \"opencode\");\n for (const overrideFile of overrideFiles) {\n const targetPath = path.join(\n rootDir,\n outputDir,\n overrideFile.relativePath\n );\n if (await fileExists(targetPath)) {\n continue;\n }\n files.push({\n path: `${outputDir}/${overrideFile.relativePath}`,\n type: \"symlink\",\n target: `../${UNIFIED_DIR}/${OVERRIDE_DIRS.opencode}/${overrideFile.relativePath}`,\n });\n }\n\n return files;\n },\n\n validate(state: UnifiedState): ValidationResult {\n const warnings: { path: string[]; message: string }[] = [];\n if (!state.agents) {\n warnings.push({\n path: [\"AGENTS.md\"],\n message: \"No AGENTS.md found - .opencode/AGENTS.md will not be created\",\n });\n }\n return { valid: true, errors: [], warnings, skipped: [] };\n },\n};\n","import type { ToolId } from \"../constants\";\nimport type { Plugin } from \"./types\";\n\nclass PluginRegistry {\n private plugins: Map<ToolId, Plugin> = new Map();\n\n register(plugin: Plugin): void {\n this.plugins.set(plugin.id, plugin);\n }\n\n get(id: ToolId): Plugin | undefined {\n return this.plugins.get(id);\n }\n\n getAll(): Plugin[] {\n return Array.from(this.plugins.values());\n }\n\n getIds(): ToolId[] {\n return Array.from(this.plugins.keys());\n }\n\n has(id: ToolId): boolean {\n return this.plugins.has(id);\n }\n}\n\nexport const pluginRegistry = new PluginRegistry();\n","import { claudeCodePlugin } from \"./claude-code/index\";\nimport { opencodePlugin } from \"./opencode/index\";\nimport { pluginRegistry } from \"./registry\";\n\nexport { claudeCodePlugin, opencodePlugin, pluginRegistry };\nexport type { Plugin } from \"./types\";\n\npluginRegistry.register(claudeCodePlugin);\npluginRegistry.register(opencodePlugin);\n","import * as crypto from \"node:crypto\";\nimport * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\n\nimport { WriteError } from \"../errors\";\nimport type { ChangeResult, OutputFile } from \"../types/index\";\n\n/**\n * Options for the file writer\n */\nexport interface WriterOptions {\n /** Root directory for output */\n rootDir: string;\n /** Preview changes without writing */\n dryRun?: boolean;\n}\n\nexport function computeHash(content: string): string {\n return crypto.createHash(\"sha256\").update(content, \"utf-8\").digest(\"hex\");\n}\n\nasync function readExistingFile(filePath: string): Promise<string | null> {\n try {\n return await fs.readFile(filePath, \"utf-8\");\n } catch {\n return null;\n }\n}\n\nasync function getSymlinkTarget(filePath: string): Promise<string | null> {\n try {\n const stats = await fs.lstat(filePath);\n if (stats.isSymbolicLink()) {\n return await fs.readlink(filePath);\n }\n return null;\n } catch {\n return null;\n }\n}\n\nasync function ensureDir(dirPath: string): Promise<void> {\n await fs.mkdir(dirPath, { recursive: true });\n}\n\nasync function removeIfExists(filePath: string): Promise<void> {\n try {\n const stats = await fs.lstat(filePath);\n if (stats.isDirectory() && !stats.isSymbolicLink()) {\n await fs.rm(filePath, { recursive: true, force: true });\n } else {\n await fs.unlink(filePath);\n }\n } catch (error) {\n if ((error as { code?: string }).code !== \"ENOENT\") {\n throw error;\n }\n }\n}\n\nasync function writeSingleFile(\n file: OutputFile,\n rootDir: string,\n dryRun: boolean\n): Promise<ChangeResult> {\n const fullPath = path.join(rootDir, file.path);\n const dirPath = path.dirname(fullPath);\n\n if (file.type === \"symlink\") {\n const target = file.target!;\n const existingTarget = await getSymlinkTarget(fullPath);\n\n if (existingTarget === target) {\n return {\n path: file.path,\n action: \"unchanged\",\n };\n }\n\n if (!dryRun) {\n await ensureDir(dirPath);\n await removeIfExists(fullPath);\n await fs.symlink(target, fullPath);\n }\n\n return {\n path: file.path,\n action: existingTarget ? \"update\" : \"create\",\n };\n }\n\n const content =\n file.type === \"json\"\n ? JSON.stringify(file.content, null, 2) + \"\\n\"\n : String(file.content);\n\n const newHash = computeHash(content);\n const existingContent = await readExistingFile(fullPath);\n const oldHash = existingContent ? computeHash(existingContent) : undefined;\n\n if (oldHash === newHash) {\n return {\n path: file.path,\n action: \"unchanged\",\n oldHash,\n newHash,\n };\n }\n\n if (!dryRun) {\n await ensureDir(dirPath);\n await fs.writeFile(fullPath, content, \"utf-8\");\n }\n\n return {\n path: file.path,\n action: existingContent ? \"update\" : \"create\",\n oldHash,\n newHash,\n };\n}\n\nexport async function writeFiles(\n files: OutputFile[],\n options: WriterOptions\n): Promise<ChangeResult[]> {\n const { rootDir, dryRun = false } = options;\n const results: ChangeResult[] = [];\n\n for (const file of files) {\n try {\n const result = await writeSingleFile(file, rootDir, dryRun);\n results.push(result);\n } catch (error) {\n throw new WriteError(\n `Failed to write file: ${file.path}`,\n file.path,\n error as Error\n );\n }\n }\n\n return results;\n}\n\n/**\n * Update .gitignore with paths that should not be version controlled.\n * Manages a dedicated \"lnai-generated\" section to avoid conflicts with user entries.\n */\nexport async function updateGitignore(\n rootDir: string,\n paths: string[]\n): Promise<void> {\n const gitignorePath = path.join(rootDir, \".gitignore\");\n let content = \"\";\n\n try {\n content = await fs.readFile(gitignorePath, \"utf-8\");\n } catch {\n // File doesn't exist, start fresh\n }\n\n const marker = \"# lnai-generated\";\n const endMarker = \"# end lnai-generated\";\n\n const markerRegex = new RegExp(`${marker}[\\\\s\\\\S]*?${endMarker}\\\\n?`, \"g\");\n content = content.replace(markerRegex, \"\");\n content = content.trimEnd();\n\n const newSection = [\"\", marker, ...paths.map((p) => p), endMarker, \"\"].join(\n \"\\n\"\n );\n\n content = content + newSection;\n\n await fs.writeFile(gitignorePath, content, \"utf-8\");\n}\n","import type { ToolId } from \"../constants\";\nimport { parseUnifiedConfig } from \"../parser/index\";\nimport { pluginRegistry } from \"../plugins/index\";\nimport type { SyncResult } from \"../types/index\";\nimport { validateUnifiedState } from \"../validator/index\";\nimport { updateGitignore, writeFiles } from \"../writer/index\";\n\n/**\n * Options for the sync pipeline\n */\nexport interface SyncOptions {\n /** Root directory containing .ai/ config */\n rootDir: string;\n /** Only sync specific tools (default: all enabled) */\n tools?: ToolId[];\n /** Preview changes without writing files */\n dryRun?: boolean;\n /** Enable verbose output */\n verbose?: boolean;\n}\n\nfunction getToolsToSync(\n config: {\n tools?: Partial<\n Record<ToolId, { enabled: boolean; versionControl?: boolean }>\n >;\n },\n requestedTools?: ToolId[]\n): ToolId[] {\n if (requestedTools && requestedTools.length > 0) {\n return requestedTools.filter((tool) => pluginRegistry.has(tool));\n }\n\n const enabledTools: ToolId[] = [];\n\n if (config.tools) {\n for (const [toolId, toolConfig] of Object.entries(config.tools)) {\n if (toolConfig?.enabled && pluginRegistry.has(toolId as ToolId)) {\n enabledTools.push(toolId as ToolId);\n }\n }\n }\n\n if (enabledTools.length === 0) {\n return pluginRegistry.getIds();\n }\n\n return enabledTools;\n}\n\n/**\n * Run the sync pipeline to export .ai/ config to native tool formats.\n */\nexport async function runSyncPipeline(\n options: SyncOptions\n): Promise<SyncResult[]> {\n const { rootDir, dryRun = false, tools: requestedTools } = options;\n\n const state = await parseUnifiedConfig(rootDir);\n\n const unifiedValidation = validateUnifiedState(state);\n if (!unifiedValidation.valid) {\n return [\n {\n tool: \"claudeCode\" as ToolId,\n changes: [],\n validation: unifiedValidation,\n },\n ];\n }\n\n const toolsToSync = getToolsToSync(state.config, requestedTools);\n\n if (toolsToSync.length === 0) {\n return [];\n }\n\n const results: SyncResult[] = [];\n const pathsToIgnore: string[] = [];\n\n for (const toolId of toolsToSync) {\n const plugin = pluginRegistry.get(toolId);\n if (!plugin) {\n continue;\n }\n\n const validation = plugin.validate(state);\n const outputFiles = await plugin.export(state, rootDir);\n const changes = await writeFiles(outputFiles, { rootDir, dryRun });\n\n results.push({\n tool: toolId,\n changes,\n validation,\n });\n\n const toolConfig = state.config.tools?.[toolId];\n if (!toolConfig?.versionControl) {\n pathsToIgnore.push(...outputFiles.map((f) => f.path));\n }\n }\n\n if (pathsToIgnore.length > 0 && !dryRun) {\n await updateGitignore(rootDir, pathsToIgnore);\n }\n\n return results;\n}\n","import * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\n\nimport {\n CONFIG_DIRS,\n CONFIG_FILES,\n TOOL_IDS,\n type ToolId,\n UNIFIED_DIR,\n} from \"../constants\";\nimport type { Config } from \"../types/index\";\n\nexport interface InitOptions {\n rootDir: string;\n tools?: ToolId[];\n minimal?: boolean;\n}\n\nexport interface InitResult {\n created: string[];\n}\n\nexport async function hasUnifiedConfig(rootDir: string): Promise<boolean> {\n const aiDir = path.join(rootDir, UNIFIED_DIR);\n try {\n const stats = await fs.stat(aiDir);\n return stats.isDirectory();\n } catch {\n return false;\n }\n}\n\nexport function generateDefaultConfig(tools?: ToolId[]): Config {\n const enabledTools = tools ?? TOOL_IDS;\n\n const toolsConfig: Config[\"tools\"] = {};\n\n for (const toolId of TOOL_IDS) {\n toolsConfig[toolId] = {\n enabled: enabledTools.includes(toolId),\n versionControl: false,\n };\n }\n\n return {\n tools: toolsConfig,\n };\n}\n\nexport async function initUnifiedConfig(\n options: InitOptions\n): Promise<InitResult> {\n const { rootDir, tools, minimal = false } = options;\n const aiDir = path.join(rootDir, UNIFIED_DIR);\n const created: string[] = [];\n\n await fs.mkdir(aiDir, { recursive: true });\n created.push(UNIFIED_DIR);\n\n const config = generateDefaultConfig(tools);\n const configPath = path.join(aiDir, CONFIG_FILES.config);\n await fs.writeFile(\n configPath,\n JSON.stringify(config, null, 2) + \"\\n\",\n \"utf-8\"\n );\n created.push(path.join(UNIFIED_DIR, CONFIG_FILES.config));\n\n if (!minimal) {\n for (const dir of [CONFIG_DIRS.rules, CONFIG_DIRS.skills]) {\n const dirPath = path.join(aiDir, dir);\n await fs.mkdir(dirPath, { recursive: true });\n created.push(path.join(UNIFIED_DIR, dir));\n\n const gitkeepPath = path.join(dirPath, \".gitkeep\");\n await fs.writeFile(gitkeepPath, \"\", \"utf-8\");\n created.push(path.join(UNIFIED_DIR, dir, \".gitkeep\"));\n }\n }\n\n return { created };\n}\n"]}