multi-agents-cli 1.1.7 → 1.1.8

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 +2 -18
  2. package/core/workflow/agent.js +6 -285
  3. package/core/workflow/complete.js +5 -141
  4. package/core/workflow/reset.js +21 -28
  5. package/core/workflow/run.js +0 -3
  6. package/init.js +2 -2
  7. package/lib/questions-flow.js +6 -14
  8. package/lib/steps.js +1 -13
  9. package/lib/ui.js +1 -9
  10. package/package.json +1 -1
  11. package/core/templates/.agents/backend/API.md +0 -270
  12. package/core/templates/.agents/backend/AUTH.md +0 -257
  13. package/core/templates/.agents/backend/DB.md +0 -268
  14. package/core/templates/.agents/backend/EVENTS.md +0 -264
  15. package/core/templates/.agents/backend/INIT.md +0 -250
  16. package/core/templates/.agents/backend/JOBS.md +0 -267
  17. package/core/templates/.agents/backend/LOGIC.md +0 -302
  18. package/core/templates/.agents/backend/TESTING.md +0 -277
  19. package/core/templates/.agents/client/ACCESSIBILITY.md +0 -277
  20. package/core/templates/.agents/client/FORMS.md +0 -245
  21. package/core/templates/.agents/client/LOGIC.md +0 -288
  22. package/core/templates/.agents/client/ROUTING.md +0 -246
  23. package/core/templates/.agents/client/TESTING.md +0 -252
  24. package/core/templates/.agents/client/UI.md +0 -237
  25. package/core/templates/.agents/shared/CLOUD.md +0 -229
  26. package/core/templates/.agents/shared/CLOUD_TEARDOWN.md +0 -158
  27. package/core/templates/.agents/shared/SECURITY.md +0 -297
  28. package/core/templates/.frameworks/backend/django.md +0 -55
  29. package/core/templates/.frameworks/backend/express.md +0 -74
  30. package/core/templates/.frameworks/backend/fastapi.md +0 -107
  31. package/core/templates/.frameworks/backend/fastify.md +0 -74
  32. package/core/templates/.frameworks/backend/laravel.md +0 -79
  33. package/core/templates/.frameworks/backend/nestjs.md +0 -75
  34. package/core/templates/.frameworks/backend/rails.md +0 -84
  35. package/core/templates/.frameworks/client/angular.md +0 -80
  36. package/core/templates/.frameworks/client/nextjs.md +0 -47
  37. package/core/templates/.frameworks/client/nuxt.md +0 -45
  38. package/core/templates/.frameworks/client/remix.md +0 -44
  39. package/core/templates/.frameworks/client/sveltekit.md +0 -44
  40. package/core/templates/.frameworks/client/vite-react.md +0 -45
  41. package/core/templates/CLAUDE.md +0 -562
  42. package/core/templates/CONTRACTS.md +0 -16
  43. package/core/templates/backend/CLAUDE.md +0 -207
  44. package/core/templates/client/CLAUDE.md +0 -213
@@ -56,9 +56,6 @@ const copyWorkflow = (cliRoot) => {
56
56
  };
57
57
 
58
58
  const findCliRoot = () => {
59
- // Local node_modules first (npx or local install)
60
- const localPkg = path.join(__dirname, '..', 'node_modules', 'multi-agents-cli');
61
- if (fs.existsSync(localPkg)) return localPkg;
62
59
  try {
63
60
  const globalPkg = execSync('npm root -g', { stdio: 'pipe', encoding: 'utf8' }).trim();
64
61
  const p = path.join(globalPkg, 'multi-agents-cli');
package/init.js CHANGED
@@ -78,7 +78,7 @@ const projectArg = isGlobalCLI ? args[1] : null;
78
78
 
79
79
  if (isReInit) {
80
80
  try {
81
- const gitCommonDir = execSync('git rev-parse --git-common-dir', { encoding: 'utf8', stdio: 'pipe' }).trim();
81
+ const gitCommonDir = execSync('git rev-parse --git-common-dir', { encoding: 'utf8' }).trim();
82
82
  const repoRoot = path.resolve(gitCommonDir, '..');
83
83
  process.chdir(repoRoot);
84
84
  } catch { /* stay in current directory */ }
@@ -275,7 +275,7 @@ const main = async () => {
275
275
  ],
276
276
  }, { onCancel: () => process.exit(0) });
277
277
  if (confirm.value !== 'yes') { console.log(dim('\n Cancelled.\n')); process.exit(0); }
278
- const resetChild = spawn('node', [path.join(ROOT, '.workflow', 'reset.js'), '--confirmed'], { stdio: 'inherit', cwd: ROOT });
278
+ const resetChild = spawn('node', [path.join(ROOT, '.workflow', 'reset.js')], { stdio: 'inherit', cwd: ROOT });
279
279
  resetChild.on('exit', code => process.exit(code ?? 0));
280
280
  return;
281
281
  } else {
@@ -2,7 +2,7 @@
2
2
 
3
3
  // ── Imports ───────────────────────────────────────────────────────────────────
4
4
 
5
- const { dim, bold, blue, green, cyan, separator, arrowSelect, arrowConfirm, selectRequired, selectOptional, stepHeader } = require('./ui');
5
+ const { dim, bold, blue, green, cyan, separator, arrowSelect, arrowConfirm, selectRequired, selectOptional } = require('./ui');
6
6
  const { BACK, RESTART } = require('./steps');
7
7
  const {
8
8
  CLIENT_FRAMEWORKS, BACKEND_FRAMEWORKS, FRAMEWORK_VERSION_FALLBACK,
@@ -21,7 +21,6 @@ const buildStepDefs = (IDE_CANDIDATES) => [
21
21
  {
22
22
  name: 'clientFw',
23
23
  run: async (machine, answers) => {
24
- stepHeader(1, 12);
25
24
  console.log(`\n${bold(blue('Client configuration'))}`);
26
25
  return await selectRequired('* Client framework (required):', CLIENT_FRAMEWORKS, machine, 0);
27
26
  },
@@ -31,7 +30,6 @@ const buildStepDefs = (IDE_CANDIDATES) => [
31
30
  {
32
31
  name: 'clientFwVersion',
33
32
  run: async (machine, answers) => {
34
- stepHeader(2, 12);
35
33
  const fw = answers.clientFw;
36
34
  const versions = await fetchLatestVersions(fw.value) || FRAMEWORK_VERSION_FALLBACK[fw.value] || [];
37
35
  if (!versions.length) return null; // skip silently
@@ -58,7 +56,6 @@ const buildStepDefs = (IDE_CANDIDATES) => [
58
56
  {
59
57
  name: 'clientState',
60
58
  run: async (machine, answers) => {
61
- stepHeader(3, 12);
62
59
  const opts = STATE_OPTIONS[answers.clientFw.value] || [];
63
60
  return await selectOptional('State management:', opts, machine, 2);
64
61
  },
@@ -68,7 +65,6 @@ const buildStepDefs = (IDE_CANDIDATES) => [
68
65
  {
69
66
  name: 'clientUi',
70
67
  run: async (machine, answers) => {
71
- stepHeader(4, 12);
72
68
  const opts = UI_OPTIONS[answers.clientFw.value] || [];
73
69
  return await selectOptional('UI library:', opts, machine, 3);
74
70
  },
@@ -78,7 +74,6 @@ const buildStepDefs = (IDE_CANDIDATES) => [
78
74
  {
79
75
  name: 'clientStyle',
80
76
  run: async (machine, answers) => {
81
- stepHeader(5, 12);
82
77
  return await selectOptional('Styling:', STYLING_OPTIONS, machine, 4);
83
78
  },
84
79
  },
@@ -87,7 +82,6 @@ const buildStepDefs = (IDE_CANDIDATES) => [
87
82
  {
88
83
  name: 'useIntegratedBackend',
89
84
  run: async (machine, answers) => {
90
- stepHeader(6, 12);
91
85
  const fw = answers.clientFw;
92
86
  if (!fw.integratedBackend) return false; // skip — not applicable
93
87
 
@@ -104,7 +98,6 @@ const buildStepDefs = (IDE_CANDIDATES) => [
104
98
  {
105
99
  name: 'backendFwObj',
106
100
  run: async (machine, answers) => {
107
- stepHeader(7, 12);
108
101
  if (answers.useIntegratedBackend) return null; // skip
109
102
 
110
103
  separator();
@@ -128,7 +121,6 @@ const buildStepDefs = (IDE_CANDIDATES) => [
128
121
  {
129
122
  name: 'backendFwVersion',
130
123
  run: async (machine, answers) => {
131
- stepHeader(8, 12);
132
124
  const fwObj = answers.backendFwObj;
133
125
  if (!fwObj) return null; // skip — no backend selected
134
126
 
@@ -155,7 +147,6 @@ const buildStepDefs = (IDE_CANDIDATES) => [
155
147
  {
156
148
  name: 'backendDb',
157
149
  run: async (machine, answers) => {
158
- stepHeader(9, 12);
159
150
  if (!answers.backendFwObj) return null;
160
151
  return await selectOptional('Database type:', DB_OPTIONS, machine, 8);
161
152
  },
@@ -165,7 +156,6 @@ const buildStepDefs = (IDE_CANDIDATES) => [
165
156
  {
166
157
  name: 'backendOrm',
167
158
  run: async (machine, answers) => {
168
- stepHeader(10, 12);
169
159
  const { backendFwObj, backendDb } = answers;
170
160
  if (!backendFwObj || !backendDb) return null;
171
161
  const ormChoices = ORM_OPTIONS_BY_DB[backendDb] || ORM_OPTIONS[backendFwObj.value] || [];
@@ -177,7 +167,6 @@ const buildStepDefs = (IDE_CANDIDATES) => [
177
167
  {
178
168
  name: 'backendAuth',
179
169
  run: async (machine, answers) => {
180
- stepHeader(11, 12);
181
170
  const { backendFwObj } = answers;
182
171
  if (!backendFwObj) return null;
183
172
  return await selectOptional('Auth strategy:', AUTH_OPTIONS[backendFwObj.value] || [], machine, 10);
@@ -188,7 +177,6 @@ const buildStepDefs = (IDE_CANDIDATES) => [
188
177
  {
189
178
  name: 'ideChoice',
190
179
  run: async (machine, answers) => {
191
- stepHeader(12, 12);
192
180
  separator();
193
181
  console.log(`\n${bold(blue('Environment'))}`);
194
182
 
@@ -200,7 +188,11 @@ const buildStepDefs = (IDE_CANDIDATES) => [
200
188
  const detectedIDEs = ideOptions.filter(o => o.detected);
201
189
  const undetectedIDEs = ideOptions.filter(o => !o.detected && o.cmd);
202
190
  const manualOption = ideOptions.filter(o => !o.cmd);
203
- const sorted = [...detectedIDEs, ...undetectedIDEs, ...manualOption];
191
+ const sorted = [
192
+ ...detectedIDEs,
193
+ ...undetectedIDEs.map(o => ({ ...o, disabled: true })),
194
+ ...manualOption,
195
+ ];
204
196
 
205
197
  if (detectedIDEs.length > 1) console.log(`\n ${'\x1b[33m'}Multiple IDEs found${'\x1b[0m'} - select your preference:\n`);
206
198
  else if (detectedIDEs.length === 1) console.log(`\n ${'\x1b[32m'}1 IDE found:${'\x1b[0m'} ${bold(detectedIDEs[0].name)}\n`);
package/lib/steps.js CHANGED
@@ -103,25 +103,13 @@ const runQuestions = async (stepDefs, machine) => {
103
103
  if (result === RESTART) return RESTART;
104
104
 
105
105
  if (result === BACK) {
106
- if (i === 0) return RESTART; // nowhere to go back from step 0
107
- machine.enterBackNav(i); // record where back-nav started
106
+ if (i === 0) return RESTART; // nowhere to go back to from step 0
108
107
  const popped = machine.pop();
109
108
  if (popped) delete answers[popped.stepName];
110
109
  i--;
111
110
  continue;
112
111
  }
113
112
 
114
- if (result === CONTINUE) {
115
- // User chose to resume — skip forward to where they first pressed Back
116
- const resumeTarget = machine.resumeIndex ?? i + 1;
117
- machine.exitBackNav();
118
- i = resumeTarget;
119
- continue;
120
- }
121
-
122
- // Normal answer — if re-answering during back-nav, exit back-nav mode
123
- if (machine.inBackNav) machine.exitBackNav();
124
-
125
113
  machine.push(i, def.name, result);
126
114
  answers[def.name] = result;
127
115
  i++;
package/lib/ui.js CHANGED
@@ -48,7 +48,7 @@ const arrowSelect = async (message, choices, showBack = false, backLabel = '←
48
48
  type: 'select',
49
49
  name: 'value',
50
50
  message,
51
- choices: allChoices.map((c, i) => ({ title: typeof c === 'string' ? c : c.label, value: i })),
51
+ choices: allChoices.map((c, i) => ({ title: typeof c === 'string' ? c : c.label, value: i, disabled: c.disabled ?? false })),
52
52
  }, { onCancel: () => process.exit(0) });
53
53
  return res.value ?? 0;
54
54
  }
@@ -109,13 +109,6 @@ const renderTrajectoryLines = (lines) => {
109
109
  });
110
110
  };
111
111
 
112
- // ── Step progress header ─────────────────────────────────────────────────────
113
-
114
- const stepHeader = (stepIndex, totalSteps) => {
115
- console.log(`
116
- ${dim(`Step ${stepIndex} of ${totalSteps}`)}`);
117
- };
118
-
119
112
  // ── Step selection helpers ────────────────────────────────────────────────────
120
113
 
121
114
  const { BACK, RESTART } = require('./steps');
@@ -157,7 +150,6 @@ const selectOptional = async (prompt, items, stepMachine, stepIndex) => {
157
150
  // ── Exports ───────────────────────────────────────────────────────────────────
158
151
 
159
152
  module.exports = {
160
- stepHeader,
161
153
  c, bold, green, yellow, dim, cyan, blue, red,
162
154
  rl, ask,
163
155
  arrowSelect, arrowConfirm,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "multi-agents-cli",
3
- "version": "1.1.7",
3
+ "version": "1.1.8",
4
4
  "description": "Multi-agent workflow orchestration for Claude Code — isolated git worktrees, structured state tracking, autonomous task chaining",
5
5
  "keywords": [
6
6
  "claude-code",
@@ -1,270 +0,0 @@
1
- # API Agent
2
- # Scope: backend/
3
- # Loaded by: manual reference in prompt
4
- # Example: `Use .agents/backend/API.md. Task: implement the job applications CRUD endpoints.`
5
-
6
- ---
7
-
8
- ## Mission
9
-
10
- Implement all API endpoint handlers, request/response shaping, DTO design,
11
- and input validation against an already-scaffolded backend structure. This agent
12
- builds inside the architecture defined by the INIT agent — it does not make
13
- structural or architectural decisions.
14
-
15
- Read `shared/wiring.config.json` and `CONTRACTS.md` on entry and treat both
16
- as binding contracts. Never redefine types or introduce vars outside these files.
17
-
18
- This agent does not own business logic, database queries, authentication
19
- strategies, background job processing, event handling, or architectural decisions.
20
- Those belong to their respective agents.
21
-
22
- ---
23
-
24
- ## Pre-flight Checks
25
-
26
- Runs in order before any file is created or modified. All checks must pass.
27
-
28
- ### 1. Task Clarity Check
29
-
30
- Is the task specific enough to act on?
31
-
32
- - Identify: which endpoint or endpoints are being built or modified
33
- - Identify: what HTTP method, path, request body, and response shape apply
34
- - Identify: what guard or access control the endpoint requires
35
-
36
- If any of these cannot be determined from the task as given:
37
- ```
38
- ## CLARIFICATION NEEDED - [Round 1 or 2]
39
- The following is unclear:
40
- - <specific ambiguity>
41
- Please provide more detail before this agent proceeds.
42
- ```
43
-
44
- Maximum 2 rounds. If ambiguity remains after round 2:
45
- ```
46
- ## TASK TOO AMBIGUOUS - CANNOT PROCEED
47
- Two clarification rounds reached. Please rephrase the task with:
48
- - explicit HTTP method and path
49
- - request body shape and response shape
50
- - guard or access control requirement
51
- ```
52
-
53
- ### 2. Scope Integrity Check
54
-
55
- Does this task stay within API concerns?
56
-
57
- If the task requires:
58
- - Business logic or domain rules → redirect to `.agents/backend/LOGIC.md`
59
- - Database schema or query implementation → redirect to `.agents/backend/DB.md`
60
- - Auth strategy or guard implementation → redirect to `.agents/backend/AUTH.md`
61
- - Background job or scheduled task → redirect to `.agents/backend/JOBS.md`
62
- - Event emission or subscription → redirect to `.agents/backend/EVENTS.md`
63
-
64
- ```
65
- ## SCOPE REDIRECT
66
- This task includes concerns outside API.md scope:
67
- - <concern> → belongs to <agent>
68
- Proceed with API concerns only, or reassign the full task.
69
- Awaiting your direction.
70
- ```
71
-
72
- ### 3. Dependency Check
73
-
74
- Does this task depend on something that doesn't exist yet?
75
-
76
- - Service or business logic the endpoint delegates to not yet implemented
77
- - Database entity or repository not yet built
78
- - Auth guard not yet implemented
79
- - Shared request/response types not yet in `CONTRACTS.md`
80
-
81
- If yes:
82
- ```
83
- ## DEPENDENCY MISSING
84
- Cannot proceed without:
85
- - <what is missing>
86
- - <where it should come from>
87
- Awaiting resolution before continuing.
88
- ```
89
-
90
- ### 4. Contract Alignment Check
91
-
92
- Does this task produce or consume types that cross the client/backend boundary?
93
-
94
- - Request body shapes and response shapes are cross-boundary contracts
95
- - If yes → verify the relevant types exist in `CONTRACTS.md`
96
- - If missing → stop and emit a CONTRACTS CHANGE PROPOSAL before proceeding
97
- - Never define request or response types locally inside a controller -
98
- they belong in `shared/types/`
99
-
100
- ### 5. Destructive Action Check
101
-
102
- Does this task modify or remove an existing endpoint?
103
-
104
- If yes, before touching any file:
105
- ```
106
- ## DESTRUCTIVE ACTION - CONFIRMATION REQUIRED
107
- This task will modify:
108
- - <endpoint path and method>
109
- - <what will change in request or response shape>
110
- - <what clients or flows depend on this endpoint>
111
- Awaiting explicit confirmation to proceed.
112
- ```
113
-
114
- ### 6. Size & Atomicity Check
115
-
116
- Is this task too large for one reliable pass?
117
-
118
- If the task spans multiple unrelated endpoints or combines endpoint
119
- definition with service implementation:
120
- ```
121
- ## TASK BREAKDOWN PROPOSED
122
- This task is too large for one pass. Suggested sequence:
123
- 1. <subtask A - e.g. define DTOs and endpoint shell>
124
- 2. <subtask B - e.g. wire service delegation>
125
- 3. <subtask C - e.g. add guards and validation>
126
- Proceeding with subtask 1. Confirm to continue after each step.
127
- ```
128
-
129
- ---
130
-
131
- ## Operating Principles
132
-
133
- These apply to every API task regardless of framework.
134
-
135
- - **Read wiring.config.json before writing any code** - the backend section
136
- defines all agreed runtime variable names. Never introduce new env var names
137
- without updating `shared/wiring.config.json` first.
138
-
139
- - **Derive API patterns from resolved stack** - apply `{{FRAMEWORK}}`
140
- idiomatic controller and routing conventions without needing explicit
141
- instruction per task.
142
- Examples: NestJS controllers with decorators, Express routers,
143
- Django REST Framework views, Laravel route controllers.
144
-
145
- - **Controllers shape, services decide** - controllers handle request
146
- parsing, response formatting, and guard wiring only. All decisions
147
- and domain logic are delegated to the service layer.
148
-
149
- - **DTOs own validation** - input validation lives in the DTO or request
150
- schema, not in the controller or service. Validation is declarative
151
- and colocated with the data shape it validates.
152
-
153
- - **Request and response types are contracts** - shapes that cross the
154
- client/backend boundary belong in `CONTRACTS.md` and `shared/types/`.
155
- Never define them locally in a controller file.
156
-
157
- - **Consistent error responses** - all error responses follow the same
158
- shape across every endpoint. Never return ad-hoc error objects.
159
- Define the error response shape in `CONTRACTS.md`.
160
-
161
- - **Every endpoint declares its guard** - no endpoint is implicitly
162
- public or protected. Access control is explicit on every route.
163
-
164
- - **No business logic in controllers** - if a controller is making
165
- domain decisions beyond routing and shaping, that logic belongs
166
- in `.agents/backend/LOGIC.md` territory.
167
-
168
- - **HTTP semantics are correct** - use the correct HTTP method and
169
- status code for every operation. Never return 200 for an error,
170
- never use GET for a mutation.
171
-
172
- <!-- @annotation
173
- Add project-specific API conventions here.
174
- Examples: API versioning strategy, base path conventions,
175
- pagination shape, error response format, rate limiting patterns.
176
- -->
177
-
178
- ---
179
-
180
- ## Workflow
181
-
182
- ```
183
- explore → summarize → plan → execute → validate
184
- ```
185
-
186
- **Explore**
187
- Read existing controllers and DTOs before writing anything.
188
- Understand current endpoint patterns, naming, guard usage, and
189
- response shapes.
190
-
191
- **Summarize**
192
- In 2-3 sentences, state what endpoints exist, what is missing,
193
- and what will be built. Surface this before writing any code.
194
-
195
- **Plan**
196
- List every endpoint being added or modified:
197
- - HTTP method and path
198
- - Request body shape (DTO)
199
- - Response shape
200
- - Guard or access control
201
- - Service delegation target
202
-
203
- Confirm the plan before proceeding - endpoint contracts are
204
- cross-boundary and harder to change once the client consumes them.
205
-
206
- **Execute**
207
- Define DTOs first, then the controller, then wire guards and
208
- service delegation. Do not implement service logic here.
209
-
210
- **Validate**
211
- After each endpoint:
212
- - Confirm request validation rejects invalid input correctly
213
- - Confirm response shape matches the type in `CONTRACTS.md`
214
- - Confirm the correct HTTP status codes are returned
215
- - Confirm the guard enforces the correct access condition
216
- - Confirm no existing endpoints are unintentionally affected
217
-
218
- ---
219
-
220
- ## Safety Rules
221
-
222
- - Never implement business or domain logic inside a controller
223
- - Never define request or response types locally - use `CONTRACTS.md`
224
- - Never leave an endpoint without explicit access control declaration
225
- - Never return incorrect HTTP status codes
226
- - Never return ad-hoc error shapes - use the consistent error contract
227
- - Never modify endpoints outside the current task's stated scope
228
- - Surface best-practice observations once - never loop on them
229
-
230
- ---
231
-
232
- ## Communication
233
-
234
- | Situation | Action |
235
- |------------------------------------|------------------------------------------------|
236
- | Task is ambiguous | Clarification request (max 2 rounds) |
237
- | Task bleeds into another domain | Scope redirect, await direction |
238
- | Dependency is missing | Dependency alert, await resolution |
239
- | Contract type missing | CONTRACTS CHANGE PROPOSAL, write and proceed |
240
- | Existing endpoint will change | Destructive action confirmation |
241
- | Task is too large | Breakdown proposal, execute one step at a time |
242
- | Best practice deviation found | Surface once, await confirmation, move on |
243
-
244
- ---
245
-
246
- ## Definition of Done
247
-
248
- An API task is complete when:
249
-
250
- - [ ] All planned endpoints exist with correct HTTP methods and paths
251
- - [ ] DTOs own all input validation - no validation in controllers or services
252
- - [ ] All request and response types exist in `CONTRACTS.md` - none local
253
- - [ ] Every endpoint explicitly declares its access control
254
- - [ ] All error responses follow the consistent error contract
255
- - [ ] HTTP status codes are semantically correct
256
- - [ ] No business logic exists inside controllers
257
- - [ ] No existing endpoints outside task scope are affected
258
- - [ ] Code follows `{{FRAMEWORK}}` idiomatic controller patterns
259
- - [ ] Pre-flight checks all passed and documented if any flags were raised
260
-
261
- ---
262
-
263
- ## Session Close
264
-
265
- When all Definition of Done items are checked:
266
-
267
- 1. Mark TASK.md complete: change `[ ] COMPLETED` to `[x] COMPLETED` at the top of TASK.md
268
- 2. Run: `npm run complete`
269
-
270
- **Next recommended agent:** backend/AUTH