nuxt-agent-md 0.0.1-alpha.1 → 0.2.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/README.md +84 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +419 -0
- package/dist/detect.d.ts +2 -0
- package/dist/download.d.ts +1 -0
- package/dist/generate.d.ts +2 -0
- package/dist/index.d.ts +7 -0
- package/dist/inject.d.ts +2 -0
- package/dist/types.d.ts +18 -0
- package/package.json +38 -4
- package/index.js +0 -1
package/README.md
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# nuxt-agent-md
|
|
2
|
+
|
|
3
|
+
Generate `AGENTS.md` with Nuxt documentation for AI coding agents.
|
|
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.
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Run directly with bunx
|
|
11
|
+
bunx nuxt-agent-md
|
|
12
|
+
|
|
13
|
+
# Or install globally
|
|
14
|
+
bun add -g nuxt-agent-md
|
|
15
|
+
nuxt-agent-md
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## What it does
|
|
19
|
+
|
|
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
|
|
24
|
+
|
|
25
|
+
## Options
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
-d, --docs-dir <path> Directory to store docs (default: .nuxt-docs)
|
|
29
|
+
-o, --output <path> Output AGENTS.md path (default: AGENTS.md)
|
|
30
|
+
-v, --nuxt-version <ver> Nuxt docs version (auto-detected from package.json)
|
|
31
|
+
--minify Generate minified index (default: true)
|
|
32
|
+
--no-minify Generate full index instead of minified
|
|
33
|
+
--dry-run Show what would be done without making changes
|
|
34
|
+
-h, --help Show this help message
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Examples
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# Auto-detect Nuxt version from package.json
|
|
41
|
+
nuxt-agent-md
|
|
42
|
+
|
|
43
|
+
# Use specific Nuxt version
|
|
44
|
+
nuxt-agent-md -v 4.0.0
|
|
45
|
+
|
|
46
|
+
# Generate full (non-minified) index
|
|
47
|
+
nuxt-agent-md --no-minify
|
|
48
|
+
|
|
49
|
+
# Custom output paths
|
|
50
|
+
nuxt-agent-md -d .docs -o CLAUDE.md
|
|
51
|
+
|
|
52
|
+
# Preview changes without writing
|
|
53
|
+
nuxt-agent-md --dry-run
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Output
|
|
57
|
+
|
|
58
|
+
The tool generates:
|
|
59
|
+
|
|
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
|
+
```
|
|
68
|
+
|
|
69
|
+
## Why this approach?
|
|
70
|
+
|
|
71
|
+
From Vercel's research:
|
|
72
|
+
|
|
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%** |
|
|
79
|
+
|
|
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.
|
|
81
|
+
|
|
82
|
+
## License
|
|
83
|
+
|
|
84
|
+
MIT
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/cli.ts
|
|
4
|
+
import { parseArgs } from "node:util";
|
|
5
|
+
|
|
6
|
+
// src/index.ts
|
|
7
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync2, appendFileSync } from "node:fs";
|
|
8
|
+
|
|
9
|
+
// src/detect.ts
|
|
10
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
11
|
+
import { join } from "node:path";
|
|
12
|
+
async function detectNuxtVersion(cwd = process.cwd()) {
|
|
13
|
+
const packageJsonPath = join(cwd, "package.json");
|
|
14
|
+
if (!existsSync(packageJsonPath)) {
|
|
15
|
+
throw new Error("No package.json found. Run this command in a Nuxt project root.");
|
|
16
|
+
}
|
|
17
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
18
|
+
const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
|
|
19
|
+
const nuxtVersion = deps.nuxt;
|
|
20
|
+
if (!nuxtVersion) {
|
|
21
|
+
throw new Error("Nuxt is not installed in this project. Add nuxt to your dependencies.");
|
|
22
|
+
}
|
|
23
|
+
const cleanVersion = nuxtVersion.replace(/[\^~>=<]/g, "").split(" ")[0];
|
|
24
|
+
if (cleanVersion === "latest" || !cleanVersion.match(/^\d/)) {
|
|
25
|
+
return "4.0.0";
|
|
26
|
+
}
|
|
27
|
+
return cleanVersion;
|
|
28
|
+
}
|
|
29
|
+
function mapToDocsVersion(nuxtVersion) {
|
|
30
|
+
const major = parseInt(nuxtVersion.split(".")[0]);
|
|
31
|
+
if (major >= 4) {
|
|
32
|
+
return "4.3.0";
|
|
33
|
+
} else if (major === 3) {
|
|
34
|
+
return "3.21.0";
|
|
35
|
+
}
|
|
36
|
+
throw new Error(`Unsupported Nuxt version: ${nuxtVersion}. Only Nuxt 3.x and 4.x are supported.`);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// src/download.ts
|
|
40
|
+
import { spawnSync } from "node:child_process";
|
|
41
|
+
import { existsSync as existsSync2, mkdirSync, rmSync, renameSync } from "node:fs";
|
|
42
|
+
import { join as join2 } from "node:path";
|
|
43
|
+
async function downloadDocs(version, targetDir) {
|
|
44
|
+
const tempDir = ".nuxt-docs-temp";
|
|
45
|
+
if (existsSync2(targetDir))
|
|
46
|
+
rmSync(targetDir, { recursive: true });
|
|
47
|
+
if (existsSync2(tempDir))
|
|
48
|
+
rmSync(tempDir, { recursive: true });
|
|
49
|
+
mkdirSync(tempDir, { recursive: true });
|
|
50
|
+
try {
|
|
51
|
+
const pack = spawnSync("npm", ["pack", `@nuxt/docs@${version}`, "--pack-destination", tempDir], {
|
|
52
|
+
encoding: "utf-8"
|
|
53
|
+
});
|
|
54
|
+
if (pack.status !== 0)
|
|
55
|
+
throw new Error(pack.stderr);
|
|
56
|
+
const tarball = pack.stdout.trim().split(`
|
|
57
|
+
`).pop();
|
|
58
|
+
if (!tarball)
|
|
59
|
+
throw new Error("No tarball");
|
|
60
|
+
const extract = spawnSync("tar", ["-xf", join2(tempDir, tarball), "-C", tempDir], {
|
|
61
|
+
encoding: "utf-8"
|
|
62
|
+
});
|
|
63
|
+
if (extract.status !== 0)
|
|
64
|
+
throw new Error(extract.stderr);
|
|
65
|
+
renameSync(join2(tempDir, "package"), targetDir);
|
|
66
|
+
} finally {
|
|
67
|
+
if (existsSync2(tempDir))
|
|
68
|
+
rmSync(tempDir, { recursive: true });
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// src/generate.ts
|
|
73
|
+
import { readdirSync, readFileSync as readFileSync2, statSync } from "node:fs";
|
|
74
|
+
import { join as join3, relative } from "node:path";
|
|
75
|
+
async function generateIndex(docsDir) {
|
|
76
|
+
const entries = [];
|
|
77
|
+
walkDir(docsDir, docsDir, entries);
|
|
78
|
+
return {
|
|
79
|
+
entries,
|
|
80
|
+
minified: generateMinifiedIndex(entries, docsDir),
|
|
81
|
+
full: generateFullIndex(entries, docsDir)
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
function walkDir(dir, baseDir, entries) {
|
|
85
|
+
let items;
|
|
86
|
+
try {
|
|
87
|
+
items = readdirSync(dir);
|
|
88
|
+
} catch {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
for (const item of items) {
|
|
92
|
+
const fullPath = join3(dir, item);
|
|
93
|
+
let stat;
|
|
94
|
+
try {
|
|
95
|
+
stat = statSync(fullPath);
|
|
96
|
+
} catch {
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
if (stat.isDirectory()) {
|
|
100
|
+
if (!item.startsWith(".") && item !== "node_modules") {
|
|
101
|
+
walkDir(fullPath, baseDir, entries);
|
|
102
|
+
}
|
|
103
|
+
} else if (item.endsWith(".md") && !item.startsWith(".")) {
|
|
104
|
+
const relativePath = relative(baseDir, fullPath);
|
|
105
|
+
const content = readFileSync2(fullPath, "utf-8");
|
|
106
|
+
const pathParts = relativePath.split("/");
|
|
107
|
+
const category = pathParts[0].replace(/^\d+\./, "").toUpperCase().replace(/-/g, "_");
|
|
108
|
+
entries.push({
|
|
109
|
+
path: relativePath,
|
|
110
|
+
title: extractTitle(content),
|
|
111
|
+
keywords: extractKeywords(content, relativePath),
|
|
112
|
+
category
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function extractTitle(content) {
|
|
118
|
+
const frontmatterMatch = content.match(/^---\s*\n([\s\S]*?)\n---/);
|
|
119
|
+
if (frontmatterMatch) {
|
|
120
|
+
const titleMatch = frontmatterMatch[1].match(/^title:\s*['"]?([^'"\n]+)['"]?/m);
|
|
121
|
+
if (titleMatch) {
|
|
122
|
+
return titleMatch[1].trim();
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
const h1Match = content.match(/^#\s+(.+)$/m);
|
|
126
|
+
return h1Match ? h1Match[1].trim() : "";
|
|
127
|
+
}
|
|
128
|
+
function extractKeywords(content, path) {
|
|
129
|
+
const keywords = new Set;
|
|
130
|
+
const pathParts = path.replace(/\.md$/, "").split("/");
|
|
131
|
+
for (const part of pathParts) {
|
|
132
|
+
const clean = part.replace(/^\d+\./, "").replace(/-/g, " ");
|
|
133
|
+
if (clean.length > 2) {
|
|
134
|
+
keywords.add(clean);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
const codeMatches = content.match(/`([a-zA-Z$][a-zA-Z0-9$]*(?:\(\))?)`/g) || [];
|
|
138
|
+
for (const match of codeMatches) {
|
|
139
|
+
const clean = match.replace(/`/g, "").replace(/\(\)$/, "");
|
|
140
|
+
if (clean.length > 2 && !["true", "false", "null", "undefined", "string", "number", "boolean", "object", "array"].includes(clean.toLowerCase())) {
|
|
141
|
+
keywords.add(clean);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
const nuxtTerms = [
|
|
145
|
+
"useFetch",
|
|
146
|
+
"useAsyncData",
|
|
147
|
+
"useState",
|
|
148
|
+
"useCookie",
|
|
149
|
+
"useRuntimeConfig",
|
|
150
|
+
"useRoute",
|
|
151
|
+
"useRouter",
|
|
152
|
+
"useHead",
|
|
153
|
+
"useSeoMeta",
|
|
154
|
+
"useNuxtApp",
|
|
155
|
+
"definePageMeta",
|
|
156
|
+
"defineNuxtConfig",
|
|
157
|
+
"defineEventHandler",
|
|
158
|
+
"defineNuxtPlugin",
|
|
159
|
+
"defineNuxtRouteMiddleware",
|
|
160
|
+
"defineNuxtModule",
|
|
161
|
+
"NuxtLink",
|
|
162
|
+
"NuxtPage",
|
|
163
|
+
"NuxtLayout",
|
|
164
|
+
"ClientOnly",
|
|
165
|
+
"navigateTo",
|
|
166
|
+
"abortNavigation",
|
|
167
|
+
"createError",
|
|
168
|
+
"$fetch",
|
|
169
|
+
"nitro",
|
|
170
|
+
"h3",
|
|
171
|
+
"server/api",
|
|
172
|
+
"server/middleware"
|
|
173
|
+
];
|
|
174
|
+
for (const term of nuxtTerms) {
|
|
175
|
+
if (content.includes(term)) {
|
|
176
|
+
keywords.add(term);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return [...keywords].slice(0, 15);
|
|
180
|
+
}
|
|
181
|
+
function generateMinifiedIndex(entries, docsDir) {
|
|
182
|
+
const sorted = [...entries].sort((a, b) => {
|
|
183
|
+
if (a.category !== b.category)
|
|
184
|
+
return a.category.localeCompare(b.category);
|
|
185
|
+
return a.path.localeCompare(b.path);
|
|
186
|
+
});
|
|
187
|
+
const lines = [];
|
|
188
|
+
for (const entry of sorted) {
|
|
189
|
+
const keywords = entry.keywords.slice(0, 6).join(",");
|
|
190
|
+
lines.push(`${entry.category}|${docsDir}/${entry.path}|${keywords}`);
|
|
191
|
+
}
|
|
192
|
+
return lines.join(`
|
|
193
|
+
`);
|
|
194
|
+
}
|
|
195
|
+
function generateFullIndex(entries, docsDir) {
|
|
196
|
+
const categories = new Map;
|
|
197
|
+
for (const entry of entries) {
|
|
198
|
+
if (!categories.has(entry.category)) {
|
|
199
|
+
categories.set(entry.category, []);
|
|
200
|
+
}
|
|
201
|
+
categories.get(entry.category).push(entry);
|
|
202
|
+
}
|
|
203
|
+
let output = "";
|
|
204
|
+
const sortedCategories = [...categories.entries()].sort((a, b) => a[0].localeCompare(b[0]));
|
|
205
|
+
for (const [category, files] of sortedCategories) {
|
|
206
|
+
output += `
|
|
207
|
+
### ${category.toLowerCase().replace(/_/g, " ")}
|
|
208
|
+
`;
|
|
209
|
+
const sortedFiles = [...files].sort((a, b) => a.path.localeCompare(b.path));
|
|
210
|
+
for (const file of sortedFiles) {
|
|
211
|
+
const title = file.title || file.path.split("/").pop()?.replace(/\.md$/, "") || file.path;
|
|
212
|
+
output += `- [${title}](${docsDir}/${file.path})`;
|
|
213
|
+
if (file.keywords.length > 0) {
|
|
214
|
+
output += ` - \`${file.keywords.slice(0, 5).join("`, `")}\``;
|
|
215
|
+
}
|
|
216
|
+
output += `
|
|
217
|
+
`;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return output;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// src/inject.ts
|
|
224
|
+
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 -->";
|
|
227
|
+
async function injectAgentsMd(outputPath, index, nuxtVersion, docsDir, minify) {
|
|
228
|
+
let content = "";
|
|
229
|
+
if (existsSync3(outputPath)) {
|
|
230
|
+
content = readFileSync3(outputPath, "utf-8");
|
|
231
|
+
}
|
|
232
|
+
const nuxtSection = generateNuxtSection(index, nuxtVersion, docsDir, minify);
|
|
233
|
+
if (content.includes(START_MARKER) && content.includes(END_MARKER)) {
|
|
234
|
+
const regex = new RegExp(`${START_MARKER}[\\s\\S]*${END_MARKER}`, "m");
|
|
235
|
+
content = content.replace(regex, nuxtSection);
|
|
236
|
+
} else if (content.length > 0) {
|
|
237
|
+
content = content.trimEnd() + `
|
|
238
|
+
|
|
239
|
+
` + nuxtSection;
|
|
240
|
+
} else {
|
|
241
|
+
content = generateFullAgentsMd(nuxtSection);
|
|
242
|
+
}
|
|
243
|
+
writeFileSync(outputPath, content);
|
|
244
|
+
}
|
|
245
|
+
function generateNuxtSection(index, nuxtVersion, docsDir, minify) {
|
|
246
|
+
const majorVersion = nuxtVersion.split(".")[0];
|
|
247
|
+
return `${START_MARKER}
|
|
248
|
+
## Nuxt Documentation
|
|
249
|
+
|
|
250
|
+
This project uses **Nuxt ${majorVersion}** (v${nuxtVersion}).
|
|
251
|
+
|
|
252
|
+
When working with Nuxt APIs, ALWAYS read the referenced documentation files before making changes.
|
|
253
|
+
|
|
254
|
+
### Quick Reference Index
|
|
255
|
+
|
|
256
|
+
\`\`\`
|
|
257
|
+
${minify ? index.minified : index.full}
|
|
258
|
+
\`\`\`
|
|
259
|
+
|
|
260
|
+
### Key Nuxt ${majorVersion} Patterns
|
|
261
|
+
|
|
262
|
+
#### Data Fetching
|
|
263
|
+
- Use \`useFetch\` for component-level data fetching (auto-deduped, SSR-safe)
|
|
264
|
+
- Use \`useAsyncData\` when you need more control over the key/handler
|
|
265
|
+
- Use \`$fetch\` in event handlers and server routes (NOT in setup for SSR)
|
|
266
|
+
- Always handle \`pending\` and \`error\` states
|
|
267
|
+
|
|
268
|
+
#### Server Routes
|
|
269
|
+
- Files in \`server/api/\` become API endpoints
|
|
270
|
+
- Use \`defineEventHandler\` for all handlers
|
|
271
|
+
- Access body with \`readBody(event)\`
|
|
272
|
+
- Access query with \`getQuery(event)\`
|
|
273
|
+
- Access params with \`event.context.params\`
|
|
274
|
+
|
|
275
|
+
#### State Management
|
|
276
|
+
- Use \`useState\` for SSR-friendly reactive state
|
|
277
|
+
- Use \`useCookie\` for cookie-based state
|
|
278
|
+
- Use \`useRuntimeConfig\` for environment variables
|
|
279
|
+
|
|
280
|
+
#### Routing & Navigation
|
|
281
|
+
- Use \`definePageMeta\` for page-level config
|
|
282
|
+
- Use \`navigateTo\` for programmatic navigation
|
|
283
|
+
- Use \`useRoute\` and \`useRouter\` for route info
|
|
284
|
+
|
|
285
|
+
#### Configuration
|
|
286
|
+
- \`nuxt.config.ts\` for build-time config
|
|
287
|
+
- \`runtimeConfig\` for environment variables (private/public)
|
|
288
|
+
- \`app.config.ts\` for public runtime config
|
|
289
|
+
|
|
290
|
+
${END_MARKER}`;
|
|
291
|
+
}
|
|
292
|
+
function generateFullAgentsMd(nuxtSection) {
|
|
293
|
+
return `# AGENTS.md
|
|
294
|
+
|
|
295
|
+
This file provides documentation references for AI coding agents.
|
|
296
|
+
|
|
297
|
+
${nuxtSection}
|
|
298
|
+
`;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// src/index.ts
|
|
302
|
+
function updateGitignore(entry) {
|
|
303
|
+
const path = ".gitignore";
|
|
304
|
+
if (!existsSync4(path)) {
|
|
305
|
+
writeFileSync2(path, entry + `
|
|
306
|
+
`);
|
|
307
|
+
return true;
|
|
308
|
+
}
|
|
309
|
+
const content = readFileSync4(path, "utf-8");
|
|
310
|
+
if (content.split(`
|
|
311
|
+
`).some((l) => l.trim() === entry))
|
|
312
|
+
return false;
|
|
313
|
+
appendFileSync(path, (content.endsWith(`
|
|
314
|
+
`) ? "" : `
|
|
315
|
+
`) + entry + `
|
|
316
|
+
`);
|
|
317
|
+
return true;
|
|
318
|
+
}
|
|
319
|
+
async function generateAgentsMd(options = {}) {
|
|
320
|
+
const {
|
|
321
|
+
docsDir = ".nuxt-docs",
|
|
322
|
+
outputPath = "AGENTS.md",
|
|
323
|
+
nuxtVersion,
|
|
324
|
+
minify = true,
|
|
325
|
+
dryRun = false
|
|
326
|
+
} = options;
|
|
327
|
+
const version = nuxtVersion || await detectNuxtVersion();
|
|
328
|
+
const docsVersion = mapToDocsVersion(version);
|
|
329
|
+
if (dryRun) {
|
|
330
|
+
console.log(`[dry-run] Would download @nuxt/docs@${docsVersion} to ${docsDir}`);
|
|
331
|
+
console.log(`[dry-run] Would generate index and inject into ${outputPath}`);
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
console.log(`Downloading @nuxt/docs@${docsVersion}...`);
|
|
335
|
+
await downloadDocs(docsVersion, docsDir);
|
|
336
|
+
const index = await generateIndex(docsDir);
|
|
337
|
+
console.log(`Indexed ${index.entries.length} files`);
|
|
338
|
+
await injectAgentsMd(outputPath, index, version, docsDir, minify);
|
|
339
|
+
if (updateGitignore(docsDir)) {
|
|
340
|
+
console.log(`Added ${docsDir} to .gitignore`);
|
|
341
|
+
}
|
|
342
|
+
console.log(`Generated ${outputPath}`);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// src/cli.ts
|
|
346
|
+
var { values } = parseArgs({
|
|
347
|
+
args: process.argv.slice(2),
|
|
348
|
+
options: {
|
|
349
|
+
"docs-dir": {
|
|
350
|
+
type: "string",
|
|
351
|
+
short: "d",
|
|
352
|
+
default: ".nuxt-docs"
|
|
353
|
+
},
|
|
354
|
+
output: {
|
|
355
|
+
type: "string",
|
|
356
|
+
short: "o",
|
|
357
|
+
default: "AGENTS.md"
|
|
358
|
+
},
|
|
359
|
+
"nuxt-version": {
|
|
360
|
+
type: "string",
|
|
361
|
+
short: "v"
|
|
362
|
+
},
|
|
363
|
+
minify: {
|
|
364
|
+
type: "boolean",
|
|
365
|
+
default: true
|
|
366
|
+
},
|
|
367
|
+
"no-minify": {
|
|
368
|
+
type: "boolean",
|
|
369
|
+
default: false
|
|
370
|
+
},
|
|
371
|
+
"dry-run": {
|
|
372
|
+
type: "boolean",
|
|
373
|
+
default: false
|
|
374
|
+
},
|
|
375
|
+
help: {
|
|
376
|
+
type: "boolean",
|
|
377
|
+
short: "h",
|
|
378
|
+
default: false
|
|
379
|
+
}
|
|
380
|
+
},
|
|
381
|
+
strict: true,
|
|
382
|
+
allowPositionals: false
|
|
383
|
+
});
|
|
384
|
+
if (values.help) {
|
|
385
|
+
console.log(`
|
|
386
|
+
nuxt-agent-md - Generate AGENTS.md with Nuxt documentation for AI coding agents
|
|
387
|
+
|
|
388
|
+
Usage:
|
|
389
|
+
nuxt-agent-md [options]
|
|
390
|
+
|
|
391
|
+
Options:
|
|
392
|
+
-d, --docs-dir <path> Directory to store docs (default: .nuxt-docs)
|
|
393
|
+
-o, --output <path> Output AGENTS.md path (default: AGENTS.md)
|
|
394
|
+
-v, --nuxt-version <ver> Nuxt docs version (auto-detected from package.json)
|
|
395
|
+
--minify Generate minified index (default: true)
|
|
396
|
+
--no-minify Generate full index instead of minified
|
|
397
|
+
--dry-run Show what would be done without making changes
|
|
398
|
+
-h, --help Show this help message
|
|
399
|
+
|
|
400
|
+
Examples:
|
|
401
|
+
nuxt-agent-md # Auto-detect Nuxt version
|
|
402
|
+
nuxt-agent-md -v 4.0.0 # Use specific version
|
|
403
|
+
nuxt-agent-md --no-minify # Generate full index
|
|
404
|
+
nuxt-agent-md -d .docs -o CLAUDE.md # Custom paths
|
|
405
|
+
`);
|
|
406
|
+
process.exit(0);
|
|
407
|
+
}
|
|
408
|
+
try {
|
|
409
|
+
await generateAgentsMd({
|
|
410
|
+
docsDir: values["docs-dir"],
|
|
411
|
+
outputPath: values.output,
|
|
412
|
+
nuxtVersion: values["nuxt-version"],
|
|
413
|
+
minify: values["no-minify"] ? false : values.minify,
|
|
414
|
+
dryRun: values["dry-run"]
|
|
415
|
+
});
|
|
416
|
+
} catch (error) {
|
|
417
|
+
console.error(`Error: ${error instanceof Error ? error.message : error}`);
|
|
418
|
+
process.exit(1);
|
|
419
|
+
}
|
package/dist/detect.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function downloadDocs(version: string, targetDir: string): Promise<void>;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Options } from './types';
|
|
2
|
+
export { detectNuxtVersion, mapToDocsVersion } from './detect';
|
|
3
|
+
export { downloadDocs } from './download';
|
|
4
|
+
export { generateIndex } from './generate';
|
|
5
|
+
export { injectAgentsMd } from './inject';
|
|
6
|
+
export type * from './types';
|
|
7
|
+
export declare function generateAgentsMd(options?: Partial<Options>): Promise<void>;
|
package/dist/inject.d.ts
ADDED
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface Options {
|
|
2
|
+
docsDir: string;
|
|
3
|
+
outputPath: string;
|
|
4
|
+
nuxtVersion?: string;
|
|
5
|
+
minify: boolean;
|
|
6
|
+
dryRun: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface DocEntry {
|
|
9
|
+
path: string;
|
|
10
|
+
title: string;
|
|
11
|
+
keywords: string[];
|
|
12
|
+
category: string;
|
|
13
|
+
}
|
|
14
|
+
export interface IndexResult {
|
|
15
|
+
entries: DocEntry[];
|
|
16
|
+
minified: string;
|
|
17
|
+
full: string;
|
|
18
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,41 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuxt-agent-md",
|
|
3
|
-
"version": "0.0
|
|
4
|
-
"description": "
|
|
5
|
-
"
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Generate AGENTS.md with Nuxt documentation for AI coding agents",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"nuxt-agent-md": "./dist/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "bun build ./src/cli.ts --outdir ./dist --target node && bun run build:types",
|
|
21
|
+
"build:types": "tsc --emitDeclarationOnly",
|
|
22
|
+
"dev": "bun run ./src/cli.ts",
|
|
23
|
+
"typecheck": "tsc --noEmit",
|
|
24
|
+
"prepublishOnly": "bun run build"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@types/bun": "^1.2.0",
|
|
28
|
+
"@types/node": "^22.0.0",
|
|
29
|
+
"typescript": "^5.7.3"
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"nuxt",
|
|
33
|
+
"agents",
|
|
34
|
+
"ai",
|
|
35
|
+
"documentation",
|
|
36
|
+
"cursor",
|
|
37
|
+
"copilot",
|
|
38
|
+
"claude"
|
|
39
|
+
],
|
|
6
40
|
"license": "MIT"
|
|
7
|
-
}
|
|
41
|
+
}
|
package/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
// placeholder
|