@undeemed/get-shit-done-codex 1.22.1 → 1.23.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.
package/README.md CHANGED
@@ -5,8 +5,9 @@ A meta-prompting, context engineering and spec-driven development system for [Op
5
5
  Fork of [get-shit-done](https://github.com/taches/get-shit-done) by TÂCHES, adapted for Codex CLI by [undeemed](https://github.com/undeemed).
6
6
 
7
7
  > [!CAUTION]
8
- > As of February 25, 2026, Codex is supported upstream. This fork remains focused on Codex-specific UX and compatibility with extra goodies.
8
+ > Codex is now supported upstream. This fork remains focused on Codex-specific UX, compatibility, and cutting-edge experimental features.
9
9
 
10
+ [![CI](https://github.com/undeemed/get-shit-done-codex/actions/workflows/ci.yml/badge.svg)](https://github.com/undeemed/get-shit-done-codex/actions/workflows/ci.yml)
10
11
  [![npm version](https://img.shields.io/npm/v/%40undeemed%2Fget-shit-done-codex?style=flat-square)](https://www.npmjs.com/package/@undeemed/get-shit-done-codex)
11
12
  [![License](https://img.shields.io/badge/license-MIT-green?style=flat-square)](LICENSE)
12
13
  ![npm Downloads](https://img.shields.io/npm/dt/@undeemed/get-shit-done-codex?style=flat-square)
@@ -46,6 +47,7 @@ npx @undeemed/get-shit-done-codex --global
46
47
  ```bash
47
48
  npx @undeemed/get-shit-done-codex --global # Install to ~/.codex/
48
49
  npx @undeemed/get-shit-done-codex --local # Install to current directory
50
+ npx @undeemed/get-shit-done-codex --path . # Install to a specific directory
49
51
  npx @undeemed/get-shit-done-codex --global --migrate # Clean up legacy prompts/
50
52
  npx @undeemed/get-shit-done-codex --verify --global # Check install integrity
51
53
  npx @undeemed/get-shit-done-codex --verify --repair --global # Auto-repair
package/bin/install.js CHANGED
@@ -41,6 +41,8 @@ const hasRepair = args.includes('--repair');
41
41
  const hasNoVersionCheck = args.includes('--no-version-check') || process.env.GSD_SKIP_VERSION_CHECK === '1';
42
42
  const hasMigrate = args.includes('--migrate');
43
43
  const hasSkipMigrate = args.includes('--skip-migrate') || args.includes('--no-migrate');
44
+ const pathIdx = args.indexOf('--path');
45
+ const customPath = pathIdx !== -1 && args[pathIdx + 1] ? args[pathIdx + 1] : null;
44
46
  const isInteractiveTerminal = Boolean(process.stdin.isTTY && process.stdout.isTTY);
45
47
  const codexMode = 'skills';
46
48
 
@@ -52,6 +54,7 @@ if (hasHelp) {
52
54
  ${yellow}Options:${reset}
53
55
  ${cyan}-g, --global${reset} Install globally (to ~/.codex/)
54
56
  ${cyan}-l, --local${reset} Install locally (to current directory)
57
+ ${cyan}--path <dir>${reset} Install into a specific directory
55
58
  ${cyan}--migrate${reset} Apply detected legacy surface cleanup without prompting
56
59
  ${cyan}--skip-migrate${reset} Keep legacy surface files when migration is detected
57
60
  ${cyan}--verify${reset} Verify current install integrity
@@ -66,6 +69,9 @@ if (hasHelp) {
66
69
  ${dim}# Install to current project only${reset}
67
70
  npx ${NPM_PACKAGE} --local
68
71
 
72
+ ${dim}# Install to a specific directory${reset}
73
+ npx ${NPM_PACKAGE} --path /path/to/project
74
+
69
75
  ${dim}# Verify global installation${reset}
70
76
  npx ${NPM_PACKAGE} --verify --global
71
77
 
@@ -357,13 +363,24 @@ function showCachedVersionWarning() {
357
363
  }
358
364
  }
359
365
 
360
- function getInstallContext(isGlobal) {
361
- const codexDir = isGlobal ? path.join(os.homedir(), '.codex') : process.cwd();
362
- return {
363
- codexDir,
364
- locationLabel: isGlobal ? '~/.codex' : '.',
365
- pathPrefix: isGlobal ? '~/.codex/' : './',
366
- };
366
+ function getInstallContext(isGlobal, targetPath) {
367
+ let codexDir;
368
+ let locationLabel;
369
+ let pathPrefix;
370
+ if (targetPath) {
371
+ codexDir = path.resolve(targetPath);
372
+ locationLabel = targetPath;
373
+ pathPrefix = codexDir.endsWith(path.sep) ? codexDir : `${codexDir}${path.sep}`;
374
+ } else if (isGlobal) {
375
+ codexDir = path.join(os.homedir(), '.codex');
376
+ locationLabel = '~/.codex';
377
+ pathPrefix = '~/.codex/';
378
+ } else {
379
+ codexDir = process.cwd();
380
+ locationLabel = '.';
381
+ pathPrefix = './';
382
+ }
383
+ return { codexDir, locationLabel, pathPrefix };
367
384
  }
368
385
 
369
386
  function listPromptCommandFiles(promptsDir) {
@@ -388,9 +405,9 @@ function detectInstalledMode(promptCount, skillCount) {
388
405
  return 'none';
389
406
  }
390
407
 
391
- function verifyInstall(isGlobal) {
408
+ function verifyInstall(isGlobal, targetPath) {
392
409
  const src = path.join(__dirname, '..');
393
- const { codexDir, locationLabel } = getInstallContext(isGlobal);
410
+ const { codexDir, locationLabel } = getInstallContext(isGlobal, targetPath);
394
411
  const promptsDir = path.join(codexDir, 'prompts');
395
412
  const skillsDir = path.join(codexDir, 'skills');
396
413
  const workflowRoot = path.join(codexDir, 'get-shit-done');
@@ -447,9 +464,9 @@ function verifyInstall(isGlobal) {
447
464
  return { ok, detectedMode };
448
465
  }
449
466
 
450
- function installCore(isGlobal, migrationPlan, applyMigration, done = () => {}) {
467
+ function installCore(isGlobal, migrationPlan, applyMigration, done = () => {}, targetPath) {
451
468
  const src = path.join(__dirname, '..');
452
- const { codexDir, locationLabel, pathPrefix } = getInstallContext(isGlobal);
469
+ const { codexDir, locationLabel, pathPrefix } = getInstallContext(isGlobal, targetPath);
453
470
 
454
471
  console.log(` Installing to ${cyan}${locationLabel}${reset}\n`);
455
472
  fs.mkdirSync(codexDir, { recursive: true });
@@ -546,12 +563,12 @@ function installCore(isGlobal, migrationPlan, applyMigration, done = () => {}) {
546
563
  }
547
564
  }
548
565
 
549
- function install(isGlobal, done = () => {}) {
550
- const { codexDir } = getInstallContext(isGlobal);
566
+ function install(isGlobal, done = () => {}, targetPath) {
567
+ const { codexDir } = getInstallContext(isGlobal, targetPath);
551
568
  const migrationPlan = detectMigrationPlan(codexDir);
552
569
 
553
570
  if (!migrationPlan.hasChanges) {
554
- installCore(isGlobal, migrationPlan, false, done);
571
+ installCore(isGlobal, migrationPlan, false, done, targetPath);
555
572
  return;
556
573
  }
557
574
 
@@ -560,13 +577,13 @@ function install(isGlobal, done = () => {}) {
560
577
 
561
578
  if (hasMigrate) {
562
579
  console.log(` ${green}✓${reset} Migration approved by --migrate`);
563
- installCore(isGlobal, migrationPlan, true, done);
580
+ installCore(isGlobal, migrationPlan, true, done, targetPath);
564
581
  return;
565
582
  }
566
583
 
567
584
  if (hasSkipMigrate) {
568
585
  console.log(` ${yellow}Skipping migration due to --skip-migrate.${reset}`);
569
- installCore(isGlobal, migrationPlan, false, done);
586
+ installCore(isGlobal, migrationPlan, false, done, targetPath);
570
587
  return;
571
588
  }
572
589
 
@@ -589,7 +606,7 @@ function install(isGlobal, done = () => {}) {
589
606
  if (!applyMigration) {
590
607
  console.log(` ${yellow}Keeping legacy files.${reset}`);
591
608
  }
592
- installCore(isGlobal, migrationPlan, applyMigration, done);
609
+ installCore(isGlobal, migrationPlan, applyMigration, done, targetPath);
593
610
  });
594
611
  }
595
612
 
@@ -614,8 +631,14 @@ function promptLocation(done) {
614
631
  });
615
632
  }
616
633
 
617
- if (hasGlobal && hasLocal) {
618
- console.error(` ${yellow}Cannot specify both --global and --local${reset}`);
634
+ const locationFlagCount = [hasGlobal, hasLocal, !!customPath].filter(Boolean).length;
635
+ if (locationFlagCount > 1) {
636
+ console.error(` ${yellow}Cannot specify more than one of --global, --local, and --path${reset}`);
637
+ process.exit(1);
638
+ }
639
+
640
+ if (pathIdx !== -1 && !customPath) {
641
+ console.error(` ${yellow}--path requires a directory argument${reset}`);
619
642
  process.exit(1);
620
643
  }
621
644
 
@@ -634,21 +657,23 @@ if (!hasNoVersionCheck && !hasVerify) {
634
657
  }
635
658
 
636
659
  if (hasVerify) {
637
- const isGlobal = hasLocal ? false : true;
638
- let result = verifyInstall(isGlobal);
660
+ const isGlobal = customPath ? false : (hasLocal ? false : true);
661
+ let result = verifyInstall(isGlobal, customPath);
639
662
 
640
663
  if (!result.ok && hasRepair) {
641
664
  console.log(`\n ${yellow}Repairing install...${reset}\n`);
642
665
  install(isGlobal, () => {
643
666
  console.log('');
644
- const repaired = verifyInstall(isGlobal);
667
+ const repaired = verifyInstall(isGlobal, customPath);
645
668
  process.exit(repaired.ok ? 0 : 1);
646
- });
669
+ }, customPath);
647
670
  } else {
648
671
  process.exit(result.ok ? 0 : 1);
649
672
  }
650
673
  } else {
651
- if (hasGlobal) {
674
+ if (customPath) {
675
+ install(false, () => {}, customPath);
676
+ } else if (hasGlobal) {
652
677
  install(true);
653
678
  } else if (hasLocal) {
654
679
  install(false);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@undeemed/get-shit-done-codex",
3
- "version": "1.22.1",
4
- "description": "A meta-prompting, context engineering and spec-driven development system for OpenAI Codex (CLI and Desktop). Fork of get-shit-done by TÂCHES, adapted for Codex by undeemed.",
3
+ "version": "1.23.0",
4
+ "description": "A meta-prompting, context engineering and spec-driven development system for OpenAI Codex (CLI and Desktop). Fork of get-shit-done by TÂCHES, adapted for Codex.",
5
5
  "bin": {
6
6
  "get-shit-done-codex": "bin/install.js"
7
7
  },