several nice UI improvements

This commit is contained in:
2026-06-16 08:52:22 +02:00
parent 6a940b9b7a
commit 7bac3fe7c5
5 changed files with 64 additions and 35 deletions

View File

@@ -25,6 +25,19 @@ try {
const terms = new Map<number, import('node-pty').IPty>()
let seq = 0
/**
* Env for spawned PTYs. Electron launched from a Homebrew/GUI context leaks
* `npm_config_prefix` (e.g. "/opt/homebrew") into the child shell, which makes
* nvm refuse to load ("nvm is not compatible with the npm_config_prefix
* environment variable"). Strip it so the user's shell init runs cleanly.
*/
function ptyEnv(): { [key: string]: string } {
const env = { ...process.env } as { [key: string]: string }
delete env.npm_config_prefix
delete env.npm_config_globalconfig
return env
}
function defaultShell(): string {
const configured = getConfig().terminal.shell
if (configured) return configured
@@ -39,12 +52,20 @@ export function ptyAvailable(): boolean {
export function createPty(sender: WebContents, kind: 'agent' | 'shell', cols: number, rows: number): number {
if (!pty) return -1
const cwd = getRoot() || process.env.HOME || process.cwd()
const proc = pty.spawn(defaultShell(), [], {
const shell = defaultShell()
const ai = getConfig().ai
const launchAgent = kind === 'agent' && ai.autoLaunch && process.platform !== 'win32'
// For the agent pane we exec the `claude` CLI directly as the shell's command
// (`zsh -i -c 'claude'`) instead of typing it into an interactive prompt — `-i`
// still sources the user's rc (nvm etc.), but there's no prompt line and no
// echoed command cluttering the pane; claude takes over a clean terminal.
const args = launchAgent ? ['-i', '-c', ai.command] : []
const proc = pty.spawn(shell, args, {
name: 'xterm-color',
cols: cols || 80,
rows: rows || 24,
cwd,
env: process.env as { [key: string]: string },
env: ptyEnv(),
})
const id = ++seq
terms.set(id, proc)
@@ -52,9 +73,8 @@ export function createPty(sender: WebContents, kind: 'agent' | 'shell', cols: nu
proc.onData((data) => { if (!sender.isDestroyed()) sender.send('pty:data', { id, data }) })
proc.onExit(() => { terms.delete(id); if (!sender.isDestroyed()) sender.send('pty:exit', { id }) })
const ai = getConfig().ai
if (kind === 'agent' && ai.autoLaunch) {
// small delay so the shell prompt is ready before we type the command
// Windows path keeps the type-into-shell launch (no `-i -c` semantics there).
if (kind === 'agent' && ai.autoLaunch && process.platform === 'win32') {
setTimeout(() => { try { proc.write(ai.command + '\r') } catch { /* exited */ } }, 350)
}
return id