4 ms·
I've been using Claude Code, Cursor, and Codex on the same projects. Each tool has its own config format: Claude wants `.claude/`, Cursor wants `.cursor/`, Code
by iamkrystian17 8mo ago
I've been using Claude Code, Cursor, and Codex on the same projects. Each tool has its own config format: Claude wants `.claude/`, Cursor wants `.cursor/`, Codex wants `.codex/`. Every time I updated a skill/rule, I had to update it in 3+ places. Usually I'd forget one, and my tools would give inconsistent suggestions.
LNAI is a CLI that lets you define your AI configs once in a `.ai/` directory:
.ai/
├── AGENTS.md
├── rules/
├── skills/
└── settings.json # MCP servers, permissions
Run `lnai sync` and it exports to native formats for 7 tools: Claude Code, Cursor, GitHub Copilot, Gemini CLI, OpenCode, Windsurf, and Codex.
The interesting part is it's not just copying files. Each tool has quirks:
- Cursor wants `.mdc` files with `globs` arrays in frontmatter
- Gemini reads rules at the directory level, so rules get grouped
- Permissions like `Bash(git:*)` become `Shell(git)` for Cursor
- Some tools don't support certain features (e.g., Cursor has no "ask" permission level). LNAI warns but doesn't fail
Where possible, it uses symlinks. So `.claude/CLAUDE.md` → `../.ai/AGENTS.md`. Edit the source, all tools see the change immediately without re-syncing.
Usage:
npm install -g lnai
lnai init # Creates .ai/ directory
lnai validate # Checks for config errors
lnai sync # Exports to all enabled tools
It's MIT licensed. The code is TypeScript with a plugin architecture, each tool is a plugin that implements import/export/validate.
GitHub: https://github.com/KrystianJonca/lnai https://github.com/KrystianJonca/lnai
Docs: https://lnai.sh https://lnai.sh
Would appreciate feedback, especially from anyone else dealing with this config hell problem.