universal-ai-config 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Kristaps Fabians Geikins
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,628 @@
1
+ # universal-ai-config
2
+
3
+ Generate tool-specific AI config files from shared templates. Write your AI instructions, skills, agents, and hooks once — generate config for Claude Code, GitHub Copilot, and Cursor automatically.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Why](#why)
8
+ - [Install](#install)
9
+ - [Quick Start](#quick-start)
10
+ - [Template Structure](#template-structure)
11
+ - [Writing Templates](#writing-templates)
12
+ - [Instructions](#instructions)
13
+ - [Skills](#skills)
14
+ - [Agents](#agents)
15
+ - [Hooks](#hooks)
16
+ - [Per-Target Overrides](#per-target-overrides)
17
+ - [EJS Template Variables](#ejs-template-variables)
18
+ - [Configuration](#configuration)
19
+ - [CLI Reference](#cli-reference)
20
+ - [`uac generate`](#uac-generate)
21
+ - [`uac init`](#uac-init)
22
+ - [`uac clean`](#uac-clean)
23
+ - [`uac seed`](#uac-seed)
24
+ - [Output Paths](#output-paths)
25
+ - [Frontmatter Mapping Reference](#frontmatter-mapping-reference)
26
+ - [Programmatic API](#programmatic-api)
27
+ - [Adding a New Target](#adding-a-new-target)
28
+
29
+ ## Why
30
+
31
+ AI coding tools each have their own config formats stored in `.claude/`, `.github/`, `.cursor/`. Teams want shared AI config but each developer may use a different tool. This CLI generates target-specific config files from shared templates in `.universal-ai-config/`, so the tool-specific folders can be gitignored and each dev generates only what they need.
32
+
33
+ ## Install
34
+
35
+ ```bash
36
+ pnpm add -D universal-ai-config
37
+ ```
38
+
39
+ ## Quick Start
40
+
41
+ ```bash
42
+ # Scaffold template directory with examples
43
+ pnpm uac init
44
+
45
+ # Generate config for all targets
46
+ pnpm uac generate
47
+
48
+ # Generate for specific targets
49
+ pnpm uac generate -t claude,cursor
50
+
51
+ # Preview without writing files
52
+ pnpm uac generate --dry-run
53
+
54
+ # Seed AI-assisted template management skills
55
+ pnpm uac seed meta-instructions
56
+ ```
57
+
58
+ ## Template Structure
59
+
60
+ ```
61
+ your-project/
62
+ ├── universal-ai-config.config.ts # Shared config (committed)
63
+ ├── universal-ai-config.overrides.config.ts # Personal overrides (gitignored)
64
+ └── .universal-ai-config/
65
+ ├── instructions/ # Rules/instructions (markdown + EJS)
66
+ │ ├── react-patterns.md
67
+ │ └── security.md
68
+ ├── skills/ # One folder per skill
69
+ │ └── test-generation/
70
+ │ └── SKILL.md
71
+ ├── agents/ # Agent/subagent definitions
72
+ │ └── code-reviewer.md
73
+ └── hooks/ # Hook configs (JSON, no templating)
74
+ ├── security.json
75
+ └── quality.json
76
+ ```
77
+
78
+ ## Writing Templates
79
+
80
+ Templates are markdown files with YAML frontmatter. The body supports [EJS](https://ejs.co/) for conditional content per target.
81
+
82
+ ### Instructions
83
+
84
+ ```markdown
85
+ ---
86
+ description: TypeScript specific rules
87
+ globs: ["**/*.ts", "**/*.tsx"]
88
+ ---
89
+
90
+ Use strict TypeScript. Prefer interfaces over type aliases for object shapes.
91
+ ```
92
+
93
+ ```markdown
94
+ ---
95
+ description: Always applied coding standards
96
+ alwaysApply: true
97
+ ---
98
+
99
+ Follow the project's coding standards at all times.
100
+
101
+ <% if (target === 'claude') { -%>
102
+ Use the Read tool to check existing patterns before creating new code.
103
+ <% } else { -%>
104
+ Check existing patterns before creating new code.
105
+ <% } -%>
106
+ ```
107
+
108
+ #### Frontmatter Fields
109
+
110
+ | Field | Type | Description |
111
+ | -------------- | -------------------- | ---------------------------------------------------------------- |
112
+ | `description` | `string` | What this instruction does |
113
+ | `globs` | `string \| string[]` | File patterns this applies to |
114
+ | `alwaysApply` | `boolean` | Apply to all files regardless of context |
115
+ | `excludeAgent` | `string` | Copilot-only: exclude from specific agent (e.g. `"code-review"`) |
116
+
117
+ ### Skills
118
+
119
+ Skills live in subdirectories with a `SKILL.md` file:
120
+
121
+ ```markdown
122
+ ---
123
+ name: test-generation
124
+ description: Generate tests for code
125
+ disableAutoInvocation: true
126
+ userInvocable: /test
127
+ ---
128
+
129
+ Generate comprehensive tests using vitest for the given code.
130
+ ```
131
+
132
+ #### Frontmatter Fields
133
+
134
+ | Field | Type | Description |
135
+ | ----------------------- | ------------------- | -------------------------------------- |
136
+ | `name` | `string` | Skill identifier |
137
+ | `description` | `string` | What this skill does |
138
+ | `disableAutoInvocation` | `boolean` | Prevent automatic triggering |
139
+ | `userInvocable` | `boolean \| string` | Slash command trigger (Claude only) |
140
+ | `allowedTools` | `string[]` | Tools this skill can use (Claude only) |
141
+ | `model` | `string` | Model to use (Claude only) |
142
+ | `subagentType` | `string` | Agent type (Claude only) |
143
+ | `forkContext` | `boolean` | Fork context (Claude only) |
144
+ | `argumentHint` | `string` | Hint for arguments (Claude only) |
145
+ | `license` | `string` | License info (Copilot/Cursor) |
146
+ | `compatibility` | `string` | Compatibility info (Copilot/Cursor) |
147
+ | `metadata` | `object` | Extra metadata (Copilot/Cursor) |
148
+ | `hooks` | `object` | Hook definitions (Claude only) |
149
+
150
+ ### Agents
151
+
152
+ ```markdown
153
+ ---
154
+ name: code-reviewer
155
+ description: Reviews code for quality
156
+ model: sonnet
157
+ tools: ["read", "grep", "glob"]
158
+ ---
159
+
160
+ You are a code reviewer. Check for bugs and best practice violations.
161
+ ```
162
+
163
+ #### Frontmatter Fields
164
+
165
+ | Field | Type | Description |
166
+ | ----------------- | ---------- | --------------------------------- |
167
+ | `name` | `string` | Agent identifier |
168
+ | `description` | `string` | What this agent does |
169
+ | `model` | `string` | Model to use |
170
+ | `tools` | `string[]` | Available tools |
171
+ | `disallowedTools` | `string[]` | Blocked tools (Claude only) |
172
+ | `permissionMode` | `string` | Permission mode (Claude only) |
173
+ | `skills` | `string[]` | Available skills (Claude only) |
174
+ | `hooks` | `object` | Hook definitions (Claude only) |
175
+ | `memory` | `string` | Memory scope (Claude only) |
176
+ | `target` | `string` | Target description (Copilot only) |
177
+ | `mcpServers` | `object` | MCP server config (Copilot only) |
178
+ | `handoffs` | `string[]` | Handoff targets (Copilot only) |
179
+
180
+ > **Note:** Cursor does not support agents. The CLI will warn and skip agent generation for the `cursor` target.
181
+
182
+ ### Hooks
183
+
184
+ Hooks are JSON files that define automated scripts running at lifecycle events (pre-tool-use, session start, etc.). Unlike other template types, hooks use pure JSON with no EJS templating. Multiple `.json` files in the `hooks/` directory are deep-merged by event name.
185
+
186
+ ```json
187
+ {
188
+ "hooks": {
189
+ "preToolUse": [
190
+ {
191
+ "matcher": "Bash",
192
+ "command": ".hooks/block-rm.sh",
193
+ "timeout": 30
194
+ }
195
+ ],
196
+ "postToolUse": [
197
+ {
198
+ "command": ".hooks/lint.sh",
199
+ "timeout": 60
200
+ }
201
+ ]
202
+ }
203
+ }
204
+ ```
205
+
206
+ #### Handler Fields
207
+
208
+ | Field | Type | Required | Description |
209
+ | ------------- | -------- | -------- | --------------------------------------- |
210
+ | `command` | `string` | yes | Shell command or script path |
211
+ | `matcher` | `string` | no | Regex pattern to filter when hook fires |
212
+ | `timeout` | `number` | no | Timeout in seconds |
213
+ | `description` | `string` | no | Human-readable description |
214
+
215
+ #### Universal Event Names
216
+
217
+ Use camelCase event names. The CLI maps them to each target's format and silently drops unsupported events.
218
+
219
+ | Universal | Claude | Cursor | Copilot |
220
+ | -------------------- | -------------------- | -------------------- | --------------------- |
221
+ | `sessionStart` | `SessionStart` | `sessionStart` | `sessionStart` |
222
+ | `sessionEnd` | `SessionEnd` | `sessionEnd` | `sessionEnd` |
223
+ | `userPromptSubmit` | `UserPromptSubmit` | `beforeSubmitPrompt` | `userPromptSubmitted` |
224
+ | `preToolUse` | `PreToolUse` | `preToolUse` | `preToolUse` |
225
+ | `postToolUse` | `PostToolUse` | `postToolUse` | `postToolUse` |
226
+ | `postToolUseFailure` | `PostToolUseFailure` | `postToolUseFailure` | — |
227
+ | `stop` | `Stop` | `stop` | — |
228
+ | `subagentStart` | `SubagentStart` | `subagentStart` | — |
229
+ | `subagentStop` | `SubagentStop` | `subagentStop` | — |
230
+ | `preCompact` | `PreCompact` | `preCompact` | — |
231
+ | `permissionRequest` | `PermissionRequest` | — | — |
232
+ | `notification` | `Notification` | — | — |
233
+ | `errorOccurred` | — | — | `errorOccurred` |
234
+
235
+ Cursor-specific events (`beforeShellExecution`, `afterFileEdit`, etc.) can be used directly — they pass through to Cursor and are dropped for other targets.
236
+
237
+ ## Per-Target Overrides
238
+
239
+ Any frontmatter field or hook handler field can accept per-target values instead of a single value. If a field's value is an object where **every key is a target name** (`claude`, `copilot`, `cursor`) or `default`, it's resolved to the matching target's value during generation. If the target isn't listed, the `default` value is used. If neither is present, the field is omitted.
240
+
241
+ ### Frontmatter
242
+
243
+ ```yaml
244
+ ---
245
+ description:
246
+ claude: Use Claude Code conventions
247
+ copilot: Use Copilot conventions
248
+ cursor: Use Cursor conventions
249
+ tools:
250
+ default: ["read", "grep", "glob"]
251
+ claude: ["Read", "Grep", "Glob"]
252
+ model:
253
+ default: sonnet
254
+ claude: opus
255
+ copilot: gpt-4o
256
+ permissionMode:
257
+ claude: acceptEdits
258
+ ---
259
+ ```
260
+
261
+ When generating for Claude: `tools: ["Read", "Grep", "Glob"]`, `model: opus`, `permissionMode: acceptEdits`. For Copilot: `tools: ["read", "grep", "glob"]` (default), `model: gpt-4o`, `permissionMode` omitted. For Cursor: `tools: ["read", "grep", "glob"]` (default), `model: sonnet` (default), `permissionMode` omitted.
262
+
263
+ You can mix per-target and plain values freely — plain values apply to all targets:
264
+
265
+ ```yaml
266
+ ---
267
+ name: my-skill
268
+ description:
269
+ claude: Claude-specific description
270
+ copilot: Copilot-specific description
271
+ license: MIT
272
+ ---
273
+ ```
274
+
275
+ ### Hooks
276
+
277
+ Hook handler fields (`command`, `matcher`, `timeout`, `description`) support the same syntax:
278
+
279
+ ```json
280
+ {
281
+ "hooks": {
282
+ "preToolUse": [
283
+ {
284
+ "command": {
285
+ "claude": ".hooks/claude-check.sh",
286
+ "copilot": ".hooks/copilot-check.sh",
287
+ "cursor": ".hooks/cursor-check.sh"
288
+ },
289
+ "matcher": {
290
+ "claude": "Bash",
291
+ "cursor": "Bash"
292
+ },
293
+ "timeout": 30
294
+ }
295
+ ]
296
+ }
297
+ }
298
+ ```
299
+
300
+ If `command` resolves to `undefined` for a target (i.e. that target isn't listed), the entire handler is skipped for that target.
301
+
302
+ > **Note:** Objects with non-target keys (e.g. `metadata: { category: "devops" }`) are **not** treated as overrides — they pass through unchanged.
303
+
304
+ ## EJS Template Variables
305
+
306
+ All templates have access to these variables:
307
+
308
+ | Variable | Type | Description |
309
+ | --------------------- | ---------------------------------------- | -------------------------------------------------- |
310
+ | `target` | `'claude' \| 'copilot' \| 'cursor'` | Current output target |
311
+ | `type` | `'instructions' \| 'skills' \| 'agents'` | Template type being rendered (hooks don't use EJS) |
312
+ | `config` | `ResolvedConfig` | Full resolved config object |
313
+ | `...config.variables` | `Record<string, unknown>` | Custom user variables spread into scope |
314
+
315
+ ### Path Helpers
316
+
317
+ Templates have access to path helper functions. All `name` parameters are optional — omit to get the directory path.
318
+
319
+ **Output path helpers** — resolve to the target-specific output path:
320
+
321
+ | Function | Returns |
322
+ | ------------------------ | ------------------------------------------------------------- |
323
+ | `instructionPath(name?)` | Target-specific output path (or directory) for an instruction |
324
+ | `skillPath(name?)` | Target-specific output path (or directory) for a skill |
325
+ | `agentPath(name?)` | Target-specific output path (or directory) for an agent |
326
+
327
+ **Template path helpers** — resolve to the source template path in the templates directory:
328
+
329
+ | Function | Returns |
330
+ | -------------------------------- | ------------------------------------------------------ |
331
+ | `instructionTemplatePath(name?)` | Template source path (or directory) for an instruction |
332
+ | `skillTemplatePath(name?)` | Template source path (or directory) for a skill |
333
+ | `agentTemplatePath(name?)` | Template source path (or directory) for an agent |
334
+ | `hookTemplatePath(name?)` | Template source path (or directory) for a hook |
335
+
336
+ For example, `<%= instructionPath('coding-style') %>` renders to:
337
+
338
+ | Target | Output |
339
+ | ------- | --------------------------------------------------- |
340
+ | Claude | `.claude/rules/coding-style.md` |
341
+ | Copilot | `.github/instructions/coding-style.instructions.md` |
342
+ | Cursor | `.cursor/rules/coding-style.mdc` |
343
+
344
+ And `<%= instructionPath() %>` (no argument) renders to:
345
+
346
+ | Target | Output |
347
+ | ------- | ---------------------- |
348
+ | Claude | `.claude/rules` |
349
+ | Copilot | `.github/instructions` |
350
+ | Cursor | `.cursor/rules` |
351
+
352
+ Template path helpers are target-independent: `<%= instructionTemplatePath('coding-style') %>` always renders to `.universal-ai-config/instructions/coding-style.md` (or the configured `templatesDir`).
353
+
354
+ ## Configuration
355
+
356
+ ### Base config (`universal-ai-config.config.ts`) — committed
357
+
358
+ ```typescript
359
+ import { defineConfig } from "universal-ai-config";
360
+
361
+ export default defineConfig({
362
+ // Where templates live (default: '.universal-ai-config')
363
+ templatesDir: ".universal-ai-config",
364
+
365
+ // Which targets to generate (default: all three)
366
+ targets: ["claude", "copilot", "cursor"],
367
+
368
+ // Which types to generate (default: all)
369
+ types: ["instructions", "skills", "agents", "hooks"],
370
+
371
+ // Custom EJS variables available in templates
372
+ variables: {
373
+ projectName: "my-app",
374
+ useStrictMode: true,
375
+ },
376
+
377
+ // Override default output directories
378
+ outputDirs: {
379
+ claude: ".claude",
380
+ copilot: ".github",
381
+ cursor: ".cursor",
382
+ },
383
+ });
384
+ ```
385
+
386
+ ### Overrides config (`universal-ai-config.overrides.config.ts`) — (ideally gitignored)
387
+
388
+ ```typescript
389
+ import { defineConfig } from "universal-ai-config";
390
+
391
+ export default defineConfig({
392
+ // I only use Claude and Cursor
393
+ targets: ["claude", "cursor"],
394
+
395
+ // Extra variables for my local setup
396
+ variables: {
397
+ myPreferredStyle: "functional",
398
+ },
399
+ });
400
+ ```
401
+
402
+ ### Merge Behavior
403
+
404
+ - **Arrays** (`targets`, `types`): overrides **replace** entirely
405
+ - **Objects** (`variables`, `outputDirs`): **deep-merged**
406
+ - **Scalars** (`templatesDir`): overrides **replace**
407
+
408
+ ### Resolution Order (later wins)
409
+
410
+ 1. Built-in defaults
411
+ 2. `universal-ai-config.{ts,js,mjs,cjs}` (base)
412
+ 3. `universal-ai-config.overrides.{ts,js,mjs,cjs}` (personal)
413
+ 4. CLI flags (`--target`, `--type`, etc.)
414
+
415
+ ## CLI Reference
416
+
417
+ ### `uac generate`
418
+
419
+ Generate config files for specified targets.
420
+
421
+ | Flag | Short | Description | Default |
422
+ | ----------- | ----- | --------------------------- | --------------- |
423
+ | `--target` | `-t` | Comma-separated targets | All from config |
424
+ | `--type` | | Comma-separated types | All from config |
425
+ | `--config` | `-c` | Config file path | Auto-detected |
426
+ | `--root` | `-r` | Project root | cwd |
427
+ | `--dry-run` | `-d` | Preview without writing | `false` |
428
+ | `--clean` | | Remove existing files first | `false` |
429
+
430
+ ### `uac init`
431
+
432
+ Scaffold `.universal-ai-config/` directory with example templates. Creates a `universal-ai-config.config.ts` config file if one doesn't exist. Adds `universal-ai-config.overrides.*` to `.gitignore`.
433
+
434
+ | Flag | Short | Description | Default |
435
+ | -------- | ----- | ------------ | ------- |
436
+ | `--root` | `-r` | Project root | cwd |
437
+
438
+ ### `uac clean`
439
+
440
+ Remove all generated config directories.
441
+
442
+ | Flag | Short | Description | Default |
443
+ | ---------- | ----- | -------------------------------- | ------- |
444
+ | `--target` | `-t` | Comma-separated targets to clean | All |
445
+ | `--root` | `-r` | Project root | cwd |
446
+
447
+ ### `uac seed`
448
+
449
+ Seed the templates directory with pre-built template sets. Currently available seed types:
450
+
451
+ - **`meta-instructions`** — Creates instruction and skill templates that teach AI tools how to create, update, and manage universal-ai-config templates. This bootstraps the AI's ability to extend its own configuration.
452
+
453
+ ```bash
454
+ # Seed with default templates directory
455
+ pnpm uac seed meta-instructions
456
+
457
+ # Seed with custom project root
458
+ pnpm uac seed meta-instructions --root ./my-project
459
+ ```
460
+
461
+ | Flag | Short | Description | Default |
462
+ | -------- | ----- | ------------ | ------- |
463
+ | `--root` | `-r` | Project root | cwd |
464
+
465
+ The `meta-instructions` seed creates 7 files in the templates directory:
466
+
467
+ | File | Purpose |
468
+ | ------------------------------------------- | -------------------------------------------------------------- |
469
+ | `instructions/uac-template-guide.md` | Decision guide for choosing the right template type |
470
+ | `skills/update-ai-config/SKILL.md` | Dispatcher — analyzes intent and delegates to the right skill |
471
+ | `skills/update-instruction/SKILL.md` | Full lifecycle management for instruction templates |
472
+ | `skills/update-skill/SKILL.md` | Full lifecycle management for skill templates |
473
+ | `skills/update-agent/SKILL.md` | Full lifecycle management for agent templates |
474
+ | `skills/update-hook/SKILL.md` | Full lifecycle management for hook templates |
475
+ | `skills/import-existing-ai-config/SKILL.md` | Import existing target-specific configs as universal templates |
476
+
477
+ Existing files are overwritten to ensure templates stay up to date.
478
+
479
+ ## Output Paths
480
+
481
+ ### Claude (`.claude/`)
482
+
483
+ | Type | Output Path |
484
+ | ------------ | ------------------------------------------------- |
485
+ | Instructions | `.claude/rules/<name>.md` |
486
+ | Skills | `.claude/skills/<name>/SKILL.md` |
487
+ | Agents | `.claude/agents/<name>.md` |
488
+ | Hooks | `.claude/settings.json` (merged into `hooks` key) |
489
+
490
+ ### Copilot (`.github/`)
491
+
492
+ | Type | Output Path |
493
+ | ---------------------------- | --------------------------------------------- |
494
+ | Instructions | `.github/instructions/<name>.instructions.md` |
495
+ | Instructions (`alwaysApply`) | `.github/copilot-instructions.md` |
496
+ | Skills | `.github/skills/<name>/SKILL.md` |
497
+ | Agents | `.github/agents/<name>.agent.md` |
498
+ | Hooks | `.github/hooks/hooks.json` |
499
+
500
+ ### Cursor (`.cursor/`)
501
+
502
+ | Type | Output Path |
503
+ | ------------ | -------------------------------- |
504
+ | Instructions | `.cursor/rules/<name>.mdc` |
505
+ | Skills | `.cursor/skills/<name>/SKILL.md` |
506
+ | Agents | Not supported |
507
+ | Hooks | `.cursor/hooks.json` |
508
+
509
+ ## Frontmatter Mapping Reference
510
+
511
+ <details>
512
+ <summary>Instructions mapping</summary>
513
+
514
+ | Universal | Claude | Copilot | Cursor |
515
+ | -------------- | ------------- | ----------------------------------- | ------------------- |
516
+ | `description` | `description` | `description` | `description` |
517
+ | `globs` | `paths` | `applyTo` (comma-joined) | `globs` |
518
+ | `alwaysApply` | omits `paths` | routes to `copilot-instructions.md` | `alwaysApply: true` |
519
+ | `excludeAgent` | — | `excludeAgent` | — |
520
+
521
+ </details>
522
+
523
+ <details>
524
+ <summary>Skills mapping</summary>
525
+
526
+ | Universal | Claude | Copilot | Cursor |
527
+ | ----------------------- | -------------------------- | --------------- | -------------------------- |
528
+ | `name` | `name` | `name` | `name` |
529
+ | `description` | `description` | `description` | `description` |
530
+ | `disableAutoInvocation` | `disable-model-invocation` | — | `disable-model-invocation` |
531
+ | `userInvocable` | `user-invocable` | — | — |
532
+ | `allowedTools` | `allowed-tools` | — | — |
533
+ | `model` | `model` | — | — |
534
+ | `subagentType` | `agent` | — | — |
535
+ | `forkContext` | `context: fork` | — | — |
536
+ | `argumentHint` | `argument-hint` | — | — |
537
+ | `license` | — | `license` | `license` |
538
+ | `compatibility` | — | `compatibility` | `compatibility` |
539
+ | `metadata` | — | `metadata` | `metadata` |
540
+ | `hooks` | `hooks` | — | — |
541
+
542
+ </details>
543
+
544
+ <details>
545
+ <summary>Agents mapping</summary>
546
+
547
+ | Universal | Claude | Copilot |
548
+ | ----------------- | ----------------- | ------------- |
549
+ | `name` | `name` | `name` |
550
+ | `description` | `description` | `description` |
551
+ | `model` | `model` | `model` |
552
+ | `tools` | `tools` | `tools` |
553
+ | `disallowedTools` | `disallowedTools` | — |
554
+ | `permissionMode` | `permissionMode` | — |
555
+ | `skills` | `skills` | — |
556
+ | `hooks` | `hooks` | — |
557
+ | `memory` | `memory` | — |
558
+ | `target` | — | `target` |
559
+ | `mcpServers` | — | `mcp-servers` |
560
+ | `handoffs` | — | `handoffs` |
561
+
562
+ </details>
563
+
564
+ <details>
565
+ <summary>Hooks mapping</summary>
566
+
567
+ | Aspect | Claude | Copilot | Cursor |
568
+ | ----------------- | ----------------------------------- | -------------------------- | ------------------------- |
569
+ | Output file | `.claude/settings.json` | `.github/hooks/hooks.json` | `.cursor/hooks.json` |
570
+ | Merge behavior | Merges into `hooks` key | Standalone file | Standalone file |
571
+ | Event names | PascalCase | camelCase (some renamed) | camelCase (some renamed) |
572
+ | `command` field | `command` | `bash` | `command` |
573
+ | `timeout` field | `timeout` | `timeoutSec` | `timeout` |
574
+ | `matcher` support | Yes (groups handlers) | Dropped | Yes (flat) |
575
+ | Handler structure | Nested: `{ matcher, hooks: [...] }` | Flat: `{ type, bash }` | Flat: `{ type, command }` |
576
+ | Version wrapper | None | `"1"` (string) | `1` (number) |
577
+
578
+ </details>
579
+
580
+ ## Programmatic API
581
+
582
+ ```typescript
583
+ import { generate, defineConfig } from "universal-ai-config";
584
+
585
+ const files = await generate({
586
+ root: process.cwd(),
587
+ targets: ["claude"],
588
+ dryRun: true,
589
+ });
590
+
591
+ for (const file of files) {
592
+ console.log(file.path); // ".claude/rules/react-patterns.md"
593
+ console.log(file.content); // Rendered file content
594
+ console.log(file.target); // "claude"
595
+ console.log(file.type); // "instructions"
596
+ }
597
+ ```
598
+
599
+ ## Adding a New Target
600
+
601
+ Create a single file in `src/targets/` implementing `TargetDefinition`:
602
+
603
+ ```typescript
604
+ import { defineTarget } from "../define-target.js";
605
+
606
+ export default defineTarget({
607
+ name: "zed",
608
+ outputDir: ".zed",
609
+ supportedTypes: ["instructions"],
610
+ instructions: {
611
+ frontmatterMap: {
612
+ globs: "path",
613
+ },
614
+ getOutputPath: (name) => `prompts/${name}.md`,
615
+ },
616
+ });
617
+ ```
618
+
619
+ Then add one line to [src/targets/index.ts](src/targets/index.ts):
620
+
621
+ ```typescript
622
+ import zed from "./zed/index.js";
623
+ export const targets = { claude, copilot, cursor, zed };
624
+ ```
625
+
626
+ ## License
627
+
628
+ MIT
package/dist/cli.d.mts ADDED
@@ -0,0 +1 @@
1
+ export { };