@patricksardinha/agentkit-cli 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 (52) hide show
  1. package/.gitattributes +2 -0
  2. package/.github/workflows/release.yml +31 -0
  3. package/AGENT_WORKFLOW.md +55 -0
  4. package/CLAUDE.md +45 -0
  5. package/README.md +327 -0
  6. package/dist/cli.cjs +1079 -0
  7. package/dist/cli.cjs.map +1 -0
  8. package/dist/cli.d.cts +1 -0
  9. package/dist/cli.d.ts +1 -0
  10. package/dist/cli.js +1056 -0
  11. package/dist/cli.js.map +1 -0
  12. package/package.json +45 -0
  13. package/src/cli.ts +18 -0
  14. package/src/commands/add.ts +166 -0
  15. package/src/commands/init.ts +130 -0
  16. package/src/commands/status.ts +57 -0
  17. package/src/detectors/gitDetector.ts +11 -0
  18. package/src/detectors/stackDetector.ts +88 -0
  19. package/src/generators/claudeMdGenerator.ts +42 -0
  20. package/src/generators/playbookGenerator.ts +76 -0
  21. package/src/generators/skillsGenerator.ts +56 -0
  22. package/src/generators/workflowGenerator.ts +62 -0
  23. package/src/templates/express.ts +64 -0
  24. package/src/templates/fastapi.ts +63 -0
  25. package/src/templates/nextjs.ts +63 -0
  26. package/src/templates/node.ts +54 -0
  27. package/src/templates/react.ts +61 -0
  28. package/src/templates/tauri.ts +65 -0
  29. package/src/templates/unknown.ts +45 -0
  30. package/src/types/agent.ts +9 -0
  31. package/src/types/inquirer.d.ts +36 -0
  32. package/src/utils/agentParser.ts +67 -0
  33. package/src/utils/blueprintParser.ts +28 -0
  34. package/src/utils/logger.ts +16 -0
  35. package/tests/commands/add.test.ts +130 -0
  36. package/tests/detectors/fixtures/express-app/package.json +9 -0
  37. package/tests/detectors/fixtures/fastapi-app/requirements.txt +3 -0
  38. package/tests/detectors/fixtures/nextjs-app/package.json +13 -0
  39. package/tests/detectors/fixtures/no-git/README.md +2 -0
  40. package/tests/detectors/fixtures/react-app/package.json +10 -0
  41. package/tests/detectors/fixtures/tauri-app/package.json +10 -0
  42. package/tests/detectors/fixtures/tauri-app/src-tauri/tauri.conf.json +12 -0
  43. package/tests/detectors/gitDetector.test.ts +29 -0
  44. package/tests/detectors/stackDetector.test.ts +50 -0
  45. package/tests/generators/blueprintSupport.test.ts +130 -0
  46. package/tests/generators/claudeMdGenerator.test.ts +86 -0
  47. package/tests/generators/playbookGenerator.test.ts +152 -0
  48. package/tests/generators/skillsGenerator.test.ts +94 -0
  49. package/tests/generators/workflowGenerator.test.ts +84 -0
  50. package/tsconfig.json +19 -0
  51. package/tsup.config.ts +11 -0
  52. package/vitest.config.ts +9 -0
package/dist/cli.cjs ADDED
@@ -0,0 +1,1079 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
18
+ // If the importer is in node compatibility mode or this is not an ESM
19
+ // file that has been converted to a CommonJS file using a Babel-
20
+ // compatible transform (i.e. "__esModule" has not been set), then set
21
+ // "default" to the CommonJS "module.exports" for node compatibility.
22
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
23
+ mod
24
+ ));
25
+
26
+ // src/cli.ts
27
+ var import_commander = require("commander");
28
+
29
+ // src/commands/init.ts
30
+ var import_promises4 = require("fs/promises");
31
+ var import_node_path4 = require("path");
32
+ var import_inquirer = __toESM(require("inquirer"), 1);
33
+ var import_ora = __toESM(require("ora"), 1);
34
+
35
+ // src/detectors/stackDetector.ts
36
+ var import_promises = require("fs/promises");
37
+ var import_node_path = require("path");
38
+ async function pathExists(p) {
39
+ try {
40
+ await (0, import_promises.access)(p);
41
+ return true;
42
+ } catch {
43
+ return false;
44
+ }
45
+ }
46
+ async function readJson(p) {
47
+ try {
48
+ const raw = await (0, import_promises.readFile)(p, "utf-8");
49
+ return JSON.parse(raw);
50
+ } catch {
51
+ return null;
52
+ }
53
+ }
54
+ async function readText(p) {
55
+ try {
56
+ return await (0, import_promises.readFile)(p, "utf-8");
57
+ } catch {
58
+ return null;
59
+ }
60
+ }
61
+ async function detectStack(projectPath) {
62
+ const info = {
63
+ framework: "unknown",
64
+ language: "unknown",
65
+ hasTypeScript: false,
66
+ extras: []
67
+ };
68
+ const packageJson = await readJson((0, import_node_path.join)(projectPath, "package.json"));
69
+ const requirementsTxt = await readText((0, import_node_path.join)(projectPath, "requirements.txt"));
70
+ const hasTauriDir = await pathExists((0, import_node_path.join)(projectPath, "src-tauri"));
71
+ const hasTsConfig = await pathExists((0, import_node_path.join)(projectPath, "tsconfig.json"));
72
+ if (packageJson !== null) {
73
+ const deps = packageJson.dependencies ?? {};
74
+ const devDeps = packageJson.devDependencies ?? {};
75
+ const allDeps = { ...deps, ...devDeps };
76
+ info.hasTypeScript = "typescript" in allDeps || hasTsConfig;
77
+ info.language = info.hasTypeScript ? "typescript" : "javascript";
78
+ if ("next" in allDeps) {
79
+ info.framework = "nextjs";
80
+ } else if (hasTauriDir || "@tauri-apps/api" in allDeps || "@tauri-apps/cli" in allDeps) {
81
+ info.framework = "tauri";
82
+ } else if ("react" in allDeps) {
83
+ info.framework = "react";
84
+ } else if ("express" in allDeps) {
85
+ info.framework = "express";
86
+ } else {
87
+ info.framework = "node";
88
+ }
89
+ if ("vitest" in allDeps || "jest" in allDeps) info.extras.push("testing");
90
+ if ("prisma" in allDeps || "@prisma/client" in allDeps) info.extras.push("prisma");
91
+ if ("tailwindcss" in allDeps) info.extras.push("tailwind");
92
+ }
93
+ if (requirementsTxt !== null && info.framework === "unknown") {
94
+ info.language = "python";
95
+ if (/\bfastapi\b/i.test(requirementsTxt)) {
96
+ info.framework = "fastapi";
97
+ }
98
+ }
99
+ if (hasTauriDir && info.framework === "unknown") {
100
+ info.framework = "tauri";
101
+ }
102
+ return info;
103
+ }
104
+
105
+ // src/detectors/gitDetector.ts
106
+ var import_promises2 = require("fs/promises");
107
+ var import_node_path2 = require("path");
108
+ async function isGitRepo(projectPath) {
109
+ try {
110
+ await (0, import_promises2.access)((0, import_node_path2.join)(projectPath, ".git"));
111
+ return true;
112
+ } catch {
113
+ return false;
114
+ }
115
+ }
116
+
117
+ // src/utils/blueprintParser.ts
118
+ function parseBlueprint(content) {
119
+ const features = [];
120
+ const sectionRegex = /^## (.+)$/gm;
121
+ const sections = [];
122
+ let m;
123
+ while ((m = sectionRegex.exec(content)) !== null) {
124
+ sections.push({ name: m[1].trim(), start: m.index });
125
+ }
126
+ for (let i = 0; i < sections.length; i++) {
127
+ const section = sections[i];
128
+ const end = i + 1 < sections.length ? sections[i + 1].start : content.length;
129
+ const body = content.slice(section.start, end);
130
+ const items = [...body.matchAll(/^[-*]\s+(.+)$/gm)].map((r) => r[1].trim());
131
+ features.push({ name: section.name, items });
132
+ }
133
+ return features;
134
+ }
135
+
136
+ // src/templates/react.ts
137
+ function claudeMd(stack) {
138
+ const lang = stack.hasTypeScript ? "TypeScript" : "JavaScript";
139
+ const testLine = stack.extras.includes("testing") ? "- `npm test` \u2014 run tests\n" : "";
140
+ return `# CLAUDE.md \u2014 React Project
141
+
142
+ ## Stack
143
+ - Framework : React (${lang})
144
+ - Language : ${lang}
145
+ - Build : Vite
146
+
147
+ ## Commands
148
+ - \`npm run dev\` \u2014 development server
149
+ - \`npm run build\` \u2014 production build
150
+ ${testLine}
151
+ ## Structure
152
+ src/
153
+ components/ \u2190 UI components (PascalCase)
154
+ hooks/ \u2190 custom hooks (prefix: use*)
155
+ pages/ \u2190 page-level components
156
+ utils/ \u2190 shared helpers
157
+
158
+ ## Conventions
159
+ 1. Components in PascalCase
160
+ 2. Hooks prefixed with \`use\`
161
+ 3. Props interfaces named \`*Props\`
162
+ 4. Tout output console passe par un logger centralis\xE9
163
+ `;
164
+ }
165
+ function workflow(stack) {
166
+ const lang = stack.hasTypeScript ? "TypeScript" : "JavaScript";
167
+ return `# Agent Workflow \u2014 React Project
168
+
169
+ ## Stack d\xE9tect\xE9e
170
+ Framework: React | Language: ${lang}
171
+
172
+ ## Agents
173
+
174
+ ### Agent 1 \xB7 Components
175
+ P\xE9rim\xE8tre : composants UI r\xE9utilisables
176
+ Produit : src/components/
177
+ Crit\xE8re : composants document\xE9s et test\xE9s
178
+
179
+ ### Agent 2 \xB7 State & Hooks
180
+ P\xE9rim\xE8tre : state management, hooks personnalis\xE9s
181
+ Produit : src/hooks/
182
+ Crit\xE8re : hooks test\xE9s unitairement
183
+
184
+ ### Agent 3 \xB7 Pages & Routing
185
+ P\xE9rim\xE8tre : assemblage des pages, react-router
186
+ Produit : src/pages/
187
+ Crit\xE8re : navigation fonctionnelle
188
+
189
+ ### Agent 4 \xB7 Tests & CI
190
+ P\xE9rim\xE8tre : couverture de tests, configuration CI
191
+ Produit : tests/, .github/workflows/
192
+ Crit\xE8re : npm test passe
193
+ `;
194
+ }
195
+
196
+ // src/templates/nextjs.ts
197
+ function claudeMd2(stack) {
198
+ const hasTailwind = stack.extras.includes("tailwind");
199
+ const hasPrisma = stack.extras.includes("prisma");
200
+ return `# CLAUDE.md \u2014 Next.js Project
201
+
202
+ ## Stack
203
+ - Framework : Next.js (TypeScript)
204
+ - Rendering : App Router (RSC + Client Components)
205
+ - Styling : ${hasTailwind ? "Tailwind CSS" : "CSS Modules"}
206
+ ${hasPrisma ? "- Database : Prisma ORM\n" : ""}
207
+ ## Commands
208
+ - \`npm run dev\` \u2014 development server (http://localhost:3000)
209
+ - \`npm run build\` \u2014 production build
210
+ - \`npm start\` \u2014 production server
211
+ - \`npm test\` \u2014 run tests
212
+
213
+ ## Structure
214
+ src/
215
+ app/ \u2190 App Router pages and layouts
216
+ components/ \u2190 shared UI components
217
+ lib/ \u2190 server utilities, db clients
218
+ utils/ \u2190 shared helpers
219
+
220
+ ## Conventions
221
+ 1. Server Components by default, \`'use client'\` only when needed
222
+ 2. API routes in \`src/app/api/\`
223
+ 3. Environment variables via \`src/env.ts\` (validated)
224
+ 4. Tout output console passe par un logger centralis\xE9
225
+ `;
226
+ }
227
+ function workflow2(stack) {
228
+ const hasPrisma = stack.extras.includes("prisma");
229
+ return `# Agent Workflow \u2014 Next.js Project
230
+
231
+ ## Stack d\xE9tect\xE9e
232
+ Framework: Next.js | Language: TypeScript
233
+
234
+ ## Agents
235
+
236
+ ### Agent 1 \xB7 Data Layer
237
+ P\xE9rim\xE8tre : sch\xE9ma${hasPrisma ? " Prisma" : ""}, types, server actions
238
+ Produit : src/lib/, ${hasPrisma ? "prisma/schema.prisma" : "src/types/"}
239
+ Crit\xE8re : types compilent, migrations propres
240
+
241
+ ### Agent 2 \xB7 UI Components
242
+ P\xE9rim\xE8tre : composants r\xE9utilisables (Server + Client)
243
+ Produit : src/components/
244
+ Crit\xE8re : composants rendus sans erreur
245
+
246
+ ### Agent 3 \xB7 Pages & Layout
247
+ P\xE9rim\xE8tre : App Router, layouts, pages
248
+ Produit : src/app/
249
+ Crit\xE8re : navigation fonctionnelle, build passe
250
+
251
+ ### Agent 4 \xB7 API & Tests
252
+ P\xE9rim\xE8tre : API routes, tests e2e/unitaires
253
+ Produit : src/app/api/, tests/
254
+ Crit\xE8re : npm test passe
255
+ `;
256
+ }
257
+
258
+ // src/templates/tauri.ts
259
+ function claudeMd3(stack) {
260
+ const lang = stack.hasTypeScript ? "TypeScript" : "JavaScript";
261
+ return `# CLAUDE.md \u2014 Tauri Project
262
+
263
+ ## Stack
264
+ - Framework : Tauri (Rust + ${lang} frontend)
265
+ - Language : Rust (backend) + ${lang} (frontend)
266
+ - Build : Cargo + Vite
267
+
268
+ ## Commands
269
+ - \`npm run tauri dev\` \u2014 development (hot reload)
270
+ - \`npm run tauri build\` \u2014 production bundle
271
+ - \`npm run build\` \u2014 frontend only
272
+ - \`npm test\` \u2014 run tests
273
+
274
+ ## Structure
275
+ src/ \u2190 frontend (${lang})
276
+ components/
277
+ utils/
278
+ src-tauri/ \u2190 Rust backend
279
+ src/
280
+ main.rs \u2190 Tauri entry point
281
+ commands.rs \u2190 Tauri commands (IPC)
282
+ tauri.conf.json
283
+
284
+ ## Conventions
285
+ 1. IPC commands defined in \`src-tauri/src/commands.rs\`
286
+ 2. Frontend invokes via \`@tauri-apps/api/tauri\`
287
+ 3. No direct filesystem access from frontend
288
+ 4. Tout output console passe par un logger centralis\xE9
289
+ `;
290
+ }
291
+ function workflow3(stack) {
292
+ const lang = stack.hasTypeScript ? "TypeScript" : "JavaScript";
293
+ return `# Agent Workflow \u2014 Tauri Project
294
+
295
+ ## Stack d\xE9tect\xE9e
296
+ Framework: Tauri | Language: Rust + ${lang}
297
+
298
+ ## Agents
299
+
300
+ ### Agent 1 \xB7 Rust Commands
301
+ P\xE9rim\xE8tre : commandes Tauri (IPC), permissions
302
+ Produit : src-tauri/src/commands.rs, tauri.conf.json
303
+ Crit\xE8re : \`cargo build\` passe
304
+
305
+ ### Agent 2 \xB7 Frontend UI
306
+ P\xE9rim\xE8tre : interface ${lang}, int\xE9gration IPC
307
+ Produit : src/components/, src/utils/
308
+ Crit\xE8re : appels IPC fonctionnels
309
+
310
+ ### Agent 3 \xB7 Build & Packaging
311
+ P\xE9rim\xE8tre : configuration build, ic\xF4nes, installeurs
312
+ Produit : src-tauri/tauri.conf.json, icons/
313
+ Crit\xE8re : \`npm run tauri build\` produit un bundle
314
+
315
+ ### Agent 4 \xB7 Tests
316
+ P\xE9rim\xE8tre : tests Rust + tests frontend
317
+ Produit : src-tauri/tests/, tests/
318
+ Crit\xE8re : \`cargo test\` + \`npm test\` passent
319
+ `;
320
+ }
321
+
322
+ // src/templates/fastapi.ts
323
+ function claudeMd4(_stack) {
324
+ return `# CLAUDE.md \u2014 FastAPI Project
325
+
326
+ ## Stack
327
+ - Framework : FastAPI (Python)
328
+ - Language : Python 3.11+
329
+ - Server : Uvicorn
330
+ - Validation: Pydantic v2
331
+
332
+ ## Commands
333
+ - \`uvicorn main:app --reload\` \u2014 development server (http://localhost:8000)
334
+ - \`pytest\` \u2014 run tests
335
+ - \`pip install -r requirements.txt\` \u2014 install dependencies
336
+
337
+ ## Structure
338
+ app/
339
+ main.py \u2190 FastAPI app entry point
340
+ routers/ \u2190 API route groups
341
+ models/ \u2190 Pydantic models
342
+ services/ \u2190 business logic
343
+ dependencies/ \u2190 FastAPI dependencies (DI)
344
+ tests/ \u2190 pytest tests
345
+
346
+ ## Conventions
347
+ 1. Routers grouped by domain in \`app/routers/\`
348
+ 2. Pydantic models for all request/response bodies
349
+ 3. Business logic in \`app/services/\`, not in routes
350
+ 4. Async endpoints by default (\`async def\`)
351
+ 5. Environment variables via \`python-dotenv\` + \`pydantic-settings\`
352
+ `;
353
+ }
354
+ function workflow4(_stack) {
355
+ return `# Agent Workflow \u2014 FastAPI Project
356
+
357
+ ## Stack d\xE9tect\xE9e
358
+ Framework: FastAPI | Language: Python
359
+
360
+ ## Agents
361
+
362
+ ### Agent 1 \xB7 Models & Schemas
363
+ P\xE9rim\xE8tre : mod\xE8les Pydantic, sch\xE9mas DB (SQLAlchemy/SQLModel)
364
+ Produit : app/models/
365
+ Crit\xE8re : mod\xE8les valid\xE9s, migrations propres
366
+
367
+ ### Agent 2 \xB7 Services
368
+ P\xE9rim\xE8tre : logique m\xE9tier, acc\xE8s base de donn\xE9es
369
+ Produit : app/services/
370
+ Crit\xE8re : services test\xE9s unitairement (pytest)
371
+
372
+ ### Agent 3 \xB7 Routers & API
373
+ P\xE9rim\xE8tre : routes FastAPI, d\xE9pendances, auth
374
+ Produit : app/routers/, app/dependencies/
375
+ Crit\xE8re : endpoints document\xE9s (OpenAPI), tests d'int\xE9gration
376
+
377
+ ### Agent 4 \xB7 Tests & CI
378
+ P\xE9rim\xE8tre : couverture pytest, configuration CI
379
+ Produit : tests/, .github/workflows/
380
+ Crit\xE8re : \`pytest\` passe \xE0 100%
381
+ `;
382
+ }
383
+
384
+ // src/templates/express.ts
385
+ function claudeMd5(stack) {
386
+ const lang = stack.hasTypeScript ? "TypeScript" : "JavaScript";
387
+ const hasPrisma = stack.extras.includes("prisma");
388
+ return `# CLAUDE.md \u2014 Express Project
389
+
390
+ ## Stack
391
+ - Framework : Express (${lang})
392
+ - Language : ${lang}
393
+ - Runtime : Node.js 20+
394
+ ${hasPrisma ? "- Database : Prisma ORM\n" : ""}
395
+ ## Commands
396
+ - \`npm run dev\` \u2014 development server (nodemon)
397
+ - \`npm run build\` \u2014 compile TypeScript
398
+ - \`npm start\` \u2014 production server
399
+ - \`npm test\` \u2014 run tests
400
+
401
+ ## Structure
402
+ src/
403
+ routes/ \u2190 Express routers (one per domain)
404
+ controllers/ \u2190 request handlers
405
+ services/ \u2190 business logic
406
+ middleware/ \u2190 Express middleware
407
+ utils/ \u2190 shared helpers
408
+
409
+ ## Conventions
410
+ 1. Routes grouped by domain in \`src/routes/\`
411
+ 2. Business logic in \`src/services/\`, not in controllers
412
+ 3. Middleware for cross-cutting concerns (auth, validation)
413
+ 4. Tout output console passe par un logger centralis\xE9
414
+ `;
415
+ }
416
+ function workflow5(stack) {
417
+ const lang = stack.hasTypeScript ? "TypeScript" : "JavaScript";
418
+ return `# Agent Workflow \u2014 Express Project
419
+
420
+ ## Stack d\xE9tect\xE9e
421
+ Framework: Express | Language: ${lang}
422
+
423
+ ## Agents
424
+
425
+ ### Agent 1 \xB7 Data & Models
426
+ P\xE9rim\xE8tre : mod\xE8les de donn\xE9es, acc\xE8s DB
427
+ Produit : src/models/, src/services/db.ts
428
+ Crit\xE8re : connexion DB fonctionnelle
429
+
430
+ ### Agent 2 \xB7 Services
431
+ P\xE9rim\xE8tre : logique m\xE9tier
432
+ Produit : src/services/
433
+ Crit\xE8re : services test\xE9s unitairement
434
+
435
+ ### Agent 3 \xB7 Routes & Controllers
436
+ P\xE9rim\xE8tre : routes Express, validation, auth
437
+ Produit : src/routes/, src/controllers/, src/middleware/
438
+ Crit\xE8re : endpoints r\xE9pondent correctement
439
+
440
+ ### Agent 4 \xB7 Tests & CI
441
+ P\xE9rim\xE8tre : tests d'int\xE9gration, configuration CI
442
+ Produit : tests/, .github/workflows/
443
+ Crit\xE8re : npm test passe
444
+ `;
445
+ }
446
+
447
+ // src/templates/node.ts
448
+ function claudeMd6(stack) {
449
+ const lang = stack.hasTypeScript ? "TypeScript" : "JavaScript";
450
+ return `# CLAUDE.md \u2014 Node.js Project
451
+
452
+ ## Stack
453
+ - Runtime : Node.js 20+
454
+ - Language : ${lang}
455
+
456
+ ## Commands
457
+ - \`npm run dev\` \u2014 development (with watch)
458
+ - \`npm run build\` \u2014 compile${stack.hasTypeScript ? " TypeScript" : ""}
459
+ - \`npm start\` \u2014 run production build
460
+ - \`npm test\` \u2014 run tests
461
+
462
+ ## Structure
463
+ src/
464
+ index.ts \u2190 entry point
465
+ lib/ \u2190 core library code
466
+ utils/ \u2190 shared helpers
467
+
468
+ ## Conventions
469
+ 1. Modules follow single-responsibility principle
470
+ 2. Async/await over callbacks
471
+ 3. Tout output console passe par un logger centralis\xE9
472
+ `;
473
+ }
474
+ function workflow6(stack) {
475
+ const lang = stack.hasTypeScript ? "TypeScript" : "JavaScript";
476
+ return `# Agent Workflow \u2014 Node.js Project
477
+
478
+ ## Stack d\xE9tect\xE9e
479
+ Runtime: Node.js | Language: ${lang}
480
+
481
+ ## Agents
482
+
483
+ ### Agent 1 \xB7 Core Library
484
+ P\xE9rim\xE8tre : logique principale
485
+ Produit : src/lib/
486
+ Crit\xE8re : module fonctionne et test\xE9
487
+
488
+ ### Agent 2 \xB7 CLI / API
489
+ P\xE9rim\xE8tre : interface utilisateur (CLI ou API)
490
+ Produit : src/index.ts, src/cli.ts
491
+ Crit\xE8re : commandes fonctionnelles
492
+
493
+ ### Agent 3 \xB7 Tests & CI
494
+ P\xE9rim\xE8tre : couverture de tests, configuration CI
495
+ Produit : tests/, .github/workflows/
496
+ Crit\xE8re : npm test passe
497
+ `;
498
+ }
499
+
500
+ // src/templates/unknown.ts
501
+ function claudeMd7(_stack) {
502
+ return `# CLAUDE.md
503
+
504
+ ## Stack
505
+ Stack non d\xE9tect\xE9e automatiquement \u2014 \xE0 remplir manuellement.
506
+
507
+ ## Commands
508
+ - \xC0 d\xE9finir selon le projet
509
+
510
+ ## Structure
511
+ src/ \u2190 code source
512
+ tests/ \u2190 tests
513
+
514
+ ## Conventions
515
+ 1. Tout output console passe par un logger centralis\xE9
516
+ 2. \xC0 compl\xE9ter selon les conventions du projet
517
+ `;
518
+ }
519
+ function workflow7(_stack) {
520
+ return `# Agent Workflow
521
+
522
+ ## Stack d\xE9tect\xE9e
523
+ Stack inconnue \u2014 workflow g\xE9n\xE9rique.
524
+
525
+ ## Agents
526
+
527
+ ### Agent 1 \xB7 Setup
528
+ P\xE9rim\xE8tre : configuration initiale du projet
529
+ Produit : structure de base
530
+ Crit\xE8re : projet compilable
531
+
532
+ ### Agent 2 \xB7 Core
533
+ P\xE9rim\xE8tre : logique principale
534
+ Produit : src/
535
+ Crit\xE8re : fonctionnalit\xE9s principales op\xE9rationnelles
536
+
537
+ ### Agent 3 \xB7 Tests
538
+ P\xE9rim\xE8tre : couverture de tests
539
+ Produit : tests/
540
+ Crit\xE8re : tests passent
541
+ `;
542
+ }
543
+
544
+ // src/generators/claudeMdGenerator.ts
545
+ function generateClaudeMd(stack, blueprintContent) {
546
+ let base;
547
+ switch (stack.framework) {
548
+ case "react":
549
+ base = claudeMd(stack);
550
+ break;
551
+ case "nextjs":
552
+ base = claudeMd2(stack);
553
+ break;
554
+ case "tauri":
555
+ base = claudeMd3(stack);
556
+ break;
557
+ case "fastapi":
558
+ base = claudeMd4(stack);
559
+ break;
560
+ case "express":
561
+ base = claudeMd5(stack);
562
+ break;
563
+ case "node":
564
+ base = claudeMd6(stack);
565
+ break;
566
+ default:
567
+ base = claudeMd7(stack);
568
+ }
569
+ if (!blueprintContent) return base;
570
+ const features = parseBlueprint(blueprintContent);
571
+ if (features.length === 0) return base;
572
+ const featureLines = features.map((f, i) => {
573
+ const sub = f.items.length > 0 ? "\n" + f.items.map((it) => ` - ${it}`).join("\n") : "";
574
+ return `${i + 1}. **${f.name}**${sub}`;
575
+ }).join("\n");
576
+ const featureSection = `
577
+ ## Features (Blueprint)
578
+
579
+ ${featureLines}
580
+ `;
581
+ const conventionsIdx = base.indexOf("\n## Conventions");
582
+ if (conventionsIdx !== -1) {
583
+ return base.slice(0, conventionsIdx) + featureSection + base.slice(conventionsIdx);
584
+ }
585
+ return base + featureSection;
586
+ }
587
+
588
+ // src/utils/agentParser.ts
589
+ function toSlug(name) {
590
+ return name.toLowerCase().replace(/[·•&]/g, " ").replace(/[^\w\s-]/g, "").trim().replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
591
+ }
592
+ function getFieldValue(lines, pattern) {
593
+ for (const line of lines) {
594
+ const m = line.match(pattern);
595
+ if (m) return (m[1] ?? "").trim();
596
+ }
597
+ return "";
598
+ }
599
+ function extractAgentsFromWorkflow(content) {
600
+ const agents = [];
601
+ const blocks = content.split(/(?=^### Agent \d)/m).filter((b) => /^### Agent \d/.test(b.trimStart()));
602
+ for (const block of blocks) {
603
+ const lines = block.split("\n");
604
+ const headerMatch = lines[0].match(/^### Agent (\d+)\s*[·•]\s*(.+)$/);
605
+ if (!headerMatch) continue;
606
+ const number = parseInt(headerMatch[1], 10);
607
+ const name = headerMatch[2].trim();
608
+ const fullName = `Agent ${number} \xB7 ${name}`;
609
+ const slug = toSlug(name);
610
+ const scope = getFieldValue(lines, /Périmètre\s*:\s*(.+)/);
611
+ const criterion = getFieldValue(lines, /Critère[s]?\s*:\s*(.+)/);
612
+ const outputs = [];
613
+ const produitIdx = lines.findIndex((l) => /Produit\s*:/.test(l));
614
+ if (produitIdx !== -1) {
615
+ const inlineVal = (lines[produitIdx].match(/Produit\s*:\s*(.+)/)?.[1] ?? "").trim();
616
+ if (inlineVal) {
617
+ outputs.push(inlineVal);
618
+ } else {
619
+ for (let i = produitIdx + 1; i < lines.length; i++) {
620
+ const line = lines[i];
621
+ if (/^\s+[-]/.test(line)) {
622
+ outputs.push(line.trim().replace(/^-\s*/, ""));
623
+ } else if (line.trim() !== "" && !/^\s/.test(line)) {
624
+ break;
625
+ }
626
+ }
627
+ }
628
+ }
629
+ agents.push({ number, name, fullName, slug, scope, outputs, criterion });
630
+ }
631
+ return agents;
632
+ }
633
+
634
+ // src/generators/workflowGenerator.ts
635
+ function generateWorkflow(stack, blueprintContent) {
636
+ if (blueprintContent) return blueprintWorkflow(stack, blueprintContent);
637
+ switch (stack.framework) {
638
+ case "react":
639
+ return workflow(stack);
640
+ case "nextjs":
641
+ return workflow2(stack);
642
+ case "tauri":
643
+ return workflow3(stack);
644
+ case "fastapi":
645
+ return workflow4(stack);
646
+ case "express":
647
+ return workflow5(stack);
648
+ case "node":
649
+ return workflow6(stack);
650
+ default:
651
+ return workflow7(stack);
652
+ }
653
+ }
654
+ function blueprintWorkflow(stack, blueprintContent) {
655
+ const features = parseBlueprint(blueprintContent);
656
+ const agentBlocks = features.map((feature, i) => {
657
+ const n = i + 1;
658
+ const slug = toSlug(feature.name);
659
+ const outputLines = feature.items.length > 0 ? feature.items.map((item) => ` - ${item}`).join("\n") : ` - src/${slug}/`;
660
+ return `### Agent ${n} \xB7 ${feature.name}
661
+ P\xE9rim\xE8tre : Impl\xE9menter la fonctionnalit\xE9 ${feature.name.toLowerCase()}
662
+ Produit :
663
+ ${outputLines}
664
+ Crit\xE8re : npm test (tests ${feature.name.toLowerCase()} passent)`;
665
+ });
666
+ const ciN = features.length + 1;
667
+ agentBlocks.push(
668
+ `### Agent ${ciN} \xB7 Tests & CI
669
+ P\xE9rim\xE8tre : Couverture de tests compl\xE8te et configuration du pipeline CI
670
+ Produit :
671
+ - tests/
672
+ - .github/workflows/
673
+ Crit\xE8re : npm test passe, pipeline CI vert`
674
+ );
675
+ return `# Agent Workflow \u2014 ${stack.framework} (Blueprint)
676
+
677
+ ## Stack d\xE9tect\xE9e
678
+ Framework: ${stack.framework} | Language: ${stack.language}
679
+
680
+ ## Agents
681
+
682
+ ${agentBlocks.join("\n\n")}
683
+ `;
684
+ }
685
+
686
+ // src/generators/playbookGenerator.ts
687
+ function generatePlaybook({ agents, projectName }) {
688
+ const agentBlocks = agents.map((a) => agentBlock(a)).join("\n---\n\n");
689
+ return `# PLAYBOOK.md \u2014 ${projectName}
690
+
691
+ > Donne cette instruction \xE0 Claude Code : 'Lis PLAYBOOK.md et ex\xE9cute la proc\xE9dure.'
692
+
693
+ ## R\xE8gles d'ex\xE9cution globales
694
+
695
+ Avant chaque agent :
696
+ 1. Lire \`CLAUDE.md\`
697
+ 2. Lire \`agents/agent-{N}-{slug}/skills.md\` (le fichier de l'agent courant)
698
+
699
+ Apr\xE8s chaque agent :
700
+ - Ex\xE9cuter le crit\xE8re de succ\xE8s
701
+ - Si succ\xE8s \u2192 annoncer "\u2705 Agent N termin\xE9" et passer au suivant
702
+ - Si \xE9chec \u2192 analyser la cause racine, corriger, r\xE9ex\xE9cuter (max 3 tentatives)
703
+ - Apr\xE8s 3 \xE9checs cons\xE9cutifs \u2192 pause et demander validation humaine
704
+ - **Ne jamais passer \xE0 l'agent suivant sans crit\xE8re valid\xE9**
705
+
706
+ ## Agents
707
+
708
+ ${agentBlocks}
709
+
710
+ ## It\xE9rations futures
711
+
712
+ Lorsqu'un nouvel agent est ajout\xE9 via \`agentkit add --feature <description>\` :
713
+ 1. Un nouveau bloc agent est ajout\xE9 \xE0 la fin de \`AGENT_WORKFLOW.md\`
714
+ 2. Le dossier \`agents/agent-{N}-{slug}/\` est cr\xE9\xE9 avec \`skills.md\` et \`context.md\`
715
+ 3. Ce \`PLAYBOOK.md\` est r\xE9g\xE9n\xE9r\xE9 automatiquement pour inclure le nouvel agent
716
+ 4. L'ex\xE9cution reprend \xE0 ce nouvel agent uniquement \u2014 les agents pr\xE9c\xE9dents ne sont pas r\xE9ex\xE9cut\xE9s
717
+
718
+ ## Validation humaine requise
719
+
720
+ Les cas suivants n\xE9cessitent une pause et une confirmation humaine avant de continuer :
721
+ - **3 \xE9checs cons\xE9cutifs** sur le crit\xE8re de succ\xE8s d'un agent
722
+ - **D\xE9pendance externe manquante** : cl\xE9 API, variable d'environnement non d\xE9finie, service tiers inaccessible
723
+ - **Conflit** entre le blueprint fourni (\`--blueprint\`) et la stack d\xE9tect\xE9e automatiquement
724
+ `;
725
+ }
726
+ function agentBlock(agent) {
727
+ const skillsPath = `agents/agent-${agent.number}-${agent.slug}/skills.md`;
728
+ const outputLines = agent.outputs.length > 0 ? agent.outputs.map((o) => `- ${o}`).join("\n") : "- (voir skills.md pour le d\xE9tail)";
729
+ return `### ${agent.fullName}
730
+
731
+ **P\xE9rim\xE8tre** : ${agent.scope}
732
+
733
+ **Skills** : \`${skillsPath}\`
734
+
735
+ **Fichiers produits** :
736
+ ${outputLines}
737
+
738
+ **Crit\xE8re de succ\xE8s** :
739
+ \`\`\`bash
740
+ ${agent.criterion || "npm run build && npm test"}
741
+ \`\`\`
742
+
743
+ **En cas d'\xE9chec** :
744
+ 1. Analyser le message d'erreur complet
745
+ 2. Corriger la cause racine (pas les sympt\xF4mes)
746
+ 3. R\xE9ex\xE9cuter le crit\xE8re (max 3 tentatives)
747
+ 4. Apr\xE8s 3 \xE9checs \u2192 demander validation humaine
748
+ `;
749
+ }
750
+
751
+ // src/generators/skillsGenerator.ts
752
+ var import_promises3 = require("fs/promises");
753
+ var import_node_path3 = require("path");
754
+ async function generateSkills(agents, outputDir) {
755
+ for (const agent of agents) {
756
+ const agentDir = (0, import_node_path3.join)(outputDir, "agents", `agent-${agent.number}-${agent.slug}`);
757
+ await (0, import_promises3.mkdir)(agentDir, { recursive: true });
758
+ await (0, import_promises3.writeFile)((0, import_node_path3.join)(agentDir, "skills.md"), skillsMd(agent), "utf-8");
759
+ await (0, import_promises3.writeFile)((0, import_node_path3.join)(agentDir, "context.md"), contextMd(agent), "utf-8");
760
+ }
761
+ }
762
+ function skillsMd(agent) {
763
+ return `# Skills \u2014 ${agent.fullName}
764
+
765
+ > Ce fichier est lu par l'agent avant de commencer.
766
+
767
+ ## Contexte technique
768
+
769
+ <!-- \xC0 remplir : biblioth\xE8ques, versions, d\xE9cisions d'architecture sp\xE9cifiques \xE0 cet agent -->
770
+
771
+ ## Documentation de r\xE9f\xE9rence
772
+
773
+ <!-- \xC0 remplir : liens vers docs, exemples, ADRs pertinents -->
774
+
775
+ ## Conventions sp\xE9cifiques
776
+
777
+ <!-- \xC0 remplir : r\xE8gles propres \xE0 cet agent (naming, patterns, structure de fichiers) -->
778
+ `;
779
+ }
780
+ function contextMd(agent) {
781
+ const outputLines = agent.outputs.length > 0 ? agent.outputs.map((o) => `- ${o}`).join("\n") : "- (voir AGENT_WORKFLOW.md)";
782
+ return `# Context \u2014 ${agent.fullName}
783
+
784
+ > Ce fichier fournit le contexte additionnel \xE0 l'agent avant ex\xE9cution.
785
+ > \xC0 compl\xE9ter avant de lancer cet agent.
786
+
787
+ ## P\xE9rim\xE8tre
788
+
789
+ ${agent.scope}
790
+
791
+ ## Fichiers produits attendus
792
+
793
+ ${outputLines}
794
+
795
+ ## Crit\xE8re de succ\xE8s
796
+
797
+ \`${agent.criterion || "npm run build && npm test"}\`
798
+ `;
799
+ }
800
+
801
+ // src/utils/logger.ts
802
+ var import_chalk = __toESM(require("chalk"), 1);
803
+ var logger = {
804
+ info: (message) => {
805
+ process.stdout.write(import_chalk.default.blue("\u2139") + " " + message + "\n");
806
+ },
807
+ success: (message) => {
808
+ process.stdout.write(import_chalk.default.green("\u2714") + " " + message + "\n");
809
+ },
810
+ warn: (message) => {
811
+ process.stdout.write(import_chalk.default.yellow("\u26A0") + " " + message + "\n");
812
+ },
813
+ error: (message) => {
814
+ process.stderr.write(import_chalk.default.red("\u2716") + " " + message + "\n");
815
+ }
816
+ };
817
+
818
+ // src/commands/init.ts
819
+ var import_node_path5 = require("path");
820
+ var FRAMEWORK_LABELS = {
821
+ react: "React",
822
+ nextjs: "Next.js",
823
+ tauri: "Tauri",
824
+ fastapi: "FastAPI (Python)",
825
+ express: "Express",
826
+ node: "Node.js",
827
+ unknown: "Unknown (generic)"
828
+ };
829
+ async function fileExists(path) {
830
+ try {
831
+ await (0, import_promises4.readFile)(path);
832
+ return true;
833
+ } catch {
834
+ return false;
835
+ }
836
+ }
837
+ function registerInit(program2) {
838
+ program2.command("init").description("G\xE9n\xE8re CLAUDE.md et AGENT_WORKFLOW.md dans le dossier courant").option("-f, --force", "\xC9crase les fichiers existants sans confirmation").option("--blueprint <path>", "Fichier blueprint .md \xE0 utiliser pour personnaliser les fichiers g\xE9n\xE9r\xE9s").action(async (options) => {
839
+ const cwd = process.cwd();
840
+ const spinner = (0, import_ora.default)("D\xE9tection de la stack\u2026").start();
841
+ const [stack, isGit] = await Promise.all([detectStack(cwd), isGitRepo(cwd)]);
842
+ spinner.stop();
843
+ if (!isGit) {
844
+ logger.warn("Ce dossier n'est pas un repo git \u2014 lancez git init si n\xE9cessaire");
845
+ }
846
+ const label = FRAMEWORK_LABELS[stack.framework];
847
+ logger.info(`Stack d\xE9tect\xE9e : ${label} (${stack.language})`);
848
+ const { confirmed } = await import_inquirer.default.prompt([
849
+ {
850
+ type: "confirm",
851
+ name: "confirmed",
852
+ message: `G\xE9n\xE9rer les fichiers pour ${label} ?`,
853
+ default: true
854
+ }
855
+ ]);
856
+ if (!confirmed) {
857
+ logger.warn("Annul\xE9.");
858
+ return;
859
+ }
860
+ const claudeMdPath = (0, import_node_path4.join)(cwd, "CLAUDE.md");
861
+ const workflowPath = (0, import_node_path4.join)(cwd, "AGENT_WORKFLOW.md");
862
+ const playbookPath = (0, import_node_path4.join)(cwd, "PLAYBOOK.md");
863
+ let projectName = (0, import_node_path5.basename)(cwd);
864
+ try {
865
+ const pkg = JSON.parse(await (0, import_promises4.readFile)((0, import_node_path4.join)(cwd, "package.json"), "utf-8"));
866
+ if (pkg.name) projectName = pkg.name;
867
+ } catch {
868
+ }
869
+ if (!options.force) {
870
+ const existing = [];
871
+ if (await fileExists(claudeMdPath)) existing.push("CLAUDE.md");
872
+ if (await fileExists(workflowPath)) existing.push("AGENT_WORKFLOW.md");
873
+ if (await fileExists(playbookPath)) existing.push("PLAYBOOK.md");
874
+ if (existing.length > 0) {
875
+ const { overwrite } = await import_inquirer.default.prompt([
876
+ {
877
+ type: "confirm",
878
+ name: "overwrite",
879
+ message: `${existing.join(" et ")} existe d\xE9j\xE0. \xC9craser ?`,
880
+ default: false
881
+ }
882
+ ]);
883
+ if (!overwrite) {
884
+ logger.warn("Annul\xE9.");
885
+ return;
886
+ }
887
+ }
888
+ }
889
+ let blueprintContent;
890
+ if (options.blueprint) {
891
+ try {
892
+ blueprintContent = await (0, import_promises4.readFile)(options.blueprint, "utf-8");
893
+ } catch {
894
+ logger.error(`Blueprint introuvable : ${options.blueprint}`);
895
+ process.exit(1);
896
+ }
897
+ }
898
+ const genSpinner = (0, import_ora.default)("G\xE9n\xE9ration des fichiers\u2026").start();
899
+ const claudeMdContent = generateClaudeMd(stack, blueprintContent);
900
+ const workflowContent = generateWorkflow(stack, blueprintContent);
901
+ const agents = extractAgentsFromWorkflow(workflowContent);
902
+ const playbookContent = generatePlaybook({ agents, projectName });
903
+ await (0, import_promises4.writeFile)(claudeMdPath, claudeMdContent, "utf-8");
904
+ await (0, import_promises4.writeFile)(workflowPath, workflowContent, "utf-8");
905
+ await (0, import_promises4.writeFile)(playbookPath, playbookContent, "utf-8");
906
+ await generateSkills(agents, cwd);
907
+ genSpinner.succeed("Fichiers g\xE9n\xE9r\xE9s");
908
+ logger.success("CLAUDE.md \u2192 cr\xE9\xE9");
909
+ logger.success("AGENT_WORKFLOW.md \u2192 cr\xE9\xE9");
910
+ logger.success("PLAYBOOK.md \u2192 cr\xE9\xE9");
911
+ logger.success(`agents/ \u2192 ${agents.length} dossier(s) cr\xE9\xE9(s)`);
912
+ });
913
+ }
914
+
915
+ // src/commands/add.ts
916
+ var import_promises5 = require("fs/promises");
917
+ var import_node_path6 = require("path");
918
+ var import_inquirer2 = __toESM(require("inquirer"), 1);
919
+ function featureToAgentName(description) {
920
+ const clean = description.replace(/^(add|implement|create|build|integrate|setup|configure|refactor|improve)\s+/i, "").trim();
921
+ return clean.replace(/\b\w/g, (c) => c.toUpperCase());
922
+ }
923
+ async function addFeatureToProject(description, projectDir) {
924
+ const workflowPath = (0, import_node_path6.join)(projectDir, "AGENT_WORKFLOW.md");
925
+ const playbookPath = (0, import_node_path6.join)(projectDir, "PLAYBOOK.md");
926
+ let workflowContent = "";
927
+ try {
928
+ workflowContent = await (0, import_promises5.readFile)(workflowPath, "utf-8");
929
+ } catch {
930
+ throw new Error(`AGENT_WORKFLOW.md introuvable dans ${projectDir} \u2014 lancez agentkit init`);
931
+ }
932
+ const existingAgents = extractAgentsFromWorkflow(workflowContent);
933
+ const nextNumber = existingAgents.length + 1;
934
+ const name = featureToAgentName(description);
935
+ const slug = toSlug(name);
936
+ const fullName = `Agent ${nextNumber} \xB7 ${name}`;
937
+ const newAgent = {
938
+ number: nextNumber,
939
+ name,
940
+ fullName,
941
+ slug,
942
+ scope: description,
943
+ outputs: [`agents/agent-${nextNumber}-${slug}/`],
944
+ criterion: "npm run build && npm test"
945
+ };
946
+ const agentBlock2 = `
947
+ ### ${fullName}
948
+ P\xE9rim\xE8tre : ${description}
949
+ Produit :
950
+ - agents/agent-${nextNumber}-${slug}/
951
+ Crit\xE8re : npm run build && npm test
952
+ `;
953
+ await (0, import_promises5.writeFile)(workflowPath, workflowContent + agentBlock2, "utf-8");
954
+ await generateSkills([newAgent], projectDir);
955
+ let projectName = (0, import_node_path6.basename)(projectDir);
956
+ try {
957
+ const pkg = JSON.parse(
958
+ await (0, import_promises5.readFile)((0, import_node_path6.join)(projectDir, "package.json"), "utf-8")
959
+ );
960
+ if (pkg.name) projectName = pkg.name;
961
+ } catch {
962
+ }
963
+ const allAgents = [...existingAgents, newAgent];
964
+ const playbookContent = generatePlaybook({ agents: allAgents, projectName });
965
+ await (0, import_promises5.writeFile)(playbookPath, playbookContent, "utf-8");
966
+ return {
967
+ agent: newAgent,
968
+ agentDirPath: (0, import_node_path6.join)(projectDir, "agents", `agent-${nextNumber}-${slug}`)
969
+ };
970
+ }
971
+ function registerAdd(program2) {
972
+ const addCmd = program2.command("add").description("Ajoute des ressources au projet agentkit").option("--feature <description>", "Ajoute un agent depuis une description de feature et r\xE9g\xE9n\xE8re PLAYBOOK.md").action(async (options) => {
973
+ if (options.feature) {
974
+ try {
975
+ const result = await addFeatureToProject(options.feature, process.cwd());
976
+ logger.success(`Agent ajout\xE9 : ${result.agent.fullName}`);
977
+ logger.success(`Dossier cr\xE9\xE9 : agents/agent-${result.agent.number}-${result.agent.slug}/`);
978
+ logger.success("PLAYBOOK.md : r\xE9g\xE9n\xE9r\xE9");
979
+ } catch (err) {
980
+ logger.error(err instanceof Error ? err.message : String(err));
981
+ process.exit(1);
982
+ }
983
+ } else {
984
+ addCmd.help();
985
+ }
986
+ });
987
+ addCmd.command("agent").description("Ajoute un nouvel agent dans AGENT_WORKFLOW.md (interactif)").action(async () => {
988
+ const cwd = process.cwd();
989
+ const workflowPath = (0, import_node_path6.join)(cwd, "AGENT_WORKFLOW.md");
990
+ let existing = "";
991
+ try {
992
+ existing = await (0, import_promises5.readFile)(workflowPath, "utf-8");
993
+ } catch {
994
+ logger.error("AGENT_WORKFLOW.md introuvable \u2014 lancez d'abord : agentkit init");
995
+ process.exit(1);
996
+ }
997
+ const agentCount = (existing.match(/^### Agent \d+/gm) ?? []).length;
998
+ const nextNumber = agentCount + 1;
999
+ const answers = await import_inquirer2.default.prompt([
1000
+ {
1001
+ type: "input",
1002
+ name: "name",
1003
+ message: `Nom de l'agent (ex: "Agent ${nextNumber} \xB7 Feature X") :`,
1004
+ default: `Agent ${nextNumber}`
1005
+ },
1006
+ {
1007
+ type: "input",
1008
+ name: "scope",
1009
+ message: "P\xE9rim\xE8tre (une phrase) :"
1010
+ },
1011
+ {
1012
+ type: "input",
1013
+ name: "outputs",
1014
+ message: "Fichiers produits (s\xE9par\xE9s par des virgules) :"
1015
+ },
1016
+ {
1017
+ type: "input",
1018
+ name: "criterion",
1019
+ message: "Crit\xE8re de succ\xE8s :"
1020
+ }
1021
+ ]);
1022
+ const outputLines = answers.outputs.split(",").map((o) => ` - ${o.trim()}`).join("\n");
1023
+ const agentSection = `
1024
+ ### ${answers.name}
1025
+ P\xE9rim\xE8tre : ${answers.scope}
1026
+ Produit :
1027
+ ${outputLines}
1028
+ Crit\xE8re : ${answers.criterion}
1029
+ `;
1030
+ await (0, import_promises5.writeFile)(workflowPath, existing + agentSection, "utf-8");
1031
+ logger.success(`Agent "${answers.name}" ajout\xE9 dans AGENT_WORKFLOW.md`);
1032
+ });
1033
+ }
1034
+
1035
+ // src/commands/status.ts
1036
+ var import_promises6 = require("fs/promises");
1037
+ var import_node_path7 = require("path");
1038
+ var import_chalk2 = __toESM(require("chalk"), 1);
1039
+ function registerStatus(program2) {
1040
+ program2.command("status").description("Affiche l'\xE9tat du workflow agentkit dans le dossier courant").action(async () => {
1041
+ const cwd = process.cwd();
1042
+ const [stack, isGit, claudeMd8, workflow8] = await Promise.all([
1043
+ detectStack(cwd),
1044
+ isGitRepo(cwd),
1045
+ (0, import_promises6.readFile)((0, import_node_path7.join)(cwd, "CLAUDE.md"), "utf-8").catch(() => null),
1046
+ (0, import_promises6.readFile)((0, import_node_path7.join)(cwd, "AGENT_WORKFLOW.md"), "utf-8").catch(() => null)
1047
+ ]);
1048
+ process.stdout.write("\n" + import_chalk2.default.bold("AgentKit Status") + "\n");
1049
+ process.stdout.write("\u2500".repeat(40) + "\n");
1050
+ process.stdout.write(
1051
+ import_chalk2.default.bold("Git repo : ") + (isGit ? import_chalk2.default.green("\u2714 oui") : import_chalk2.default.red("\u2716 non")) + "\n"
1052
+ );
1053
+ process.stdout.write(
1054
+ import_chalk2.default.bold("Stack : ") + import_chalk2.default.cyan(stack.framework) + " (" + stack.language + ")\n"
1055
+ );
1056
+ process.stdout.write(
1057
+ import_chalk2.default.bold("CLAUDE.md : ") + (claudeMd8 !== null ? import_chalk2.default.green("\u2714 pr\xE9sent") : import_chalk2.default.yellow("\u2716 absent \u2014 lancez agentkit init")) + "\n"
1058
+ );
1059
+ process.stdout.write(
1060
+ import_chalk2.default.bold("AGENT_WORKFLOW.md : ") + (workflow8 !== null ? import_chalk2.default.green("\u2714 pr\xE9sent") : import_chalk2.default.yellow("\u2716 absent \u2014 lancez agentkit init")) + "\n"
1061
+ );
1062
+ if (workflow8 !== null) {
1063
+ const agentMatches = workflow8.match(/^### Agent \d+/gm) ?? [];
1064
+ process.stdout.write(
1065
+ import_chalk2.default.bold("Agents d\xE9finis : ") + import_chalk2.default.cyan(String(agentMatches.length)) + "\n"
1066
+ );
1067
+ }
1068
+ process.stdout.write("\u2500".repeat(40) + "\n\n");
1069
+ });
1070
+ }
1071
+
1072
+ // src/cli.ts
1073
+ var program = new import_commander.Command();
1074
+ program.name("agentkit").description("Scaffolder des workflows multi-agents Claude Code").version("0.1.0");
1075
+ registerInit(program);
1076
+ registerAdd(program);
1077
+ registerStatus(program);
1078
+ program.parse();
1079
+ //# sourceMappingURL=cli.cjs.map