@tacuchi/agent-factory 0.3.0 → 0.4.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.
@@ -38,6 +38,8 @@ program
38
38
  .option('-s, --scope <path>', 'Repository path (for stack detection)')
39
39
  .option('-o, --output <path>', 'Output directory (default: current dir)')
40
40
  .option('-t, --target <target>', 'Target: claude, codex, all', 'all')
41
+ .option('--stack <csv>', 'Override detected stack (comma-separated)')
42
+ .option('--dry-run', 'Preview generated agent without writing files')
41
43
  .option('--tools <tools>', 'Comma-separated tools: Read,Write,Edit,Bash')
42
44
  .option('--specialists <list>', 'CSV list of specialist agent names (for coordinator role)')
43
45
  .option('--repo-count <n>', 'Number of repos in workspace (for coordinator role)', parseInt)
package/package.json CHANGED
@@ -1,45 +1 @@
1
- {
2
- "name": "@tacuchi/agent-factory",
3
- "version": "0.3.0",
4
- "description": "CLI to create AI agents for Claude Code, Codex, Gemini CLI and more",
5
- "bin": {
6
- "agent-factory": "bin/agent-factory.js"
7
- },
8
- "files": [
9
- "bin/",
10
- "src/",
11
- "templates/",
12
- "README.md",
13
- "LICENSE"
14
- ],
15
- "engines": {
16
- "node": ">=16"
17
- },
18
- "scripts": {
19
- "test": "node --test tests/",
20
- "start": "node bin/agent-factory.js"
21
- },
22
- "keywords": [
23
- "claude-code",
24
- "agents",
25
- "codex",
26
- "gemini",
27
- "ai",
28
- "cli",
29
- "agent-factory"
30
- ],
31
- "author": "tacuchi",
32
- "license": "MIT",
33
- "repository": {
34
- "type": "git",
35
- "url": "https://github.com/tacuchi/agent-factory"
36
- },
37
- "dependencies": {
38
- "chalk": "^4.1.2",
39
- "commander": "^11.1.0",
40
- "fs-extra": "^11.2.0",
41
- "inquirer": "^8.2.6",
42
- "js-yaml": "^4.1.0",
43
- "ora": "^5.4.1"
44
- }
45
- }
1
+ {"name":"@tacuchi/agent-factory","version":"0.4.0","description":"CLI to create AI agents for Claude Code, Codex, Gemini CLI and more","bin":{"agent-factory":"bin/agent-factory.js"},"files":["bin/","src/","templates/","README.md","LICENSE"],"engines":{"node":">=16"},"scripts":{"test":"node --test tests/*.test.js","start":"node bin/agent-factory.js"},"keywords":["claude-code","agents","codex","gemini","ai","cli","agent-factory"],"author":"tacuchi","license":"MIT","repository":{"type":"git","url":"https://github.com/tacuchi/agent-factory"},"dependencies":{"chalk":"^4.1.2","commander":"^11.1.0","fs-extra":"^11.2.0","inquirer":"^8.2.6","js-yaml":"^4.1.0","ora":"^5.4.1"}}
@@ -10,7 +10,7 @@ async function runCreate(options = {}) {
10
10
  const isInteractive = !options.name;
11
11
  const config = isInteractive ? await askCreateOptions() : normalizeFlags(options);
12
12
 
13
- const { name, role, model, scope, output, target, tools, specialists, repoCount, description, instructions } = config;
13
+ const { name, role, model, scope, output, target, tools, specialists, repoCount, description, instructions, stack, dryRun } = config;
14
14
 
15
15
  const spin = spinner('Generating agent...').start();
16
16
 
@@ -21,7 +21,16 @@ async function runCreate(options = {}) {
21
21
  spin.succeed('Custom agent generated');
22
22
  } else {
23
23
  let stackResult = { primaryTech: 'Generic', framework: '', verifyCommands: '', stackParts: [], stackCsv: 'Generic' };
24
- if (scope) {
24
+ if (stack) {
25
+ const parts = stack.split(',').map(s => s.trim()).filter(Boolean);
26
+ stackResult = {
27
+ primaryTech: parts[0] || 'Generic',
28
+ framework: parts[1] || '',
29
+ verifyCommands: '',
30
+ stackParts: parts,
31
+ stackCsv: parts.join(', '),
32
+ };
33
+ } else if (scope) {
25
34
  stackResult = await detect(scope);
26
35
  }
27
36
 
@@ -61,6 +70,13 @@ async function runCreate(options = {}) {
61
70
  if (target === 'claude' || target === 'all') targetDirs.push('.claude/agents/');
62
71
  if (target === 'codex' || target === 'all') targetDirs.push('.agents/');
63
72
 
73
+ if (dryRun) {
74
+ log.info('--- DRY RUN: Agent preview ---');
75
+ console.log(body);
76
+ log.info('--- End preview ---');
77
+ return;
78
+ }
79
+
64
80
  if (!options.yes && isInteractive) {
65
81
  const confirmed = await confirmGeneration(name, targetDirs);
66
82
  if (!confirmed) {
@@ -116,6 +132,8 @@ function normalizeFlags(options) {
116
132
  repoCount: options.repoCount || 0,
117
133
  description: options.description || '',
118
134
  instructions: options.instructions || '',
135
+ stack: options.stack || '',
136
+ dryRun: options.dryRun || false,
119
137
  };
120
138
  }
121
139
 
@@ -141,4 +159,4 @@ async function resolveCustomBody(instructions, name, description) {
141
159
  return `# ${name}\n\n${instructions}\n`;
142
160
  }
143
161
 
144
- module.exports = { runCreate };
162
+ module.exports = { runCreate, normalizeFlags, formatSpecialistList };
@@ -112,6 +112,20 @@ async function detect(repoPath) {
112
112
  verifyCommands = 'npm run build, npm test';
113
113
  stackParts.push('Node.js');
114
114
  }
115
+
116
+ // Fallback: Node.js CLI (has bin field) or plain JS
117
+ if (!primaryTech && pkg) {
118
+ if (pkg.bin) {
119
+ primaryTech = 'Node.js';
120
+ framework = 'CLI';
121
+ verifyCommands = 'npm test';
122
+ stackParts.push('Node.js', 'CLI');
123
+ } else {
124
+ primaryTech = 'JavaScript';
125
+ verifyCommands = 'npm test';
126
+ stackParts.push('JavaScript');
127
+ }
128
+ }
115
129
  }
116
130
  }
117
131
 
@@ -267,6 +281,26 @@ async function detect(repoPath) {
267
281
  }
268
282
  }
269
283
 
284
+ // --- Shell / Bash ---
285
+ if (!primaryTech) {
286
+ const shFiles = await findFiles(abs, ['.sh'], 1);
287
+ if (shFiles.length > 0) {
288
+ primaryTech = 'Bash';
289
+ framework = 'Shell';
290
+ verifyCommands = 'bash -n *.sh, shellcheck *.sh';
291
+ stackParts.push('Bash', 'Shell');
292
+ }
293
+ }
294
+
295
+ // --- Makefile (standalone) ---
296
+ if (!primaryTech) {
297
+ if (await fs.pathExists(path.join(abs, 'Makefile'))) {
298
+ primaryTech = 'Make';
299
+ verifyCommands = 'make';
300
+ stackParts.push('Make');
301
+ }
302
+ }
303
+
270
304
  // --- Supplementary ---
271
305
  if (await fs.pathExists(path.join(abs, 'tsconfig.json'))) {
272
306
  if (!stackParts.includes('TypeScript') && primaryTech !== 'TypeScript') {