@acmeacmeio/setup-sh 0.2.6

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 (32) hide show
  1. package/README.md +212 -0
  2. package/package.json +39 -0
  3. package/src/cli.mjs +614 -0
  4. package/templates/.claude/agents/code-simplifier.md +52 -0
  5. package/templates/.claude/commands/auto.md +85 -0
  6. package/templates/.claude/commands/clean-copy.md +93 -0
  7. package/templates/.claude/commands/fix-issue.md +34 -0
  8. package/templates/.claude/commands/review.md +46 -0
  9. package/templates/.claude/router/classify.js +241 -0
  10. package/templates/.claude/router/registry.json +49 -0
  11. package/templates/.claude/settings.json +113 -0
  12. package/templates/.claude/skills/api-design/SKILL.md +77 -0
  13. package/templates/.claude/skills/security-review/SKILL.md +65 -0
  14. package/templates/.codex/config.toml +31 -0
  15. package/templates/.codex/skills/api-design/SKILL.md +77 -0
  16. package/templates/.codex/skills/security-review/SKILL.md +65 -0
  17. package/templates/.cursor/commands/auto.md +55 -0
  18. package/templates/.cursor/commands/clean-copy.md +80 -0
  19. package/templates/.cursor/commands/code-simplifier.md +28 -0
  20. package/templates/.cursor/commands/fix-issue.md +28 -0
  21. package/templates/.cursor/commands/review.md +41 -0
  22. package/templates/.cursor/hooks.json +11 -0
  23. package/templates/.cursor/rules/api-design.mdc +80 -0
  24. package/templates/.cursor/rules/git-workflow.mdc +73 -0
  25. package/templates/.cursor/rules/security.mdc +69 -0
  26. package/templates/.cursor/rules/tdd.mdc +35 -0
  27. package/templates/.cursor/rules/typescript.mdc +82 -0
  28. package/templates/.cursorignore.template +20 -0
  29. package/templates/.gitignore.template +10 -0
  30. package/templates/.mcp.json +16 -0
  31. package/templates/AGENTS.md +118 -0
  32. package/templates/CLAUDE.md +138 -0
package/src/cli.mjs ADDED
@@ -0,0 +1,614 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { execSync, spawn } from "node:child_process";
4
+ import {
5
+ existsSync,
6
+ mkdirSync,
7
+ writeFileSync,
8
+ readFileSync,
9
+ cpSync,
10
+ } from "node:fs";
11
+ import { join, dirname, resolve, isAbsolute } from "node:path";
12
+ import { fileURLToPath } from "node:url";
13
+ import { createInterface } from "node:readline";
14
+
15
+ const __filename = fileURLToPath(import.meta.url);
16
+ const __dirname = dirname(__filename);
17
+ const TEMPLATES_DIR = join(__dirname, "..", "templates");
18
+
19
+ // ============================================================================
20
+ // ANSI Colors (no dependencies)
21
+ // ============================================================================
22
+ const colors = {
23
+ reset: "\x1b[0m",
24
+ bold: "\x1b[1m",
25
+ dim: "\x1b[2m",
26
+ red: "\x1b[31m",
27
+ green: "\x1b[32m",
28
+ yellow: "\x1b[33m",
29
+ blue: "\x1b[34m",
30
+ magenta: "\x1b[35m",
31
+ cyan: "\x1b[36m",
32
+ };
33
+
34
+ const log = {
35
+ info: (msg) => console.log(`${colors.blue}info${colors.reset} ${msg}`),
36
+ success: (msg) => console.log(`${colors.green}done${colors.reset} ${msg}`),
37
+ warn: (msg) => console.log(`${colors.yellow}warn${colors.reset} ${msg}`),
38
+ error: (msg) => console.log(`${colors.red}error${colors.reset} ${msg}`),
39
+ step: (msg) => console.log(`${colors.cyan} -> ${colors.reset}${msg}`),
40
+ title: (msg) =>
41
+ console.log(`\n${colors.bold}${colors.magenta}${msg}${colors.reset}\n`),
42
+ };
43
+
44
+ // ============================================================================
45
+ // Platform Detection
46
+ // ============================================================================
47
+ function detectPlatform() {
48
+ const platform = process.platform;
49
+
50
+ if (platform === "darwin") {
51
+ return { os: "macos", pm: "brew" };
52
+ }
53
+
54
+ if (platform === "linux") {
55
+ try {
56
+ const osRelease = readFileSync("/etc/os-release", "utf8");
57
+ if (osRelease.includes("Ubuntu") || osRelease.includes("Debian")) {
58
+ return { os: "debian", pm: "apt" };
59
+ }
60
+ if (
61
+ osRelease.includes("Fedora") ||
62
+ osRelease.includes("RHEL") ||
63
+ osRelease.includes("CentOS")
64
+ ) {
65
+ return { os: "fedora", pm: "dnf" };
66
+ }
67
+ if (osRelease.includes("Arch")) {
68
+ return { os: "arch", pm: "pacman" };
69
+ }
70
+ } catch {
71
+ // ignore
72
+ }
73
+ return { os: "linux", pm: "unknown" };
74
+ }
75
+
76
+ if (platform === "win32") {
77
+ return { os: "windows", pm: "winget" };
78
+ }
79
+
80
+ return { os: "unknown", pm: "unknown" };
81
+ }
82
+
83
+ // ============================================================================
84
+ // Command Execution Helpers
85
+ // ============================================================================
86
+ function commandExists(cmd) {
87
+ try {
88
+ execSync(`command -v ${cmd}`, { stdio: "ignore" });
89
+ return true;
90
+ } catch {
91
+ return false;
92
+ }
93
+ }
94
+
95
+ function exec(cmd, options = {}) {
96
+ try {
97
+ return execSync(cmd, {
98
+ encoding: "utf8",
99
+ stdio: options.silent ? "pipe" : "inherit",
100
+ ...options,
101
+ });
102
+ } catch (error) {
103
+ if (!options.ignoreError) {
104
+ throw error;
105
+ }
106
+ return null;
107
+ }
108
+ }
109
+
110
+ // ============================================================================
111
+ // Interactive Prompts
112
+ // ============================================================================
113
+ function createPrompt(autoYes = false) {
114
+ const rl = createInterface({
115
+ input: process.stdin,
116
+ output: process.stdout,
117
+ });
118
+
119
+ return {
120
+ ask: (question) =>
121
+ new Promise((resolve) => {
122
+ rl.question(question, (answer) => resolve(answer));
123
+ }),
124
+ confirm: async (question, defaultYes = true) => {
125
+ if (autoYes) {
126
+ console.log(`${question} [Y/n] y (auto)`);
127
+ return true;
128
+ }
129
+ const suffix = defaultYes ? "[Y/n]" : "[y/N]";
130
+ const answer = await new Promise((resolve) => {
131
+ rl.question(`${question} ${suffix} `, resolve);
132
+ });
133
+ if (answer === "") return defaultYes;
134
+ return answer.toLowerCase() === "y";
135
+ },
136
+ select: async (question, options) => {
137
+ console.log(`\n${question}`);
138
+ options.forEach((opt, i) => {
139
+ console.log(
140
+ ` ${colors.cyan}${i + 1}${colors.reset}) ${opt.label}${opt.default ? ` ${colors.dim}(default)${colors.reset}` : ""}`,
141
+ );
142
+ });
143
+ const answer = await new Promise((resolve) => {
144
+ rl.question(`\nSelect [1-${options.length}]: `, resolve);
145
+ });
146
+ const idx = parseInt(answer, 10) - 1;
147
+ if (isNaN(idx) || idx < 0 || idx >= options.length) {
148
+ const defaultOpt = options.find((o) => o.default);
149
+ return defaultOpt ? defaultOpt.value : options[0].value;
150
+ }
151
+ return options[idx].value;
152
+ },
153
+ close: () => rl.close(),
154
+ };
155
+ }
156
+
157
+ // ============================================================================
158
+ // Tool Installation
159
+ // ============================================================================
160
+ const TOOLS = {
161
+ gh: {
162
+ name: "GitHub CLI",
163
+ check: () => commandExists("gh"),
164
+ install: {
165
+ macos: "brew install gh",
166
+ debian: "sudo apt install -y gh",
167
+ fedora: "sudo dnf install -y gh",
168
+ arch: "sudo pacman -S --noconfirm github-cli",
169
+ windows: "winget install GitHub.cli",
170
+ },
171
+ },
172
+ node: {
173
+ name: "Node.js",
174
+ check: () => commandExists("node"),
175
+ install: {
176
+ macos: "brew install node",
177
+ debian:
178
+ "curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash - && sudo apt install -y nodejs",
179
+ fedora: "sudo dnf install -y nodejs",
180
+ arch: "sudo pacman -S --noconfirm nodejs npm",
181
+ windows: "winget install OpenJS.NodeJS.LTS",
182
+ },
183
+ },
184
+ pnpm: {
185
+ name: "pnpm",
186
+ check: () => commandExists("pnpm"),
187
+ install: {
188
+ macos: "brew install pnpm",
189
+ debian: "npm install -g pnpm",
190
+ fedora: "npm install -g pnpm",
191
+ arch: "npm install -g pnpm",
192
+ windows: "npm install -g pnpm",
193
+ },
194
+ },
195
+ python: {
196
+ name: "Python 3.11+",
197
+ check: () => commandExists("python3.11") || commandExists("python3"),
198
+ install: {
199
+ macos: "brew install python@3.11",
200
+ debian: "sudo apt install -y python3.11 python3.11-venv",
201
+ fedora: "sudo dnf install -y python3.11",
202
+ arch: "sudo pacman -S --noconfirm python",
203
+ windows: "winget install Python.Python.3.11",
204
+ },
205
+ },
206
+ uv: {
207
+ name: "uv (Python package manager)",
208
+ check: () => commandExists("uv"),
209
+ install: {
210
+ macos: "curl -LsSf https://astral.sh/uv/install.sh | sh",
211
+ debian: "curl -LsSf https://astral.sh/uv/install.sh | sh",
212
+ fedora: "curl -LsSf https://astral.sh/uv/install.sh | sh",
213
+ arch: "curl -LsSf https://astral.sh/uv/install.sh | sh",
214
+ windows: 'powershell -c "irm https://astral.sh/uv/install.ps1 | iex"',
215
+ },
216
+ },
217
+ "browser-use": {
218
+ name: "browser-use (Browser automation)",
219
+ check: () => commandExists("browser-use"),
220
+ install: {
221
+ macos: "uv tool install browser-use && uvx browser-use install",
222
+ debian: "uv tool install browser-use && uvx browser-use install",
223
+ fedora: "uv tool install browser-use && uvx browser-use install",
224
+ arch: "uv tool install browser-use && uvx browser-use install",
225
+ windows: "uv tool install browser-use && uvx browser-use install",
226
+ },
227
+ },
228
+ };
229
+
230
+ async function installTools(platform, prompt) {
231
+ log.title("Checking Required Tools");
232
+
233
+ const missing = [];
234
+
235
+ for (const [key, tool] of Object.entries(TOOLS)) {
236
+ if (tool.check()) {
237
+ log.success(`${tool.name} is installed`);
238
+ } else {
239
+ log.warn(`${tool.name} is not installed`);
240
+ missing.push(key);
241
+ }
242
+ }
243
+
244
+ if (missing.length === 0) {
245
+ return true;
246
+ }
247
+
248
+ const install = await prompt.confirm(
249
+ `\nInstall missing tools (${missing.join(", ")})?`,
250
+ );
251
+
252
+ if (!install) {
253
+ log.warn("Skipping tool installation. Some features may not work.");
254
+ return false;
255
+ }
256
+
257
+ for (const key of missing) {
258
+ const tool = TOOLS[key];
259
+ const cmd = tool.install[platform.os];
260
+
261
+ if (!cmd) {
262
+ log.error(`No install command for ${tool.name} on ${platform.os}`);
263
+ continue;
264
+ }
265
+
266
+ log.step(`Installing ${tool.name}...`);
267
+ try {
268
+ exec(cmd);
269
+ log.success(`${tool.name} installed`);
270
+ } catch (error) {
271
+ log.error(`Failed to install ${tool.name}: ${error.message}`);
272
+ }
273
+ }
274
+
275
+ return true;
276
+ }
277
+
278
+ // ============================================================================
279
+ // Skills Installation
280
+ // ============================================================================
281
+ const SKILL_SOURCES = [
282
+ // Official Anthropic skills
283
+ { repo: "anthropics/anthropic-skills", skills: ["frontend-design"] },
284
+ // Browser automation
285
+ { repo: "browser-use/browser-use", skills: ["browser-use"] },
286
+ // TDD workflow
287
+ { repo: "obra/superpowers", skills: ["test-driven-development"] },
288
+ // Supabase Postgres
289
+ { repo: "supabase/agent-skills", skills: ["supabase-postgres-best-practices"] },
290
+ ];
291
+
292
+ async function installSkills(prompt, agentChoice) {
293
+ // Skills installation only applies to Claude Code
294
+ // Codex uses the bundled skills from .codex/skills/
295
+ // Cursor uses MDC rules bundled in .cursor/rules/
296
+ if (agentChoice === "codex") {
297
+ log.info("Codex skills are bundled in .codex/skills/ directory");
298
+ return;
299
+ }
300
+
301
+ if (agentChoice === "cursor") {
302
+ log.info("Cursor rules are bundled in .cursor/rules/ directory");
303
+ return;
304
+ }
305
+
306
+ log.title("Installing Claude Code Skills");
307
+
308
+ const install = await prompt.confirm("Install recommended external skills?");
309
+
310
+ if (!install) {
311
+ log.warn("Skipping skill installation. Bundled skills in .claude/skills/ are ready to use.");
312
+ return;
313
+ }
314
+
315
+ for (const source of SKILL_SOURCES) {
316
+ for (const skill of source.skills) {
317
+ log.step(`Installing ${skill} from ${source.repo}...`);
318
+ try {
319
+ exec(`npx add-skill ${source.repo} ${skill}`, {
320
+ silent: true,
321
+ ignoreError: true,
322
+ });
323
+ log.success(`Installed ${skill}`);
324
+ } catch {
325
+ log.warn(`Could not install ${skill} (may require manual setup)`);
326
+ }
327
+ }
328
+ }
329
+ }
330
+
331
+ // ============================================================================
332
+ // Template Files
333
+ // ============================================================================
334
+ function copyTemplates(targetDir, agentChoice) {
335
+ log.title("Setting Up Workspace");
336
+
337
+ const shouldCopyClaude = agentChoice === "claude" || agentChoice === "all";
338
+ const shouldCopyCodex = agentChoice === "codex" || agentChoice === "all";
339
+ const shouldCopyCursor = agentChoice === "cursor" || agentChoice === "all";
340
+
341
+ // Copy Claude Code templates
342
+ if (shouldCopyClaude) {
343
+ const claudeDir = join(targetDir, ".claude");
344
+ if (!existsSync(claudeDir)) {
345
+ mkdirSync(claudeDir, { recursive: true });
346
+ }
347
+ cpSync(join(TEMPLATES_DIR, ".claude"), claudeDir, { recursive: true });
348
+ log.step("Created .claude/ directory with settings, commands, skills, and agents");
349
+
350
+ // Copy CLAUDE.md
351
+ cpSync(
352
+ join(TEMPLATES_DIR, "CLAUDE.md"),
353
+ join(targetDir, "CLAUDE.md"),
354
+ );
355
+ log.step("Created CLAUDE.md");
356
+
357
+ // Copy .mcp.json (Claude Code MCP config)
358
+ cpSync(
359
+ join(TEMPLATES_DIR, ".mcp.json"),
360
+ join(targetDir, ".mcp.json"),
361
+ );
362
+ log.step("Created .mcp.json");
363
+ }
364
+
365
+ // Copy Codex templates
366
+ if (shouldCopyCodex) {
367
+ const codexDir = join(targetDir, ".codex");
368
+ if (!existsSync(codexDir)) {
369
+ mkdirSync(codexDir, { recursive: true });
370
+ }
371
+ cpSync(join(TEMPLATES_DIR, ".codex"), codexDir, { recursive: true });
372
+ log.step("Created .codex/ directory with config and skills");
373
+
374
+ // Copy AGENTS.md
375
+ cpSync(
376
+ join(TEMPLATES_DIR, "AGENTS.md"),
377
+ join(targetDir, "AGENTS.md"),
378
+ );
379
+ log.step("Created AGENTS.md");
380
+ }
381
+
382
+ // Copy Cursor templates
383
+ if (shouldCopyCursor) {
384
+ const cursorDir = join(targetDir, ".cursor");
385
+ if (!existsSync(cursorDir)) {
386
+ mkdirSync(cursorDir, { recursive: true });
387
+ }
388
+ cpSync(join(TEMPLATES_DIR, ".cursor"), cursorDir, { recursive: true });
389
+ log.step("Created .cursor/ directory with rules, commands, and hooks");
390
+
391
+ // Copy .cursorignore
392
+ if (existsSync(join(TEMPLATES_DIR, ".cursorignore.template"))) {
393
+ cpSync(
394
+ join(TEMPLATES_DIR, ".cursorignore.template"),
395
+ join(targetDir, ".cursorignore"),
396
+ );
397
+ log.step("Created .cursorignore");
398
+ }
399
+
400
+ // Cursor reads CLAUDE.md natively - copy if not already present
401
+ const claudeMdPath = join(targetDir, "CLAUDE.md");
402
+ if (!existsSync(claudeMdPath) && !shouldCopyClaude) {
403
+ cpSync(
404
+ join(TEMPLATES_DIR, "CLAUDE.md"),
405
+ claudeMdPath,
406
+ );
407
+ log.step("Created CLAUDE.md (Cursor reads this natively)");
408
+ }
409
+
410
+ // Copy AGENTS.md if not already present (Cursor reads this too)
411
+ const agentsMdPath = join(targetDir, "AGENTS.md");
412
+ if (!existsSync(agentsMdPath) && !shouldCopyCodex) {
413
+ cpSync(
414
+ join(TEMPLATES_DIR, "AGENTS.md"),
415
+ agentsMdPath,
416
+ );
417
+ log.step("Created AGENTS.md (Cursor reads this natively)");
418
+ }
419
+ }
420
+
421
+ // Copy shared templates (.gitignore)
422
+ if (existsSync(join(TEMPLATES_DIR, ".gitignore.template"))) {
423
+ const gitignorePath = join(targetDir, ".gitignore");
424
+ const gitignoreContent = existsSync(gitignorePath)
425
+ ? readFileSync(gitignorePath, "utf8")
426
+ : "";
427
+
428
+ const templateContent = readFileSync(
429
+ join(TEMPLATES_DIR, ".gitignore.template"),
430
+ "utf8",
431
+ );
432
+
433
+ // Add new entries that don't already exist
434
+ const additions = templateContent
435
+ .split("\n")
436
+ .filter((line) => line.trim() && !gitignoreContent.includes(line.trim()));
437
+
438
+ if (additions.length > 0) {
439
+ writeFileSync(
440
+ gitignorePath,
441
+ gitignoreContent + (gitignoreContent.endsWith("\n") ? "" : "\n") + additions.join("\n") + "\n",
442
+ );
443
+ log.step("Updated .gitignore");
444
+ }
445
+ }
446
+
447
+ log.success("Workspace templates copied");
448
+ }
449
+
450
+ // ============================================================================
451
+ // Main CLI
452
+ // ============================================================================
453
+ function parseArgs(argv) {
454
+ const args = { flags: {}, positional: [] };
455
+ for (const arg of argv) {
456
+ if (arg === "--yes" || arg === "-y") {
457
+ args.flags.yes = true;
458
+ } else if (arg.startsWith("--agent=")) {
459
+ const agent = arg.split("=")[1];
460
+ if (["claude", "codex", "cursor", "all"].includes(agent)) {
461
+ args.flags.agent = agent;
462
+ } else {
463
+ log.warn(`Unknown agent "${agent}". Valid options: claude, codex, cursor, all`);
464
+ }
465
+ } else if (arg === "--help" || arg === "-h") {
466
+ args.flags.help = true;
467
+ } else if (arg.startsWith("-")) {
468
+ // ignore unknown flags
469
+ } else {
470
+ args.positional.push(arg);
471
+ }
472
+ }
473
+ return args;
474
+ }
475
+
476
+ function showHelp() {
477
+ console.log(`
478
+ ${colors.bold}Usage:${colors.reset}
479
+ npx @acmeacmeio/setup-sh [directory] [options]
480
+
481
+ ${colors.bold}Options:${colors.reset}
482
+ --agent=<agent> Select AI coding agent (claude, codex, cursor, all)
483
+ -y, --yes Auto-confirm all prompts
484
+ -h, --help Show this help message
485
+
486
+ ${colors.bold}Examples:${colors.reset}
487
+ npx @acmeacmeio/setup-sh # Current directory, interactive
488
+ npx @acmeacmeio/setup-sh my-project # New directory, interactive
489
+ npx @acmeacmeio/setup-sh . --agent=claude # Claude Code only
490
+ npx @acmeacmeio/setup-sh . --agent=codex # Codex only
491
+ npx @acmeacmeio/setup-sh . --agent=cursor # Cursor IDE only
492
+ npx @acmeacmeio/setup-sh . --agent=all # All agents
493
+ `);
494
+ }
495
+
496
+ async function main() {
497
+ const { flags, positional } = parseArgs(process.argv.slice(2));
498
+
499
+ if (flags.help) {
500
+ showHelp();
501
+ process.exit(0);
502
+ }
503
+
504
+ const autoYes = flags.yes;
505
+ const targetDir = positional[0]
506
+ ? isAbsolute(positional[0])
507
+ ? positional[0]
508
+ : resolve(process.cwd(), positional[0])
509
+ : process.cwd();
510
+
511
+ console.log(`
512
+ ${colors.bold}${colors.magenta}
513
+ ███████╗███████╗████████╗██╗ ██╗██████╗ ███████╗██╗ ██╗
514
+ ██╔════╝██╔════╝╚══██╔══╝██║ ██║██╔══██╗ ██╔════╝██║ ██║
515
+ ███████╗█████╗ ██║ ██║ ██║██████╔╝ █████╗███████╗███████║
516
+ ╚════██║██╔══╝ ██║ ██║ ██║██╔═══╝ ╚════╝╚════██║██╔══██║
517
+ ███████║███████╗ ██║ ╚██████╔╝██║ ███████║██║ ██║
518
+ ╚══════╝╚══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝
519
+ ${colors.reset}
520
+ ${colors.dim}Multi-Agent Workspace Initializer${colors.reset}
521
+ `);
522
+
523
+ // Ensure target directory exists
524
+ if (!existsSync(targetDir)) {
525
+ mkdirSync(targetDir, { recursive: true });
526
+ }
527
+
528
+ const platform = detectPlatform();
529
+ log.info(`Detected platform: ${platform.os} (${platform.pm})`);
530
+ log.info(`Target directory: ${targetDir}`);
531
+
532
+ const prompt = createPrompt(autoYes);
533
+
534
+ try {
535
+ // Step 0: Select AI coding agent
536
+ let agentChoice = flags.agent;
537
+ if (!agentChoice) {
538
+ agentChoice = await prompt.select(
539
+ "Which AI coding agent are you using?",
540
+ [
541
+ { value: "claude", label: "Claude Code (Anthropic)", default: true },
542
+ { value: "codex", label: "Codex (OpenAI)" },
543
+ { value: "cursor", label: "Cursor IDE" },
544
+ { value: "all", label: "All agents (generate all configs)" },
545
+ ],
546
+ );
547
+ }
548
+ log.info(`Selected agent: ${agentChoice}`);
549
+
550
+ // Step 1: Install system tools
551
+ await installTools(platform, prompt);
552
+
553
+ // Step 2: Copy/create workspace files based on agent selection
554
+ copyTemplates(targetDir, agentChoice);
555
+
556
+ // Step 3: Install external skills (Claude Code only)
557
+ await installSkills(prompt, agentChoice);
558
+
559
+ // Done! Show appropriate next steps based on agent choice
560
+ const nextSteps = getNextSteps(agentChoice);
561
+ console.log(`
562
+ ${colors.green}${colors.bold}
563
+ Workspace is ready!${colors.reset}
564
+
565
+ ${colors.cyan}Next steps:${colors.reset}
566
+ ${nextSteps}
567
+
568
+ ${colors.dim}Tips:${colors.reset}
569
+ ${getTips(agentChoice)}
570
+ `);
571
+ } catch (error) {
572
+ log.error(`Setup failed: ${error.message}`);
573
+ process.exit(1);
574
+ } finally {
575
+ prompt.close();
576
+ }
577
+ }
578
+
579
+ function getNextSteps(agentChoice) {
580
+ const claudeSteps = ` - Review and customize ${colors.bold}CLAUDE.md${colors.reset} for your project
581
+ - Run ${colors.bold}claude${colors.reset} to start coding with AI assistance`;
582
+
583
+ const codexSteps = ` - Review and customize ${colors.bold}AGENTS.md${colors.reset} for your project
584
+ - Run ${colors.bold}codex${colors.reset} to start coding with AI assistance`;
585
+
586
+ const cursorSteps = ` - Review and customize ${colors.bold}CLAUDE.md${colors.reset} for your project (Cursor reads this)
587
+ - Add custom rules in ${colors.bold}.cursor/rules/${colors.reset}
588
+ - Open the project in Cursor IDE`;
589
+
590
+ if (agentChoice === "claude") return claudeSteps;
591
+ if (agentChoice === "codex") return codexSteps;
592
+ if (agentChoice === "cursor") return cursorSteps;
593
+ return claudeSteps + "\n" + codexSteps + "\n" + cursorSteps;
594
+ }
595
+
596
+ function getTips(agentChoice) {
597
+ const claudeTips = ` - Create ${colors.bold}CLAUDE.local.md${colors.reset} for personal preferences (gitignored)
598
+ - Edit ${colors.bold}.claude/settings.local.json${colors.reset} for local overrides`;
599
+
600
+ const codexTips = ` - Create ${colors.bold}AGENTS.local.md${colors.reset} for personal preferences (gitignored)
601
+ - Edit ${colors.bold}.codex/config.local.toml${colors.reset} for local overrides`;
602
+
603
+ const cursorTips = ` - Add ${colors.bold}alwaysApply: true${colors.reset} to rules that should always be active
604
+ - Use ${colors.bold}globs${colors.reset} in rules for file-specific context`;
605
+
606
+ const sharedTips = ` - Run ${colors.bold}gh auth login${colors.reset} if GitHub CLI needs authentication`;
607
+
608
+ if (agentChoice === "claude") return claudeTips + "\n" + sharedTips;
609
+ if (agentChoice === "codex") return codexTips + "\n" + sharedTips;
610
+ if (agentChoice === "cursor") return cursorTips + "\n" + sharedTips;
611
+ return claudeTips + "\n" + codexTips + "\n" + cursorTips + "\n" + sharedTips;
612
+ }
613
+
614
+ main();
@@ -0,0 +1,52 @@
1
+ ---
2
+ name: code-simplifier
3
+ description: Simplifies and refines code for clarity, consistency, and maintainability while preserving all functionality. Focuses on recently modified code unless instructed otherwise.
4
+ model: opus
5
+ ---
6
+
7
+ You are an expert code simplification specialist focused on enhancing code clarity, consistency, and maintainability while preserving exact functionality. Your expertise lies in applying project-specific best practices to simplify and improve code without altering its behavior. You prioritize readable, explicit code over overly compact solutions. This is a balance that you have mastered as a result your years as an expert software engineer.
8
+
9
+ You will analyze recently modified code and apply refinements that:
10
+
11
+ 1. **Preserve Functionality**: Never change what the code does - only how it does it. All original features, outputs, and behaviors must remain intact.
12
+
13
+ 2. **Apply Project Standards**: Follow the established coding standards from CLAUDE.md including:
14
+
15
+ - Use ES modules with proper import sorting and extensions
16
+ - Prefer `function` keyword over arrow functions
17
+ - Use explicit return type annotations for top-level functions
18
+ - Follow proper React component patterns with explicit Props types
19
+ - Use proper error handling patterns (avoid try/catch when possible)
20
+ - Maintain consistent naming conventions
21
+
22
+ 3. **Enhance Clarity**: Simplify code structure by:
23
+
24
+ - Reducing unnecessary complexity and nesting
25
+ - Eliminating redundant code and abstractions
26
+ - Improving readability through clear variable and function names
27
+ - Consolidating related logic
28
+ - Removing unnecessary comments that describe obvious code
29
+ - IMPORTANT: Avoid nested ternary operators - prefer switch statements or if/else chains for multiple conditions
30
+ - Choose clarity over brevity - explicit code is often better than overly compact code
31
+
32
+ 4. **Maintain Balance**: Avoid over-simplification that could:
33
+
34
+ - Reduce code clarity or maintainability
35
+ - Create overly clever solutions that are hard to understand
36
+ - Combine too many concerns into single functions or components
37
+ - Remove helpful abstractions that improve code organization
38
+ - Prioritize "fewer lines" over readability (e.g., nested ternaries, dense one-liners)
39
+ - Make the code harder to debug or extend
40
+
41
+ 5. **Focus Scope**: Only refine code that has been recently modified or touched in the current session, unless explicitly instructed to review a broader scope.
42
+
43
+ Your refinement process:
44
+
45
+ 1. Identify the recently modified code sections
46
+ 2. Analyze for opportunities to improve elegance and consistency
47
+ 3. Apply project-specific best practices and coding standards
48
+ 4. Ensure all functionality remains unchanged
49
+ 5. Verify the refined code is simpler and more maintainable
50
+ 6. Document only significant changes that affect understanding
51
+
52
+ You operate autonomously and proactively, refining code immediately after it's written or modified without requiring explicit requests. Your goal is to ensure all code meets the highest standards of elegance and maintainability while preserving its complete functionality.