@a16njs/plugin-claude 0.0.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,127 @@
1
+ # @a16njs/plugin-claude
2
+
3
+ Claude Code plugin for a16n. Discovers and emits Claude configuration.
4
+
5
+ ## Installation
6
+
7
+ This plugin is bundled with the `a16n` CLI. For programmatic use:
8
+
9
+ ```bash
10
+ npm install @a16njs/plugin-claude
11
+ ```
12
+
13
+ ## Supported Types
14
+
15
+ This plugin supports four customization types:
16
+
17
+ | Type | Claude Format | Description |
18
+ |------|---------------|-------------|
19
+ | **GlobalPrompt** | `CLAUDE.md` | Always-active instructions |
20
+ | **FileRule** | `.claude/settings.local.json` + `.a16n/rules/` | Glob-triggered via hooks |
21
+ | **AgentSkill** | `.claude/skills/*/SKILL.md` | Description-triggered skills |
22
+ | **AgentIgnore** | `.claude/settings.json` `permissions.deny` | Files to exclude |
23
+
24
+ ## Supported Files
25
+
26
+ ### Discovery
27
+
28
+ - `CLAUDE.md` - Root Claude configuration (GlobalPrompt)
29
+ - `*/CLAUDE.md` - Nested Claude configuration files (GlobalPrompt)
30
+ - `.claude/skills/*/SKILL.md` - Skills with description frontmatter (AgentSkill)
31
+ - `.claude/settings.json` - Permissions deny rules (AgentIgnore)
32
+
33
+ > **Note:** Skills with `hooks:` in their frontmatter are skipped (not convertible to Cursor).
34
+ > **Note:** Only `Read()` permission denials are discovered (other types like `Bash()` or `Edit()` are ignored).
35
+
36
+ ### Emission
37
+
38
+ - **GlobalPrompt** → `CLAUDE.md` (merged with section headers)
39
+ - **FileRule** → `.a16n/rules/<name>.txt` + `.claude/settings.local.json` with hooks
40
+ - **AgentSkill** → `.claude/skills/<name>/SKILL.md` with description frontmatter
41
+ - **AgentIgnore** → `.claude/settings.json` with `permissions.deny` Read rules
42
+
43
+ ## File Formats
44
+
45
+ ### CLAUDE.md (GlobalPrompt)
46
+
47
+ ```markdown
48
+ # Project Guidelines
49
+
50
+ Your instructions for Claude here.
51
+ ```
52
+
53
+ ### SKILL.md (AgentSkill)
54
+
55
+ ```markdown
56
+ ---
57
+ description: Testing best practices
58
+ ---
59
+
60
+ Write unit tests first.
61
+ Aim for 80% code coverage.
62
+ ```
63
+
64
+ ### settings.local.json (FileRule via hooks)
65
+
66
+ FileRules are converted using `@a16njs/glob-hook` for runtime glob matching:
67
+
68
+ ```json
69
+ {
70
+ "hooks": {
71
+ "PreToolUse": [{
72
+ "matcher": "Read|Write|Edit",
73
+ "hooks": [{
74
+ "type": "command",
75
+ "command": "npx @a16njs/glob-hook --globs \"**/*.tsx\" --context-file \".a16n/rules/react.txt\""
76
+ }]
77
+ }]
78
+ }
79
+ }
80
+ ```
81
+
82
+ > **Note:** FileRule conversion emits an "Approximated" warning because hook-based matching may differ slightly from Cursor's native glob matching.
83
+
84
+ ### settings.json (AgentIgnore via permissions.deny)
85
+
86
+ AgentIgnore patterns are converted to `permissions.deny` Read rules:
87
+
88
+ ```json
89
+ {
90
+ "permissions": {
91
+ "deny": [
92
+ "Read(./dist/**)",
93
+ "Read(./.env)",
94
+ "Read(./**/*.log)",
95
+ "Read(./secrets/**)"
96
+ ]
97
+ }
98
+ }
99
+ ```
100
+
101
+ Pattern conversion rules:
102
+ - `dist/` → `Read(./dist/**)`
103
+ - `.env` → `Read(./.env)`
104
+ - `*.log` → `Read(./**/*.log)`
105
+ - `**/*.tmp` → `Read(./**/*.tmp)`
106
+
107
+ > **Note:** AgentIgnore conversion emits an "Approximated" warning because Claude's permission system may behave slightly differently than `.cursorignore`.
108
+
109
+ ## Usage
110
+
111
+ ```typescript
112
+ import claudePlugin from '@a16njs/plugin-claude';
113
+ import { A16nEngine } from '@a16njs/engine';
114
+
115
+ const engine = new A16nEngine([claudePlugin]);
116
+
117
+ // Discover Claude configuration
118
+ const result = await claudePlugin.discover('./my-project');
119
+ console.log(`Found ${result.items.length} items`);
120
+
121
+ // Emit to Claude format
122
+ await claudePlugin.emit(result.items, './my-project');
123
+ ```
124
+
125
+ ## License
126
+
127
+ MIT
@@ -0,0 +1,6 @@
1
+ import { type DiscoveryResult } from '@a16njs/models';
2
+ /**
3
+ * Discover all CLAUDE.md files and skills in a project directory.
4
+ */
5
+ export declare function discover(root: string): Promise<DiscoveryResult>;
6
+ //# sourceMappingURL=discover.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discover.d.ts","sourceRoot":"","sources":["../src/discover.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,eAAe,EAKrB,MAAM,gBAAgB,CAAC;AAyMxB;;GAEG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CA8FrE"}
@@ -0,0 +1,251 @@
1
+ import * as fs from 'fs/promises';
2
+ import * as path from 'path';
3
+ import { CustomizationType, WarningCode, createId, } from '@a16njs/models';
4
+ /**
5
+ * Convert a Claude Read() permission rule to a gitignore-style pattern.
6
+ * Returns null for non-Read rules.
7
+ */
8
+ function convertReadRuleToPattern(rule) {
9
+ const match = rule.match(/^Read\(\.\/(.+)\)$/);
10
+ if (!match)
11
+ return null;
12
+ let pattern = match[1];
13
+ // Read(./dist/**) → dist/
14
+ if (pattern.endsWith('/**')) {
15
+ return pattern.slice(0, -2);
16
+ }
17
+ // Read(./**/*.log) → *.log
18
+ if (pattern.startsWith('**/')) {
19
+ return pattern.slice(3);
20
+ }
21
+ // Read(./.env) → .env
22
+ return pattern;
23
+ }
24
+ function parseSkillFrontmatter(content) {
25
+ const lines = content.split('\n');
26
+ let frontmatterStart = -1;
27
+ let frontmatterEnd = -1;
28
+ for (let i = 0; i < lines.length; i++) {
29
+ const line = lines[i]?.trim();
30
+ if (line === '---') {
31
+ if (frontmatterStart === -1) {
32
+ frontmatterStart = i;
33
+ }
34
+ else {
35
+ frontmatterEnd = i;
36
+ break;
37
+ }
38
+ }
39
+ }
40
+ // No frontmatter found
41
+ if (frontmatterStart === -1 || frontmatterEnd === -1) {
42
+ return {
43
+ frontmatter: { hasHooks: false },
44
+ body: content.trim(),
45
+ };
46
+ }
47
+ const frontmatter = { hasHooks: false };
48
+ // Parse frontmatter lines
49
+ for (let i = frontmatterStart + 1; i < frontmatterEnd; i++) {
50
+ const line = lines[i];
51
+ if (!line)
52
+ continue;
53
+ // Check for hooks: key (indicates skill-scoped hooks)
54
+ if (line.match(/^hooks:\s*$/)) {
55
+ frontmatter.hasHooks = true;
56
+ continue;
57
+ }
58
+ // Parse description: "..."
59
+ const descriptionMatch = line.match(/^description:\s*["']?(.+?)["']?\s*$/);
60
+ if (descriptionMatch) {
61
+ frontmatter.description = descriptionMatch[1];
62
+ continue;
63
+ }
64
+ // Parse name: "..."
65
+ const nameMatch = line.match(/^name:\s*["']?(.+?)["']?\s*$/);
66
+ if (nameMatch) {
67
+ frontmatter.name = nameMatch[1];
68
+ continue;
69
+ }
70
+ }
71
+ // Extract body (everything after second ---)
72
+ const bodyLines = lines.slice(frontmatterEnd + 1);
73
+ const body = bodyLines.join('\n').trim();
74
+ return { frontmatter, body };
75
+ }
76
+ /**
77
+ * Find all SKILL.md files in .claude/skills/ subdirectories.
78
+ * Returns paths like ".claude/skills/testing/SKILL.md"
79
+ */
80
+ async function findSkillFiles(root) {
81
+ const results = [];
82
+ const skillsDir = path.join(root, '.claude', 'skills');
83
+ try {
84
+ const entries = await fs.readdir(skillsDir, { withFileTypes: true });
85
+ for (const entry of entries) {
86
+ if (entry.isDirectory()) {
87
+ const skillFile = path.join(skillsDir, entry.name, 'SKILL.md');
88
+ try {
89
+ await fs.access(skillFile);
90
+ results.push(`.claude/skills/${entry.name}/SKILL.md`);
91
+ }
92
+ catch {
93
+ // No SKILL.md in this directory
94
+ }
95
+ }
96
+ }
97
+ }
98
+ catch {
99
+ // .claude/skills doesn't exist
100
+ }
101
+ return results;
102
+ }
103
+ /**
104
+ * Recursively find all CLAUDE.md files in a directory tree.
105
+ */
106
+ async function findClaudeFiles(root, currentDir = '') {
107
+ const results = [];
108
+ const fullPath = currentDir ? path.join(root, currentDir) : root;
109
+ try {
110
+ const entries = await fs.readdir(fullPath, { withFileTypes: true });
111
+ for (const entry of entries) {
112
+ // Skip node_modules and hidden directories
113
+ if (entry.name.startsWith('.') || entry.name === 'node_modules') {
114
+ continue;
115
+ }
116
+ const relativePath = currentDir
117
+ ? path.join(currentDir, entry.name)
118
+ : entry.name;
119
+ if (entry.isFile() && entry.name === 'CLAUDE.md') {
120
+ results.push(relativePath);
121
+ }
122
+ else if (entry.isDirectory()) {
123
+ const nested = await findClaudeFiles(root, relativePath);
124
+ results.push(...nested);
125
+ }
126
+ }
127
+ }
128
+ catch {
129
+ // Directory doesn't exist or can't be read
130
+ }
131
+ return results;
132
+ }
133
+ /**
134
+ * Discover AgentIgnore from .claude/settings.json permissions.deny Read rules.
135
+ * Returns null if settings.json doesn't exist or has no Read rules.
136
+ */
137
+ async function discoverAgentIgnore(root) {
138
+ const settingsPath = path.join(root, '.claude', 'settings.json');
139
+ try {
140
+ const content = await fs.readFile(settingsPath, 'utf-8');
141
+ const settings = JSON.parse(content);
142
+ const permissions = settings.permissions;
143
+ const rawDeny = Array.isArray(permissions?.deny) ? permissions.deny : [];
144
+ // Filter to only string entries to avoid startsWith throwing on non-strings
145
+ const denyRules = rawDeny.filter((r) => typeof r === 'string');
146
+ const readRules = denyRules.filter(r => r.startsWith('Read('));
147
+ const patterns = readRules
148
+ .map(convertReadRuleToPattern)
149
+ .filter((p) => p !== null);
150
+ if (patterns.length === 0)
151
+ return null;
152
+ return {
153
+ id: createId(CustomizationType.AgentIgnore, '.claude/settings.json'),
154
+ type: CustomizationType.AgentIgnore,
155
+ sourcePath: '.claude/settings.json',
156
+ content: JSON.stringify({ permissions: { deny: readRules } }, null, 2),
157
+ patterns,
158
+ metadata: { originalRules: readRules },
159
+ };
160
+ }
161
+ catch {
162
+ return null;
163
+ }
164
+ }
165
+ /**
166
+ * Discover all CLAUDE.md files and skills in a project directory.
167
+ */
168
+ export async function discover(root) {
169
+ const items = [];
170
+ const warnings = [];
171
+ // Find all CLAUDE.md files (GlobalPrompt)
172
+ const claudeFiles = await findClaudeFiles(root);
173
+ for (const file of claudeFiles) {
174
+ const fullPath = path.join(root, file);
175
+ // Normalize path separators for cross-platform consistency
176
+ const normalizedPath = file.split(path.sep).join('/');
177
+ try {
178
+ const content = await fs.readFile(fullPath, 'utf-8');
179
+ // Calculate nesting depth
180
+ const depth = file.split(path.sep).length - 1;
181
+ const isNested = depth > 0;
182
+ items.push({
183
+ id: createId(CustomizationType.GlobalPrompt, normalizedPath),
184
+ type: CustomizationType.GlobalPrompt,
185
+ sourcePath: normalizedPath,
186
+ content,
187
+ metadata: {
188
+ nested: isNested,
189
+ depth,
190
+ },
191
+ });
192
+ }
193
+ catch (error) {
194
+ // File couldn't be read - add warning and continue
195
+ warnings.push({
196
+ code: WarningCode.Skipped,
197
+ message: `Could not read ${normalizedPath}: ${error.message}`,
198
+ sources: [normalizedPath],
199
+ });
200
+ }
201
+ }
202
+ // Find all .claude/skills/*/SKILL.md files (AgentSkill)
203
+ const skillFiles = await findSkillFiles(root);
204
+ for (const skillPath of skillFiles) {
205
+ const fullPath = path.join(root, skillPath);
206
+ try {
207
+ const content = await fs.readFile(fullPath, 'utf-8');
208
+ const { frontmatter, body } = parseSkillFrontmatter(content);
209
+ // Extract skill name from path (e.g., "testing" from ".claude/skills/testing/SKILL.md")
210
+ const skillName = skillPath.split('/')[2] || 'unknown';
211
+ // Skip skills with hooks - they're not convertible to Cursor
212
+ if (frontmatter.hasHooks) {
213
+ const displayName = frontmatter.name || skillName;
214
+ warnings.push({
215
+ code: WarningCode.Skipped,
216
+ message: `Skipped skill '${displayName}': Contains hooks (not convertible to Cursor)`,
217
+ sources: [skillPath],
218
+ });
219
+ continue;
220
+ }
221
+ // Only include skills that have a description
222
+ if (frontmatter.description) {
223
+ const skill = {
224
+ id: createId(CustomizationType.AgentSkill, skillPath),
225
+ type: CustomizationType.AgentSkill,
226
+ sourcePath: skillPath,
227
+ content: body,
228
+ description: frontmatter.description,
229
+ metadata: {
230
+ name: frontmatter.name || skillName,
231
+ },
232
+ };
233
+ items.push(skill);
234
+ }
235
+ }
236
+ catch (error) {
237
+ warnings.push({
238
+ code: WarningCode.Skipped,
239
+ message: `Could not read ${skillPath}: ${error.message}`,
240
+ sources: [skillPath],
241
+ });
242
+ }
243
+ }
244
+ // Discover AgentIgnore from .claude/settings.json (Phase 3)
245
+ const agentIgnore = await discoverAgentIgnore(root);
246
+ if (agentIgnore) {
247
+ items.push(agentIgnore);
248
+ }
249
+ return { items, warnings };
250
+ }
251
+ //# sourceMappingURL=discover.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discover.js","sourceRoot":"","sources":["../src/discover.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAML,iBAAiB,EACjB,WAAW,EACX,QAAQ,GACT,MAAM,gBAAgB,CAAC;AAExB;;;GAGG;AACH,SAAS,wBAAwB,CAAC,IAAY;IAC5C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;IAC/C,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IAExB,IAAI,OAAO,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC;IAExB,0BAA0B;IAC1B,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC9B,CAAC;IACD,2BAA2B;IAC3B,IAAI,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC1B,CAAC;IACD,sBAAsB;IACtB,OAAO,OAAO,CAAC;AACjB,CAAC;AAiBD,SAAS,qBAAqB,CAAC,OAAe;IAC5C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAElC,IAAI,gBAAgB,GAAG,CAAC,CAAC,CAAC;IAC1B,IAAI,cAAc,GAAG,CAAC,CAAC,CAAC;IAExB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;QAC9B,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;YACnB,IAAI,gBAAgB,KAAK,CAAC,CAAC,EAAE,CAAC;gBAC5B,gBAAgB,GAAG,CAAC,CAAC;YACvB,CAAC;iBAAM,CAAC;gBACN,cAAc,GAAG,CAAC,CAAC;gBACnB,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;IAED,uBAAuB;IACvB,IAAI,gBAAgB,KAAK,CAAC,CAAC,IAAI,cAAc,KAAK,CAAC,CAAC,EAAE,CAAC;QACrD,OAAO;YACL,WAAW,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE;YAChC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE;SACrB,CAAC;IACJ,CAAC;IAED,MAAM,WAAW,GAAqB,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IAE1D,0BAA0B;IAC1B,KAAK,IAAI,CAAC,GAAG,gBAAgB,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3D,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,IAAI,CAAC,IAAI;YAAE,SAAS;QAEpB,sDAAsD;QACtD,IAAI,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE,CAAC;YAC9B,WAAW,CAAC,QAAQ,GAAG,IAAI,CAAC;YAC5B,SAAS;QACX,CAAC;QAED,2BAA2B;QAC3B,MAAM,gBAAgB,GAAG,IAAI,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;QAC3E,IAAI,gBAAgB,EAAE,CAAC;YACrB,WAAW,CAAC,WAAW,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC;YAC9C,SAAS;QACX,CAAC;QAED,oBAAoB;QACpB,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAC7D,IAAI,SAAS,EAAE,CAAC;YACd,WAAW,CAAC,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;YAChC,SAAS;QACX,CAAC;IACH,CAAC;IAED,6CAA6C;IAC7C,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,cAAc,GAAG,CAAC,CAAC,CAAC;IAClD,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;IAEzC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;AAC/B,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,cAAc,CAAC,IAAY;IACxC,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;IAEvD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAErE,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxB,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;gBAC/D,IAAI,CAAC;oBACH,MAAM,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;oBAC3B,OAAO,CAAC,IAAI,CAAC,kBAAkB,KAAK,CAAC,IAAI,WAAW,CAAC,CAAC;gBACxD,CAAC;gBAAC,MAAM,CAAC;oBACP,gCAAgC;gBAClC,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,+BAA+B;IACjC,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,eAAe,CAC5B,IAAY,EACZ,aAAqB,EAAE;IAEvB,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,QAAQ,GAAG,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAEjE,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAEpE,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,2CAA2C;YAC3C,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;gBAChE,SAAS;YACX,CAAC;YAED,MAAM,YAAY,GAAG,UAAU;gBAC7B,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC;gBACnC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC;YAEf,IAAI,KAAK,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;gBACjD,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAC7B,CAAC;iBAAM,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBAC/B,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;gBACzD,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,2CAA2C;IAC7C,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,mBAAmB,CAAC,IAAY;IAC7C,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC;IAEjE,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QACzD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAA4B,CAAC;QAChE,MAAM,WAAW,GAAG,QAAQ,CAAC,WAAkD,CAAC;QAChF,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QACzE,4EAA4E;QAC5E,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC;QAC5E,MAAM,SAAS,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;QAE/D,MAAM,QAAQ,GAAG,SAAS;aACvB,GAAG,CAAC,wBAAwB,CAAC;aAC7B,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;QAE1C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QAEvC,OAAO;YACL,EAAE,EAAE,QAAQ,CAAC,iBAAiB,CAAC,WAAW,EAAE,uBAAuB,CAAC;YACpE,IAAI,EAAE,iBAAiB,CAAC,WAAW;YACnC,UAAU,EAAE,uBAAuB;YACnC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;YACtE,QAAQ;YACR,QAAQ,EAAE,EAAE,aAAa,EAAE,SAAS,EAAE;SACvC,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,IAAY;IACzC,MAAM,KAAK,GAAyB,EAAE,CAAC;IACvC,MAAM,QAAQ,GAAc,EAAE,CAAC;IAE/B,0CAA0C;IAC1C,MAAM,WAAW,GAAG,MAAM,eAAe,CAAC,IAAI,CAAC,CAAC;IAEhD,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAEvC,2DAA2D;QAC3D,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEtD,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAErD,0BAA0B;YAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;YAC9C,MAAM,QAAQ,GAAG,KAAK,GAAG,CAAC,CAAC;YAE3B,KAAK,CAAC,IAAI,CAAC;gBACT,EAAE,EAAE,QAAQ,CAAC,iBAAiB,CAAC,YAAY,EAAE,cAAc,CAAC;gBAC5D,IAAI,EAAE,iBAAiB,CAAC,YAAY;gBACpC,UAAU,EAAE,cAAc;gBAC1B,OAAO;gBACP,QAAQ,EAAE;oBACR,MAAM,EAAE,QAAQ;oBAChB,KAAK;iBACN;aACF,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,mDAAmD;YACnD,QAAQ,CAAC,IAAI,CAAC;gBACZ,IAAI,EAAE,WAAW,CAAC,OAAO;gBACzB,OAAO,EAAE,kBAAkB,cAAc,KAAM,KAAe,CAAC,OAAO,EAAE;gBACxE,OAAO,EAAE,CAAC,cAAc,CAAC;aAC1B,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,wDAAwD;IACxD,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,CAAC;IAE9C,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QAE5C,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACrD,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;YAE7D,wFAAwF;YACxF,MAAM,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC;YAEvD,6DAA6D;YAC7D,IAAI,WAAW,CAAC,QAAQ,EAAE,CAAC;gBACzB,MAAM,WAAW,GAAG,WAAW,CAAC,IAAI,IAAI,SAAS,CAAC;gBAClD,QAAQ,CAAC,IAAI,CAAC;oBACZ,IAAI,EAAE,WAAW,CAAC,OAAO;oBACzB,OAAO,EAAE,kBAAkB,WAAW,+CAA+C;oBACrF,OAAO,EAAE,CAAC,SAAS,CAAC;iBACrB,CAAC,CAAC;gBACH,SAAS;YACX,CAAC;YAED,8CAA8C;YAC9C,IAAI,WAAW,CAAC,WAAW,EAAE,CAAC;gBAC5B,MAAM,KAAK,GAAe;oBACxB,EAAE,EAAE,QAAQ,CAAC,iBAAiB,CAAC,UAAU,EAAE,SAAS,CAAC;oBACrD,IAAI,EAAE,iBAAiB,CAAC,UAAU;oBAClC,UAAU,EAAE,SAAS;oBACrB,OAAO,EAAE,IAAI;oBACb,WAAW,EAAE,WAAW,CAAC,WAAW;oBACpC,QAAQ,EAAE;wBACR,IAAI,EAAE,WAAW,CAAC,IAAI,IAAI,SAAS;qBACpC;iBACF,CAAC;gBACF,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACpB,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,QAAQ,CAAC,IAAI,CAAC;gBACZ,IAAI,EAAE,WAAW,CAAC,OAAO;gBACzB,OAAO,EAAE,kBAAkB,SAAS,KAAM,KAAe,CAAC,OAAO,EAAE;gBACnE,OAAO,EAAE,CAAC,SAAS,CAAC;aACrB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,4DAA4D;IAC5D,MAAM,WAAW,GAAG,MAAM,mBAAmB,CAAC,IAAI,CAAC,CAAC;IACpD,IAAI,WAAW,EAAE,CAAC;QAChB,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC1B,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;AAC7B,CAAC"}
package/dist/emit.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ import { type AgentCustomization, type EmitResult } from '@a16njs/models';
2
+ /**
3
+ * Emit agent customizations to Claude format.
4
+ * - GlobalPrompts → CLAUDE.md
5
+ * - FileRules → .a16n/rules/ + .claude/settings.local.json
6
+ * - AgentSkills → .claude/skills/ subdirectories
7
+ */
8
+ export declare function emit(models: AgentCustomization[], root: string): Promise<EmitResult>;
9
+ //# sourceMappingURL=emit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../src/emit.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,UAAU,EAWhB,MAAM,gBAAgB,CAAC;AAgGxB;;;;;GAKG;AACH,wBAAsB,IAAI,CACxB,MAAM,EAAE,kBAAkB,EAAE,EAC5B,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,UAAU,CAAC,CAsOrB"}
package/dist/emit.js ADDED
@@ -0,0 +1,292 @@
1
+ import * as fs from 'fs/promises';
2
+ import * as path from 'path';
3
+ import { CustomizationType, WarningCode, isGlobalPrompt, isFileRule, isAgentSkill, isAgentIgnore, } from '@a16njs/models';
4
+ /**
5
+ * Convert a gitignore-style pattern to a Claude Read() permission rule.
6
+ * Returns null for patterns that cannot be converted (e.g., negation patterns).
7
+ */
8
+ function convertPatternToReadRule(pattern) {
9
+ // Negation patterns cannot be converted to deny rules
10
+ // (they would need to REMOVE entries from deny, not add them)
11
+ if (pattern.startsWith('!')) {
12
+ return null;
13
+ }
14
+ // Directory pattern: dist/ → Read(./dist/**)
15
+ if (pattern.endsWith('/')) {
16
+ return `Read(./${pattern}**)`;
17
+ }
18
+ // Glob pattern: *.log → Read(./**/*.log)
19
+ if (pattern.startsWith('*') && !pattern.startsWith('**')) {
20
+ return `Read(./**/${pattern})`;
21
+ }
22
+ // Already has **: **/*.tmp → Read(./**/*.tmp)
23
+ if (pattern.startsWith('**')) {
24
+ return `Read(./${pattern})`;
25
+ }
26
+ // Simple file: .env → Read(./.env)
27
+ return `Read(./${pattern})`;
28
+ }
29
+ /**
30
+ * Sanitize a filename from a source path.
31
+ * Extracts base name and makes it filesystem-safe.
32
+ */
33
+ function sanitizeFilename(sourcePath) {
34
+ const basename = path.basename(sourcePath);
35
+ const nameWithoutExt = basename.replace(/\.[^.]+$/, '');
36
+ const sanitized = nameWithoutExt
37
+ .toLowerCase()
38
+ .replace(/[^a-z0-9]+/g, '-')
39
+ .replace(/^-+|-+$/g, '');
40
+ return sanitized || 'rule';
41
+ }
42
+ /**
43
+ * Escape a string for safe use in double-quoted shell arguments.
44
+ * Escapes: backslash, double quote, dollar sign, backtick.
45
+ */
46
+ function escapeShellArg(str) {
47
+ return str.replace(/[\\"`$]/g, '\\$&');
48
+ }
49
+ /**
50
+ * Build hook configuration for a FileRule.
51
+ */
52
+ function buildHookConfig(fileRule, rulePath) {
53
+ // Escape globs and rulePath to prevent command injection
54
+ const escapedGlobs = fileRule.globs.map(g => escapeShellArg(g));
55
+ const globsArg = escapedGlobs.join(',');
56
+ const escapedRulePath = escapeShellArg(rulePath);
57
+ return {
58
+ matcher: 'Read|Write|Edit',
59
+ hooks: [{
60
+ type: 'command',
61
+ command: `npx @a16njs/glob-hook --globs "${globsArg}" --context-file "${escapedRulePath}"`,
62
+ }],
63
+ };
64
+ }
65
+ /**
66
+ * Format a skill file with YAML frontmatter.
67
+ * Name and description are quoted to handle YAML special characters.
68
+ */
69
+ function formatSkill(skill) {
70
+ // Quote values to handle YAML special characters (: # { } etc.)
71
+ const safeDescription = JSON.stringify(skill.description);
72
+ const skillName = skill.metadata?.name;
73
+ // Include name in frontmatter if available
74
+ if (skillName) {
75
+ const safeName = JSON.stringify(skillName);
76
+ return `---
77
+ name: ${safeName}
78
+ description: ${safeDescription}
79
+ ---
80
+
81
+ ${skill.content}
82
+ `;
83
+ }
84
+ return `---
85
+ description: ${safeDescription}
86
+ ---
87
+
88
+ ${skill.content}
89
+ `;
90
+ }
91
+ /**
92
+ * Emit agent customizations to Claude format.
93
+ * - GlobalPrompts → CLAUDE.md
94
+ * - FileRules → .a16n/rules/ + .claude/settings.local.json
95
+ * - AgentSkills → .claude/skills/ subdirectories
96
+ */
97
+ export async function emit(models, root) {
98
+ const written = [];
99
+ const warnings = [];
100
+ const unsupported = [];
101
+ // Separate by type
102
+ const globalPrompts = models.filter(isGlobalPrompt);
103
+ const fileRules = models.filter(isFileRule);
104
+ const agentSkills = models.filter(isAgentSkill);
105
+ const agentIgnores = models.filter(isAgentIgnore);
106
+ // Track unsupported types (future types)
107
+ for (const model of models) {
108
+ if (!isGlobalPrompt(model) && !isFileRule(model) && !isAgentSkill(model) && !isAgentIgnore(model)) {
109
+ unsupported.push(model);
110
+ }
111
+ }
112
+ // === Emit GlobalPrompts as CLAUDE.md ===
113
+ if (globalPrompts.length > 0) {
114
+ const sections = globalPrompts.map((gp) => {
115
+ const header = `## From: ${gp.sourcePath}`;
116
+ return `${header}\n\n${gp.content}`;
117
+ });
118
+ const content = sections.join('\n\n---\n\n');
119
+ const claudePath = path.join(root, 'CLAUDE.md');
120
+ await fs.writeFile(claudePath, content, 'utf-8');
121
+ written.push({
122
+ path: claudePath,
123
+ type: CustomizationType.GlobalPrompt,
124
+ itemCount: globalPrompts.length,
125
+ });
126
+ if (globalPrompts.length > 1) {
127
+ warnings.push({
128
+ code: WarningCode.Merged,
129
+ message: `Merged ${globalPrompts.length} items into single CLAUDE.md`,
130
+ sources: globalPrompts.map((gp) => gp.sourcePath),
131
+ });
132
+ }
133
+ }
134
+ // === Emit FileRules as .a16n/rules/*.txt + .claude/settings.local.json ===
135
+ if (fileRules.length > 0) {
136
+ // Create .a16n/rules directory
137
+ const rulesDir = path.join(root, '.a16n', 'rules');
138
+ await fs.mkdir(rulesDir, { recursive: true });
139
+ // Create .claude directory for settings
140
+ const claudeDir = path.join(root, '.claude');
141
+ await fs.mkdir(claudeDir, { recursive: true });
142
+ const hooks = [];
143
+ const usedFilenames = new Set();
144
+ for (const rule of fileRules) {
145
+ // Get unique filename to avoid collisions
146
+ let baseName = sanitizeFilename(rule.sourcePath);
147
+ let filename = baseName + '.txt';
148
+ let counter = 1;
149
+ while (usedFilenames.has(filename)) {
150
+ filename = `${baseName}-${counter}.txt`;
151
+ counter++;
152
+ }
153
+ usedFilenames.add(filename);
154
+ const rulePath = `.a16n/rules/${filename}`;
155
+ const fullPath = path.join(root, rulePath);
156
+ // Write rule content
157
+ await fs.writeFile(fullPath, rule.content, 'utf-8');
158
+ written.push({
159
+ path: fullPath,
160
+ type: CustomizationType.FileRule,
161
+ itemCount: 1,
162
+ });
163
+ // Build hook for this rule
164
+ hooks.push(buildHookConfig(rule, rulePath));
165
+ }
166
+ // Write settings.local.json, merging with existing content if present
167
+ const settingsPath = path.join(claudeDir, 'settings.local.json');
168
+ let settings = { hooks: { PreToolUse: hooks } };
169
+ try {
170
+ const existingContent = await fs.readFile(settingsPath, 'utf-8');
171
+ const existing = JSON.parse(existingContent);
172
+ const existingHooks = existing.hooks;
173
+ const existingPreToolUse = Array.isArray(existingHooks?.PreToolUse)
174
+ ? existingHooks.PreToolUse
175
+ : [];
176
+ // Merge: preserve existing settings, append new PreToolUse hooks
177
+ settings = {
178
+ ...existing,
179
+ hooks: {
180
+ ...existingHooks,
181
+ PreToolUse: [...existingPreToolUse, ...hooks],
182
+ },
183
+ };
184
+ }
185
+ catch (err) {
186
+ // File doesn't exist or isn't valid JSON - use fresh settings
187
+ if (err.code !== 'ENOENT') {
188
+ // Only warn if it's not a "file not found" error
189
+ warnings.push({
190
+ code: WarningCode.Skipped,
191
+ message: `Could not parse existing settings.local.json, overwriting: ${err.message}`,
192
+ sources: [settingsPath],
193
+ });
194
+ }
195
+ }
196
+ await fs.writeFile(settingsPath, JSON.stringify(settings, null, 2), 'utf-8');
197
+ written.push({
198
+ path: settingsPath,
199
+ type: CustomizationType.FileRule,
200
+ itemCount: fileRules.length,
201
+ });
202
+ // Emit approximation warning
203
+ warnings.push({
204
+ code: WarningCode.Approximated,
205
+ message: `FileRule approximated via @a16njs/glob-hook (behavior may differ slightly)`,
206
+ sources: fileRules.map((r) => r.sourcePath),
207
+ });
208
+ }
209
+ // === Emit AgentSkills as .claude/skills/*/SKILL.md ===
210
+ if (agentSkills.length > 0) {
211
+ const usedSkillNames = new Set();
212
+ for (const skill of agentSkills) {
213
+ // Get unique skill name to avoid directory collisions
214
+ let baseName = sanitizeFilename(skill.sourcePath);
215
+ let skillName = baseName;
216
+ let counter = 1;
217
+ while (usedSkillNames.has(skillName)) {
218
+ skillName = `${baseName}-${counter}`;
219
+ counter++;
220
+ }
221
+ usedSkillNames.add(skillName);
222
+ const skillDir = path.join(root, '.claude', 'skills', skillName);
223
+ await fs.mkdir(skillDir, { recursive: true });
224
+ const skillPath = path.join(skillDir, 'SKILL.md');
225
+ const content = formatSkill(skill);
226
+ await fs.writeFile(skillPath, content, 'utf-8');
227
+ written.push({
228
+ path: skillPath,
229
+ type: CustomizationType.AgentSkill,
230
+ itemCount: 1,
231
+ });
232
+ }
233
+ }
234
+ // === Emit AgentIgnores as .claude/settings.json permissions.deny ===
235
+ if (agentIgnores.length > 0) {
236
+ const allPatterns = agentIgnores.flatMap(ai => ai.patterns);
237
+ const negationPatterns = allPatterns.filter(p => p.startsWith('!'));
238
+ const convertiblePatterns = allPatterns.filter(p => !p.startsWith('!'));
239
+ const denyRules = convertiblePatterns
240
+ .map(convertPatternToReadRule)
241
+ .filter((rule) => rule !== null);
242
+ // Warn about skipped negation patterns
243
+ if (negationPatterns.length > 0) {
244
+ warnings.push({
245
+ code: WarningCode.Skipped,
246
+ message: `Negation patterns cannot be converted to permissions.deny (skipped ${negationPatterns.length} pattern${negationPatterns.length > 1 ? 's' : ''}: ${negationPatterns.join(', ')})`,
247
+ sources: agentIgnores.map(ai => ai.sourcePath),
248
+ });
249
+ }
250
+ const claudeDir = path.join(root, '.claude');
251
+ await fs.mkdir(claudeDir, { recursive: true });
252
+ const settingsPath = path.join(claudeDir, 'settings.json');
253
+ let settings = {};
254
+ try {
255
+ const existing = await fs.readFile(settingsPath, 'utf-8');
256
+ settings = JSON.parse(existing);
257
+ }
258
+ catch (err) {
259
+ if (err.code !== 'ENOENT') {
260
+ // File exists but is malformed - warn and proceed with fresh settings
261
+ warnings.push({
262
+ code: WarningCode.Skipped,
263
+ message: `Could not parse existing settings.json, overwriting: ${err.message}`,
264
+ sources: [settingsPath],
265
+ });
266
+ }
267
+ // File doesn't exist or is malformed - use empty settings
268
+ }
269
+ // Merge deny rules (deduplicate)
270
+ const existingPermissions = settings.permissions;
271
+ const existingDeny = Array.isArray(existingPermissions?.deny)
272
+ ? existingPermissions.deny
273
+ : [];
274
+ settings.permissions = {
275
+ ...existingPermissions,
276
+ deny: [...new Set([...existingDeny, ...denyRules])],
277
+ };
278
+ await fs.writeFile(settingsPath, JSON.stringify(settings, null, 2), 'utf-8');
279
+ written.push({
280
+ path: settingsPath,
281
+ type: CustomizationType.AgentIgnore,
282
+ itemCount: agentIgnores.length,
283
+ });
284
+ warnings.push({
285
+ code: WarningCode.Approximated,
286
+ message: `AgentIgnore approximated as permissions.deny (behavior may differ slightly)`,
287
+ sources: agentIgnores.map(ai => ai.sourcePath),
288
+ });
289
+ }
290
+ return { written, warnings, unsupported };
291
+ }
292
+ //# sourceMappingURL=emit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emit.js","sourceRoot":"","sources":["../src/emit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { type A16nPlugin } from '@a16njs/models';
2
+ /**
3
+ * Claude Code plugin for a16n.
4
+ * Supports discovery and emission of Claude configuration.
5
+ */
6
+ declare const claudePlugin: A16nPlugin;
7
+ export default claudePlugin;
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAqB,MAAM,gBAAgB,CAAC;AAIpE;;;GAGG;AACH,QAAA,MAAM,YAAY,EAAE,UAWnB,CAAC;AAEF,eAAe,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,20 @@
1
+ import { CustomizationType } from '@a16njs/models';
2
+ import { discover } from './discover.js';
3
+ import { emit } from './emit.js';
4
+ /**
5
+ * Claude Code plugin for a16n.
6
+ * Supports discovery and emission of Claude configuration.
7
+ */
8
+ const claudePlugin = {
9
+ id: 'claude',
10
+ name: 'Claude Code',
11
+ supports: [
12
+ CustomizationType.GlobalPrompt,
13
+ CustomizationType.FileRule,
14
+ CustomizationType.AgentSkill,
15
+ ],
16
+ discover,
17
+ emit,
18
+ };
19
+ export default claudePlugin;
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACpE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC;;;GAGG;AACH,MAAM,YAAY,GAAe;IAC/B,EAAE,EAAE,QAAQ;IACZ,IAAI,EAAE,aAAa;IACnB,QAAQ,EAAE;QACR,iBAAiB,CAAC,YAAY;QAC9B,iBAAiB,CAAC,QAAQ;QAC1B,iBAAiB,CAAC,UAAU;KAC7B;IAED,QAAQ;IACR,IAAI;CACL,CAAC;AAEF,eAAe,YAAY,CAAC"}
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@a16njs/plugin-claude",
3
+ "version": "0.0.1",
4
+ "description": "Claude Code plugin for a16n",
5
+ "license": "AGPL-3.0",
6
+ "author": "Texarkanine",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/Texarkanine/a16n.git",
10
+ "directory": "packages/plugin-claude"
11
+ },
12
+ "homepage": "https://github.com/Texarkanine/a16n#readme",
13
+ "bugs": {
14
+ "url": "https://github.com/Texarkanine/a16n/issues"
15
+ },
16
+ "keywords": [
17
+ "a16n",
18
+ "plugin",
19
+ "claude",
20
+ "anthropic",
21
+ "claude-code"
22
+ ],
23
+ "type": "module",
24
+ "main": "./dist/index.js",
25
+ "types": "./dist/index.d.ts",
26
+ "exports": {
27
+ ".": {
28
+ "types": "./dist/index.d.ts",
29
+ "import": "./dist/index.js"
30
+ }
31
+ },
32
+ "files": ["dist"],
33
+ "scripts": {
34
+ "build": "tsc",
35
+ "clean": "rimraf dist *.tsbuildinfo",
36
+ "typecheck": "tsc --noEmit",
37
+ "test": "vitest run",
38
+ "test:watch": "vitest"
39
+ },
40
+ "dependencies": {
41
+ "@a16njs/models": "workspace:*"
42
+ },
43
+ "devDependencies": {
44
+ "@types/node": "^20.0.0",
45
+ "typescript": "^5.4.0",
46
+ "vitest": "^2.0.0"
47
+ }
48
+ }