fix(server): Claude no longer shows unavailable when its health check can't run in $HOME#19320
Fixes #2867.
Packaged desktop builds start the server with cwd = $HOME. The Claude --version health check inherited that cwd, and the capability probe used it. Some claude wrappers (containers, sandboxes, governance shims) refuse to run outside a project, so Claude showed as unavailable and the user never reached a session.
Fix
The Claude driver now runs its instance-level probes in the server's stateDir. This is T3's own data directory. It is never a project, and server startup creates it. The change applies to the capability probe, its cache key, and the status check. runClaudeCommand now takes an optional cwd.
Session spawns and per-thread workspace probes (snapshotForCwd) still use the thread's directory. They are not changed.
Proof
I started a real server from a fake $HOME, with a claude shim on PATH that logs its cwd and refuses to run in $HOME:
| Where the spawns ran | Claude status | |
|---|---|---|
| main | --version in $HOME | error: installed but failed to run |
| main, shim refusal off | --version and SDK probe in $HOME | ready |
| this PR | both in <base-dir>/userdata | ready, authenticated |
A new test in ProviderInstanceRegistry.test.ts uses the mock CLI with an opt-in guard that refuses to run outside one directory. Without the fix it fails with error. With only the --version half it fails with warning. It passes with the full fix.
vp test run on ProviderInstanceRegistry, ProviderRegistry, and ClaudeCapabilitiesProbe tests: 77 passed. Server typecheck and lint on the changed files are clean.
Diagnosis credit: #19174, which found the root cause. This PR is a separate implementation.
Reviewed with sol-loop: 1 round with GPT-6.1-Sol.
Model and harness: Claude Opus 5.5 in Claude Code via T3 Code.
π€ Generated with Claude Code
Checks
Added 1 commit
- fix(server): Claude health check no longer runs in the server's home cwd8f42bc6
Approvability
Verdict: Approved at 8f42bc6
Macroscope's review found this PR approvable β This is a focused server bug fix that moves only instance-level Claude probes to the existing state directory, while preserving project-scoped workspace and session execution. A live regression test covers the packaged-desktop cwd scenario, and no product defaults or static-analysis settings are changed.
You can add or adjust custom eligibility rules. Learn more.
Thread transfer impact
β Thread transfer remains within every enforced ceiling.
| Provider | Metric | Main baseline | This PR | Impact | PR ceiling | |
|---|---|---|---|---|---|---|
| Codex | Total thread wire | 4.9 KiB | 5.0 KiB | +23 B (+0.5%) | 6.8 KiB | β |
| Codex | Thread snapshot wire | 3.8 KiB | 3.8 KiB | 0 B (0.0%) | 4.9 KiB | β |
| Codex | Live turn WebSocket wire | 1.2 KiB | 1.2 KiB | +23 B (+1.9%) | 2.0 KiB | β |
| Codex | Live turn WebSocket decoded | 20.8 KiB | 20.9 KiB | +41 B (+0.2%) | 29.3 KiB | β |
| Codex | Live turn messages | 1 | 2 | +1 (+100.0%) | 8 | β |
| Claude | Total thread wire | 5.0 KiB | 5.0 KiB | β7 B (β0.1%) | 6.8 KiB | β |
| Claude | Thread snapshot wire | 3.8 KiB | 3.8 KiB | 0 B (0.0%) | 4.9 KiB | β |
| Claude | Live turn WebSocket wire | 1.2 KiB | 1.2 KiB | β7 B (β0.6%) | 2.0 KiB | β |
| Claude | Live turn WebSocket decoded | 21.2 KiB | 21.2 KiB | 0 B (0.0%) | 29.3 KiB | β |
| Claude | Live turn messages | 2 | 2 | 0 (0.0%) | 8 | β |
Baseline: 614b432 Β· PR result: 8f42bc6 Β· Source CI: success
Scenario and decoded snapshot size
10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.
- Codex decoded thread snapshot: 108.5 KiB
- Claude decoded thread snapshot: 108.8 KiB
Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.
No actionable comments were generated in the recent review. π
βΉοΈ Recent review info
βοΈ Run configuration
- Configuration used: Path: .coderabbit.config.ts
- Review profile: CHILL
- Plan: Team
- Run ID:
25283be5-a5bf-42f1-82cf-2b7be7cff085
π₯ Commits
Reviewing files that changed from the base of the PR and between 614b432a79b0acae38c27c00b1e4eece223ecfe4 and 8f42bc660d06a67527682f67c8564cb98bd115c4.
π Files selected for processing: 4
apps/server/src/provider/ClaudeProvider.tsapps/server/src/provider/Drivers/ClaudeDriver.tsapps/server/src/provider/ProviderInstanceRegistry.test.tsapps/server/src/provider/testing/ProviderInstanceRegistryLive.fixture.mjs
Included review availability: This review used your included allowance. 1 included review remains after this review. Your included PR review attempts over the past 7 days set your current allowance at 10 reviews per hour.
π Walkthrough
Claude instance-level capability probes and provider-status checks now run from the server state directory. Claude command execution accepts an explicit working directory. Workspace snapshot probes continue to use the thread working directory.
Changes: Claude probe working directory
Layer / File(s) Summary Explicit working directory for Claude probes
apps/server/src/provider/ClaudeProvider.ts,apps/server/src/provider/Drivers/ClaudeDriver.ts,apps/server/src/provider/ProviderInstanceRegistry.test.ts,apps/server/src/provider/testing/ProviderInstanceRegistryLive.fixture.mjsrunClaudeCommandaccepts and uses an optionalcwd, which the provider-status version check now supplies. Instance-level probes, capability-cache keys, and status checks usestateDir; workspace snapshot probes retain the threadcwd. The fixture can reject an unexpected working directory, and a live test checks readiness, version, and authentication.Priority: β Normal
Estimated code review effort: 2 (Simple) | ~10 minutes
Change: Bug fix Β· Severity of issue fixed: Medium
Suggested reviewers:
juliusmarminge
Merge Risk: βͺ Minimal Β· up to 8f42b
Claudeβs instance-level probes now use the server state directory, while workspace probes retain their thread directory. No merge-blocking issue is established; the change appears ready for normal checks.
Pre-merge checks: Passed 4
Passed Passed checks: 4 passed
Check name Status Explanation Title check Passed The title clearly and concisely describes the primary fix: Claude no longer reports unavailable when health checks inherit an unsuitable $HOME working directory. Description check Passed The description explains the problem, affected behavior, implementation scope, issue reference, verification steps, observed results, and test coverage. It uses "Fix" and "Proof" headings instead of tβ¦ Linked Issues check Passed Issue #2867requires Claude auxiliary probes to use an explicit scoped working directory.ClaudeDriver.createnow usesstateDirfor the capability probe, capability cache key, and provider status β¦Out of Scope Changes check Passed The changed driver code, command cwd support, registry test, and opt-in fixture guard all directly verify or implement issue #2867. The test and fixture changes are supporting automated coverage. No uβ¦
β¨ Finishing Touches
π Generate docstrings
- Commit to this branch
- Create a new PR
π§ͺ Generate unit tests (beta)
- Commit to this branch
- Create a new PR
- Autofix Β· Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Comment @coderabbitai help to get the list of available commands.