diff --git a/src/main/manifest/login-shell.ts b/src/main/manifest/login-shell.ts index 032c25e0..16a9688b 100644 --- a/src/main/manifest/login-shell.ts +++ b/src/main/manifest/login-shell.ts @@ -16,8 +16,8 @@ * three callers read the same definition. */ -/** The flag that makes a shell a login shell. */ -export const LOGIN_SHELL_FLAG = '-l'; +/** The flags that make a shell an interactive login shell. */ +export const LOGIN_SHELL_FLAG = '-il'; /** * `argv` with the login flag directly after the binary. @@ -34,6 +34,8 @@ export const LOGIN_SHELL_FLAG = '-l'; export function withLoginShellFlag(argv: readonly string[]): string[] { const bin = argv[0]; if (bin === undefined) return [...argv]; - if (argv.includes(LOGIN_SHELL_FLAG)) return [...argv]; + if (argv.some((arg) => arg === LOGIN_SHELL_FLAG || arg === '-l' || arg === '-li')) { + return [...argv]; + } return [bin, LOGIN_SHELL_FLAG, ...argv.slice(1)]; } diff --git a/src/main/restart/extras.ts b/src/main/restart/extras.ts index 931a5d81..55d1eede 100644 --- a/src/main/restart/extras.ts +++ b/src/main/restart/extras.ts @@ -117,7 +117,9 @@ export function recoverLaunchExtras( // that display would need a manifest field, and one dialog line does not // earn one. if (rec.agent === 'shell') { - return argv[1] === LOGIN_SHELL_FLAG ? argv.slice(2) : argv.slice(1); + return [LOGIN_SHELL_FLAG, '-l', '-li'].includes(argv[1] ?? '') + ? argv.slice(2) + : argv.slice(1); } // Narrowed by the shell early-return above, and by getLaunchableEntry diff --git a/src/main/tmux/resolve.ts b/src/main/tmux/resolve.ts index ab405579..7734a43e 100644 --- a/src/main/tmux/resolve.ts +++ b/src/main/tmux/resolve.ts @@ -276,7 +276,18 @@ export function captureLoginShellPath( if (settled) return; settled = true; const capturedDirs = - captured === null ? [] : captured.split(delimiter).filter(Boolean); + captured === null + ? [] + : captured + .split(delimiter) + .filter(Boolean) + .map((entry) => + entry === '~' + ? homedir() + : entry.startsWith('~/') + ? join(homedir(), entry.slice(2)) + : entry + ); // Captured dirs first (user's own ordering wins), then the safety net. const merged = mergePathDirs( capturedDirs,