Skip to content

Feat/host compare default codex claude code#2997

Open
IgnacioC44 wants to merge 2 commits into
mainfrom
feat/host-compare-default-codex-claude-code
Open

Feat/host compare default codex claude code#2997
IgnacioC44 wants to merge 2 commits into
mainfrom
feat/host-compare-default-codex-claude-code

Conversation

@IgnacioC44

@IgnacioC44 IgnacioC44 commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

fix(server) + feat(hosts): Windows guest-auth fix, default Host Compare to Codex + Claude Code

Branch: feat/host-compare-default-codex-claude-code (2 commits on top of main)

Summary

  • Fix guest-auth Convex provisioning on Windows (spawn EINVAL / npx.cmd shim issue) by invoking the Convex CLI directly via node.
  • Default Host Compare (/clients/compare and the caniuse.dev embed) to Codex + Claude Code instead of an empty "all live hosts" fallback.

Why

  • The Windows fix was blocking local dev entirely.
  • The default was requested by Bernard (Slack, 2026-06-30) so caniuse.dev shows a meaningful comparison with no manual setup.

Changes

  • convex-guest-auth-sync.ts — resolve/invoke Convex CLI via node, not npx.
  • host-compare-selection.ts — new DEFAULT_COMPARE_HOST_IDS fallback.
  • HostConfigCompareView.tsx — URL-default check updated to match.
  • host-compare-selection.test.ts — updated/added tests (13/13 passing).
image

Test plan

  • vitest 13/13 passing
  • tsc clean on touched files
  • Playwright manual repro of the loader fix

Summary by cubic

Fixes Windows guest-auth provisioning by invoking the convex CLI via Node, and defaults Host Compare to Codex + Claude Code so fresh visits and embeds show a useful comparison.

  • New Features

    • Default Host Compare (/clients/compare and the caniuse.dev embed) to Codex + Claude Code; falls back to live hosts if presets are unavailable.
    • Clean URLs by suppressing ?hosts= when the selection matches the default order.
  • Bug Fixes

    • Windows: provision guest auth by running node <convex CLI entry> instead of npx to avoid spawn EINVAL and newline-arg splitting, unblocking local dev.

Written for commit 06c2d3c. Summary will update on new commits.

Review in cubic

…on Windows

npx resolves to the npx.cmd shim, which execFile can't invoke without a
shell on Windows (spawn EINVAL), and routing through a shell instead
breaks because the PEM values we pass as argv get split on their
embedded newlines. Invoke the Convex CLI's bin entry via node directly
to sidestep both.
Host Compare (including the caniuse.dev landing) previously fell back
to "all live hosts" when nothing else picked a selection, which is
empty for anyone who hasn't created a host yet. Default to the Codex
and Claude Code presets instead so a fresh visit shows a meaningful
comparison immediately, with live hosts as the fallback if those
presets are ever unavailable.
@dosubot dosubot Bot added the size:M This PR changes 30-99 lines, ignoring generated files. label Jul 2, 2026
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

@chelojimenez

Copy link
Copy Markdown
Contributor

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Internal preview

Preview URL: https://mcp-inspector-pr-2997.up.railway.app
Deployed commit: aae46fe
PR head commit: 06c2d3c
Backend target: staging fallback.
Health: ✅ Convex reachable
Access is employee-only in non-production environments.

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

This PR changes two unrelated areas. In the client, a new DEFAULT_COMPARE_HOST_IDS constant (Codex + Claude Code presets) is added and used both as a fallback for initial host comparison selection and as the criterion for suppressing the ?hosts= URL parameter, replacing the prior "all live hosts" logic; tests are updated and extended accordingly. In the server, convex-guest-auth-sync.ts now resolves the Convex CLI's entry script path via createRequire and invokes it directly through process.execPath, replacing the previous npx/npx.cmd invocation for setting guest auth environment variables.

Related PRs

No related PRs were provided in the given context.

Suggested labels

client, server, bug, tests

Suggested reviewers

No reviewer information was provided in the given context.

Poem
A rabbit hops through host and shell,
Presets chosen, URLs as well,
Codex, Claude, now paired by default,
While Convex's CLI takes a cleaner vault—
No more npx, just node runs true,
Hop, hop, the tests pass through. 🐇

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

mcpjam-inspector/client/src/components/hosts/comparison/HostConfigCompareView.tsx

Oops! Something went wrong! :(

ESLint: 8.57.1

Error: ESLint configuration in --config is invalid:

  • Unexpected top-level property "__esModule".

    at ConfigValidator.validateConfigSchema (/soundcheck/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2177:19)
    at ConfigArrayFactory._normalizeConfigData (/soundcheck/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3019:19)
    at ConfigArrayFactory._loadConfigData (/soundcheck/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2984:21)
    at ConfigArrayFactory.loadFile (/soundcheck/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2850:40)
    at createCLIConfigArray (/soundcheck/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3660:35)
    at new CascadingConfigArrayFactory (/soundcheck/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3735:29)
    at new CLIEngine (/soundcheck/node_modules/eslint/lib/cli-engine/cli-engine.js:617:36)
    at new ESLint (/soundcheck/node_modules/eslint/lib/eslint/eslint.js:430:27)
    at Object.execute (/soundcheck/node_modules/eslint/lib/cli.js:410:24)
    at async main (/soundcheck/node_modules/eslint/bin/eslint.js:152:22)

mcpjam-inspector/client/src/components/hosts/comparison/__tests__/host-compare-selection.test.ts

Oops! Something went wrong! :(

ESLint: 8.57.1

Error: ESLint configuration in --config is invalid:

  • Unexpected top-level property "__esModule".

    at ConfigValidator.validateConfigSchema (/soundcheck/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2177:19)
    at ConfigArrayFactory._normalizeConfigData (/soundcheck/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3019:19)
    at ConfigArrayFactory._loadConfigData (/soundcheck/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2984:21)
    at ConfigArrayFactory.loadFile (/soundcheck/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2850:40)
    at createCLIConfigArray (/soundcheck/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3660:35)
    at new CascadingConfigArrayFactory (/soundcheck/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3735:29)
    at new CLIEngine (/soundcheck/node_modules/eslint/lib/cli-engine/cli-engine.js:617:36)
    at new ESLint (/soundcheck/node_modules/eslint/lib/eslint/eslint.js:430:27)
    at Object.execute (/soundcheck/node_modules/eslint/lib/cli.js:410:24)
    at async main (/soundcheck/node_modules/eslint/bin/eslint.js:152:22)

mcpjam-inspector/client/src/components/hosts/comparison/host-compare-selection.ts

Oops! Something went wrong! :(

ESLint: 8.57.1

Error: ESLint configuration in --config is invalid:

  • Unexpected top-level property "__esModule".

    at ConfigValidator.validateConfigSchema (/soundcheck/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2177:19)
    at ConfigArrayFactory._normalizeConfigData (/soundcheck/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3019:19)
    at ConfigArrayFactory._loadConfigData (/soundcheck/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2984:21)
    at ConfigArrayFactory.loadFile (/soundcheck/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2850:40)
    at createCLIConfigArray (/soundcheck/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3660:35)
    at new CascadingConfigArrayFactory (/soundcheck/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3735:29)
    at new CLIEngine (/soundcheck/node_modules/eslint/lib/cli-engine/cli-engine.js:617:36)
    at new ESLint (/soundcheck/node_modules/eslint/lib/eslint/eslint.js:430:27)
    at Object.execute (/soundcheck/node_modules/eslint/lib/cli.js:410:24)
    at async main (/soundcheck/node_modules/eslint/bin/eslint.js:152:22)

  • 1 others

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 4 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="mcpjam-inspector/client/src/components/hosts/comparison/host-compare-selection.ts">

<violation number="1" location="mcpjam-inspector/client/src/components/hosts/comparison/host-compare-selection.ts:116">
P3: A fresh Host Compare visit can default to a single preset if only one of Codex/Claude Code is present, producing a partial one-column default instead of the documented live-host fallback. Since the default is intended as the Codex + Claude Code pair, consider requiring both default ids before returning it.</violation>
</file>

<file name="mcpjam-inspector/client/src/components/hosts/comparison/HostConfigCompareView.tsx">

<violation number="1" location="mcpjam-inspector/client/src/components/hosts/comparison/HostConfigCompareView.tsx:137">
P3: The fallback default path can still dirty clean compare URLs: when the Codex/Claude Code preset ids are unavailable, the resolver returns the live-host fallback but this mirror check only suppresses the exact preset pair. Consider deriving the suppressed default from the same reconciliation/fallback logic used by resolveInitialHostCompareSelection.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

DEFAULT_COMPARE_HOST_IDS,
known,
);
if (fromDefaultPresets.length > 0) return fromDefaultPresets;

@cubic-dev-ai cubic-dev-ai Bot Jul 2, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: A fresh Host Compare visit can default to a single preset if only one of Codex/Claude Code is present, producing a partial one-column default instead of the documented live-host fallback. Since the default is intended as the Codex + Claude Code pair, consider requiring both default ids before returning it.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At mcpjam-inspector/client/src/components/hosts/comparison/host-compare-selection.ts, line 116:

<comment>A fresh Host Compare visit can default to a single preset if only one of Codex/Claude Code is present, producing a partial one-column default instead of the documented live-host fallback. Since the default is intended as the Codex + Claude Code pair, consider requiring both default ids before returning it.</comment>

<file context>
@@ -91,5 +106,14 @@ export function resolveInitialHostCompareSelection(args: {
+    DEFAULT_COMPARE_HOST_IDS,
+    known,
+  );
+  if (fromDefaultPresets.length > 0) return fromDefaultPresets;
+
   return [...args.liveHostIds];
</file context>
Suggested change
if (fromDefaultPresets.length > 0) return fromDefaultPresets;
if (fromDefaultPresets.length === DEFAULT_COMPARE_HOST_IDS.length) return fromDefaultPresets;
Fix with cubic

const isDefault =
selectedHostIds.length === liveHostIds.length &&
selectedHostIds.every((id, i) => id === liveHostIds[i]);
selectedHostIds.length === DEFAULT_COMPARE_HOST_IDS.length &&

@cubic-dev-ai cubic-dev-ai Bot Jul 2, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The fallback default path can still dirty clean compare URLs: when the Codex/Claude Code preset ids are unavailable, the resolver returns the live-host fallback but this mirror check only suppresses the exact preset pair. Consider deriving the suppressed default from the same reconciliation/fallback logic used by resolveInitialHostCompareSelection.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At mcpjam-inspector/client/src/components/hosts/comparison/HostConfigCompareView.tsx, line 137:

<comment>The fallback default path can still dirty clean compare URLs: when the Codex/Claude Code preset ids are unavailable, the resolver returns the live-host fallback but this mirror check only suppresses the exact preset pair. Consider deriving the suppressed default from the same reconciliation/fallback logic used by resolveInitialHostCompareSelection.</comment>

<file context>
@@ -126,12 +129,13 @@ export function HostConfigCompareView({
     const isDefault =
-      selectedHostIds.length === liveHostIds.length &&
-      selectedHostIds.every((id, i) => id === liveHostIds[i]);
+      selectedHostIds.length === DEFAULT_COMPARE_HOST_IDS.length &&
+      selectedHostIds.every((id, i) => id === DEFAULT_COMPARE_HOST_IDS[i]);
     const current = searchParams.get(HOSTS_QUERY_PARAM);
</file context>
Fix with cubic

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
mcpjam-inspector/client/src/components/hosts/comparison/HostConfigCompareView.tsx (1)

121-152: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Order-sensitive isDefault check can spuriously show ?hosts= for the default set.

isDefault requires exact positional equality against DEFAULT_COMPARE_HOST_IDS (Line 136-138). But toggleHostCompareSelection appends newly-added ids to the end of the array (per the test: toggleHostCompareSelection(["a"], "b")["a", "b"]). If a user toggles off Codex and re-toggles it back on while Claude Code remains selected, the resulting order becomes ["claude-code", "codex"] — the same set as the default, but positionally different — so isDefault evaluates false and the URL is populated with ?hosts=... even though the selection is functionally the default. This undercuts the stated goal that "shared links stay clean" (Line 122) for the common toggle-off/toggle-on interaction.

Consider comparing as an order-independent set instead of index-by-index equality.

🔧 Suggested fix
-    const isDefault =
-      selectedHostIds.length === DEFAULT_COMPARE_HOST_IDS.length &&
-      selectedHostIds.every((id, i) => id === DEFAULT_COMPARE_HOST_IDS[i]);
+    const defaultIdSet = new Set(DEFAULT_COMPARE_HOST_IDS);
+    const isDefault =
+      selectedHostIds.length === DEFAULT_COMPARE_HOST_IDS.length &&
+      selectedHostIds.every((id) => defaultIdSet.has(id));
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@mcpjam-inspector/client/src/components/hosts/comparison/HostConfigCompareView.tsx`
around lines 121 - 152, The default-selection check in HostConfigCompareView is
order-sensitive, so the URL can incorrectly keep ?hosts= even when the selected
hosts match DEFAULT_COMPARE_HOST_IDS in a different order. Update the isDefault
logic inside the useEffect to compare selectedHostIds as an order-independent
set (or normalized order) before deciding whether to delete HOSTS_QUERY_PARAM.
Keep the existing urlConsumedRef and toggleHostCompareSelection behavior, but
make the default detection robust to re-adding hosts in a different sequence.
🧹 Nitpick comments (1)
mcpjam-inspector/server/utils/convex-guest-auth-sync.ts (1)

27-28: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Read the Convex CLI entry from package.json#bin. The package currently declares bin/main.js, so resolving it from metadata keeps this aligned if Convex changes its entrypoint later.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@mcpjam-inspector/server/utils/convex-guest-auth-sync.ts` around lines 27 -
28, The Convex CLI entry is being hardcoded from the package directory instead
of using the package metadata. Update the logic in convex-guest-auth-sync.ts
around cachedConvexCliEntry and require.resolve("convex/package.json") to read
the CLI entry from package.json#bin, then resolve that path relative to the
package root so it stays aligned if Convex changes its entrypoint.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In
`@mcpjam-inspector/client/src/components/hosts/comparison/HostConfigCompareView.tsx`:
- Around line 121-152: The default-selection check in HostConfigCompareView is
order-sensitive, so the URL can incorrectly keep ?hosts= even when the selected
hosts match DEFAULT_COMPARE_HOST_IDS in a different order. Update the isDefault
logic inside the useEffect to compare selectedHostIds as an order-independent
set (or normalized order) before deciding whether to delete HOSTS_QUERY_PARAM.
Keep the existing urlConsumedRef and toggleHostCompareSelection behavior, but
make the default detection robust to re-adding hosts in a different sequence.

---

Nitpick comments:
In `@mcpjam-inspector/server/utils/convex-guest-auth-sync.ts`:
- Around line 27-28: The Convex CLI entry is being hardcoded from the package
directory instead of using the package metadata. Update the logic in
convex-guest-auth-sync.ts around cachedConvexCliEntry and
require.resolve("convex/package.json") to read the CLI entry from
package.json#bin, then resolve that path relative to the package root so it
stays aligned if Convex changes its entrypoint.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 44f80126-8e93-454a-a491-8249438a8700

📥 Commits

Reviewing files that changed from the base of the PR and between 9a59821 and 06c2d3c.

📒 Files selected for processing (4)
  • mcpjam-inspector/client/src/components/hosts/comparison/HostConfigCompareView.tsx
  • mcpjam-inspector/client/src/components/hosts/comparison/__tests__/host-compare-selection.test.ts
  • mcpjam-inspector/client/src/components/hosts/comparison/host-compare-selection.ts
  • mcpjam-inspector/server/utils/convex-guest-auth-sync.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants