- Shortcut: Cmd+Shift+C → Cmd+Shift+M (avoid Chrome DevTools conflict) - Preload: onData/onExit now return cleanup functions (fix memory leak) - PTY: resolve shell path at construction time, throw on missing claude CLI - Terminal: remove allowProposedApi, dedupe resize listeners, add cleanup - Main: debounce window move config writes (500ms), restart PTY on activate - CSS: remove unused orbGlow keyframes - Package: fix appId to com.apaam.myclaude, skip code signing, remove unused deps
66 lines
1.4 KiB
TypeScript
66 lines
1.4 KiB
TypeScript
import * as pty from 'node-pty'
|
|
import { EventEmitter } from 'events'
|
|
|
|
export class PTYManager extends EventEmitter {
|
|
private ptyProcess: pty.IPty | null = null
|
|
private resolvedShell: string
|
|
|
|
constructor() {
|
|
super()
|
|
this.resolvedShell = this.resolveShell('claude')
|
|
}
|
|
|
|
start(_shell: string = 'claude', args: string[] = []) {
|
|
this.ptyProcess = pty.spawn(this.resolvedShell, args, {
|
|
name: 'xterm-color',
|
|
cols: 80,
|
|
rows: 24,
|
|
cwd: process.env.HOME,
|
|
env: process.env as { [key: string]: string },
|
|
})
|
|
|
|
this.ptyProcess.onData((data: string) => {
|
|
this.emit('data', data)
|
|
})
|
|
|
|
this.ptyProcess.onExit(({ exitCode }) => {
|
|
this.emit('exit', exitCode)
|
|
})
|
|
|
|
return this.ptyProcess
|
|
}
|
|
|
|
write(data: string) {
|
|
if (this.ptyProcess) {
|
|
this.ptyProcess.write(data)
|
|
}
|
|
}
|
|
|
|
resize(cols: number, rows: number) {
|
|
if (this.ptyProcess) {
|
|
this.ptyProcess.resize(cols, rows)
|
|
}
|
|
}
|
|
|
|
kill() {
|
|
if (this.ptyProcess) {
|
|
this.ptyProcess.kill()
|
|
this.ptyProcess = null
|
|
}
|
|
}
|
|
|
|
private resolveShell(shell: string): string {
|
|
if (shell === 'claude') {
|
|
const { execSync } = require('child_process')
|
|
try {
|
|
return execSync('which claude', { encoding: 'utf8' }).trim()
|
|
} catch {
|
|
throw new Error(
|
|
'Claude CLI not found. Please install it: https://claude.ai/download'
|
|
)
|
|
}
|
|
}
|
|
return shell
|
|
}
|
|
}
|