Skip to content

feat: add CHROME_DEVTOOLS_AXI_SESSION for concurrent bridge isolation#48

Open
codevibesmatter wants to merge 2 commits into
kunchenguid:mainfrom
codevibesmatter:feat/named-sessions
Open

feat: add CHROME_DEVTOOLS_AXI_SESSION for concurrent bridge isolation#48
codevibesmatter wants to merge 2 commits into
kunchenguid:mainfrom
codevibesmatter:feat/named-sessions

Conversation

@codevibesmatter
Copy link
Copy Markdown
Contributor

Summary

Adds named-session support so multiple bridges can run concurrently — one per worktree, one per test user, one per Chrome profile, etc. — without stepping on each other.

CHROME_DEVTOOLS_AXI_SESSION=widecorp-ceo chrome-devtools-axi open https://...
CHROME_DEVTOOLS_AXI_SESSION=deb-admin     chrome-devtools-axi open https://...

Each named session gets its own:

  • Bridge process and port — auto-allocated from name hash to 9225..9324. Override with CHROME_DEVTOOLS_AXI_PORT if you hit a collision.
  • PID file~/.chrome-devtools-axi/sessions/<name>/bridge.pid.
  • Persistent profile dir~/.cache/chrome-devtools-axi/sessions/<name>. Auth state and cookies survive bridge restarts. Composes with the existing CHROME_DEVTOOLS_AXI_USER_DATA_DIR override (explicit env wins over the per-session default).

Backward compatible. When CHROME_DEVTOOLS_AXI_SESSION is unset (or set to "default"), behavior is identical to before: port 9224, legacy ~/.chrome-devtools-axi/bridge.pid path, --isolated profile.

Motivation

Monorepos with many worktrees need per-worktree browser isolation so tools in different working directories don't share auth state or interfere with each other's bridges. Today a single global bridge means switching between worktrees clobbers state.

Named sessions solve that without forcing every worktree to manage CHROME_DEVTOOLS_AXI_PORT + USER_DATA_DIR + a custom PID file location by hand.

Also useful for:

  • Parallel test runs (one session per test worker)
  • Keeping multiple test-user sessions alive simultaneously (logged in as ceo and deb-admin in separate browsers, no re-login between agent calls)

Changes

  • src/sessions.ts (new) — single source of truth for session-scoped resources:
    • resolveSessionName() reads CHROME_DEVTOOLS_AXI_SESSION, defaults to "default"
    • validateSessionName() rejects path-traversal, shell metachars, overlong names (1-64 chars from [a-zA-Z0-9._-])
    • defaultPortForSession() deterministic FNV-1a-ish hash → port in [9225, 9324]
    • resolveSessionPort() env override > session-derived
    • resolveSessionPidFile() legacy path for default, sessions/<name>/ subdir otherwise
    • defaultUserDataDirForSession() returns null for default (preserves --isolated), per-session path otherwise
  • src/bridge.tswritePidFile/removePidFile use the session's PID file. runBridge() resolves the port lazily (was a module-load constant). buildTransportArgs falls back to the session's profile dir when no other profile env is set.
  • src/client.tsensureBridge() is session-aware: validates name, resolves session port + PID file, propagates CHROME_DEVTOOLS_AXI_SESSION to the spawned bridge child so it uses the same paths. readPidFile accepts an optional path so call sites can pass session-specific paths if needed.
  • src/cli.ts — documents CHROME_DEVTOOLS_AXI_SESSION in TOP_HELP.
  • test/sessions.test.ts (new) — 21 tests covering name resolution, validation (rejects path-traversal / shell metachars / overlong / empty), port allocation, PID file paths, profile path defaults.
  • test/bridge.test.ts — 3 new tests for the session-aware profile resolution: default session uses --isolated; named session auto-derives a profile dir; explicit USER_DATA_DIR overrides the session default.

Stat: 6 files changed, 370 insertions(+), 33 deletions(-).

Test plan

  • All existing tests pass
  • 24 new tests pass (246 total)
  • Backward compat: CHROME_DEVTOOLS_AXI_SESSION unset → same code path / paths / port as before
  • Build: npm run build clean

Stacked on #47

This branch builds on #47 (cold-start npx-bootstrap fix) — that's the first commit shown in the diff. The two PRs are independent in scope and reviewable separately. After #47 merges, I'll rebase this onto post-merge main so the diff cleanly shows only the named-session changes.

If you'd prefer this PR not depend on #47 at all, I can split out the lazy port-resolution change (the only bridge.ts overlap) into a precursor commit on main. Let me know.

Notes

  • Port collisions in [9225, 9324] are possible with deterministic hashing. Collision domain is small but real. If two named sessions hash to the same port, set CHROME_DEVTOOLS_AXI_PORT on one of them. Could add probe-and-allocate later if it becomes a common issue.
  • A natural follow-up is a --session <name> CLI flag (in addition to the env var). Skipped here to keep this PR focused — same resolution can be added without breaking changes.
  • Validation on the session name is strict (1-64 alphanumerics + ._-) to keep filesystem paths safe and prevent injection through env var manipulation.

codevibesmatter and others added 2 commits May 2, 2026 09:18
Adds two env vars that together unblock bridge cold-start on systems
where `npx -y chrome-devtools-mcp@latest` is slow.

- CHROME_DEVTOOLS_AXI_MCP_PATH — absolute path to a chrome-devtools-mcp
  script. When set, the bridge spawns `node $MCP_PATH` directly instead
  of going through npx. Skips the 30s+ npx bootstrap on systems with
  registry latency or large global caches.

- CHROME_DEVTOOLS_AXI_BRIDGE_TIMEOUT_MS — bridge readiness deadline in
  milliseconds (default 30000, min 1000). Lets users extend the timeout
  on slow machines without a code change.

Also improves the BRIDGE_NOT_READY error message: when MCP_PATH is unset
the suggestion now points at the npx-skip workaround as well as the
existing "check that mcp is installed" hint.

Motivation: on some machines `npx -y chrome-devtools-mcp@latest --help`
takes 30+ seconds even with --offline (cold node startup + npm cache
lookup). That races the bridge's hardcoded 30s readiness deadline and
yields BRIDGE_NOT_READY with no useful diagnostic. Direct-node spawn of
the same binary takes ~1.6s.

Backward compatible: when neither env var is set, behavior is identical
to before — `npx -y chrome-devtools-mcp@latest` with a 30s deadline.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds named-session support so multiple bridges can run concurrently — one
per worktree, one per test user, one per Chrome profile, etc. — without
stepping on each other.

  CHROME_DEVTOOLS_AXI_SESSION=widecorp-ceo chrome-devtools-axi open ...
  CHROME_DEVTOOLS_AXI_SESSION=deb-admin     chrome-devtools-axi open ...

Each named session gets its own:

- Bridge process and port (auto-allocated from name hash, or override
  with CHROME_DEVTOOLS_AXI_PORT)
- PID file at ~/.chrome-devtools-axi/sessions/<name>/bridge.pid
- Persistent profile dir at ~/.cache/chrome-devtools-axi/sessions/<name>
  (so auth state and cookies survive bridge restarts — combines naturally
  with the existing CHROME_DEVTOOLS_AXI_USER_DATA_DIR override)

Backward compatible: when CHROME_DEVTOOLS_AXI_SESSION is unset (or set
to "default"), behavior is identical to before — port 9224, the legacy
~/.chrome-devtools-axi/bridge.pid path, and --isolated profile.

Motivation: monorepos with many worktrees need per-worktree browser
isolation so tools running in different working directories don't share
auth state or interfere with each other's bridges. Today a single global
bridge means switching between worktrees clobbers state. Named sessions
solve that without forcing every worktree to manage CHROME_DEVTOOLS_AXI_PORT
+ USER_DATA_DIR + a custom PID file location by hand.

Also useful for parallel test runs and for keeping multiple test-user
sessions alive simultaneously (logged in as ceo and deb-admin at the
same time, in separate browsers).

Stacked on kunchenguid#47 (cold-start npx-bootstrap fix).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant