Merge pull request #209 from timkjr/fix/shell-login-shell

fix(shell): launch shell tabs as an interactive login shell
This commit is contained in:
Codeman maintainer
2026-08-05 01:34:22 +02:00
2 changed files with 13 additions and 1 deletions
+5 -1
View File
@@ -784,7 +784,11 @@ export function buildSpawnCommand(options: {
// SERVER process's env — empty in containers and system systemd units, leaving
// the pane command ending in a dangling `&&` ("syntax error: unexpected end of
// file", pane dead on arrival). Resolve it in Node and quote the result.
return shellescape(resolveLocalShell());
// -i -l: interactive login shell, so the resolved shell sources the user's rc
// files (~/.zshrc, ~/.bashrc, etc.) instead of running as a bare non-interactive
// child of the non-interactive `bash -c` that launches the pane — without this,
// aliases, PATH additions, and tool init (zoxide, nvm, etc.) are silently dropped.
return `${shellescape(resolveLocalShell())} -i -l`;
}
/**
+8
View File
@@ -88,6 +88,14 @@ describe('shell-mode spawn command (issue #208)', () => {
expect(cmd.trim()).not.toBe('');
});
it('launches an interactive login shell, so rc files (~/.zshrc, ~/.bashrc, etc.) are sourced', () => {
// Without -i -l, the resolved shell runs as a bare non-interactive child of
// the non-interactive `bash -c` that launches the pane, silently dropping
// aliases, PATH additions, and tool init (zoxide, nvm, etc.).
const cmd = buildSpawnCommand({ mode: 'shell', sessionId: 'abc123de-0000-0000-0000-000000000000' });
expect(cmd.trim().endsWith('-i -l')).toBe(true);
});
it('produces a launch command that parses after the outer sh -c expansion layer', () => {
const cmd = buildSpawnCommand({ mode: 'shell', sessionId: 'abc123de-0000-0000-0000-000000000000' });
// Mirrors tmux-manager: `… bash -c ${JSON.stringify(launchCmd)}` handed to `sh -c`.