@howlil/ez-agents 2.0.0 → 2.0.1

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 (106) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +93 -93
  3. package/agents/ez-plan-checker.md +2 -2
  4. package/agents/ez-research-synthesizer.md +1 -1
  5. package/agents/ez-ui-researcher.md +1 -1
  6. package/agents/ez-verifier.md +1 -1
  7. package/bin/install.js +132 -132
  8. package/get-shit-done/bin/lib/assistant-adapter.cjs +205 -205
  9. package/get-shit-done/bin/lib/audit-exec.cjs +150 -150
  10. package/get-shit-done/bin/lib/auth.cjs +175 -175
  11. package/get-shit-done/bin/lib/circuit-breaker.cjs +118 -118
  12. package/get-shit-done/bin/lib/commands.cjs +666 -666
  13. package/get-shit-done/bin/lib/config.cjs +183 -183
  14. package/get-shit-done/bin/lib/core.cjs +495 -495
  15. package/get-shit-done/bin/lib/file-lock.cjs +236 -236
  16. package/get-shit-done/bin/lib/frontmatter.cjs +299 -299
  17. package/get-shit-done/bin/lib/fs-utils.cjs +153 -153
  18. package/get-shit-done/bin/lib/git-utils.cjs +203 -203
  19. package/get-shit-done/bin/lib/health-check.cjs +163 -163
  20. package/get-shit-done/bin/lib/index.cjs +113 -113
  21. package/get-shit-done/bin/lib/init.cjs +710 -710
  22. package/get-shit-done/bin/lib/logger.cjs +117 -117
  23. package/get-shit-done/bin/lib/milestone.cjs +241 -241
  24. package/get-shit-done/bin/lib/model-provider.cjs +146 -146
  25. package/get-shit-done/bin/lib/phase.cjs +908 -908
  26. package/get-shit-done/bin/lib/retry.cjs +119 -119
  27. package/get-shit-done/bin/lib/roadmap.cjs +305 -305
  28. package/get-shit-done/bin/lib/safe-exec.cjs +128 -128
  29. package/get-shit-done/bin/lib/safe-path.cjs +130 -130
  30. package/get-shit-done/bin/lib/state.cjs +721 -721
  31. package/get-shit-done/bin/lib/temp-file.cjs +239 -239
  32. package/get-shit-done/bin/lib/template.cjs +222 -222
  33. package/get-shit-done/bin/lib/test-file-lock.cjs +112 -112
  34. package/get-shit-done/bin/lib/test-graceful.cjs +93 -93
  35. package/get-shit-done/bin/lib/test-logger.cjs +60 -60
  36. package/get-shit-done/bin/lib/test-safe-exec.cjs +38 -38
  37. package/get-shit-done/bin/lib/test-safe-path.cjs +33 -33
  38. package/get-shit-done/bin/lib/test-temp-file.cjs +125 -125
  39. package/get-shit-done/bin/lib/timeout-exec.cjs +62 -62
  40. package/get-shit-done/bin/lib/verify.cjs +820 -820
  41. package/get-shit-done/references/checkpoints.md +776 -776
  42. package/get-shit-done/references/questioning.md +162 -162
  43. package/get-shit-done/references/tdd.md +263 -263
  44. package/get-shit-done/templates/codebase/concerns.md +310 -310
  45. package/get-shit-done/templates/codebase/conventions.md +307 -307
  46. package/get-shit-done/templates/codebase/integrations.md +280 -280
  47. package/get-shit-done/templates/codebase/stack.md +186 -186
  48. package/get-shit-done/templates/codebase/testing.md +480 -480
  49. package/get-shit-done/templates/config.json +37 -37
  50. package/get-shit-done/templates/continue-here.md +78 -78
  51. package/get-shit-done/templates/milestone-archive.md +123 -123
  52. package/get-shit-done/templates/milestone.md +115 -115
  53. package/get-shit-done/templates/requirements.md +231 -231
  54. package/get-shit-done/templates/research-project/ARCHITECTURE.md +204 -204
  55. package/get-shit-done/templates/research-project/FEATURES.md +147 -147
  56. package/get-shit-done/templates/research-project/PITFALLS.md +200 -200
  57. package/get-shit-done/templates/research-project/STACK.md +120 -120
  58. package/get-shit-done/templates/research-project/SUMMARY.md +170 -170
  59. package/get-shit-done/templates/retrospective.md +54 -54
  60. package/get-shit-done/templates/roadmap.md +202 -202
  61. package/get-shit-done/templates/summary-minimal.md +41 -41
  62. package/get-shit-done/templates/summary-standard.md +48 -48
  63. package/get-shit-done/templates/summary.md +248 -248
  64. package/get-shit-done/templates/user-setup.md +311 -311
  65. package/get-shit-done/templates/verification-report.md +322 -322
  66. package/get-shit-done/workflows/add-phase.md +112 -112
  67. package/get-shit-done/workflows/add-tests.md +351 -351
  68. package/get-shit-done/workflows/add-todo.md +158 -158
  69. package/get-shit-done/workflows/audit-milestone.md +332 -332
  70. package/get-shit-done/workflows/autonomous.md +743 -743
  71. package/get-shit-done/workflows/check-todos.md +177 -177
  72. package/get-shit-done/workflows/cleanup.md +152 -152
  73. package/get-shit-done/workflows/complete-milestone.md +766 -766
  74. package/get-shit-done/workflows/diagnose-issues.md +219 -219
  75. package/get-shit-done/workflows/discovery-phase.md +289 -289
  76. package/get-shit-done/workflows/discuss-phase.md +762 -762
  77. package/get-shit-done/workflows/execute-phase.md +468 -468
  78. package/get-shit-done/workflows/execute-plan.md +483 -483
  79. package/get-shit-done/workflows/health.md +159 -159
  80. package/get-shit-done/workflows/help.md +492 -492
  81. package/get-shit-done/workflows/insert-phase.md +130 -130
  82. package/get-shit-done/workflows/list-phase-assumptions.md +178 -178
  83. package/get-shit-done/workflows/map-codebase.md +316 -316
  84. package/get-shit-done/workflows/new-milestone.md +384 -384
  85. package/get-shit-done/workflows/new-project.md +1111 -1111
  86. package/get-shit-done/workflows/node-repair.md +92 -92
  87. package/get-shit-done/workflows/pause-work.md +122 -122
  88. package/get-shit-done/workflows/plan-milestone-gaps.md +274 -274
  89. package/get-shit-done/workflows/plan-phase.md +651 -651
  90. package/get-shit-done/workflows/progress.md +382 -382
  91. package/get-shit-done/workflows/quick.md +610 -610
  92. package/get-shit-done/workflows/remove-phase.md +155 -155
  93. package/get-shit-done/workflows/research-phase.md +74 -74
  94. package/get-shit-done/workflows/resume-project.md +307 -307
  95. package/get-shit-done/workflows/set-profile.md +81 -81
  96. package/get-shit-done/workflows/settings.md +242 -242
  97. package/get-shit-done/workflows/stats.md +57 -57
  98. package/get-shit-done/workflows/transition.md +544 -544
  99. package/get-shit-done/workflows/ui-phase.md +290 -290
  100. package/get-shit-done/workflows/ui-review.md +157 -157
  101. package/get-shit-done/workflows/update.md +320 -320
  102. package/get-shit-done/workflows/validate-phase.md +167 -167
  103. package/get-shit-done/workflows/verify-phase.md +243 -243
  104. package/package.json +1 -1
  105. package/scripts/build-hooks.js +43 -43
  106. package/scripts/run-tests.cjs +29 -29
package/bin/install.js CHANGED
@@ -249,12 +249,12 @@ function getGlobalDir(runtime, explicitDir = null) {
249
249
  }
250
250
 
251
251
  const banner = '\n' +
252
- cyan + ' ██████╗ ███████╗██████╗\n' +
253
- ' ██╔════╝ ██╔════╝██╔══██╗\n' +
254
- ' ██║ ███╗███████╗██║ ██║\n' +
255
- ' ██║ ██║╚════██║██║ ██║\n' +
256
- ' ╚██████╔╝███████║██████╔╝\n' +
257
- ' ╚═════╝ ╚══════╝╚═════╝' + reset + '\n' +
252
+ cyan + ' ███████╗██╗ ██╗\n' +
253
+ ' ██╔════╝╚██╗██╔╝\n' +
254
+ ' █████╗ ╚███╔╝ \n' +
255
+ ' ██╔══╝ ██╔██╗ \n' +
256
+ ' ███████╗██╔╝╚██╗\n' +
257
+ ' ╚══════╝╚═╝ ╚═╝' + reset + '\n' +
258
258
  '\n' +
259
259
  ' EZ Agents ' + dim + 'v' + pkg.version + reset + '\n' +
260
260
  ' ' + dim + 'Multi-Model Edition' + reset + '\n' +
@@ -1220,12 +1220,12 @@ function convertClaudeToGeminiToml(content) {
1220
1220
 
1221
1221
  /**
1222
1222
  * Copy commands to a flat structure for OpenCode
1223
- * OpenCode expects: command/gsd-help.md (invoked as /gsd-help)
1224
- * Source structure: commands/gsd/help.md
1225
- *
1226
- * @param {string} srcDir - Source directory (e.g., commands/gsd/)
1223
+ * OpenCode expects: command/ez-help.md (invoked as /ez-help)
1224
+ * Source structure: commands/ez/help.md
1225
+ *
1226
+ * @param {string} srcDir - Source directory (e.g., commands/ez/)
1227
1227
  * @param {string} destDir - Destination directory (e.g., command/)
1228
- * @param {string} prefix - Prefix for filenames (e.g., 'gsd')
1228
+ * @param {string} prefix - Prefix for filenames (e.g., 'ez')
1229
1229
  * @param {string} pathPrefix - Path prefix for file references
1230
1230
  * @param {string} runtime - Target runtime ('claude' or 'opencode')
1231
1231
  */
@@ -1233,8 +1233,8 @@ function copyFlattenedCommands(srcDir, destDir, prefix, pathPrefix, runtime) {
1233
1233
  if (!fs.existsSync(srcDir)) {
1234
1234
  return;
1235
1235
  }
1236
-
1237
- // Remove old gsd-*.md files before copying new ones
1236
+
1237
+ // Remove old ez-*.md files before copying new ones
1238
1238
  if (fs.existsSync(destDir)) {
1239
1239
  for (const file of fs.readdirSync(destDir)) {
1240
1240
  if (file.startsWith(`${prefix}-`) && file.endsWith('.md')) {
@@ -1244,18 +1244,18 @@ function copyFlattenedCommands(srcDir, destDir, prefix, pathPrefix, runtime) {
1244
1244
  } else {
1245
1245
  fs.mkdirSync(destDir, { recursive: true });
1246
1246
  }
1247
-
1247
+
1248
1248
  const entries = fs.readdirSync(srcDir, { withFileTypes: true });
1249
-
1249
+
1250
1250
  for (const entry of entries) {
1251
1251
  const srcPath = path.join(srcDir, entry.name);
1252
-
1252
+
1253
1253
  if (entry.isDirectory()) {
1254
1254
  // Recurse into subdirectories, adding to prefix
1255
- // e.g., commands/gsd/debug/start.md -> command/gsd-debug-start.md
1255
+ // e.g., commands/ez/debug/start.md -> command/ez-debug-start.md
1256
1256
  copyFlattenedCommands(srcPath, destDir, `${prefix}-${entry.name}`, pathPrefix, runtime);
1257
1257
  } else if (entry.name.endsWith('.md')) {
1258
- // Flatten: help.md -> gsd-help.md
1258
+ // Flatten: help.md -> ez-help.md
1259
1259
  const baseName = entry.name.replace('.md', '');
1260
1260
  const destName = `${prefix}-${baseName}.md`;
1261
1261
  const destPath = path.join(destDir, destName);
@@ -1277,7 +1277,7 @@ function copyFlattenedCommands(srcDir, destDir, prefix, pathPrefix, runtime) {
1277
1277
  }
1278
1278
  }
1279
1279
 
1280
- function listCodexSkillNames(skillsDir, prefix = 'gsd-') {
1280
+ function listCodexSkillNames(skillsDir, prefix = 'ez-') {
1281
1281
  if (!fs.existsSync(skillsDir)) return [];
1282
1282
  const entries = fs.readdirSync(skillsDir, { withFileTypes: true });
1283
1283
  return entries
@@ -1294,7 +1294,7 @@ function copyCommandsAsCodexSkills(srcDir, skillsDir, prefix, pathPrefix, runtim
1294
1294
 
1295
1295
  fs.mkdirSync(skillsDir, { recursive: true });
1296
1296
 
1297
- // Remove previous GSD Codex skills to avoid stale command skills.
1297
+ // Remove previous EZ Codex skills to avoid stale command skills.
1298
1298
  const existing = fs.readdirSync(skillsDir, { withFileTypes: true });
1299
1299
  for (const entry of existing) {
1300
1300
  if (entry.isDirectory() && entry.name.startsWith(`${prefix}-`)) {
@@ -1351,7 +1351,7 @@ function copyCommandsAsCopilotSkills(srcDir, skillsDir, prefix, isGlobal = false
1351
1351
 
1352
1352
  fs.mkdirSync(skillsDir, { recursive: true });
1353
1353
 
1354
- // Remove previous GSD Copilot skills
1354
+ // Remove previous EZ Copilot skills
1355
1355
  const existing = fs.readdirSync(skillsDir, { withFileTypes: true });
1356
1356
  for (const entry of existing) {
1357
1357
  if (entry.isDirectory() && entry.name.startsWith(`${prefix}-`)) {
@@ -1468,12 +1468,12 @@ function copyWithPathReplacement(srcDir, destDir, pathPrefix, runtime, isCommand
1468
1468
  }
1469
1469
 
1470
1470
  /**
1471
- * Clean up orphaned files from previous GSD versions
1471
+ * Clean up orphaned files from previous versions
1472
1472
  */
1473
1473
  function cleanupOrphanedFiles(configDir) {
1474
1474
  const orphanedFiles = [
1475
- 'hooks/gsd-notify.sh', // Removed in v1.6.x
1476
- 'hooks/statusline.js', // Renamed to gsd-statusline.js in v1.9.0
1475
+ 'hooks/ez-notify.sh', // Removed in v1.6.x
1476
+ 'hooks/statusline.js', // Renamed to ez-statusline.js in v1.9.0
1477
1477
  ];
1478
1478
 
1479
1479
  for (const relPath of orphanedFiles) {
@@ -1490,11 +1490,11 @@ function cleanupOrphanedFiles(configDir) {
1490
1490
  */
1491
1491
  function cleanupOrphanedHooks(settings) {
1492
1492
  const orphanedHookPatterns = [
1493
- 'gsd-notify.sh', // Removed in v1.6.x
1494
- 'hooks/statusline.js', // Renamed to gsd-statusline.js in v1.9.0
1495
- 'gsd-intel-index.js', // Removed in v1.9.2
1496
- 'gsd-intel-session.js', // Removed in v1.9.2
1497
- 'gsd-intel-prune.js', // Removed in v1.9.2
1493
+ 'ez-notify.sh', // Removed in v1.6.x
1494
+ 'hooks/statusline.js', // Renamed to ez-statusline.js in v1.9.0
1495
+ 'ez-intel-index.js', // Removed in v1.9.2
1496
+ 'ez-intel-session.js', // Removed in v1.9.2
1497
+ 'ez-intel-prune.js', // Removed in v1.9.2
1498
1498
  ];
1499
1499
 
1500
1500
  let cleanedHooks = false;
@@ -1527,16 +1527,16 @@ function cleanupOrphanedHooks(settings) {
1527
1527
  console.log(` ${green}✓${reset} Removed orphaned hook registrations`);
1528
1528
  }
1529
1529
 
1530
- // Fix #330: Update statusLine if it points to old GSD statusline.js path
1531
- // Only match the specific old GSD path pattern (hooks/statusline.js),
1530
+ // Fix #330: Update statusLine if it points to old statusline.js path
1531
+ // Only match the specific old path pattern (hooks/statusline.js),
1532
1532
  // not third-party statusline scripts that happen to contain 'statusline.js'
1533
1533
  if (settings.statusLine && settings.statusLine.command &&
1534
1534
  /hooks[\/\\]statusline\.js/.test(settings.statusLine.command)) {
1535
1535
  settings.statusLine.command = settings.statusLine.command.replace(
1536
1536
  /hooks([\/\\])statusline\.js/,
1537
- 'hooks$1gsd-statusline.js'
1537
+ 'hooks$1ez-statusline.js'
1538
1538
  );
1539
- console.log(` ${green}✓${reset} Updated statusline path (hooks/statusline.js → hooks/gsd-statusline.js)`);
1539
+ console.log(` ${green}✓${reset} Updated statusline path (hooks/statusline.js → hooks/ez-statusline.js)`);
1540
1540
  }
1541
1541
 
1542
1542
  return settings;
@@ -1580,14 +1580,14 @@ function uninstall(isGlobal, runtime = 'claude') {
1580
1580
 
1581
1581
  let removedCount = 0;
1582
1582
 
1583
- // 1. Remove GSD commands/skills
1583
+ // 1. Remove EZ commands/skills
1584
1584
  if (isOpencode) {
1585
- // OpenCode: remove command/gsd-*.md files
1585
+ // OpenCode: remove command/ez-*.md files
1586
1586
  const commandDir = path.join(targetDir, 'command');
1587
1587
  if (fs.existsSync(commandDir)) {
1588
1588
  const files = fs.readdirSync(commandDir);
1589
1589
  for (const file of files) {
1590
- if (file.startsWith('gsd-') && file.endsWith('.md')) {
1590
+ if (file.startsWith('ez-') && file.endsWith('.md')) {
1591
1591
  fs.unlinkSync(path.join(commandDir, file));
1592
1592
  removedCount++;
1593
1593
  }
@@ -1595,13 +1595,13 @@ function uninstall(isGlobal, runtime = 'claude') {
1595
1595
  console.log(` ${green}✓${reset} Removed EZ Agents commands from command/`);
1596
1596
  }
1597
1597
  } else if (isCodex) {
1598
- // Codex: remove skills/gsd-*/SKILL.md skill directories
1598
+ // Codex: remove skills/ez-*/SKILL.md skill directories
1599
1599
  const skillsDir = path.join(targetDir, 'skills');
1600
1600
  if (fs.existsSync(skillsDir)) {
1601
1601
  let skillCount = 0;
1602
1602
  const entries = fs.readdirSync(skillsDir, { withFileTypes: true });
1603
1603
  for (const entry of entries) {
1604
- if (entry.isDirectory() && entry.name.startsWith('gsd-')) {
1604
+ if (entry.isDirectory() && entry.name.startsWith('ez-')) {
1605
1605
  fs.rmSync(path.join(skillsDir, entry.name), { recursive: true });
1606
1606
  skillCount++;
1607
1607
  }
@@ -1612,13 +1612,13 @@ function uninstall(isGlobal, runtime = 'claude') {
1612
1612
  }
1613
1613
  }
1614
1614
 
1615
- // Codex: remove GSD agent .toml config files
1615
+ // Codex: remove EZ agent .toml config files
1616
1616
  const codexAgentsDir = path.join(targetDir, 'agents');
1617
1617
  if (fs.existsSync(codexAgentsDir)) {
1618
1618
  const tomlFiles = fs.readdirSync(codexAgentsDir);
1619
1619
  let tomlCount = 0;
1620
1620
  for (const file of tomlFiles) {
1621
- if (file.startsWith('gsd-') && file.endsWith('.toml')) {
1621
+ if (file.startsWith('ez-') && file.endsWith('.toml')) {
1622
1622
  fs.unlinkSync(path.join(codexAgentsDir, file));
1623
1623
  tomlCount++;
1624
1624
  }
@@ -1629,7 +1629,7 @@ function uninstall(isGlobal, runtime = 'claude') {
1629
1629
  }
1630
1630
  }
1631
1631
 
1632
- // Codex: clean GSD sections from config.toml
1632
+ // Codex: clean EZ sections from config.toml
1633
1633
  const configPath = path.join(targetDir, 'config.toml');
1634
1634
  if (fs.existsSync(configPath)) {
1635
1635
  const content = fs.readFileSync(configPath, 'utf8');
@@ -1646,13 +1646,13 @@ function uninstall(isGlobal, runtime = 'claude') {
1646
1646
  }
1647
1647
  }
1648
1648
  } else if (isCopilot) {
1649
- // Copilot: remove skills/gsd-*/ directories (same layout as Codex skills)
1649
+ // Copilot: remove skills/ez-*/ directories (same layout as Codex skills)
1650
1650
  const skillsDir = path.join(targetDir, 'skills');
1651
1651
  if (fs.existsSync(skillsDir)) {
1652
1652
  let skillCount = 0;
1653
1653
  const entries = fs.readdirSync(skillsDir, { withFileTypes: true });
1654
1654
  for (const entry of entries) {
1655
- if (entry.isDirectory() && entry.name.startsWith('gsd-')) {
1655
+ if (entry.isDirectory() && entry.name.startsWith('ez-')) {
1656
1656
  fs.rmSync(path.join(skillsDir, entry.name), { recursive: true });
1657
1657
  skillCount++;
1658
1658
  }
@@ -1663,7 +1663,7 @@ function uninstall(isGlobal, runtime = 'claude') {
1663
1663
  }
1664
1664
  }
1665
1665
 
1666
- // Copilot: clean GSD section from copilot-instructions.md
1666
+ // Copilot: clean EZ section from copilot-instructions.md
1667
1667
  const instructionsPath = path.join(targetDir, 'copilot-instructions.md');
1668
1668
  if (fs.existsSync(instructionsPath)) {
1669
1669
  const content = fs.readFileSync(instructionsPath, 'utf8');
@@ -1679,29 +1679,29 @@ function uninstall(isGlobal, runtime = 'claude') {
1679
1679
  }
1680
1680
  }
1681
1681
  } else {
1682
- const gsdCommandsDir = path.join(targetDir, 'commands', 'gsd');
1683
- if (fs.existsSync(gsdCommandsDir)) {
1684
- fs.rmSync(gsdCommandsDir, { recursive: true });
1682
+ const ezCommandsDir = path.join(targetDir, 'commands', 'ez');
1683
+ if (fs.existsSync(ezCommandsDir)) {
1684
+ fs.rmSync(ezCommandsDir, { recursive: true });
1685
1685
  removedCount++;
1686
- console.log(` ${green}✓${reset} Removed commands/gsd/`);
1686
+ console.log(` ${green}✓${reset} Removed commands/ez/`);
1687
1687
  }
1688
1688
  }
1689
1689
 
1690
1690
  // 2. Remove get-shit-done directory
1691
- const gsdDir = path.join(targetDir, 'get-shit-done');
1692
- if (fs.existsSync(gsdDir)) {
1693
- fs.rmSync(gsdDir, { recursive: true });
1691
+ const ezDir = path.join(targetDir, 'get-shit-done');
1692
+ if (fs.existsSync(ezDir)) {
1693
+ fs.rmSync(ezDir, { recursive: true });
1694
1694
  removedCount++;
1695
1695
  console.log(` ${green}✓${reset} Removed get-shit-done/`);
1696
1696
  }
1697
1697
 
1698
- // 3. Remove EZ Agents agents (gsd-*.md files only)
1698
+ // 3. Remove EZ Agents agents (ez-*.md files only)
1699
1699
  const agentsDir = path.join(targetDir, 'agents');
1700
1700
  if (fs.existsSync(agentsDir)) {
1701
1701
  const files = fs.readdirSync(agentsDir);
1702
1702
  let agentCount = 0;
1703
1703
  for (const file of files) {
1704
- if (file.startsWith('gsd-') && file.endsWith('.md')) {
1704
+ if (file.startsWith('ez-') && file.endsWith('.md')) {
1705
1705
  fs.unlinkSync(path.join(agentsDir, file));
1706
1706
  agentCount++;
1707
1707
  }
@@ -1712,12 +1712,12 @@ function uninstall(isGlobal, runtime = 'claude') {
1712
1712
  }
1713
1713
  }
1714
1714
 
1715
- // 4. Remove GSD hooks
1715
+ // 4. Remove EZ hooks
1716
1716
  const hooksDir = path.join(targetDir, 'hooks');
1717
1717
  if (fs.existsSync(hooksDir)) {
1718
- const gsdHooks = ['gsd-statusline.js', 'gsd-check-update.js', 'gsd-check-update.sh', 'gsd-context-monitor.js'];
1718
+ const ezHooks = ['ez-statusline.js', 'ez-check-update.js', 'ez-check-update.sh', 'ez-context-monitor.js'];
1719
1719
  let hookCount = 0;
1720
- for (const hook of gsdHooks) {
1720
+ for (const hook of ezHooks) {
1721
1721
  const hookPath = path.join(hooksDir, hook);
1722
1722
  if (fs.existsSync(hookPath)) {
1723
1723
  fs.unlinkSync(hookPath);
@@ -1726,11 +1726,11 @@ function uninstall(isGlobal, runtime = 'claude') {
1726
1726
  }
1727
1727
  if (hookCount > 0) {
1728
1728
  removedCount++;
1729
- console.log(` ${green}✓${reset} Removed ${hookCount} GSD hooks`);
1729
+ console.log(` ${green}✓${reset} Removed ${hookCount} EZ hooks`);
1730
1730
  }
1731
1731
  }
1732
1732
 
1733
- // 5. Remove GSD package.json (CommonJS mode marker)
1733
+ // 5. Remove EZ package.json (CommonJS mode marker)
1734
1734
  const pkgJsonPath = path.join(targetDir, 'package.json');
1735
1735
  if (fs.existsSync(pkgJsonPath)) {
1736
1736
  try {
@@ -1739,43 +1739,43 @@ function uninstall(isGlobal, runtime = 'claude') {
1739
1739
  if (content === '{"type":"commonjs"}') {
1740
1740
  fs.unlinkSync(pkgJsonPath);
1741
1741
  removedCount++;
1742
- console.log(` ${green}✓${reset} Removed GSD package.json`);
1742
+ console.log(` ${green}✓${reset} Removed EZ package.json`);
1743
1743
  }
1744
1744
  } catch (e) {
1745
1745
  // Ignore read errors
1746
1746
  }
1747
1747
  }
1748
1748
 
1749
- // 6. Clean up settings.json (remove GSD hooks and statusline)
1749
+ // 6. Clean up settings.json (remove EZ hooks and statusline)
1750
1750
  const settingsPath = path.join(targetDir, 'settings.json');
1751
1751
  if (fs.existsSync(settingsPath)) {
1752
1752
  let settings = readSettings(settingsPath);
1753
1753
  let settingsModified = false;
1754
1754
 
1755
- // Remove GSD statusline if it references our hook
1755
+ // Remove EZ statusline if it references our hook
1756
1756
  if (settings.statusLine && settings.statusLine.command &&
1757
- settings.statusLine.command.includes('gsd-statusline')) {
1757
+ settings.statusLine.command.includes('ez-statusline')) {
1758
1758
  delete settings.statusLine;
1759
1759
  settingsModified = true;
1760
- console.log(` ${green}✓${reset} Removed GSD statusline from settings`);
1760
+ console.log(` ${green}✓${reset} Removed EZ statusline from settings`);
1761
1761
  }
1762
1762
 
1763
- // Remove GSD hooks from SessionStart
1763
+ // Remove EZ hooks from SessionStart
1764
1764
  if (settings.hooks && settings.hooks.SessionStart) {
1765
1765
  const before = settings.hooks.SessionStart.length;
1766
1766
  settings.hooks.SessionStart = settings.hooks.SessionStart.filter(entry => {
1767
1767
  if (entry.hooks && Array.isArray(entry.hooks)) {
1768
- // Filter out GSD hooks
1769
- const hasGsdHook = entry.hooks.some(h =>
1770
- h.command && (h.command.includes('gsd-check-update') || h.command.includes('gsd-statusline'))
1768
+ // Filter out EZ hooks
1769
+ const hasEzHook = entry.hooks.some(h =>
1770
+ h.command && (h.command.includes('ez-check-update') || h.command.includes('ez-statusline'))
1771
1771
  );
1772
- return !hasGsdHook;
1772
+ return !hasEzHook;
1773
1773
  }
1774
1774
  return true;
1775
1775
  });
1776
1776
  if (settings.hooks.SessionStart.length < before) {
1777
1777
  settingsModified = true;
1778
- console.log(` ${green}✓${reset} Removed GSD hooks from settings`);
1778
+ console.log(` ${green}✓${reset} Removed EZ hooks from settings`);
1779
1779
  }
1780
1780
  // Clean up empty array
1781
1781
  if (settings.hooks.SessionStart.length === 0) {
@@ -1783,16 +1783,16 @@ function uninstall(isGlobal, runtime = 'claude') {
1783
1783
  }
1784
1784
  }
1785
1785
 
1786
- // Remove GSD hooks from PostToolUse and AfterTool (Gemini uses AfterTool)
1786
+ // Remove EZ hooks from PostToolUse and AfterTool (Gemini uses AfterTool)
1787
1787
  for (const eventName of ['PostToolUse', 'AfterTool']) {
1788
1788
  if (settings.hooks && settings.hooks[eventName]) {
1789
1789
  const before = settings.hooks[eventName].length;
1790
1790
  settings.hooks[eventName] = settings.hooks[eventName].filter(entry => {
1791
1791
  if (entry.hooks && Array.isArray(entry.hooks)) {
1792
- const hasGsdHook = entry.hooks.some(h =>
1793
- h.command && h.command.includes('gsd-context-monitor')
1792
+ const hasEzHook = entry.hooks.some(h =>
1793
+ h.command && h.command.includes('ez-context-monitor')
1794
1794
  );
1795
- return !hasGsdHook;
1795
+ return !hasEzHook;
1796
1796
  }
1797
1797
  return true;
1798
1798
  });
@@ -1830,7 +1830,7 @@ function uninstall(isGlobal, runtime = 'claude') {
1830
1830
  const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
1831
1831
  let modified = false;
1832
1832
 
1833
- // Remove GSD permission entries
1833
+ // Remove EZ permission entries
1834
1834
  if (config.permission) {
1835
1835
  for (const permType of ['read', 'external_directory']) {
1836
1836
  if (config.permission[permType]) {
@@ -1855,7 +1855,7 @@ function uninstall(isGlobal, runtime = 'claude') {
1855
1855
  if (modified) {
1856
1856
  fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n');
1857
1857
  removedCount++;
1858
- console.log(` ${green}✓${reset} Removed GSD permissions from opencode.json`);
1858
+ console.log(` ${green}✓${reset} Removed EZ permissions from opencode.json`);
1859
1859
  }
1860
1860
  } catch (e) {
1861
1861
  // Ignore JSON parse errors
@@ -1935,8 +1935,8 @@ function parseJsonc(content) {
1935
1935
  }
1936
1936
 
1937
1937
  /**
1938
- * Configure OpenCode permissions to allow reading GSD reference docs
1939
- * This prevents permission prompts when GSD accesses the get-shit-done directory
1938
+ * Configure OpenCode permissions to allow reading EZ reference docs
1939
+ * This prevents permission prompts when EZ accesses the get-shit-done directory
1940
1940
  * @param {boolean} isGlobal - Whether this is a global or local install
1941
1941
  */
1942
1942
  function configureOpencodePermissions(isGlobal = true) {
@@ -1970,21 +1970,21 @@ function configureOpencodePermissions(isGlobal = true) {
1970
1970
  config.permission = {};
1971
1971
  }
1972
1972
 
1973
- // Build the GSD path using the actual config directory
1973
+ // Build the EZ path using the actual config directory
1974
1974
  // Use ~ shorthand if it's in the default location, otherwise use full path
1975
1975
  const defaultConfigDir = path.join(os.homedir(), '.config', 'opencode');
1976
- const gsdPath = opencodeConfigDir === defaultConfigDir
1976
+ const ezPath = opencodeConfigDir === defaultConfigDir
1977
1977
  ? '~/.config/opencode/get-shit-done/*'
1978
1978
  : `${opencodeConfigDir.replace(/\\/g, '/')}/get-shit-done/*`;
1979
-
1979
+
1980
1980
  let modified = false;
1981
1981
 
1982
1982
  // Configure read permission
1983
1983
  if (!config.permission.read || typeof config.permission.read !== 'object') {
1984
1984
  config.permission.read = {};
1985
1985
  }
1986
- if (config.permission.read[gsdPath] !== 'allow') {
1987
- config.permission.read[gsdPath] = 'allow';
1986
+ if (config.permission.read[ezPath] !== 'allow') {
1987
+ config.permission.read[ezPath] = 'allow';
1988
1988
  modified = true;
1989
1989
  }
1990
1990
 
@@ -1992,8 +1992,8 @@ function configureOpencodePermissions(isGlobal = true) {
1992
1992
  if (!config.permission.external_directory || typeof config.permission.external_directory !== 'object') {
1993
1993
  config.permission.external_directory = {};
1994
1994
  }
1995
- if (config.permission.external_directory[gsdPath] !== 'allow') {
1996
- config.permission.external_directory[gsdPath] = 'allow';
1995
+ if (config.permission.external_directory[ezPath] !== 'allow') {
1996
+ config.permission.external_directory[ezPath] = 'allow';
1997
1997
  modified = true;
1998
1998
  }
1999
1999
 
@@ -2048,8 +2048,8 @@ function verifyFileInstalled(filePath, description) {
2048
2048
  // Local Patch Persistence
2049
2049
  // ──────────────────────────────────────────────────────
2050
2050
 
2051
- const PATCHES_DIR_NAME = 'gsd-local-patches';
2052
- const MANIFEST_NAME = 'gsd-file-manifest.json';
2051
+ const PATCHES_DIR_NAME = 'ez-local-patches';
2052
+ const MANIFEST_NAME = 'ez-file-manifest.json';
2053
2053
 
2054
2054
  /**
2055
2055
  * Compute SHA256 hash of file contents
@@ -2086,26 +2086,26 @@ function writeManifest(configDir, runtime = 'claude') {
2086
2086
  const isOpencode = runtime === 'opencode';
2087
2087
  const isCodex = runtime === 'codex';
2088
2088
  const isCopilot = runtime === 'copilot';
2089
- const gsdDir = path.join(configDir, 'get-shit-done');
2090
- const commandsDir = path.join(configDir, 'commands', 'gsd');
2089
+ const ezDir = path.join(configDir, 'get-shit-done');
2090
+ const commandsDir = path.join(configDir, 'commands', 'ez');
2091
2091
  const opencodeCommandDir = path.join(configDir, 'command');
2092
2092
  const codexSkillsDir = path.join(configDir, 'skills');
2093
2093
  const agentsDir = path.join(configDir, 'agents');
2094
2094
  const manifest = { version: pkg.version, timestamp: new Date().toISOString(), files: {} };
2095
2095
 
2096
- const gsdHashes = generateManifest(gsdDir);
2097
- for (const [rel, hash] of Object.entries(gsdHashes)) {
2096
+ const ezHashes = generateManifest(ezDir);
2097
+ for (const [rel, hash] of Object.entries(ezHashes)) {
2098
2098
  manifest.files['get-shit-done/' + rel] = hash;
2099
2099
  }
2100
2100
  if (!isOpencode && !isCodex && !isCopilot && fs.existsSync(commandsDir)) {
2101
2101
  const cmdHashes = generateManifest(commandsDir);
2102
2102
  for (const [rel, hash] of Object.entries(cmdHashes)) {
2103
- manifest.files['commands/gsd/' + rel] = hash;
2103
+ manifest.files['commands/ez/' + rel] = hash;
2104
2104
  }
2105
2105
  }
2106
2106
  if (isOpencode && fs.existsSync(opencodeCommandDir)) {
2107
2107
  for (const file of fs.readdirSync(opencodeCommandDir)) {
2108
- if (file.startsWith('gsd-') && file.endsWith('.md')) {
2108
+ if (file.startsWith('ez-') && file.endsWith('.md')) {
2109
2109
  manifest.files['command/' + file] = fileHash(path.join(opencodeCommandDir, file));
2110
2110
  }
2111
2111
  }
@@ -2121,7 +2121,7 @@ function writeManifest(configDir, runtime = 'claude') {
2121
2121
  }
2122
2122
  if (fs.existsSync(agentsDir)) {
2123
2123
  for (const file of fs.readdirSync(agentsDir)) {
2124
- if (file.startsWith('gsd-') && file.endsWith('.md')) {
2124
+ if (file.startsWith('ez-') && file.endsWith('.md')) {
2125
2125
  manifest.files['agents/' + file] = fileHash(path.join(agentsDir, file));
2126
2126
  }
2127
2127
  }
@@ -2133,7 +2133,7 @@ function writeManifest(configDir, runtime = 'claude') {
2133
2133
 
2134
2134
  /**
2135
2135
  * Detect user-modified EZ Agents files by comparing against install manifest.
2136
- * Backs up modified files to gsd-local-patches/ for reapply after update.
2136
+ * Backs up modified files to ez-local-patches/ for reapply after update.
2137
2137
  */
2138
2138
  function saveLocalPatches(configDir) {
2139
2139
  const manifestPath = path.join(configDir, MANIFEST_NAME);
@@ -2164,7 +2164,7 @@ function saveLocalPatches(configDir) {
2164
2164
  files: modified
2165
2165
  };
2166
2166
  fs.writeFileSync(path.join(patchesDir, 'backup-meta.json'), JSON.stringify(meta, null, 2));
2167
- console.log(' ' + yellow + 'i' + reset + ' Found ' + modified.length + ' locally modified GSD file(s) — backed up to ' + PATCHES_DIR_NAME + '/');
2167
+ console.log(' ' + yellow + 'i' + reset + ' Found ' + modified.length + ' locally modified EZ file(s) — backed up to ' + PATCHES_DIR_NAME + '/');
2168
2168
  for (const f of modified) {
2169
2169
  console.log(' ' + dim + f + reset);
2170
2170
  }
@@ -2245,58 +2245,58 @@ function install(isGlobal, runtime = 'claude') {
2245
2245
  // Clean up orphaned files from previous versions
2246
2246
  cleanupOrphanedFiles(targetDir);
2247
2247
 
2248
- // OpenCode uses command/ (flat), Codex uses skills/, Claude/Gemini use commands/gsd/
2248
+ // OpenCode uses command/ (flat), Codex uses skills/, Claude/Gemini use commands/ez/
2249
2249
  if (isOpencode) {
2250
2250
  // OpenCode: flat structure in command/ directory
2251
2251
  const commandDir = path.join(targetDir, 'command');
2252
2252
  fs.mkdirSync(commandDir, { recursive: true });
2253
-
2254
- // Copy commands/gsd/*.md as command/gsd-*.md (flatten structure)
2255
- const gsdSrc = path.join(src, 'commands', 'gsd');
2256
- copyFlattenedCommands(gsdSrc, commandDir, 'gsd', pathPrefix, runtime);
2257
- if (verifyInstalled(commandDir, 'command/gsd-*')) {
2258
- const count = fs.readdirSync(commandDir).filter(f => f.startsWith('gsd-')).length;
2253
+
2254
+ // Copy commands/ez/*.md as command/ez-*.md (flatten structure)
2255
+ const ezSrc = path.join(src, 'commands', 'ez');
2256
+ copyFlattenedCommands(ezSrc, commandDir, 'ez', pathPrefix, runtime);
2257
+ if (verifyInstalled(commandDir, 'command/ez-*')) {
2258
+ const count = fs.readdirSync(commandDir).filter(f => f.startsWith('ez-')).length;
2259
2259
  console.log(` ${green}✓${reset} Installed ${count} commands to command/`);
2260
2260
  } else {
2261
- failures.push('command/gsd-*');
2261
+ failures.push('command/ez-*');
2262
2262
  }
2263
2263
  } else if (isCodex) {
2264
2264
  const skillsDir = path.join(targetDir, 'skills');
2265
- const gsdSrc = path.join(src, 'commands', 'gsd');
2266
- copyCommandsAsCodexSkills(gsdSrc, skillsDir, 'gsd', pathPrefix, runtime);
2265
+ const ezSrc = path.join(src, 'commands', 'ez');
2266
+ copyCommandsAsCodexSkills(ezSrc, skillsDir, 'ez', pathPrefix, runtime);
2267
2267
  const installedSkillNames = listCodexSkillNames(skillsDir);
2268
2268
  if (installedSkillNames.length > 0) {
2269
2269
  console.log(` ${green}✓${reset} Installed ${installedSkillNames.length} skills to skills/`);
2270
2270
  } else {
2271
- failures.push('skills/gsd-*');
2271
+ failures.push('skills/ez-*');
2272
2272
  }
2273
2273
  } else if (isCopilot) {
2274
2274
  const skillsDir = path.join(targetDir, 'skills');
2275
- const gsdSrc = path.join(src, 'commands', 'gsd');
2276
- copyCommandsAsCopilotSkills(gsdSrc, skillsDir, 'gsd', isGlobal);
2275
+ const ezSrc = path.join(src, 'commands', 'ez');
2276
+ copyCommandsAsCopilotSkills(ezSrc, skillsDir, 'ez', isGlobal);
2277
2277
  if (fs.existsSync(skillsDir)) {
2278
2278
  const count = fs.readdirSync(skillsDir, { withFileTypes: true })
2279
- .filter(e => e.isDirectory() && e.name.startsWith('gsd-')).length;
2279
+ .filter(e => e.isDirectory() && e.name.startsWith('ez-')).length;
2280
2280
  if (count > 0) {
2281
2281
  console.log(` ${green}✓${reset} Installed ${count} skills to skills/`);
2282
2282
  } else {
2283
- failures.push('skills/gsd-*');
2283
+ failures.push('skills/ez-*');
2284
2284
  }
2285
2285
  } else {
2286
- failures.push('skills/gsd-*');
2286
+ failures.push('skills/ez-*');
2287
2287
  }
2288
2288
  } else {
2289
2289
  // Claude Code & Gemini: nested structure in commands/ directory
2290
2290
  const commandsDir = path.join(targetDir, 'commands');
2291
2291
  fs.mkdirSync(commandsDir, { recursive: true });
2292
-
2293
- const gsdSrc = path.join(src, 'commands', 'gsd');
2294
- const gsdDest = path.join(commandsDir, 'gsd');
2295
- copyWithPathReplacement(gsdSrc, gsdDest, pathPrefix, runtime, true, isGlobal);
2296
- if (verifyInstalled(gsdDest, 'commands/gsd')) {
2297
- console.log(` ${green}✓${reset} Installed commands/gsd`);
2292
+
2293
+ const ezSrc = path.join(src, 'commands', 'ez');
2294
+ const ezDest = path.join(commandsDir, 'ez');
2295
+ copyWithPathReplacement(ezSrc, ezDest, pathPrefix, runtime, true, isGlobal);
2296
+ if (verifyInstalled(ezDest, 'commands/ez')) {
2297
+ console.log(` ${green}✓${reset} Installed commands/ez`);
2298
2298
  } else {
2299
- failures.push('commands/gsd');
2299
+ failures.push('commands/ez');
2300
2300
  }
2301
2301
  }
2302
2302
 
@@ -2325,10 +2325,10 @@ function install(isGlobal, runtime = 'claude') {
2325
2325
  const agentsDest = path.join(targetDir, 'agents');
2326
2326
  fs.mkdirSync(agentsDest, { recursive: true });
2327
2327
 
2328
- // Remove old EZ Agents agents (gsd-*.md) before copying new ones
2328
+ // Remove old EZ Agents agents (ez-*.md) before copying new ones
2329
2329
  if (fs.existsSync(agentsDest)) {
2330
2330
  for (const file of fs.readdirSync(agentsDest)) {
2331
- if (file.startsWith('gsd-') && file.endsWith('.md')) {
2331
+ if (file.startsWith('ez-') && file.endsWith('.md')) {
2332
2332
  fs.unlinkSync(path.join(agentsDest, file));
2333
2333
  }
2334
2334
  }
@@ -2390,7 +2390,7 @@ function install(isGlobal, runtime = 'claude') {
2390
2390
  }
2391
2391
 
2392
2392
  if (!isCodex && !isCopilot) {
2393
- // Write package.json to force CommonJS mode for GSD scripts
2393
+ // Write package.json to force CommonJS mode for EZ scripts
2394
2394
  // Prevents "require is not defined" errors when project has "type": "module"
2395
2395
  // Node.js walks up looking for package.json - this stops inheritance from project
2396
2396
  const pkgJsonDest = path.join(targetDir, 'package.json');
@@ -2499,14 +2499,14 @@ function install(isGlobal, runtime = 'claude') {
2499
2499
  const settingsPath = path.join(targetDir, 'settings.json');
2500
2500
  const settings = cleanupOrphanedHooks(readSettings(settingsPath));
2501
2501
  const statuslineCommand = isGlobal
2502
- ? buildHookCommand(targetDir, 'gsd-statusline.js')
2503
- : 'node ' + dirName + '/hooks/gsd-statusline.js';
2502
+ ? buildHookCommand(targetDir, 'ez-statusline.js')
2503
+ : 'node ' + dirName + '/hooks/ez-statusline.js';
2504
2504
  const updateCheckCommand = isGlobal
2505
- ? buildHookCommand(targetDir, 'gsd-check-update.js')
2506
- : 'node ' + dirName + '/hooks/gsd-check-update.js';
2505
+ ? buildHookCommand(targetDir, 'ez-check-update.js')
2506
+ : 'node ' + dirName + '/hooks/ez-check-update.js';
2507
2507
  const contextMonitorCommand = isGlobal
2508
- ? buildHookCommand(targetDir, 'gsd-context-monitor.js')
2509
- : 'node ' + dirName + '/hooks/gsd-context-monitor.js';
2508
+ ? buildHookCommand(targetDir, 'ez-context-monitor.js')
2509
+ : 'node ' + dirName + '/hooks/ez-context-monitor.js';
2510
2510
 
2511
2511
  // Enable experimental agents for Gemini CLI (required for custom sub-agents)
2512
2512
  if (isGemini) {
@@ -2528,11 +2528,11 @@ function install(isGlobal, runtime = 'claude') {
2528
2528
  settings.hooks.SessionStart = [];
2529
2529
  }
2530
2530
 
2531
- const hasGsdUpdateHook = settings.hooks.SessionStart.some(entry =>
2532
- entry.hooks && entry.hooks.some(h => h.command && h.command.includes('gsd-check-update'))
2531
+ const hasEzUpdateHook = settings.hooks.SessionStart.some(entry =>
2532
+ entry.hooks && entry.hooks.some(h => h.command && h.command.includes('ez-check-update'))
2533
2533
  );
2534
2534
 
2535
- if (!hasGsdUpdateHook) {
2535
+ if (!hasEzUpdateHook) {
2536
2536
  settings.hooks.SessionStart.push({
2537
2537
  hooks: [
2538
2538
  {
@@ -2550,7 +2550,7 @@ function install(isGlobal, runtime = 'claude') {
2550
2550
  }
2551
2551
 
2552
2552
  const hasContextMonitorHook = settings.hooks[postToolEvent].some(entry =>
2553
- entry.hooks && entry.hooks.some(h => h.command && h.command.includes('gsd-context-monitor'))
2553
+ entry.hooks && entry.hooks.some(h => h.command && h.command.includes('ez-context-monitor'))
2554
2554
  );
2555
2555
 
2556
2556
  if (!hasContextMonitorHook) {
@@ -2608,7 +2608,7 @@ function finishInstall(settingsPath, settings, statuslineCommand, shouldInstallS
2608
2608
  console.log(`
2609
2609
  ${green}Done!${reset} Open a blank directory in ${program} and run ${cyan}${command}${reset}.
2610
2610
 
2611
- ${cyan}Join the community:${reset} https://discord.gg/gsd
2611
+ ${cyan}Join the community:${reset} https://discord.gg/ez-agents
2612
2612
  `);
2613
2613
  }
2614
2614