@imdeadpool/guardex 7.0.12 → 7.0.13

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
@@ -1,7 +1,13 @@
1
1
  # GitGuardex — Guardian T-Rex for your repo
2
2
 
3
- [![npm version](https://img.shields.io/npm/v/%40imdeadpool%2Fguardex?color=cb3837&logo=npm)](https://www.npmjs.com/package/@imdeadpool/guardex)
4
- [![CI](https://github.com/recodeee/gitguardex/actions/workflows/ci.yml/badge.svg)](https://github.com/recodeee/gitguardex/actions/workflows/ci.yml)
3
+ [![npm version](https://img.shields.io/npm/v/%40imdeadpool%2Fguardex?label=npm&color=cb3837&logo=npm)](https://www.npmjs.com/package/@imdeadpool/guardex)
4
+ [![npm downloads](https://img.shields.io/npm/dm/%40imdeadpool%2Fguardex?label=downloads&color=0b76c5)](https://www.npmjs.com/package/@imdeadpool/guardex)
5
+ [![GitHub stars](https://img.shields.io/github/stars/recodeee/gitguardex?label=stars&color=d4ac0d)](https://github.com/recodeee/gitguardex/stargazers)
6
+ [![License](https://img.shields.io/npm/l/%40imdeadpool%2Fguardex?label=License&color=97ca00)](./LICENSE)
7
+
8
+ [![CI](https://img.shields.io/github/actions/workflow/status/recodeee/gitguardex/ci.yml?branch=main&label=CI)](https://github.com/recodeee/gitguardex/actions/workflows/ci.yml)
9
+ [![Release](https://img.shields.io/github/actions/workflow/status/recodeee/gitguardex/release.yml?label=Release)](https://github.com/recodeee/gitguardex/actions/workflows/release.yml)
10
+ [![CodeQL](https://img.shields.io/github/actions/workflow/status/recodeee/gitguardex/codeql.yml?branch=main&label=CodeQL)](https://github.com/recodeee/gitguardex/actions/workflows/codeql.yml)
5
11
  [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/recodeee/gitguardex/badge)](https://securityscorecards.dev/viewer/?uri=github.com/recodeee/gitguardex)
6
12
 
7
13
  **GitGuardex is a safety layer for parallel agent work in git repos.** If you're running more than one Codex or Claude agent on the same codebase, this is what keeps them from deleting each other's work.
@@ -20,6 +26,8 @@ I was running ~30 Codex agents in parallel and hit a wall: they kept working on
20
26
 
21
27
  GitGuardex exists to stop that loop. Every agent gets its own worktree, claims the files it's touching, and can't clobber files another agent has claimed. Your local branch stays clean; agents stay in their lanes.
22
28
 
29
+ ### Solution
30
+
23
31
  ```mermaid
24
32
  flowchart LR
25
33
  A[Agent A adds assertions in a shared test] --> S[Several agents touch the same files]
@@ -34,6 +42,8 @@ flowchart LR
34
42
  I --> S
35
43
  ```
36
44
 
45
+ ### Dashboard
46
+
37
47
  ![Multi-agent dashboard example](https://raw.githubusercontent.com/recodeee/gitguardex/main/docs/images/dashboard-multi-agent.png)
38
48
 
39
49
  Coming soon: [recodee.com](https://recodee.com) — live account health, usage, routing, and capacity in one place.
@@ -277,6 +287,7 @@ npm i -g oh-my-codex
277
287
  ```
278
288
 
279
289
  Repo: <https://github.com/Yeachan-Heo/oh-my-codex>
290
+ [![GitHub stars](https://img.shields.io/github/stars/Yeachan-Heo/oh-my-codex?style=social)](https://github.com/Yeachan-Heo/oh-my-codex)
280
291
 
281
292
  ### oh-my-claudecode — Claude Code equivalent
282
293
 
@@ -287,6 +298,7 @@ npm i -g oh-my-claude-sisyphus@latest
287
298
  ```
288
299
 
289
300
  Repo: <https://github.com/Yeachan-Heo/oh-my-claudecode>
301
+ [![GitHub stars](https://img.shields.io/github/stars/Yeachan-Heo/oh-my-claudecode?style=social)](https://github.com/Yeachan-Heo/oh-my-claudecode)
290
302
 
291
303
  ### Caveman — output compression for long agent runs
292
304
 
@@ -297,6 +309,7 @@ npx skills add JuliusBrussee/caveman
297
309
  ```
298
310
 
299
311
  Repo: <https://github.com/JuliusBrussee/caveman>
312
+ [![GitHub stars](https://img.shields.io/github/stars/JuliusBrussee/caveman?style=social)](https://github.com/JuliusBrussee/caveman)
300
313
 
301
314
  ### Cavemem — local persistent memory for agents
302
315
 
@@ -309,6 +322,7 @@ cavemem status
309
322
  ```
310
323
 
311
324
  Repo: <https://github.com/JuliusBrussee/cavemem>
325
+ [![GitHub stars](https://img.shields.io/github/stars/JuliusBrussee/cavemem?style=social)](https://github.com/JuliusBrussee/cavemem)
312
326
 
313
327
  ### Cavekit — spec-driven build loop
314
328
 
@@ -319,6 +333,7 @@ npx skills add JuliusBrussee/cavekit
319
333
  ```
320
334
 
321
335
  Repo: <https://github.com/JuliusBrussee/cavekit>
336
+ [![GitHub stars](https://img.shields.io/github/stars/JuliusBrussee/cavekit?style=social)](https://github.com/JuliusBrussee/cavekit)
322
337
 
323
338
  ### OpenSpec — spec-driven workflows
324
339
 
@@ -329,6 +344,7 @@ npm i -g @fission-ai/openspec
329
344
  ```
330
345
 
331
346
  Repo: <https://github.com/Fission-AI/OpenSpec>
347
+ [![GitHub stars](https://img.shields.io/github/stars/Fission-AI/OpenSpec?style=social)](https://github.com/Fission-AI/OpenSpec)
332
348
 
333
349
  ### codex-auth — multi-account switcher
334
350
 
@@ -344,6 +360,7 @@ codex-auth current
344
360
  ```
345
361
 
346
362
  Repo: [recodeecom/codex-account-switcher-cli](https://github.com/recodeecom/codex-account-switcher-cli)
363
+ [![GitHub stars](https://img.shields.io/github/stars/recodeecom/codex-account-switcher-cli?style=social)](https://github.com/recodeecom/codex-account-switcher-cli)
347
364
 
348
365
  ### GitHub CLI (`gh`)
349
366
 
@@ -490,6 +507,11 @@ npm pack --dry-run
490
507
  <details>
491
508
  <summary><strong>v7.x</strong></summary>
492
509
 
510
+ ### v7.0.13
511
+ - `gx status` and `gx setup` now present the Claude companion as `oh-my-claudecode` while still installing the published npm package `oh-my-claude-sisyphus`.
512
+ - When that dependency is inactive or the user declines the optional install, Guardex now prints the upstream repo URL so the missing dependency is explicit instead of hidden behind the npm package name.
513
+ - Bumped `@imdeadpool/guardex` from `7.0.12` → `7.0.13` after npm rejected a republish over the already-published `7.0.12`.
514
+
493
515
  ### v7.0.12
494
516
  - Fixed the self-update handoff after `gx` installs a newer global package. When the on-disk install advances, GitGuardex now restarts into the installed CLI instead of continuing in the old process and printing the stale in-memory version.
495
517
  - This removes the confusing `Updated to latest published version` followed by `CLI: ...7.0.10` mismatch that happened when `7.0.11` finished installing during the same `gx` invocation.
@@ -13,15 +13,26 @@ const SHORT_TOOL_NAME = 'gx';
13
13
  const LEGACY_NAMES = ['guardex', 'multiagent-safety'];
14
14
  const OPENSPEC_PACKAGE = '@fission-ai/openspec';
15
15
  const OMC_PACKAGE = 'oh-my-claude-sisyphus';
16
+ const OMC_REPO_URL = 'https://github.com/Yeachan-Heo/oh-my-claudecode';
16
17
  const CAVEMEM_PACKAGE = 'cavemem';
17
18
  const NPX_BIN = process.env.GUARDEX_NPX_BIN || 'npx';
18
19
  const GUARDEX_HOME_DIR = path.resolve(process.env.GUARDEX_HOME_DIR || os.homedir());
20
+ const GLOBAL_TOOLCHAIN_SERVICES = [
21
+ { name: 'oh-my-codex', packageName: 'oh-my-codex' },
22
+ {
23
+ name: 'oh-my-claudecode',
24
+ packageName: OMC_PACKAGE,
25
+ dependencyUrl: OMC_REPO_URL,
26
+ },
27
+ { name: OPENSPEC_PACKAGE, packageName: OPENSPEC_PACKAGE },
28
+ { name: CAVEMEM_PACKAGE, packageName: CAVEMEM_PACKAGE },
29
+ {
30
+ name: '@imdeadpool/codex-account-switcher',
31
+ packageName: '@imdeadpool/codex-account-switcher',
32
+ },
33
+ ];
19
34
  const GLOBAL_TOOLCHAIN_PACKAGES = [
20
- 'oh-my-codex',
21
- OMC_PACKAGE,
22
- OPENSPEC_PACKAGE,
23
- CAVEMEM_PACKAGE,
24
- '@imdeadpool/codex-account-switcher',
35
+ ...GLOBAL_TOOLCHAIN_SERVICES.map((service) => service.packageName),
25
36
  ];
26
37
  const OPTIONAL_LOCAL_COMPANION_TOOLS = [
27
38
  {
@@ -3629,6 +3640,36 @@ function resolveGlobalInstallApproval(options) {
3629
3640
  return { approved: true, source: 'prompt' };
3630
3641
  }
3631
3642
 
3643
+ function getGlobalToolchainService(packageName) {
3644
+ const service = GLOBAL_TOOLCHAIN_SERVICES.find(
3645
+ (candidate) => candidate.packageName === packageName,
3646
+ );
3647
+ return service || { name: packageName, packageName };
3648
+ }
3649
+
3650
+ function formatGlobalToolchainServiceName(packageName) {
3651
+ return getGlobalToolchainService(packageName).name;
3652
+ }
3653
+
3654
+ function describeMissingGlobalDependencyWarnings(packageNames) {
3655
+ return packageNames
3656
+ .map((packageName) => getGlobalToolchainService(packageName))
3657
+ .filter((service) => service.dependencyUrl)
3658
+ .map(
3659
+ (service) =>
3660
+ `Guardex needs ${service.name} as a dependency: ${service.dependencyUrl}`,
3661
+ );
3662
+ }
3663
+
3664
+ function buildMissingCompanionInstallPrompt(missingPackages, missingLocalTools) {
3665
+ const dependencyWarnings = describeMissingGlobalDependencyWarnings(missingPackages);
3666
+ const installCommands = describeCompanionInstallCommands(missingPackages, missingLocalTools);
3667
+ const dependencyPrefix = dependencyWarnings.length > 0
3668
+ ? `${dependencyWarnings.join(' ')} `
3669
+ : '';
3670
+ return `${dependencyPrefix}Install missing companion tools now? (${installCommands.join(' && ')})`;
3671
+ }
3672
+
3632
3673
  function detectGlobalToolchainPackages() {
3633
3674
  const result = run(NPM_BIN, ['list', '-g', '--depth=0', '--json']);
3634
3675
  if (result.status !== 0) {
@@ -3721,17 +3762,15 @@ function describeCompanionInstallCommands(missingPackages, missingLocalTools) {
3721
3762
  return commands;
3722
3763
  }
3723
3764
 
3724
- function askGlobalInstallForMissing(options, missingPackages) {
3765
+ function askGlobalInstallForMissing(options, missingPackages, missingLocalTools) {
3725
3766
  const approval = resolveGlobalInstallApproval(options);
3726
3767
  if (!approval.approved) {
3727
3768
  return approval;
3728
3769
  }
3729
3770
 
3730
- const missingLocalTools = detectOptionalLocalCompanionTools().filter((tool) => tool.status !== 'active');
3731
- const installCommands = describeCompanionInstallCommands(missingPackages, missingLocalTools);
3732
3771
  if (approval.source === 'prompt') {
3733
3772
  const approved = promptYesNoStrict(
3734
- `Install missing companion tools now? (${installCommands.join(' && ')})`,
3773
+ buildMissingCompanionInstallPrompt(missingPackages, missingLocalTools),
3735
3774
  );
3736
3775
  return { approved, source: 'prompt' };
3737
3776
  }
@@ -3750,7 +3789,10 @@ function installGlobalToolchain(options) {
3750
3789
  console.log(`[${TOOL_NAME}] ⚠️ Could not detect global packages: ${detection.error}`);
3751
3790
  } else {
3752
3791
  if (detection.installed.length > 0) {
3753
- console.log(`[${TOOL_NAME}] Already installed globally: ${detection.installed.join(', ')}`);
3792
+ console.log(
3793
+ `[${TOOL_NAME}] Already installed globally: ` +
3794
+ `${detection.installed.map((pkg) => formatGlobalToolchainServiceName(pkg)).join(', ')}`,
3795
+ );
3754
3796
  }
3755
3797
  const installedLocalTools = localCompanionTools
3756
3798
  .filter((tool) => tool.status === 'active')
@@ -3765,9 +3807,14 @@ function installGlobalToolchain(options) {
3765
3807
 
3766
3808
  const missingPackages = detection.ok ? detection.missing : [...GLOBAL_TOOLCHAIN_PACKAGES];
3767
3809
  const missingLocalTools = localCompanionTools.filter((tool) => tool.status !== 'active');
3768
- const approval = askGlobalInstallForMissing(options, missingPackages);
3810
+ const approval = askGlobalInstallForMissing(options, missingPackages, missingLocalTools);
3769
3811
  if (!approval.approved) {
3770
- return { status: 'skipped', reason: approval.source };
3812
+ return {
3813
+ status: 'skipped',
3814
+ reason: approval.source,
3815
+ missingPackages,
3816
+ missingLocalTools,
3817
+ };
3771
3818
  }
3772
3819
 
3773
3820
  const installed = [];
@@ -4142,11 +4189,21 @@ function status(rawArgs) {
4142
4189
 
4143
4190
  const toolchain = detectGlobalToolchainPackages();
4144
4191
  const npmServices = GLOBAL_TOOLCHAIN_PACKAGES.map((pkg) => {
4192
+ const service = getGlobalToolchainService(pkg);
4145
4193
  if (!toolchain.ok) {
4146
- return { name: pkg, status: 'unknown' };
4194
+ return {
4195
+ name: service.name,
4196
+ displayName: service.name,
4197
+ packageName: pkg,
4198
+ dependencyUrl: service.dependencyUrl || null,
4199
+ status: 'unknown',
4200
+ };
4147
4201
  }
4148
4202
  return {
4149
- name: pkg,
4203
+ name: service.name,
4204
+ displayName: service.name,
4205
+ packageName: pkg,
4206
+ dependencyUrl: service.dependencyUrl || null,
4150
4207
  status: toolchain.installed.includes(pkg) ? 'active' : 'inactive',
4151
4208
  };
4152
4209
  });
@@ -4224,6 +4281,13 @@ function status(rawArgs) {
4224
4281
  console.log(
4225
4282
  `[${TOOL_NAME}] Optional companion tools inactive: ${inactiveOptionalCompanions.join(', ')}`,
4226
4283
  );
4284
+ for (const warning of describeMissingGlobalDependencyWarnings(
4285
+ npmServices
4286
+ .filter((service) => service.status === 'inactive')
4287
+ .map((service) => service.packageName),
4288
+ )) {
4289
+ console.log(`[${TOOL_NAME}] ${warning}`);
4290
+ }
4227
4291
  console.log(
4228
4292
  `[${TOOL_NAME}] Run '${SHORT_TOOL_NAME} setup' to install missing companions with an explicit Y/N prompt.`,
4229
4293
  );
@@ -4881,6 +4945,13 @@ function setup(rawArgs) {
4881
4945
  `[${TOOL_NAME}] Skipping companion installs (non-interactive mode). ` +
4882
4946
  `Use --yes-global-install to force or run interactively for Y/N prompt.`,
4883
4947
  );
4948
+ } else if (globalInstallStatus.status === 'skipped') {
4949
+ console.log(`[${TOOL_NAME}] ⚠️ Companion installs skipped by user choice.`);
4950
+ for (const warning of describeMissingGlobalDependencyWarnings(
4951
+ globalInstallStatus.missingPackages || [],
4952
+ )) {
4953
+ console.log(`[${TOOL_NAME}] ⚠️ ${warning}`);
4954
+ }
4884
4955
  }
4885
4956
  const requiredSystemTools = detectRequiredSystemTools();
4886
4957
  const missingSystemTools = requiredSystemTools.filter((tool) => tool.status !== 'active');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@imdeadpool/guardex",
3
- "version": "7.0.12",
3
+ "version": "7.0.13",
4
4
  "description": "GitGuardex: hardened multi-agent git guardrails for parallel agent work.",
5
5
  "license": "MIT",
6
6
  "preferGlobal": true,