authorgravatar for gbarros1095@gmail.comGuilherme Barros <gbarros1095@gmail.com> 2026-08-22 22:00:21+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-08-22 16:00:21-04:00
log49c2b4471c59b21759eb2e254e9c4fa2579888a3
tree9a88d788d35ad603347572db4a30c928efaf1bb7
parent2c4158f87a1b6a586d0aa5e0338f122cb7887c4f
signature Signed by PGP key B5690EEEBB952194

fix(ssh): restore user PATH for remote servers (#7213)


5 files changed, 13 insertions(+), 14 deletions(-)

apps/server/src/provider/Layers/ClaudeProvider.ts+1-1
......@@ -862,7 +862,7 @@ export const checkClaudeProviderStatus = Effect.fn("checkClaudeProviderStatus")(
862862 status: "error",
863863 auth: { status: "unknown" },
864864 message: isCommandMissingCause(error)
865 ? "Claude Agent CLI (`claude`) is not installed or not on PATH."
865 ? "Claude Agent CLI (`claude`) was not found on PATH."
866866 : "Failed to execute Claude Agent CLI health check.",
867867 },
868868 });
apps/server/src/provider/Layers/CodexProvider.ts+1-1
......@@ -576,7 +576,7 @@ export const checkCodexProviderStatus = Effect.fn("checkCodexProviderStatus")(fu
576576 auth: { status: "unknown" },
577577 message: installed
578578 ? `Codex app-server provider probe failed: ${error.message}.`
579 : "Codex CLI (`codex`) is not installed or not on PATH.",
579 : "Codex CLI (`codex`) was not found on PATH.",
580580 },
581581 });
582582 }
apps/server/src/provider/Layers/ProviderRegistry.test.ts+3-9
......@@ -494,10 +494,7 @@ it.layer(Layer.mergeAll(NodeServices.layer, ServerSettingsModule.layerTest(), Te
494494 assert.strictEqual(status.status, "error");
495495 assert.strictEqual(status.installed, false);
496496 assert.strictEqual(status.auth.status, "unknown");
497 assert.strictEqual(
498 status.message,
499 "Codex CLI (`codex`) is not installed or not on PATH.",
500 );
497 assert.strictEqual(status.message, "Codex CLI (`codex`) was not found on PATH.");
501498 }),
502499 );
503500
......@@ -1462,7 +1459,7 @@ it.layer(Layer.mergeAll(NodeServices.layer, ServerSettingsModule.layerTest(), Te
14621459 assert.strictEqual(codexPersonal?.installed, false);
14631460 assert.strictEqual(
14641461 codexPersonal?.message,
1465 "Codex CLI (`codex`) is not installed or not on PATH.",
1462 "Codex CLI (`codex`) was not found on PATH.",
14661463 );
14671464 }).pipe(Effect.provide(runtimeServices));
14681465 }),
......@@ -2252,10 +2249,7 @@ it.layer(Layer.mergeAll(NodeServices.layer, ServerSettingsModule.layerTest(), Te
22522249 assert.strictEqual(status.status, "error");
22532250 assert.strictEqual(status.installed, false);
22542251 assert.strictEqual(status.auth.status, "unknown");
2255 assert.strictEqual(
2256 status.message,
2257 "Claude Agent CLI (`claude`) is not installed or not on PATH.",
2258 );
2252 assert.strictEqual(status.message, "Claude Agent CLI (`claude`) was not found on PATH.");
22592253 }).pipe(Effect.provide(failingSpawnerLayer("spawn claude ENOENT"))),
22602254 );
22612255
packages/ssh/src/tunnel.test.ts+7-2
......@@ -243,8 +243,12 @@ describe("ssh tunnel scripts", () => {
243243 username: "julius",
244244 port: 2222,
245245 } as const;
246 const spawner = ChildProcessSpawner.make(() =>
247 Effect.succeed(makeSuccessfulProcess('loaded nvm default\n{"remotePort":3774}\n')),
246 const spawnedCommands: Array<ReadonlyArray<string>> = [];
247 const spawner = ChildProcessSpawner.make((command) =>
248 Effect.sync(() => {
249 spawnedCommands.push(commandArgs(command));
250 return makeSuccessfulProcess('loaded nvm default\n{"remotePort":3774}\n');
251 }),
248252 );
249253 const spawnerLayer = Layer.succeed(ChildProcessSpawner.ChildProcessSpawner, spawner);
250254 const processLayer = Layer.merge(NodeServices.layer, spawnerLayer);
......@@ -252,6 +256,7 @@ describe("ssh tunnel scripts", () => {
252256 return Effect.gen(function* () {
253257 const result = yield* launchOrReuseRemoteServer(target);
254258 assert.equal(result.remotePort, 3774);
259 assert.deepEqual(spawnedCommands[0]?.slice(-5, -1), ["sh", "-l", "-s", "--"]);
255260 }).pipe(Effect.provide(processLayer));
256261 });
257262
packages/ssh/src/tunnel.ts+1-1
......@@ -724,7 +724,7 @@ export const launchOrReuseRemoteServer = Effect.fn("ssh/tunnel.launchOrReuseRemo
724724 stateKey: remoteStateKey(target),
725725 });
726726 const result = yield* runSshCommand(target, {
727 remoteCommandArgs: ["sh", "-s", "--", remoteStateKey(target)],
727 remoteCommandArgs: ["sh", "-l", "-s", "--", remoteStateKey(target)],
728728 stdin: buildRemoteLaunchScript(runner),
729729 timeoutMs: REMOTE_LAUNCH_TIMEOUT_MS,
730730 ...(input?.authSecret === undefined ? {} : { authSecret: input.authSecret }),