@damenor/agent-docs 0.1.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 (44) hide show
  1. package/README.md +115 -0
  2. package/dist/index.js +568 -0
  3. package/package.json +53 -0
  4. package/templates/base/AGENTS.md +177 -0
  5. package/templates/base/CHANGELOG.md +86 -0
  6. package/templates/base/README.md +110 -0
  7. package/templates/base/docs/CONTEXT.md +111 -0
  8. package/templates/base/docs/README.md +131 -0
  9. package/templates/base/docs/adr/TEMPLATE.md +83 -0
  10. package/templates/modules/agents/.agents/agents/doc-designer.md +56 -0
  11. package/templates/modules/agents/.agents/agents/doc-maintainer.md +54 -0
  12. package/templates/modules/agents/.agents/agents/doc-reviewer.md +80 -0
  13. package/templates/modules/agents/.agents/agents/doc-writer.md +66 -0
  14. package/templates/modules/agents/.agents/agents/reviewer.md +138 -0
  15. package/templates/modules/agents/.agents/skills/doc-design/SKILL.md +359 -0
  16. package/templates/modules/agents/.agents/skills/doc-design/references/design-system-format.md +550 -0
  17. package/templates/modules/agents/.agents/skills/doc-maintain/SKILL.md +345 -0
  18. package/templates/modules/agents/.agents/skills/doc-maintain/references/triggers.md +311 -0
  19. package/templates/modules/agents/.agents/skills/doc-review/SKILL.md +324 -0
  20. package/templates/modules/agents/.agents/skills/doc-review/references/health-checklist.md +290 -0
  21. package/templates/modules/agents/.agents/skills/doc-scaffold/SKILL.md +277 -0
  22. package/templates/modules/agents/.agents/skills/doc-scaffold/references/diataxis-quick-ref.md +149 -0
  23. package/templates/modules/agents/.agents/skills/doc-write/SKILL.md +414 -0
  24. package/templates/modules/agents/.agents/skills/doc-write/references/adr-format.md +194 -0
  25. package/templates/modules/agents/.agents/skills/doc-write/references/diataxis-patterns.md +351 -0
  26. package/templates/modules/ci/.github/workflows/docs-check.yml +94 -0
  27. package/templates/modules/design/docs/DESIGN.md +253 -0
  28. package/templates/modules/explanation/docs/explanation/agent-flow.md +15 -0
  29. package/templates/modules/explanation/docs/explanation/architecture.md +138 -0
  30. package/templates/modules/guides/docs/guides/deployment.md +189 -0
  31. package/templates/modules/guides/docs/guides/runbooks/TEMPLATE.md +86 -0
  32. package/templates/modules/guides/docs/guides/troubleshooting.md +65 -0
  33. package/templates/modules/operations/docs/operations/README.md +115 -0
  34. package/templates/modules/product/docs/product/overview.md +90 -0
  35. package/templates/modules/product/docs/roadmap.md +80 -0
  36. package/templates/modules/reference/docs/reference/api.md +131 -0
  37. package/templates/modules/reference/docs/reference/code-style.md +275 -0
  38. package/templates/modules/reference/docs/reference/configuration.md +117 -0
  39. package/templates/modules/reference/docs/reference/infrastructure.md +191 -0
  40. package/templates/modules/tutorials/docs/tutorials/environment-setup.md +212 -0
  41. package/templates/modules/tutorials/docs/tutorials/first-task.md +246 -0
  42. package/templates/modules/tutorials/docs/tutorials/quick-start.md +146 -0
  43. package/templates/shared/.editorconfig +20 -0
  44. package/templates/shared/.markdownlint.json +14 -0
package/README.md ADDED
@@ -0,0 +1,115 @@
1
+ <h1 align="center">
2
+ <img src="https://img.shields.io/badge/agents-docs-blueviolet?style=for-the-badge" alt="agent-docs">
3
+ <br>
4
+ @damenor/agent-docs
5
+ </h1>
6
+
7
+ <p align="center">
8
+ <strong>Documentación profesional para proyectos con agentes AI</strong>
9
+ <br>
10
+ <sub>CLI interactivo que genera estructura Diátaxis + ADR + AGENTS.md en segundos</sub>
11
+ </p>
12
+
13
+ <p align="center">
14
+ <img src="https://img.shields.io/npm/v/@damenor/agent-docs?style=flat-square" alt="npm version">
15
+ <img src="https://img.shields.io/npm/dt/@damenor/agent-docs?style=flat-square" alt="downloads">
16
+ <img src="https://img.shields.io/github/license/damenordev/doc-projects?style=flat-square" alt="license">
17
+ <img src="https://img.shields.io/node/v/@damenor/agent-docs?style=flat-square" alt="node version">
18
+ </p>
19
+
20
+ ---
21
+
22
+ ## Quick start
23
+
24
+ ```bash
25
+ npx @damenor/agent-docs
26
+ ```
27
+
28
+ That's it. The wizard guides you through 7 steps and generates a complete documentation structure.
29
+
30
+ ## What it does
31
+
32
+ ```
33
+ npx @damenor/agent-docs
34
+
35
+ ├── 1. Project name
36
+ ├── 2. Target directory
37
+ ├── 3. Stack detection (auto/manual/skip)
38
+ │ package.json · pyproject.toml · go.mod · Cargo.toml · pom.xml
39
+ ├── 4. Language (ES/EN)
40
+ ├── 5. Module selection
41
+ ├── 6. Git init
42
+ └── 7. Generate → docs/ ready to customize
43
+ ```
44
+
45
+ ## 9 selectable modules
46
+
47
+ | Module | Generates |
48
+ |--------|-----------|
49
+ | Tutorials | quick-start, environment-setup, first-task |
50
+ | Guides | deployment, troubleshooting, runbooks |
51
+ | Reference | API, configuration, infrastructure, code-style |
52
+ | Explanation | architecture.md |
53
+ | Product | overview, roadmap |
54
+ | Operations | monitoring, incidents, SLAs |
55
+ | Design System | DESIGN.md with tokens |
56
+ | AI Agent Skills | `.agents/` with 5 skills + 5 agents |
57
+ | CI/CD | GitHub Actions docs-check workflow |
58
+
59
+ **Plus**, every run includes the base layer: `AGENTS.md`, `CONTEXT.md`, `README.md`, ADR template, and shared config files.
60
+
61
+ ## Stack detection
62
+
63
+ Automatically detects your tech stack from project files:
64
+
65
+ | File detected | Stack |
66
+ |---------------|-------|
67
+ | `package.json` | Node.js (npm/pnpm/yarn/bun) |
68
+ | `pyproject.toml` / `requirements.txt` | Python (pip/poetry) |
69
+ | `go.mod` | Go |
70
+ | `Cargo.toml` | Rust |
71
+ | `pom.xml` / `build.gradle` | Java/Kotlin |
72
+
73
+ Detected commands (`dev`, `build`, `test`, `lint`) are injected into templates automatically.
74
+
75
+ ## Output example
76
+
77
+ ```
78
+ my-project/
79
+ ├── AGENTS.md ← AI agent protocol
80
+ ├── docs/
81
+ │ ├── CONTEXT.md ← Domain language & glossary
82
+ │ ├── README.md ← Documentation index
83
+ │ ├── tutorials/ ← Step-by-step learning
84
+ │ ├── guides/ ← How-to guides
85
+ │ ├── reference/ ← Technical reference
86
+ │ ├── explanation/ ← Architecture & ADRs
87
+ │ ├── product/ ← Overview & roadmap
88
+ │ ├── operations/ ← Runbooks & monitoring
89
+ │ ├── DESIGN.md ← Design system tokens
90
+ │ └── adr/ ← Architecture Decision Records
91
+ ├── .agents/ ← Skills & agent configs
92
+ ├── .github/workflows/ ← CI/CD for docs
93
+ ├── .editorconfig
94
+ └── .markdownlint.json
95
+ ```
96
+
97
+ ## Why this exists
98
+
99
+ Most projects have **no documentation structure**. When you add AI agents to the mix, they need a shared vocabulary (`CONTEXT.md`), operating rules (`AGENTS.md`), and a consistent organization system (Diátaxis).
100
+
101
+ This CLI scaffolds all of that in one command, so your team and your AI agents speak the same language from day one.
102
+
103
+ ## Built for
104
+
105
+ - **Developers** who want professional docs without starting from zero
106
+ - **AI agents** that need structured context to work effectively
107
+ - **Teams** that follow Diátaxis (Tutorials / How-to / Reference / Explanation)
108
+
109
+ ## Requirements
110
+
111
+ - Node.js >= 18
112
+
113
+ ## License
114
+
115
+ MIT — [github.com/damenordev/doc-projects](https://github.com/damenordev/doc-projects)
package/dist/index.js ADDED
@@ -0,0 +1,568 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/cli.ts
4
+ import * as p from "@clack/prompts";
5
+ import pc2 from "picocolors";
6
+ import path4 from "path";
7
+
8
+ // src/utils/colors.ts
9
+ import pc from "picocolors";
10
+ var brand = {
11
+ name: "@damenor/agent-docs",
12
+ version: "0.1.0",
13
+ /** Título con estilo */
14
+ title: (text2) => pc.bold(pc.cyan(text2)),
15
+ /** Texto de éxito */
16
+ success: (text2) => pc.bold(pc.green(text2)),
17
+ /** Texto de advertencia */
18
+ warn: (text2) => pc.bold(pc.yellow(text2)),
19
+ /** Texto de error */
20
+ error: (text2) => pc.bold(pc.red(text2)),
21
+ /** Texto sutil */
22
+ dim: (text2) => pc.dim(text2),
23
+ /** Texto de enlace/path */
24
+ path: (text2) => pc.underline(pc.cyan(text2)),
25
+ /** Texto destacado */
26
+ highlight: (text2) => pc.bold(pc.magenta(text2)),
27
+ /** Label de sección */
28
+ label: (text2) => pc.bold(pc.white(text2))
29
+ };
30
+ var icons = {
31
+ docs: "\u{1F4DA}",
32
+ check: "\u2705",
33
+ folder: "\u{1F4C1}",
34
+ file: "\u{1F4C4}",
35
+ rocket: "\u{1F680}",
36
+ gear: "\u2699\uFE0F",
37
+ search: "\u{1F50D}",
38
+ sparkle: "\u2728",
39
+ warning: "\u26A0\uFE0F",
40
+ bolt: "\u26A1",
41
+ shield: "\u{1F6E1}\uFE0F",
42
+ palette: "\u{1F3A8}",
43
+ robot: "\u{1F916}",
44
+ chart: "\u{1F4CA}",
45
+ wrench: "\u{1F527}",
46
+ package: "\u{1F4E6}"
47
+ };
48
+
49
+ // src/constants.ts
50
+ var DOC_MODULES = [
51
+ {
52
+ value: "tutorials",
53
+ label: "Tutoriales",
54
+ hint: "quick-start, environment, first-task",
55
+ templateDir: "tutorials",
56
+ files: [
57
+ "docs/tutorials/quick-start.md",
58
+ "docs/tutorials/environment-setup.md",
59
+ "docs/tutorials/first-task.md"
60
+ ]
61
+ },
62
+ {
63
+ value: "guides",
64
+ label: "Gu\xEDas",
65
+ hint: "deployment, troubleshooting, runbooks",
66
+ templateDir: "guides",
67
+ files: [
68
+ "docs/guides/deployment.md",
69
+ "docs/guides/troubleshooting.md",
70
+ "docs/guides/runbooks/TEMPLATE.md"
71
+ ]
72
+ },
73
+ {
74
+ value: "reference",
75
+ label: "Referencia",
76
+ hint: "API, config, infra, code-style",
77
+ templateDir: "reference",
78
+ files: [
79
+ "docs/reference/api.md",
80
+ "docs/reference/configuration.md",
81
+ "docs/reference/infrastructure.md",
82
+ "docs/reference/code-style.md"
83
+ ]
84
+ },
85
+ {
86
+ value: "explanation",
87
+ label: "Explicaci\xF3n",
88
+ hint: "architecture",
89
+ templateDir: "explanation",
90
+ files: ["docs/explanation/architecture.md"]
91
+ },
92
+ {
93
+ value: "product",
94
+ label: "Producto",
95
+ hint: "overview, roadmap",
96
+ templateDir: "product",
97
+ files: ["docs/product/overview.md", "docs/roadmap.md"]
98
+ },
99
+ {
100
+ value: "operations",
101
+ label: "Operaciones",
102
+ hint: "monitoring, incidents, SLAs",
103
+ templateDir: "operations",
104
+ files: ["docs/operations/README.md"]
105
+ },
106
+ {
107
+ value: "design",
108
+ label: "Design System",
109
+ hint: "DESIGN.md con tokens",
110
+ templateDir: "design",
111
+ files: ["docs/DESIGN.md"]
112
+ },
113
+ {
114
+ value: "agents",
115
+ label: "Skills para agentes AI",
116
+ hint: ".agents/ con 5 skills + 5 agents",
117
+ templateDir: "agents",
118
+ files: [".agents/"]
119
+ },
120
+ {
121
+ value: "ci",
122
+ label: "CI/CD",
123
+ hint: "GitHub Actions docs check",
124
+ templateDir: "ci",
125
+ files: [".github/workflows/docs-check.yml"]
126
+ }
127
+ ];
128
+ var LANGUAGES = [
129
+ { value: "es", label: "Espa\xF1ol", hint: "recomendado" },
130
+ { value: "en", label: "English" }
131
+ ];
132
+
133
+ // src/detector.ts
134
+ import fs from "fs";
135
+ import path from "path";
136
+ function detectStack(targetDir) {
137
+ const checks = [
138
+ {
139
+ file: "package.json",
140
+ detect: (content, dir) => detectNodeStack(content, dir)
141
+ },
142
+ {
143
+ file: "requirements.txt",
144
+ detect: () => ({
145
+ language: "Python",
146
+ packageManager: "pip",
147
+ devCommand: "python manage.py runserver",
148
+ testCommand: "pytest",
149
+ lintCommand: "ruff check ."
150
+ })
151
+ },
152
+ {
153
+ file: "pyproject.toml",
154
+ detect: (content) => ({
155
+ language: "Python",
156
+ framework: content.includes("django") ? "Django" : content.includes("fastapi") ? "FastAPI" : content.includes("flask") ? "Flask" : void 0,
157
+ packageManager: content.includes("[tool.poetry]") ? "poetry" : "pip",
158
+ devCommand: content.includes("django") ? "python manage.py runserver" : "uvicorn main:app --reload",
159
+ testCommand: "pytest",
160
+ lintCommand: "ruff check ."
161
+ })
162
+ },
163
+ {
164
+ file: "go.mod",
165
+ detect: () => ({
166
+ language: "Go",
167
+ packageManager: "go modules",
168
+ devCommand: "go run .",
169
+ testCommand: "go test ./...",
170
+ lintCommand: "golangci-lint run"
171
+ })
172
+ },
173
+ {
174
+ file: "Cargo.toml",
175
+ detect: () => ({
176
+ language: "Rust",
177
+ packageManager: "cargo",
178
+ devCommand: "cargo run",
179
+ buildCommand: "cargo build --release",
180
+ testCommand: "cargo test",
181
+ lintCommand: "cargo clippy"
182
+ })
183
+ },
184
+ {
185
+ file: "pom.xml",
186
+ detect: () => ({
187
+ language: "Java",
188
+ framework: "Spring Boot",
189
+ packageManager: "maven",
190
+ devCommand: "mvn spring-boot:run",
191
+ buildCommand: "mvn package",
192
+ testCommand: "mvn test",
193
+ lintCommand: "mvn checkstyle:check"
194
+ })
195
+ },
196
+ {
197
+ file: "build.gradle",
198
+ detect: () => ({
199
+ language: "Java/Kotlin",
200
+ framework: "Spring Boot",
201
+ packageManager: "gradle",
202
+ devCommand: "gradle bootRun",
203
+ buildCommand: "gradle build",
204
+ testCommand: "gradle test"
205
+ })
206
+ }
207
+ ];
208
+ for (const check of checks) {
209
+ const filePath = path.join(targetDir, check.file);
210
+ if (fs.existsSync(filePath)) {
211
+ const content = fs.readFileSync(filePath, "utf-8");
212
+ return check.detect(content, targetDir);
213
+ }
214
+ }
215
+ return null;
216
+ }
217
+ function detectNodeStack(packageJsonContent, dir) {
218
+ const pkg = JSON.parse(packageJsonContent);
219
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
220
+ let framework;
221
+ if (deps["next"]) framework = `Next.js ${deps["next"].replace("^", "").replace("~", "")}`;
222
+ else if (deps["nuxt"]) framework = `Nuxt ${deps["nuxt"].replace("^", "").replace("~", "")}`;
223
+ else if (deps["astro"]) framework = `Astro ${deps["astro"].replace("^", "").replace("~", "")}`;
224
+ else if (deps["svelte"] || deps["@sveltejs/kit"]) framework = "SvelteKit";
225
+ else if (deps["react"]) framework = `React ${deps["react"].replace("^", "").replace("~", "")}`;
226
+ else if (deps["vue"]) framework = `Vue ${deps["vue"].replace("^", "").replace("~", "")}`;
227
+ else if (deps["express"]) framework = "Express";
228
+ else if (deps["fastify"]) framework = "Fastify";
229
+ else if (deps["hono"]) framework = "Hono";
230
+ else if (deps["@nestjs/core"]) framework = "NestJS";
231
+ let packageManager = "npm";
232
+ if (fs.existsSync(path.join(dir, "pnpm-lock.yaml"))) packageManager = "pnpm";
233
+ else if (fs.existsSync(path.join(dir, "yarn.lock"))) packageManager = "yarn";
234
+ else if (fs.existsSync(path.join(dir, "bun.lockb"))) packageManager = "bun";
235
+ const scripts = pkg.scripts || {};
236
+ const run = packageManager === "npm" ? "npm run" : packageManager;
237
+ const hasTypeScript = deps["typescript"] || fs.existsSync(path.join(dir, "tsconfig.json"));
238
+ return {
239
+ language: hasTypeScript ? "TypeScript" : "JavaScript",
240
+ framework,
241
+ packageManager,
242
+ devCommand: scripts.dev ? `${run} dev` : void 0,
243
+ buildCommand: scripts.build ? `${run} build` : void 0,
244
+ testCommand: scripts.test ? `${run} test` : void 0,
245
+ lintCommand: scripts.lint ? `${run} lint` : void 0
246
+ };
247
+ }
248
+ function formatStack(stack) {
249
+ const parts = [stack.language];
250
+ if (stack.framework) parts.push(stack.framework);
251
+ if (stack.packageManager) parts.push(`(${stack.packageManager})`);
252
+ return parts.join(" + ");
253
+ }
254
+
255
+ // src/generator.ts
256
+ import path3 from "path";
257
+ import { fileURLToPath } from "url";
258
+
259
+ // src/utils/fs.ts
260
+ import fs2 from "fs";
261
+ import path2 from "path";
262
+ function ensureDir(dirPath) {
263
+ if (!fs2.existsSync(dirPath)) {
264
+ fs2.mkdirSync(dirPath, { recursive: true });
265
+ }
266
+ }
267
+ function writeFile(filePath, content) {
268
+ ensureDir(path2.dirname(filePath));
269
+ fs2.writeFileSync(filePath, content, "utf-8");
270
+ }
271
+ function isDirEmpty(dirPath) {
272
+ if (!fs2.existsSync(dirPath)) return true;
273
+ const files = fs2.readdirSync(dirPath);
274
+ return files.length === 0 || files.length === 1 && files[0] === ".git";
275
+ }
276
+ function copyTemplateDir(src, dest, replacements) {
277
+ ensureDir(dest);
278
+ const entries = fs2.readdirSync(src, { withFileTypes: true });
279
+ for (const entry of entries) {
280
+ const srcPath = path2.join(src, entry.name);
281
+ const destPath = path2.join(dest, entry.name);
282
+ if (entry.isDirectory()) {
283
+ copyTemplateDir(srcPath, destPath, replacements);
284
+ } else {
285
+ let content = fs2.readFileSync(srcPath, "utf-8");
286
+ if (isTextFile(entry.name)) {
287
+ for (const [placeholder, value] of Object.entries(replacements)) {
288
+ content = content.replaceAll(placeholder, value);
289
+ }
290
+ }
291
+ writeFile(destPath, content);
292
+ }
293
+ }
294
+ }
295
+ function isTextFile(filename) {
296
+ const textExtensions = [".md", ".yml", ".yaml", ".json", ".txt", ".editorconfig"];
297
+ return textExtensions.some((ext) => filename.endsWith(ext)) || filename.startsWith(".");
298
+ }
299
+
300
+ // src/generator.ts
301
+ var __dirname = path3.dirname(fileURLToPath(import.meta.url));
302
+ async function generate(options) {
303
+ const { projectName, targetDir, stack, modules, language } = options;
304
+ const createdFiles = [];
305
+ const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
306
+ const replacements = {
307
+ "{{PROJECT_NAME}}": projectName,
308
+ "{{TECH_STACK}}": stack ? formatStackForTemplate(stack) : "[TECNOLOG\xCDA PRINCIPAL]",
309
+ "{{DEV_COMMAND}}": stack?.devCommand || "[comando de dev]",
310
+ "{{BUILD_COMMAND}}": stack?.buildCommand || "[comando de build]",
311
+ "{{TEST_COMMAND}}": stack?.testCommand || "[comando de test]",
312
+ "{{LINT_COMMAND}}": stack?.lintCommand || "[comando de lint]",
313
+ "{{LANGUAGE}}": stack?.language || "[lenguaje]",
314
+ "{{FRAMEWORK}}": stack?.framework || "[framework]",
315
+ "{{PACKAGE_MANAGER}}": stack?.packageManager || "[package manager]",
316
+ "{{DATE}}": today,
317
+ // Mantener los placeholders originales para compatibilidad
318
+ "[NOMBRE DEL PROYECTO]": projectName
319
+ };
320
+ const templatesDir = await resolveTemplatesDir();
321
+ const baseDir = path3.join(templatesDir, "base");
322
+ copyTemplateDir(baseDir, targetDir, replacements);
323
+ createdFiles.push(...await listGeneratedFiles(baseDir, targetDir));
324
+ for (const moduleName of modules) {
325
+ const moduleDir = path3.join(templatesDir, "modules", moduleName);
326
+ copyTemplateDir(moduleDir, targetDir, replacements);
327
+ createdFiles.push(...await listGeneratedFiles(moduleDir, targetDir));
328
+ }
329
+ const sharedDir = path3.join(templatesDir, "shared");
330
+ copyTemplateDir(sharedDir, targetDir, replacements);
331
+ createdFiles.push(...await listGeneratedFiles(sharedDir, targetDir));
332
+ if (options.initGit) {
333
+ await initGit(targetDir);
334
+ }
335
+ return createdFiles;
336
+ }
337
+ async function resolveTemplatesDir() {
338
+ const prodPath = path3.resolve(__dirname, "..", "templates");
339
+ const devPath = path3.resolve(__dirname, "..", "..", "templates");
340
+ const { existsSync } = await import("fs");
341
+ if (existsSync(prodPath)) return prodPath;
342
+ if (existsSync(devPath)) return devPath;
343
+ throw new Error("No se encontr\xF3 el directorio de templates. \xBFSe instal\xF3 correctamente el paquete?");
344
+ }
345
+ async function listGeneratedFiles(templateDir, targetDir) {
346
+ const { readdirSync } = await import("fs");
347
+ const files = [];
348
+ function walk(dir, base) {
349
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
350
+ const rel = path3.join(base, entry.name);
351
+ if (entry.isDirectory()) {
352
+ walk(path3.join(dir, entry.name), rel);
353
+ } else {
354
+ files.push(rel);
355
+ }
356
+ }
357
+ }
358
+ walk(templateDir, "");
359
+ return files;
360
+ }
361
+ async function initGit(dir) {
362
+ const { execSync } = await import("child_process");
363
+ try {
364
+ execSync("git init", { cwd: dir, stdio: "ignore" });
365
+ execSync("git add -A", { cwd: dir, stdio: "ignore" });
366
+ execSync('git commit -m "docs: inicializaci\xF3n de documentaci\xF3n con @damenor/agent-docs"', {
367
+ cwd: dir,
368
+ stdio: "ignore"
369
+ });
370
+ } catch {
371
+ }
372
+ }
373
+ function formatStackForTemplate(stack) {
374
+ const parts = [stack.language];
375
+ if (stack.framework) parts.push(stack.framework);
376
+ return parts.join(" + ");
377
+ }
378
+
379
+ // src/cli.ts
380
+ async function cli() {
381
+ console.clear();
382
+ p.intro(
383
+ `${icons.docs} ${brand.title("@damenor/agent-docs")} ${pc2.dim("v0.1.0")}
384
+ ${pc2.dim("Documentaci\xF3n profesional para proyectos con agentes AI")}`
385
+ );
386
+ const projectName = await p.text({
387
+ message: `${icons.sparkle} Nombre del proyecto`,
388
+ placeholder: "mi-proyecto",
389
+ validate: (value) => {
390
+ if (!value.trim()) return "El nombre del proyecto es obligatorio.";
391
+ if (!/^[a-zA-Z0-9_-][a-zA-Z0-9_.\- ]*$/.test(value.trim())) {
392
+ return "Usa letras, n\xFAmeros, guiones o espacios.";
393
+ }
394
+ }
395
+ });
396
+ if (p.isCancel(projectName)) {
397
+ p.cancel("Operaci\xF3n cancelada.");
398
+ process.exit(0);
399
+ }
400
+ const targetDir = await p.text({
401
+ message: `${icons.folder} Directorio de destino`,
402
+ placeholder: "./",
403
+ initialValue: "./",
404
+ validate: (value) => {
405
+ if (!value.trim()) return "El directorio es obligatorio.";
406
+ }
407
+ });
408
+ if (p.isCancel(targetDir)) {
409
+ p.cancel("Operaci\xF3n cancelada.");
410
+ process.exit(0);
411
+ }
412
+ const resolvedDir = path4.resolve(targetDir.trim());
413
+ if (!isDirEmpty(resolvedDir)) {
414
+ const overwrite = await p.confirm({
415
+ message: `${icons.warning} El directorio no est\xE1 vac\xEDo. \xBFContinuar? (puede sobrescribir archivos)`,
416
+ initialValue: false
417
+ });
418
+ if (p.isCancel(overwrite) || !overwrite) {
419
+ p.cancel("Operaci\xF3n cancelada.");
420
+ process.exit(0);
421
+ }
422
+ }
423
+ const stackOption = await p.select({
424
+ message: `${icons.search} Stack tecnol\xF3gico`,
425
+ options: [
426
+ { value: "auto", label: "Auto-detectar", hint: "recomendado \u2014 analiza el proyecto" },
427
+ { value: "manual", label: "Configurar manualmente" },
428
+ { value: "skip", label: "Omitir", hint: "rellenar despu\xE9s" }
429
+ ]
430
+ });
431
+ if (p.isCancel(stackOption)) {
432
+ p.cancel("Operaci\xF3n cancelada.");
433
+ process.exit(0);
434
+ }
435
+ let stack = null;
436
+ if (stackOption === "auto") {
437
+ const s2 = p.spinner();
438
+ s2.start("Analizando proyecto...");
439
+ await new Promise((r) => setTimeout(r, 800));
440
+ stack = detectStack(resolvedDir);
441
+ if (stack) {
442
+ s2.stop(`${icons.check} Detectado: ${brand.highlight(formatStack(stack))}`);
443
+ } else {
444
+ s2.stop(`${icons.warning} No se detect\xF3 stack \u2014 los placeholders se rellenar\xE1n despu\xE9s`);
445
+ }
446
+ } else if (stackOption === "manual") {
447
+ const manualStack = await p.group(
448
+ {
449
+ language: () => p.select({
450
+ message: "Lenguaje principal",
451
+ options: [
452
+ { value: "TypeScript", label: "TypeScript" },
453
+ { value: "JavaScript", label: "JavaScript" },
454
+ { value: "Python", label: "Python" },
455
+ { value: "Go", label: "Go" },
456
+ { value: "Rust", label: "Rust" },
457
+ { value: "Java", label: "Java" },
458
+ { value: "Other", label: "Otro" }
459
+ ]
460
+ }),
461
+ framework: () => p.text({
462
+ message: "Framework (opcional)",
463
+ placeholder: "Next.js 14, Django 5, etc."
464
+ })
465
+ },
466
+ {
467
+ onCancel: () => {
468
+ p.cancel("Operaci\xF3n cancelada.");
469
+ process.exit(0);
470
+ }
471
+ }
472
+ );
473
+ stack = {
474
+ language: manualStack.language,
475
+ framework: manualStack.framework?.trim() || void 0
476
+ };
477
+ }
478
+ const language = await p.select({
479
+ message: `${icons.docs} Idioma de la documentaci\xF3n`,
480
+ options: LANGUAGES.map((lang) => ({
481
+ value: lang.value,
482
+ label: lang.label,
483
+ hint: lang.hint
484
+ }))
485
+ });
486
+ if (p.isCancel(language)) {
487
+ p.cancel("Operaci\xF3n cancelada.");
488
+ process.exit(0);
489
+ }
490
+ const selectedModules = await p.multiselect({
491
+ message: `${icons.package} M\xF3dulos a incluir ${pc2.dim("(espacio para seleccionar)")}`,
492
+ options: DOC_MODULES.map((mod) => ({
493
+ value: mod.value,
494
+ label: mod.label,
495
+ hint: mod.hint
496
+ })),
497
+ required: false
498
+ });
499
+ if (p.isCancel(selectedModules)) {
500
+ p.cancel("Operaci\xF3n cancelada.");
501
+ process.exit(0);
502
+ }
503
+ const initGit2 = await p.confirm({
504
+ message: `${icons.gear} \xBFInicializar repositorio git?`,
505
+ initialValue: true
506
+ });
507
+ if (p.isCancel(initGit2)) {
508
+ p.cancel("Operaci\xF3n cancelada.");
509
+ process.exit(0);
510
+ }
511
+ const modulesLabel = selectedModules.length > 0 ? selectedModules.join(", ") : pc2.dim("ninguno (solo archivos base)");
512
+ p.note(
513
+ [
514
+ `${brand.label("Proyecto")}: ${projectName}`,
515
+ `${brand.label("Directorio")}: ${brand.path(resolvedDir)}`,
516
+ `${brand.label("Stack")}: ${stack ? formatStack(stack) : pc2.dim("no detectado")}`,
517
+ `${brand.label("Idioma")}: ${language === "es" ? "Espa\xF1ol" : "English"}`,
518
+ `${brand.label("M\xF3dulos")}: ${modulesLabel}`,
519
+ `${brand.label("Git")}: ${initGit2 ? "S\xED" : "No"}`
520
+ ].join("\n"),
521
+ `${icons.chart} Resumen`
522
+ );
523
+ const confirmed = await p.confirm({
524
+ message: "\xBFGenerar documentaci\xF3n?",
525
+ initialValue: true
526
+ });
527
+ if (p.isCancel(confirmed) || !confirmed) {
528
+ p.cancel("Operaci\xF3n cancelada.");
529
+ process.exit(0);
530
+ }
531
+ const s = p.spinner();
532
+ s.start("Creando estructura de documentaci\xF3n...");
533
+ await new Promise((r) => setTimeout(r, 400));
534
+ s.message("Generando archivos base (AGENTS.md, CONTEXT.md, ADR...)");
535
+ await new Promise((r) => setTimeout(r, 500));
536
+ if (selectedModules.length > 0) {
537
+ s.message(`A\xF1adiendo m\xF3dulos: ${selectedModules.join(", ")}`);
538
+ await new Promise((r) => setTimeout(r, 400));
539
+ }
540
+ const createdFiles = await generate({
541
+ projectName: projectName.trim(),
542
+ targetDir: resolvedDir,
543
+ stack,
544
+ modules: selectedModules,
545
+ language,
546
+ initGit: initGit2
547
+ });
548
+ if (initGit2) {
549
+ s.message("Inicializando repositorio git...");
550
+ await new Promise((r) => setTimeout(r, 300));
551
+ }
552
+ s.stop(`${icons.check} ${brand.success(`${createdFiles.length} archivos generados`)}`);
553
+ const nextSteps = [
554
+ `${pc2.bold("1.")} Rellenar ${brand.path("docs/CONTEXT.md")} con los t\xE9rminos del dominio`,
555
+ `${pc2.bold("2.")} Revisar ${brand.path("AGENTS.md")} y ajustar stack/comandos`,
556
+ `${pc2.bold("3.")} Ejecutar ${pc2.cyan("npx @damenor/agent-docs --help")} para m\xE1s opciones`
557
+ ];
558
+ p.note(nextSteps.join("\n"), `${icons.rocket} Pr\xF3ximos pasos`);
559
+ p.outro(
560
+ `${icons.sparkle} ${brand.title("\xA1Documentaci\xF3n lista!")} ${pc2.dim("\u2014 github.com/damenordev/doc-projects")}`
561
+ );
562
+ }
563
+
564
+ // src/index.ts
565
+ cli().catch((error) => {
566
+ console.error(error);
567
+ process.exit(1);
568
+ });