lnai 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/README.md ADDED
@@ -0,0 +1,51 @@
1
+ <p align="center">
2
+ <img alt="LNAI Logo" src="apps/docs/public/lnai_white_on_black.png" width="200">
3
+ </p>
4
+
5
+ # LNAI
6
+
7
+ Unified AI configuration management CLI. Define your AI tool configurations once in `.ai/` and sync them to native formats for Claude Code, Opencode, and more.
8
+
9
+ ## Documentation
10
+
11
+ See the [documentation](https://lnai.sh) for detailed guides.
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm install -g lnai
17
+ ```
18
+
19
+ ## Quick Start
20
+
21
+ ```bash
22
+ # Initialize a new .ai/ configuration
23
+ lnai init
24
+
25
+ # Validate your configuration
26
+ lnai validate
27
+
28
+ # Sync to native tool configs
29
+ lnai sync
30
+ ```
31
+
32
+ ## Commands
33
+
34
+ - `lnai init` - Create a new `.ai/` configuration directory
35
+ - `lnai validate` - Validate your `.ai/` configuration
36
+ - `lnai sync` - Export `.ai/` to native tool configs
37
+
38
+ ## Configuration Structure
39
+
40
+ ```
41
+ .ai/
42
+ ├── config.json # Tool settings and enabled tools
43
+ ├── settings.json # Permissions and MCP servers
44
+ ├── AGENTS.md # Project instructions
45
+ ├── rules/ # Path-based rules
46
+ └── skills/ # Custom commands
47
+ ```
48
+
49
+ ## License
50
+
51
+ MIT
package/dist/index.js CHANGED
@@ -1,8 +1,7 @@
1
1
  #!/usr/bin/env node
2
+ import { createRequire } from 'module';
2
3
  import { Command } from 'commander';
3
- import * as fs from 'fs/promises';
4
- import * as path from 'path';
5
- import { hasUnifiedConfig, UNIFIED_DIR, initUnifiedConfig, runSyncPipeline, parseUnifiedConfig, validateUnifiedState, pluginRegistry } from '@lnai/core';
4
+ import { initUnifiedConfig, runSyncPipeline, parseUnifiedConfig, validateUnifiedState, pluginRegistry } from '@lnai/core';
6
5
  import chalk3 from 'chalk';
7
6
  import ora from 'ora';
8
7
 
@@ -10,23 +9,11 @@ var initCommand = new Command("init").description("Initialize a new .ai/ configu
10
9
  const rootDir = process.cwd();
11
10
  const spinner = ora("Initializing .ai/ configuration...").start();
12
11
  try {
13
- const exists = await hasUnifiedConfig(rootDir);
14
- if (exists && !options.force) {
15
- spinner.fail(
16
- `Directory ${UNIFIED_DIR}/ already exists. Use --force to overwrite.`
17
- );
18
- process.exit(1);
19
- }
20
- if (exists && options.force) {
21
- await fs.rm(path.join(rootDir, UNIFIED_DIR), {
22
- recursive: true,
23
- force: true
24
- });
25
- }
26
12
  const result = await initUnifiedConfig({
27
13
  rootDir,
28
14
  tools: options.tools,
29
- minimal: options.minimal
15
+ minimal: options.minimal,
16
+ force: options.force
30
17
  });
31
18
  spinner.succeed("Initialized .ai/ configuration");
32
19
  console.log(chalk3.gray("\nCreated:"));
@@ -153,13 +140,13 @@ ${plugin} skipped features:`));
153
140
  });
154
141
 
155
142
  // src/index.ts
143
+ var require2 = createRequire(import.meta.url);
144
+ var pkg = require2("../package.json");
156
145
  var program = new Command();
157
146
  program.name("lnai").description(
158
147
  "CLI tool that syncs a unified .ai/ config to native formats for AI coding tools"
159
- ).version("0.1.0");
148
+ ).version(pkg.version);
160
149
  program.addCommand(initCommand);
161
150
  program.addCommand(syncCommand);
162
151
  program.addCommand(validateCommand);
163
152
  program.parse();
164
- //# sourceMappingURL=index.js.map
165
- //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lnai",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "CLI tool that syncs a unified .ai/ config to native formats for AI coding tools",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -28,13 +28,14 @@
28
28
  "lnai": "./dist/index.js"
29
29
  },
30
30
  "files": [
31
- "dist"
31
+ "dist",
32
+ "README.md"
32
33
  ],
33
34
  "dependencies": {
34
35
  "chalk": "^5.6.2",
35
36
  "commander": "^14.0.2",
36
37
  "ora": "^9.1.0",
37
- "@lnai/core": "0.1.0"
38
+ "@lnai/core": "0.1.1"
38
39
  },
39
40
  "devDependencies": {
40
41
  "@types/node": "^25.0.10",
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/init.ts","../src/commands/sync.ts","../src/commands/validate.ts","../src/index.ts"],"names":["chalk","Command","ora"],"mappings":"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","file":"index.js","sourcesContent":["import * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\n\nimport {\n hasUnifiedConfig,\n initUnifiedConfig,\n type ToolId,\n UNIFIED_DIR,\n} from \"@lnai/core\";\nimport chalk from \"chalk\";\nimport { Command } from \"commander\";\nimport ora from \"ora\";\n\nexport const initCommand = new Command(\"init\")\n .description(\"Initialize a new .ai/ configuration directory\")\n .option(\"--force\", \"Overwrite existing .ai/ directory\")\n .option(\"--minimal\", \"Create only config.json (no subdirectories)\")\n .option(\"-t, --tools <tools...>\", \"Enable only specific tools\")\n .action(async (options) => {\n const rootDir = process.cwd();\n const spinner = ora(\"Initializing .ai/ configuration...\").start();\n\n try {\n const exists = await hasUnifiedConfig(rootDir);\n\n if (exists && !options.force) {\n spinner.fail(\n `Directory ${UNIFIED_DIR}/ already exists. Use --force to overwrite.`\n );\n process.exit(1);\n }\n\n if (exists && options.force) {\n await fs.rm(path.join(rootDir, UNIFIED_DIR), {\n recursive: true,\n force: true,\n });\n }\n\n const result = await initUnifiedConfig({\n rootDir,\n tools: options.tools as ToolId[] | undefined,\n minimal: options.minimal,\n });\n\n spinner.succeed(\"Initialized .ai/ configuration\");\n\n console.log(chalk.gray(\"\\nCreated:\"));\n for (const file of result.created) {\n console.log(chalk.green(` + ${file}`));\n }\n\n console.log(\n chalk.gray(\"\\nRun \") +\n chalk.cyan(\"lnai sync\") +\n chalk.gray(\" to generate tool configs.\")\n );\n } catch (error) {\n spinner.fail(\"Initialization failed\");\n console.error(\n chalk.red(error instanceof Error ? error.message : String(error))\n );\n process.exit(1);\n }\n });\n","import { runSyncPipeline, type ToolId } from \"@lnai/core\";\nimport chalk from \"chalk\";\nimport { Command } from \"commander\";\nimport ora from \"ora\";\n\nexport const syncCommand = new Command(\"sync\")\n .description(\"Export .ai/ to native configs\")\n .option(\"--dry-run\", \"Preview without writing\")\n .option(\"-t, --tools <tools...>\", \"Filter to specific tools\")\n .option(\"-v, --verbose\", \"Detailed output\")\n .action(async (options) => {\n const spinner = ora(\"Syncing configuration...\").start();\n\n try {\n const results = await runSyncPipeline({\n rootDir: process.cwd(),\n dryRun: options.dryRun,\n tools: options.tools as ToolId[] | undefined,\n verbose: options.verbose,\n });\n\n spinner.succeed(\"Sync complete\");\n\n if (results.length === 0) {\n console.log(chalk.yellow(\"\\nNo tools configured or enabled.\"));\n return;\n }\n\n for (const result of results) {\n console.log(chalk.blue(`\\n${result.tool}:`));\n\n if (result.changes.length === 0) {\n console.log(chalk.gray(\" No changes\"));\n }\n\n for (const change of result.changes) {\n const icon =\n change.action === \"create\"\n ? chalk.green(\"+\")\n : change.action === \"update\"\n ? chalk.yellow(\"~\")\n : change.action === \"delete\"\n ? chalk.red(\"-\")\n : chalk.gray(\"=\");\n console.log(` ${icon} ${change.path}`);\n }\n }\n } catch (error) {\n spinner.fail(\"Sync failed\");\n console.error(\n chalk.red(error instanceof Error ? error.message : String(error))\n );\n process.exit(1);\n }\n });\n","import {\n parseUnifiedConfig,\n pluginRegistry,\n type ToolId,\n validateUnifiedState,\n} from \"@lnai/core\";\nimport chalk from \"chalk\";\nimport { Command } from \"commander\";\nimport ora from \"ora\";\n\nexport const validateCommand = new Command(\"validate\")\n .description(\"Validate .ai/ configuration\")\n .option(\"-t, --tools <tools...>\", \"Filter to specific tools\")\n .action(async (options) => {\n const spinner = ora(\"Validating configuration...\").start();\n\n try {\n const rootDir = process.cwd();\n const state = await parseUnifiedConfig(rootDir);\n\n const unifiedResult = validateUnifiedState(state);\n\n if (!unifiedResult.valid) {\n spinner.fail(\"Validation failed\");\n console.log(chalk.red(\"\\nUnified config errors:\"));\n for (const error of unifiedResult.errors) {\n console.log(\n chalk.red(` - ${error.path.join(\".\")}: ${error.message}`)\n );\n }\n process.exit(1);\n }\n\n const tools =\n (options.tools as ToolId[] | undefined) ?? pluginRegistry.getIds();\n\n const toolErrors: Array<{\n plugin: string;\n errors: typeof unifiedResult.errors;\n }> = [];\n const toolWarnings: Array<{\n plugin: string;\n warnings: typeof unifiedResult.errors;\n }> = [];\n const toolSkipped: Array<{\n plugin: string;\n skipped: Array<{ feature: string; reason: string }>;\n }> = [];\n\n for (const toolId of tools) {\n const plugin = pluginRegistry.get(toolId);\n if (!plugin) {\n continue;\n }\n\n const result = plugin.validate(state);\n\n if (!result.valid) {\n toolErrors.push({ plugin: plugin.name, errors: result.errors });\n }\n\n if (result.warnings.length > 0) {\n toolWarnings.push({ plugin: plugin.name, warnings: result.warnings });\n }\n\n if (result.skipped.length > 0) {\n toolSkipped.push({ plugin: plugin.name, skipped: result.skipped });\n }\n }\n\n if (toolErrors.length > 0) {\n spinner.fail(\"Validation failed\");\n for (const { plugin, errors } of toolErrors) {\n console.log(chalk.red(`\\n${plugin} errors:`));\n for (const error of errors) {\n console.log(\n chalk.red(` - ${error.path.join(\".\")}: ${error.message}`)\n );\n }\n }\n process.exit(1);\n }\n\n spinner.succeed(\"Validation passed\");\n\n for (const { plugin, warnings } of toolWarnings) {\n console.log(chalk.yellow(`\\n${plugin} warnings:`));\n for (const warning of warnings) {\n console.log(\n chalk.yellow(` - ${warning.path.join(\".\")}: ${warning.message}`)\n );\n }\n }\n\n for (const { plugin, skipped } of toolSkipped) {\n console.log(chalk.gray(`\\n${plugin} skipped features:`));\n for (const item of skipped) {\n console.log(chalk.gray(` - ${item.feature}: ${item.reason}`));\n }\n }\n } catch (error) {\n spinner.fail(\"Validation failed\");\n console.error(\n chalk.red(error instanceof Error ? error.message : String(error))\n );\n process.exit(1);\n }\n });\n","import { Command } from \"commander\";\n\nimport { initCommand } from \"./commands/init.js\";\nimport { syncCommand } from \"./commands/sync.js\";\nimport { validateCommand } from \"./commands/validate.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"lnai\")\n .description(\n \"CLI tool that syncs a unified .ai/ config to native formats for AI coding tools\"\n )\n .version(\"0.1.0\");\n\nprogram.addCommand(initCommand);\nprogram.addCommand(syncCommand);\nprogram.addCommand(validateCommand);\n\nprogram.parse();\n"]}