elsabro 2.1.0 → 2.3.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 (64) hide show
  1. package/agents/elsabro-orchestrator.md +113 -0
  2. package/commands/elsabro/add-phase.md +17 -0
  3. package/commands/elsabro/add-todo.md +111 -53
  4. package/commands/elsabro/audit-milestone.md +19 -0
  5. package/commands/elsabro/check-todos.md +210 -31
  6. package/commands/elsabro/complete-milestone.md +20 -1
  7. package/commands/elsabro/debug.md +19 -0
  8. package/commands/elsabro/discuss-phase.md +18 -1
  9. package/commands/elsabro/execute.md +511 -58
  10. package/commands/elsabro/insert-phase.md +18 -1
  11. package/commands/elsabro/list-phase-assumptions.md +17 -0
  12. package/commands/elsabro/new-milestone.md +19 -0
  13. package/commands/elsabro/new.md +19 -0
  14. package/commands/elsabro/pause-work.md +19 -0
  15. package/commands/elsabro/plan-milestone-gaps.md +20 -1
  16. package/commands/elsabro/plan.md +264 -36
  17. package/commands/elsabro/progress.md +203 -79
  18. package/commands/elsabro/quick.md +19 -0
  19. package/commands/elsabro/remove-phase.md +17 -0
  20. package/commands/elsabro/research-phase.md +18 -1
  21. package/commands/elsabro/resume-work.md +19 -0
  22. package/commands/elsabro/start.md +399 -98
  23. package/commands/elsabro/verify-work.md +138 -5
  24. package/hooks/confirm-destructive.sh +145 -0
  25. package/hooks/hooks-config.json +81 -0
  26. package/hooks/lint-check.sh +238 -0
  27. package/hooks/post-edit-test.sh +189 -0
  28. package/package.json +3 -2
  29. package/references/SYSTEM_INDEX.md +241 -0
  30. package/references/command-flow.md +352 -0
  31. package/references/enforcement-rules.md +331 -0
  32. package/references/error-contracts-tests.md +1171 -0
  33. package/references/error-contracts.md +3102 -0
  34. package/references/error-handling-instructions.md +26 -12
  35. package/references/parallel-worktrees.md +293 -0
  36. package/references/state-sync.md +381 -0
  37. package/references/task-dispatcher.md +388 -0
  38. package/references/tasks-integration.md +380 -0
  39. package/scripts/setup-parallel-worktrees.sh +319 -0
  40. package/skills/api-microservice.md +765 -0
  41. package/skills/api-setup.md +76 -3
  42. package/skills/auth-setup.md +46 -6
  43. package/skills/chrome-extension.md +584 -0
  44. package/skills/cicd-setup.md +1206 -0
  45. package/skills/cli-tool.md +884 -0
  46. package/skills/database-setup.md +41 -5
  47. package/skills/desktop-app.md +1351 -0
  48. package/skills/expo-app.md +35 -2
  49. package/skills/full-stack-app.md +543 -0
  50. package/skills/memory-update.md +207 -0
  51. package/skills/mobile-app.md +813 -0
  52. package/skills/nextjs-app.md +33 -2
  53. package/skills/payments-setup.md +76 -1
  54. package/skills/review.md +331 -0
  55. package/skills/saas-starter.md +639 -0
  56. package/skills/sentry-setup.md +41 -7
  57. package/skills/techdebt.md +289 -0
  58. package/skills/testing-setup.md +1218 -0
  59. package/skills/tutor.md +219 -0
  60. package/templates/.planning/notes/.gitkeep +0 -0
  61. package/templates/CLAUDE.md.template +48 -0
  62. package/templates/error-handling-config.json +79 -2
  63. package/templates/mistakes.md.template +52 -0
  64. package/templates/patterns.md.template +114 -0
@@ -0,0 +1,884 @@
1
+ ---
2
+ name: cli-tool
3
+ description: Crear herramientas CLI profesionales con Node.js, Commander.js, publicacion en npm y testing
4
+ tags: [cli, command-line, npm, node, terminal, automation]
5
+ difficulty: intermediate
6
+ estimated_time: 25min
7
+ ---
8
+
9
+ # Skill: CLI Tool
10
+
11
+ <when_to_use>
12
+ Usar cuando el usuario menciona:
13
+ - "crear CLI"
14
+ - "herramienta de terminal"
15
+ - "comando npm"
16
+ - "script interactivo"
17
+ - "utilidad de linea de comandos"
18
+ - "tool para consola"
19
+ - "automatizar con scripts"
20
+ </when_to_use>
21
+
22
+ <pre_requisites>
23
+ ## Pre-requisitos
24
+ - Node.js 20+
25
+ - Cuenta npm (para publicar)
26
+ - Conocimiento basico de JavaScript/TypeScript
27
+ </pre_requisites>
28
+
29
+ <tech_stack>
30
+ ## Stack Tecnologico
31
+ | Categoria | Tecnologia | Version |
32
+ |-----------|------------|---------|
33
+ | Runtime | Node.js | 20.x |
34
+ | CLI Framework | Commander.js | 12.x |
35
+ | Colors | Chalk | 5.x |
36
+ | Prompts | Inquirer | 9.x |
37
+ | Testing | Vitest | 2.x |
38
+ | Build | tsup | 8.x |
39
+ | Linting | ESLint | 9.x |
40
+ </tech_stack>
41
+
42
+ <project_structure>
43
+ ## Estructura de Proyecto
44
+ ```
45
+ my-cli/
46
+ ├── src/
47
+ │ ├── index.ts # Entry point
48
+ │ ├── commands/
49
+ │ │ ├── index.ts # Export all commands
50
+ │ │ ├── init.ts # Init command
51
+ │ │ └── run.ts # Run command
52
+ │ ├── lib/
53
+ │ │ ├── config.ts # Configuration loader
54
+ │ │ ├── logger.ts # Styled console output
55
+ │ │ └── utils.ts # Helper functions
56
+ │ └── types.ts # TypeScript types
57
+ ├── tests/
58
+ │ ├── commands.test.ts # Command tests
59
+ │ └── utils.test.ts # Utility tests
60
+ ├── bin/
61
+ │ └── cli.js # Shebang wrapper
62
+ ├── package.json
63
+ ├── tsconfig.json
64
+ ├── tsup.config.ts
65
+ ├── vitest.config.ts
66
+ └── README.md
67
+ ```
68
+ </project_structure>
69
+
70
+ <setup_steps>
71
+ ## Pasos de Setup
72
+
73
+ ### 1. Inicializar Proyecto
74
+
75
+ ```bash
76
+ mkdir my-cli && cd my-cli
77
+ npm init -y
78
+ ```
79
+
80
+ ### 2. Instalar Dependencias
81
+
82
+ ```bash
83
+ # Dependencias de produccion
84
+ npm install commander@12 chalk@5 inquirer@9
85
+
86
+ # Dependencias de desarrollo
87
+ npm install -D typescript @types/node @types/inquirer tsup vitest
88
+ ```
89
+
90
+ ### 3. Configurar TypeScript
91
+
92
+ **tsconfig.json:**
93
+ ```json
94
+ {
95
+ "compilerOptions": {
96
+ "target": "ES2022",
97
+ "module": "ESNext",
98
+ "moduleResolution": "bundler",
99
+ "lib": ["ES2022"],
100
+ "outDir": "./dist",
101
+ "rootDir": "./src",
102
+ "strict": true,
103
+ "esModuleInterop": true,
104
+ "skipLibCheck": true,
105
+ "forceConsistentCasingInFileNames": true,
106
+ "declaration": true,
107
+ "declarationMap": true,
108
+ "sourceMap": true
109
+ },
110
+ "include": ["src/**/*"],
111
+ "exclude": ["node_modules", "dist", "tests"]
112
+ }
113
+ ```
114
+
115
+ ### 4. Configurar tsup
116
+
117
+ **tsup.config.ts:**
118
+ ```typescript
119
+ import { defineConfig } from 'tsup';
120
+
121
+ export default defineConfig({
122
+ entry: ['src/index.ts'],
123
+ format: ['esm'],
124
+ dts: true,
125
+ clean: true,
126
+ sourcemap: true,
127
+ target: 'node20',
128
+ outDir: 'dist',
129
+ shims: true,
130
+ });
131
+ ```
132
+
133
+ ### 5. Configurar Vitest
134
+
135
+ **vitest.config.ts:**
136
+ ```typescript
137
+ import { defineConfig } from 'vitest/config';
138
+
139
+ export default defineConfig({
140
+ test: {
141
+ globals: true,
142
+ environment: 'node',
143
+ include: ['tests/**/*.test.ts'],
144
+ coverage: {
145
+ provider: 'v8',
146
+ reporter: ['text', 'json', 'html'],
147
+ },
148
+ },
149
+ });
150
+ ```
151
+
152
+ ### 6. Crear Entry Point
153
+
154
+ **src/index.ts:**
155
+ ```typescript
156
+ #!/usr/bin/env node
157
+ import { Command } from 'commander';
158
+ import chalk from 'chalk';
159
+ import { initCommand } from './commands/init.js';
160
+ import { runCommand } from './commands/run.js';
161
+
162
+ const program = new Command();
163
+
164
+ program
165
+ .name('my-cli')
166
+ .description('A professional CLI tool')
167
+ .version('1.0.0');
168
+
169
+ // Register commands
170
+ program.addCommand(initCommand);
171
+ program.addCommand(runCommand);
172
+
173
+ // Error handling
174
+ program.exitOverride();
175
+
176
+ try {
177
+ await program.parseAsync(process.argv);
178
+ } catch (error) {
179
+ if (error instanceof Error) {
180
+ console.error(chalk.red('Error:'), error.message);
181
+ process.exit(1);
182
+ }
183
+ }
184
+ ```
185
+
186
+ ### 7. Crear Comandos
187
+
188
+ **src/commands/init.ts:**
189
+ ```typescript
190
+ import { Command } from 'commander';
191
+ import chalk from 'chalk';
192
+ import inquirer from 'inquirer';
193
+ import { logger } from '../lib/logger.js';
194
+
195
+ interface InitOptions {
196
+ name?: string;
197
+ template?: string;
198
+ force?: boolean;
199
+ }
200
+
201
+ export const initCommand = new Command('init')
202
+ .description('Initialize a new project')
203
+ .option('-n, --name <name>', 'Project name')
204
+ .option('-t, --template <template>', 'Template to use', 'default')
205
+ .option('-f, --force', 'Overwrite existing files', false)
206
+ .action(async (options: InitOptions) => {
207
+ logger.info('Initializing project...');
208
+
209
+ // Interactive prompts if name not provided
210
+ let projectName = options.name;
211
+ if (!projectName) {
212
+ const answers = await inquirer.prompt([
213
+ {
214
+ type: 'input',
215
+ name: 'name',
216
+ message: 'Project name:',
217
+ default: 'my-project',
218
+ validate: (input: string) => {
219
+ if (/^[a-z0-9-]+$/.test(input)) return true;
220
+ return 'Name must be lowercase with hyphens only';
221
+ },
222
+ },
223
+ ]);
224
+ projectName = answers.name;
225
+ }
226
+
227
+ // Template selection
228
+ const { confirmTemplate } = await inquirer.prompt([
229
+ {
230
+ type: 'confirm',
231
+ name: 'confirmTemplate',
232
+ message: `Use template "${options.template}"?`,
233
+ default: true,
234
+ },
235
+ ]);
236
+
237
+ if (!confirmTemplate) {
238
+ const { template } = await inquirer.prompt([
239
+ {
240
+ type: 'list',
241
+ name: 'template',
242
+ message: 'Select template:',
243
+ choices: ['default', 'minimal', 'full'],
244
+ },
245
+ ]);
246
+ options.template = template;
247
+ }
248
+
249
+ logger.success(`Project "${projectName}" initialized with ${options.template} template`);
250
+ });
251
+ ```
252
+
253
+ **src/commands/run.ts:**
254
+ ```typescript
255
+ import { Command } from 'commander';
256
+ import { logger } from '../lib/logger.js';
257
+
258
+ interface RunOptions {
259
+ watch?: boolean;
260
+ verbose?: boolean;
261
+ }
262
+
263
+ export const runCommand = new Command('run')
264
+ .description('Run the project')
265
+ .argument('[script]', 'Script to run', 'start')
266
+ .option('-w, --watch', 'Watch mode', false)
267
+ .option('-v, --verbose', 'Verbose output', false)
268
+ .action(async (script: string, options: RunOptions) => {
269
+ logger.info(`Running script: ${script}`);
270
+
271
+ if (options.verbose) {
272
+ logger.debug('Options:', JSON.stringify(options, null, 2));
273
+ }
274
+
275
+ if (options.watch) {
276
+ logger.info('Watch mode enabled');
277
+ }
278
+
279
+ // Simulate running
280
+ await new Promise((resolve) => setTimeout(resolve, 1000));
281
+ logger.success('Script completed successfully');
282
+ });
283
+ ```
284
+
285
+ **src/commands/index.ts:**
286
+ ```typescript
287
+ export { initCommand } from './init.js';
288
+ export { runCommand } from './run.js';
289
+ ```
290
+
291
+ ### 8. Crear Utilities
292
+
293
+ **src/lib/logger.ts:**
294
+ ```typescript
295
+ import chalk from 'chalk';
296
+
297
+ export const logger = {
298
+ info: (message: string, ...args: unknown[]) => {
299
+ console.log(chalk.blue('info'), message, ...args);
300
+ },
301
+ success: (message: string, ...args: unknown[]) => {
302
+ console.log(chalk.green('success'), message, ...args);
303
+ },
304
+ warn: (message: string, ...args: unknown[]) => {
305
+ console.log(chalk.yellow('warn'), message, ...args);
306
+ },
307
+ error: (message: string, ...args: unknown[]) => {
308
+ console.error(chalk.red('error'), message, ...args);
309
+ },
310
+ debug: (message: string, ...args: unknown[]) => {
311
+ if (process.env.DEBUG) {
312
+ console.log(chalk.gray('debug'), message, ...args);
313
+ }
314
+ },
315
+ };
316
+ ```
317
+
318
+ **src/lib/config.ts:**
319
+ ```typescript
320
+ import { readFileSync, existsSync } from 'node:fs';
321
+ import { join } from 'node:path';
322
+
323
+ export interface Config {
324
+ name: string;
325
+ version: string;
326
+ settings: Record<string, unknown>;
327
+ }
328
+
329
+ const CONFIG_FILE = '.myclirc.json';
330
+
331
+ export function loadConfig(cwd: string = process.cwd()): Config | null {
332
+ const configPath = join(cwd, CONFIG_FILE);
333
+
334
+ if (!existsSync(configPath)) {
335
+ return null;
336
+ }
337
+
338
+ try {
339
+ const content = readFileSync(configPath, 'utf-8');
340
+ return JSON.parse(content) as Config;
341
+ } catch {
342
+ return null;
343
+ }
344
+ }
345
+
346
+ export function getDefaultConfig(): Config {
347
+ return {
348
+ name: 'my-project',
349
+ version: '1.0.0',
350
+ settings: {},
351
+ };
352
+ }
353
+ ```
354
+
355
+ **src/lib/utils.ts:**
356
+ ```typescript
357
+ export function isGitRepo(): boolean {
358
+ try {
359
+ const { spawnSync } = require('node:child_process');
360
+ const result = spawnSync('git', ['rev-parse', '--is-inside-work-tree'], { stdio: 'ignore' });
361
+ return result.status === 0;
362
+ } catch {
363
+ return false;
364
+ }
365
+ }
366
+
367
+ export function slugify(text: string): string {
368
+ return text
369
+ .toLowerCase()
370
+ .replace(/[^a-z0-9]+/g, '-')
371
+ .replace(/^-|-$/g, '');
372
+ }
373
+
374
+ export async function sleep(ms: number): Promise<void> {
375
+ return new Promise((resolve) => setTimeout(resolve, ms));
376
+ }
377
+
378
+ export function formatBytes(bytes: number): string {
379
+ const units = ['B', 'KB', 'MB', 'GB'];
380
+ let unitIndex = 0;
381
+ let value = bytes;
382
+
383
+ while (value >= 1024 && unitIndex < units.length - 1) {
384
+ value /= 1024;
385
+ unitIndex++;
386
+ }
387
+
388
+ return `${value.toFixed(2)} ${units[unitIndex]}`;
389
+ }
390
+ ```
391
+
392
+ **src/types.ts:**
393
+ ```typescript
394
+ export interface CliContext {
395
+ cwd: string;
396
+ verbose: boolean;
397
+ config: import('./lib/config.js').Config | null;
398
+ }
399
+
400
+ export interface CommandResult {
401
+ success: boolean;
402
+ message?: string;
403
+ data?: unknown;
404
+ }
405
+ ```
406
+
407
+ ### 9. Crear Bin Wrapper
408
+
409
+ **bin/cli.js:**
410
+ ```javascript
411
+ #!/usr/bin/env node
412
+ import '../dist/index.js';
413
+ ```
414
+
415
+ ### 10. Configurar package.json
416
+
417
+ **package.json:**
418
+ ```json
419
+ {
420
+ "name": "my-cli",
421
+ "version": "1.0.0",
422
+ "description": "A professional CLI tool",
423
+ "type": "module",
424
+ "bin": {
425
+ "my-cli": "./bin/cli.js"
426
+ },
427
+ "main": "./dist/index.js",
428
+ "types": "./dist/index.d.ts",
429
+ "files": [
430
+ "dist",
431
+ "bin"
432
+ ],
433
+ "scripts": {
434
+ "dev": "tsup --watch",
435
+ "build": "tsup",
436
+ "test": "vitest run",
437
+ "test:watch": "vitest",
438
+ "test:coverage": "vitest run --coverage",
439
+ "lint": "eslint src",
440
+ "prepublishOnly": "npm run build && npm run test"
441
+ },
442
+ "keywords": ["cli", "tool", "command-line"],
443
+ "author": "Your Name",
444
+ "license": "MIT",
445
+ "engines": {
446
+ "node": ">=20.0.0"
447
+ },
448
+ "repository": {
449
+ "type": "git",
450
+ "url": "https://github.com/username/my-cli"
451
+ }
452
+ }
453
+ ```
454
+
455
+ ### 11. Crear Tests
456
+
457
+ **tests/commands.test.ts:**
458
+ ```typescript
459
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
460
+ import { Command } from 'commander';
461
+
462
+ describe('CLI Commands', () => {
463
+ beforeEach(() => {
464
+ vi.clearAllMocks();
465
+ });
466
+
467
+ describe('init command', () => {
468
+ it('should accept name option', async () => {
469
+ const program = new Command();
470
+ let capturedOptions: Record<string, unknown> = {};
471
+
472
+ program
473
+ .command('init')
474
+ .option('-n, --name <name>', 'Project name')
475
+ .action((options) => {
476
+ capturedOptions = options;
477
+ });
478
+
479
+ await program.parseAsync(['node', 'cli', 'init', '-n', 'test-project']);
480
+ expect(capturedOptions.name).toBe('test-project');
481
+ });
482
+
483
+ it('should use default template', async () => {
484
+ const program = new Command();
485
+ let capturedOptions: Record<string, unknown> = {};
486
+
487
+ program
488
+ .command('init')
489
+ .option('-t, --template <template>', 'Template', 'default')
490
+ .action((options) => {
491
+ capturedOptions = options;
492
+ });
493
+
494
+ await program.parseAsync(['node', 'cli', 'init']);
495
+ expect(capturedOptions.template).toBe('default');
496
+ });
497
+ });
498
+
499
+ describe('run command', () => {
500
+ it('should accept script argument', async () => {
501
+ const program = new Command();
502
+ let capturedScript = '';
503
+
504
+ program
505
+ .command('run')
506
+ .argument('[script]', 'Script to run', 'start')
507
+ .action((script) => {
508
+ capturedScript = script;
509
+ });
510
+
511
+ await program.parseAsync(['node', 'cli', 'run', 'build']);
512
+ expect(capturedScript).toBe('build');
513
+ });
514
+
515
+ it('should use default script when not provided', async () => {
516
+ const program = new Command();
517
+ let capturedScript = '';
518
+
519
+ program
520
+ .command('run')
521
+ .argument('[script]', 'Script to run', 'start')
522
+ .action((script) => {
523
+ capturedScript = script;
524
+ });
525
+
526
+ await program.parseAsync(['node', 'cli', 'run']);
527
+ expect(capturedScript).toBe('start');
528
+ });
529
+ });
530
+ });
531
+ ```
532
+
533
+ **tests/utils.test.ts:**
534
+ ```typescript
535
+ import { describe, it, expect } from 'vitest';
536
+ import { slugify, formatBytes } from '../src/lib/utils.js';
537
+
538
+ describe('Utils', () => {
539
+ describe('slugify', () => {
540
+ it('should convert to lowercase', () => {
541
+ expect(slugify('Hello World')).toBe('hello-world');
542
+ });
543
+
544
+ it('should replace spaces with hyphens', () => {
545
+ expect(slugify('my project name')).toBe('my-project-name');
546
+ });
547
+
548
+ it('should remove special characters', () => {
549
+ expect(slugify('hello@world!')).toBe('hello-world');
550
+ });
551
+
552
+ it('should remove leading and trailing hyphens', () => {
553
+ expect(slugify('--hello--')).toBe('hello');
554
+ });
555
+ });
556
+
557
+ describe('formatBytes', () => {
558
+ it('should format bytes', () => {
559
+ expect(formatBytes(500)).toBe('500.00 B');
560
+ });
561
+
562
+ it('should format kilobytes', () => {
563
+ expect(formatBytes(1024)).toBe('1.00 KB');
564
+ });
565
+
566
+ it('should format megabytes', () => {
567
+ expect(formatBytes(1048576)).toBe('1.00 MB');
568
+ });
569
+
570
+ it('should format gigabytes', () => {
571
+ expect(formatBytes(1073741824)).toBe('1.00 GB');
572
+ });
573
+ });
574
+ });
575
+ ```
576
+ </setup_steps>
577
+
578
+ <verification>
579
+ ## Verificacion
580
+
581
+ ### Probar Localmente
582
+
583
+ ```bash
584
+ # Build del proyecto
585
+ npm run build
586
+
587
+ # Link global para testing
588
+ npm link
589
+
590
+ # Probar comandos
591
+ my-cli --help
592
+ my-cli init --help
593
+ my-cli init -n test-project
594
+ my-cli run build --verbose
595
+
596
+ # Desinstalar link
597
+ npm unlink -g my-cli
598
+ ```
599
+
600
+ ### Ejecutar Tests
601
+
602
+ ```bash
603
+ # Tests una vez
604
+ npm run test
605
+
606
+ # Tests en modo watch
607
+ npm run test:watch
608
+
609
+ # Tests con coverage
610
+ npm run test:coverage
611
+ ```
612
+
613
+ ### Verificar Build
614
+
615
+ ```bash
616
+ # Verificar que compila
617
+ npm run build
618
+
619
+ # Verificar estructura de dist
620
+ ls -la dist/
621
+
622
+ # Verificar dry-run de publicacion
623
+ npm publish --dry-run
624
+ ```
625
+ </verification>
626
+
627
+ <publishing>
628
+ ## Publicar en npm
629
+
630
+ ### Preparacion
631
+
632
+ 1. **Verificar nombre disponible:**
633
+ ```bash
634
+ npm search my-cli
635
+ # O visitar https://www.npmjs.com/package/my-cli
636
+ ```
637
+
638
+ 2. **Login en npm:**
639
+ ```bash
640
+ npm login
641
+ # Seguir prompts de autenticacion
642
+ ```
643
+
644
+ 3. **Verificar configuracion:**
645
+ ```bash
646
+ npm whoami
647
+ npm config list
648
+ ```
649
+
650
+ ### Publicacion
651
+
652
+ ```bash
653
+ # Primera publicacion
654
+ npm publish
655
+
656
+ # Si es scoped package (@usuario/my-cli)
657
+ npm publish --access public
658
+ ```
659
+
660
+ ### Versionado
661
+
662
+ ```bash
663
+ # Patch: 1.0.0 -> 1.0.1 (bug fixes)
664
+ npm version patch
665
+
666
+ # Minor: 1.0.0 -> 1.1.0 (new features)
667
+ npm version minor
668
+
669
+ # Major: 1.0.0 -> 2.0.0 (breaking changes)
670
+ npm version major
671
+
672
+ # Publicar nueva version
673
+ npm publish
674
+ ```
675
+
676
+ ### Tags
677
+
678
+ ```bash
679
+ # Publicar como beta
680
+ npm publish --tag beta
681
+
682
+ # Publicar como next
683
+ npm publish --tag next
684
+
685
+ # Instalar version especifica
686
+ npm install my-cli@beta
687
+ ```
688
+ </publishing>
689
+
690
+ <common_issues>
691
+ ## Problemas Comunes
692
+
693
+ ### Shebang no funciona
694
+
695
+ **Problema:** Error "command not found" o permisos denegados.
696
+
697
+ **Solucion:**
698
+ ```bash
699
+ # Verificar shebang en bin/cli.js
700
+ # Debe ser: #!/usr/bin/env node
701
+
702
+ # Dar permisos de ejecucion
703
+ chmod +x bin/cli.js
704
+ ```
705
+
706
+ ### ESM vs CommonJS
707
+
708
+ **Problema:** "Cannot use import statement outside a module"
709
+
710
+ **Solucion:**
711
+ ```json
712
+ // package.json
713
+ {
714
+ "type": "module"
715
+ }
716
+ ```
717
+
718
+ ### Chalk no muestra colores
719
+
720
+ **Problema:** Output sin colores en terminal.
721
+
722
+ **Causas:**
723
+ - Variable `NO_COLOR` activa
724
+ - Terminal no soporta colores
725
+ - Stdout no es TTY
726
+
727
+ **Solucion:**
728
+ ```typescript
729
+ import chalk from 'chalk';
730
+
731
+ // Forzar colores (no recomendado generalmente)
732
+ const forceChalk = new chalk.Instance({ level: 3 });
733
+ ```
734
+
735
+ ### Inquirer no funciona en CI
736
+
737
+ **Problema:** Prompts cuelgan en CI/CD.
738
+
739
+ **Solucion:**
740
+ ```typescript
741
+ // Detectar CI y usar defaults
742
+ const isCI = process.env.CI === 'true';
743
+
744
+ if (isCI) {
745
+ // Usar valores por defecto sin prompts
746
+ return defaultOptions;
747
+ }
748
+
749
+ // Prompts interactivos
750
+ const answers = await inquirer.prompt([...]);
751
+ ```
752
+
753
+ ### TypeScript paths no resuelven
754
+
755
+ **Problema:** Imports con `@/` no funcionan.
756
+
757
+ **Solucion:**
758
+ ```typescript
759
+ // tsup.config.ts
760
+ import { defineConfig } from 'tsup';
761
+
762
+ export default defineConfig({
763
+ // ... otras opciones
764
+ esbuildOptions(options) {
765
+ options.alias = {
766
+ '@': './src',
767
+ };
768
+ },
769
+ });
770
+ ```
771
+
772
+ ### Build falla con dependencias nativas
773
+
774
+ **Problema:** Modulos nativos causan error en build.
775
+
776
+ **Solucion:**
777
+ ```typescript
778
+ // tsup.config.ts
779
+ export default defineConfig({
780
+ // Excluir modulos nativos del bundle
781
+ external: ['fsevents'],
782
+ noExternal: [], // Incluir todo lo demas
783
+ });
784
+ ```
785
+ </common_issues>
786
+
787
+ <best_practices>
788
+ ## Mejores Practicas
789
+
790
+ ### Estructura de Comandos
791
+
792
+ ```typescript
793
+ // Patron recomendado para comandos complejos
794
+ export function createCommand(): Command {
795
+ return new Command('name')
796
+ .description('...')
797
+ .option('...')
798
+ .action(async (options) => {
799
+ try {
800
+ await executeCommand(options);
801
+ } catch (error) {
802
+ handleError(error);
803
+ process.exit(1);
804
+ }
805
+ });
806
+ }
807
+ ```
808
+
809
+ ### Manejo de Errores
810
+
811
+ ```typescript
812
+ // Errores con codigos de salida apropiados
813
+ process.exit(0); // Exito
814
+ process.exit(1); // Error general
815
+ process.exit(2); // Mal uso del comando
816
+ ```
817
+
818
+ ### Configuracion Progresiva
819
+
820
+ ```typescript
821
+ // Prioridad: CLI args > env vars > config file > defaults
822
+ function getConfig(cliOptions: Options): Config {
823
+ const fileConfig = loadConfigFile();
824
+ const envConfig = loadEnvConfig();
825
+
826
+ return {
827
+ ...getDefaults(),
828
+ ...fileConfig,
829
+ ...envConfig,
830
+ ...cliOptions,
831
+ };
832
+ }
833
+ ```
834
+
835
+ ### Output Amigable
836
+
837
+ ```typescript
838
+ // Usar spinners para operaciones largas
839
+ import ora from 'ora';
840
+
841
+ const spinner = ora('Loading...').start();
842
+ await longOperation();
843
+ spinner.succeed('Done!');
844
+ ```
845
+ </best_practices>
846
+
847
+ <examples>
848
+ ## Ejemplos de Uso
849
+
850
+ ### CLI Basico
851
+
852
+ ```bash
853
+ # Crear proyecto
854
+ my-cli init -n my-app
855
+
856
+ # Ejecutar script
857
+ my-cli run dev --watch
858
+
859
+ # Ver ayuda
860
+ my-cli --help
861
+ ```
862
+
863
+ ### CLI con Config
864
+
865
+ ```bash
866
+ # Generar configuracion
867
+ my-cli config init
868
+
869
+ # Mostrar configuracion actual
870
+ my-cli config show
871
+
872
+ # Modificar valor
873
+ my-cli config set key value
874
+ ```
875
+
876
+ ### CLI con Subcomandos
877
+
878
+ ```bash
879
+ # Comandos anidados
880
+ my-cli project create
881
+ my-cli project list
882
+ my-cli project delete <id>
883
+ ```
884
+ </examples>