nuxt-agent-md 0.2.0 → 0.4.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.
Files changed (3) hide show
  1. package/README.md +19 -25
  2. package/dist/cli.js +43 -9
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # nuxt-agent-md
2
2
 
3
- Generate `AGENTS.md` with Nuxt documentation for AI coding agents.
3
+ Generate `AGENTS.md` and `CLAUDE.md` with Nuxt documentation for AI coding agents (Cursor, Copilot, Claude Code, etc.).
4
4
 
5
- Inspired by [Vercel's blog post](https://vercel.com/blog/agents-md-outperforms-skills-in-our-agent-evals) showing that `AGENTS.md` with a documentation index achieves 100% success rate on agent evaluations.
5
+ Gives your AI assistant instant access to accurate Nuxt API references, reducing hallucinations and improving code quality.
6
6
 
7
7
  ## Usage
8
8
 
@@ -18,9 +18,16 @@ nuxt-agent-md
18
18
  ## What it does
19
19
 
20
20
  1. Detects your Nuxt version from `package.json`
21
- 2. Downloads the corresponding `@nuxt/docs` documentation
22
- 3. Generates a minified index of all documentation files
23
- 4. Creates/updates `AGENTS.md` with the index and key Nuxt patterns
21
+ 2. Downloads the corresponding `@nuxt/docs` documentation (~1.5 MB)
22
+ 3. Generates a minified index (~20 KB) of all documentation files
23
+ 4. Creates/updates `AGENTS.md` with the index
24
+ 5. Creates `CLAUDE.md` that references `@AGENTS.md`
25
+
26
+ The index format is pipe-delimited for minimal token usage:
27
+
28
+ ```
29
+ CATEGORY|path/to/file.md|keyword1,keyword2,keyword3
30
+ ```
24
31
 
25
32
  ## Options
26
33
 
@@ -48,36 +55,23 @@ nuxt-agent-md --no-minify
48
55
 
49
56
  # Custom output paths
50
57
  nuxt-agent-md -d .docs -o CLAUDE.md
51
-
52
- # Preview changes without writing
53
- nuxt-agent-md --dry-run
54
58
  ```
55
59
 
56
60
  ## Output
57
61
 
58
62
  The tool generates:
59
63
 
60
- 1. `.nuxt-docs/` - Directory containing raw markdown documentation
61
- 2. `AGENTS.md` - File with minified index pointing to the docs
62
-
63
- The index format is pipe-delimited for minimal token usage:
64
-
65
- ```
66
- CATEGORY|path/to/file.md|keyword1,keyword2,keyword3
67
- ```
64
+ 1. `.nuxt-docs/` - Directory containing markdown documentation (auto-added to `.gitignore`)
65
+ 2. `AGENTS.md` - File with documentation index (wrapped in `<!-- BEGIN:nuxt-agent-rules -->` markers)
66
+ 3. `CLAUDE.md` - File that references `@AGENTS.md` for Claude Code/Cursor compatibility
68
67
 
69
- ## Why this approach?
68
+ ## Why?
70
69
 
71
- From Vercel's research:
70
+ AI coding agents work better when they have access to accurate documentation rather than relying on training data that may be outdated. By providing a compact index in `AGENTS.md`, the agent can quickly find and read the relevant documentation files for any Nuxt API.
72
71
 
73
- | Approach | Success Rate |
74
- |----------|--------------|
75
- | Baseline (no docs) | 53% |
76
- | Skills | 53% |
77
- | Skills with explicit instructions | 79% |
78
- | **AGENTS.md with docs index** | **100%** |
72
+ ## Credits
79
73
 
80
- The key insight: providing a compressed index in `AGENTS.md` that points to detailed documentation files gives agents immediate access to accurate API information without decision overhead.
74
+ Inspired by [Vercel's research](https://vercel.com/blog/agents-md-outperforms-skills-in-our-agent-evals) showing that documentation indexes in `AGENTS.md` significantly improve agent accuracy.
81
75
 
82
76
  ## License
83
77
 
package/dist/cli.js CHANGED
@@ -38,8 +38,10 @@ function mapToDocsVersion(nuxtVersion) {
38
38
 
39
39
  // src/download.ts
40
40
  import { spawnSync } from "node:child_process";
41
- import { existsSync as existsSync2, mkdirSync, rmSync, renameSync } from "node:fs";
41
+ import { existsSync as existsSync2, mkdirSync, rmSync, renameSync, readdirSync } from "node:fs";
42
42
  import { join as join2 } from "node:path";
43
+ var CLEANUP_FILES = ["LICENSE", "README.md", "package.json", ".navigation.yml"];
44
+ var CLEANUP_DIRS = ["bridge", "community", "migration"];
43
45
  async function downloadDocs(version, targetDir) {
44
46
  const tempDir = ".nuxt-docs-temp";
45
47
  if (existsSync2(targetDir))
@@ -63,6 +65,17 @@ async function downloadDocs(version, targetDir) {
63
65
  if (extract.status !== 0)
64
66
  throw new Error(extract.stderr);
65
67
  renameSync(join2(tempDir, "package"), targetDir);
68
+ for (const file of CLEANUP_FILES) {
69
+ const path = join2(targetDir, file);
70
+ if (existsSync2(path))
71
+ rmSync(path);
72
+ }
73
+ for (const item of readdirSync(targetDir)) {
74
+ const dirName = item.replace(/^\d+\./, "");
75
+ if (CLEANUP_DIRS.includes(dirName)) {
76
+ rmSync(join2(targetDir, item), { recursive: true });
77
+ }
78
+ }
66
79
  } finally {
67
80
  if (existsSync2(tempDir))
68
81
  rmSync(tempDir, { recursive: true });
@@ -70,7 +83,7 @@ async function downloadDocs(version, targetDir) {
70
83
  }
71
84
 
72
85
  // src/generate.ts
73
- import { readdirSync, readFileSync as readFileSync2, statSync } from "node:fs";
86
+ import { readdirSync as readdirSync2, readFileSync as readFileSync2, statSync } from "node:fs";
74
87
  import { join as join3, relative } from "node:path";
75
88
  async function generateIndex(docsDir) {
76
89
  const entries = [];
@@ -81,10 +94,11 @@ async function generateIndex(docsDir) {
81
94
  full: generateFullIndex(entries, docsDir)
82
95
  };
83
96
  }
97
+ var EXCLUDED_DIRS = ["bridge", "community"];
84
98
  function walkDir(dir, baseDir, entries) {
85
99
  let items;
86
100
  try {
87
- items = readdirSync(dir);
101
+ items = readdirSync2(dir);
88
102
  } catch {
89
103
  return;
90
104
  }
@@ -97,7 +111,8 @@ function walkDir(dir, baseDir, entries) {
97
111
  continue;
98
112
  }
99
113
  if (stat.isDirectory()) {
100
- if (!item.startsWith(".") && item !== "node_modules") {
114
+ const dirName = item.replace(/^\d+\./, "");
115
+ if (!item.startsWith(".") && item !== "node_modules" && !EXCLUDED_DIRS.includes(dirName)) {
101
116
  walkDir(fullPath, baseDir, entries);
102
117
  }
103
118
  } else if (item.endsWith(".md") && !item.startsWith(".")) {
@@ -186,7 +201,7 @@ function generateMinifiedIndex(entries, docsDir) {
186
201
  });
187
202
  const lines = [];
188
203
  for (const entry of sorted) {
189
- const keywords = entry.keywords.slice(0, 6).join(",");
204
+ const keywords = entry.keywords.slice(0, 5).join(",");
190
205
  lines.push(`${entry.category}|${docsDir}/${entry.path}|${keywords}`);
191
206
  }
192
207
  return lines.join(`
@@ -221,17 +236,23 @@ function generateFullIndex(entries, docsDir) {
221
236
  }
222
237
 
223
238
  // src/inject.ts
239
+ import { dirname, join as join4 } from "node:path";
224
240
  import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync } from "node:fs";
225
- var START_MARKER = "<!-- NUXT_DOCS_START -->";
226
- var END_MARKER = "<!-- NUXT_DOCS_END -->";
241
+ var START_MARKER = "<!-- BEGIN:nuxt-agent-rules -->";
242
+ var END_MARKER = "<!-- END:nuxt-agent-rules -->";
227
243
  async function injectAgentsMd(outputPath, index, nuxtVersion, docsDir, minify) {
228
244
  let content = "";
229
245
  if (existsSync3(outputPath)) {
230
246
  content = readFileSync3(outputPath, "utf-8");
231
247
  }
232
248
  const nuxtSection = generateNuxtSection(index, nuxtVersion, docsDir, minify);
249
+ const oldStartMarker = "<!-- NUXT_DOCS_START -->";
250
+ const oldEndMarker = "<!-- NUXT_DOCS_END -->";
233
251
  if (content.includes(START_MARKER) && content.includes(END_MARKER)) {
234
- const regex = new RegExp(`${START_MARKER}[\\s\\S]*${END_MARKER}`, "m");
252
+ const regex = new RegExp(`${escapeRegex(START_MARKER)}[\\s\\S]*${escapeRegex(END_MARKER)}`, "m");
253
+ content = content.replace(regex, nuxtSection);
254
+ } else if (content.includes(oldStartMarker) && content.includes(oldEndMarker)) {
255
+ const regex = new RegExp(`${escapeRegex(oldStartMarker)}[\\s\\S]*${escapeRegex(oldEndMarker)}`, "m");
235
256
  content = content.replace(regex, nuxtSection);
236
257
  } else if (content.length > 0) {
237
258
  content = content.trimEnd() + `
@@ -241,6 +262,18 @@ async function injectAgentsMd(outputPath, index, nuxtVersion, docsDir, minify) {
241
262
  content = generateFullAgentsMd(nuxtSection);
242
263
  }
243
264
  writeFileSync(outputPath, content);
265
+ generateClaudeMd(outputPath);
266
+ }
267
+ function escapeRegex(str) {
268
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
269
+ }
270
+ function generateClaudeMd(agentsMdPath) {
271
+ const dir = dirname(agentsMdPath);
272
+ const claudeMdPath = join4(dir, "CLAUDE.md");
273
+ const agentsMdFilename = agentsMdPath.split("/").pop() || "AGENTS.md";
274
+ const claudeMdContent = `@${agentsMdFilename}
275
+ `;
276
+ writeFileSync(claudeMdPath, claudeMdContent, "utf-8");
244
277
  }
245
278
  function generateNuxtSection(index, nuxtVersion, docsDir, minify) {
246
279
  const majorVersion = nuxtVersion.split(".")[0];
@@ -339,7 +372,8 @@ async function generateAgentsMd(options = {}) {
339
372
  if (updateGitignore(docsDir)) {
340
373
  console.log(`Added ${docsDir} to .gitignore`);
341
374
  }
342
- console.log(`Generated ${outputPath}`);
375
+ const claudeMdPath = outputPath.replace(/[^/]+$/, "CLAUDE.md");
376
+ console.log(`Generated ${outputPath} and ${claudeMdPath}`);
343
377
  }
344
378
 
345
379
  // src/cli.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-agent-md",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "Generate AGENTS.md with Nuxt documentation for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {