Goal: Electron app that opens multiple pseudo-terminals, one per Git worktree/branch, and lets users invoke CLI assistants (aider/ollama/anthropic/openai). Local-only, BYO keys.
- Node 18+, Git 2.38+, pnpm (or npm/yarn)
- Electron + Vite scaffold (or create one)
- Optional CLIs installed on PATH:
aider,ollama,anthropic,openai
Tasks
- Create or use an Electron+Vite project.
- In
BrowserWindow, enablepreload,contextIsolation:true,nodeIntegration:false. - In
preload.ts,contextBridge.exposeInMainWorld('ipc', { invoke, on }).
Done when renderer can window.ipc.invoke('ping') and get "pong" via ipcMain.handle('ping', ...).
Tasks
- Install:
pnpm add node-pty xterm && pnpm add -D @types/node - Create
src/main/ptyManager.tswith:startPty(id, cwd, shell?) -> IPty(stores inMap)writePty(id, data),resizePty(id, cols, rows),killPty(id)
- Create
src/main/ipcPty.tswith IPC:pty:start(spawns, pipesonData→webContents.send('pty:data:<id>', chunk),onExit→pty:exit:<id>)pty:input,pty:resize,pty:kill
- In renderer, make
TerminalPaneusing xterm.js:term.open(el)ipc.invoke('pty:start', { id, cwd })- Listen:
pty:data:<id>,pty:exit:<id> term.onData(d => ipc.invoke('pty:input', { id, data: d }))
Done when you can run ls/git status in the terminal.
Tasks
- Add
src/main/git.tswithensureWorktree(mainRepo, name, branch): Promise<string>usingchild_process.execFile('git', ['worktree','add', worktreePath, branch], { cwd: mainRepo }). Reuse if exists. - UI “New Session” modal:
- Pick main repo root, enter branch, optional worktree name (default = branch).
- Call
ensureWorktree→ returns absolute path → pass ascwdtopty:start.
Done when terminal git status shows the selected branch per session.
Tasks
- Add
ipcMain.handle('agent:launchCli', ({ id, cmd, args }))→writePty(id, \${cmd} ${args.join(' ')}\r`)`. - UI: “Launch CLI” button with presets (
aider,ollama,anthropic,openai) + freeform args. - Optional: PATH check (
which/where) → show install tips if missing.
Done when pressing the button starts the chosen CLI inside that session’s shell.
Tasks
- Simple session store:
{ id, label, cwd, cli? }. - Render one
TerminalPaneper session (tabs or splits). - Controls per session: Kill, Clear, Resize to fit.
Done when two sessions run concurrently, isolated by worktrees.
Tasks
- Dev only:
dotenvin main; ship.env.examplewith commented keys (e.g.,ANTHROPIC_API_KEY=,OPENAI_API_KEY=). - Pass
envtonode-pty.spawn(mergeprocess.env+ optional per-session overrides stored locally). - Settings UI: allow per-session env overrides (never send secrets to renderer except for display with masking).
Done when echo $ANTHROPIC_API_KEY (or platform equivalent) shows the value when set.
Tasks
- Resize: call
pty.resize()on container resize (e.g., viaResizeObserver). - Scrollback: 5k–10k lines in xterm.
- Save logs: stream PTY output to
${worktree}/.agentlogs/session-YYYYMMDD-HHMM.log. - Exit handling: show
[Process exited], disable input.
Done when resizing feels natural, logs are written, exits are clear.
Tasks
- Add
LICENSE(MIT),.env.example,.gitignorefor.env,CONTRIBUTING.md,SECURITY.md. - Configure packaging (
electron-builder/electron-vite); rebuild native deps if needed. - Smoke test packaged app on your target OSes.
Done when packaged app launches, terminals work, CLIs spawn.
- Step 1: “Add preload and secure IPC in Electron+Vite; expose
ipc.invoke/ipc.on; implement a ping handler.” - Step 2: “Add node-pty in main, xterm in renderer; wire IPC to echo shell output and keystrokes.”
- Step 3: “Implement
ensureWorktree(mainRepo, name, branch)usinggit worktree; add a modal to create and start a session.” - Step 4: “Add
agent:launchCliIPC that types a command into the PTY; add UI with CLI presets and args.” - Step 5: “Create a session store and tabbed UI; mount one TerminalPane per session.”
- Step 6: “Load .env in main; pass env to
node-pty.spawn; add per-session env overrides in settings.” - Step 7: “Implement PTY resize, scrollback config, session log writing, and exit handling.”
- Step 8: “Add MIT license, .env.example, and packaging; ensure node-pty rebuild works in CI.”
- node-pty native ABI must match Electron: use
electron-rebuildif needed. - macOS GUI PATH may be empty: set PATH in
envor use login shell. - Windows quoting: keep args simple or wrap in
.cmd/.sh. - Permissions: ensure worktree dirs are writable.
- Never auto-merge branches; keep changes per-agent, PR manually.