AIDE Architecture — Phase 8: Terminal + Tasks
SkillProductivityPhase 8 SOP for the AIDE offline-first IDE rebuild, the integrated terminal + task runner: xterm.js frontend over a daemon-hosted PTY (node-pty with ConPTY on Windows), typed task contract (npm scripts etc. run with streaming output + clean stop), process tree management, and the ANSI/unicode/quoting pitfalls. Use whenever wiring terminal UI, spawning shell sessions, running tasks with live output, or debugging "terminal shows nothing", "control chars garbage", or "task won't stop". Research-grounded (VS Code terminal engineering docs, node-pty docs, xterm.js docs, nodejs.org child_process).
Use AIDE Architecture — Phase 8: Terminal + Tasks in Claude, ChatGPT or Ahel Desktop
Free. Sign in, add AIDE Architecture — Phase 8: Terminal + Tasks and connect your AI. About a minute.
Also: Claude Code · Cursor · Codex
Then ask your AI: use the AIDE Architecture skill
Details
Instructions available. Your AI can read the instructions. Execution depends on the setup they require.
Account requirements not reviewed. Check the skill instructions before use; Ahel provides instructions and does not run this skill.
No other account needed.
Add Ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.
What this skill tells your AI
The instructions your AI receives, as published by anonymousnomad/covert-coder in skills/packs/aide-arch-terminal/SKILL.md and read by Ahel’s review.
Doctrine
- The daemon owns the PTY. The browser renders xterm.js; every keystroke/resize round-trips to the daemon (WS event channel, Phase 4). The renderer NEVER spawns processes (renderer rule).
- ConPTY on Windows. node-pty with
useConPTY: true(Windows 10+ native pseudoconsole) — the modern, correct terminal backend; winpty is the legacy fallback only. - One shell, many sessions: a terminal panel with tabs; each session = one PTY (default shell:
pwshon this machine — PowerShell 7 is the user's shell; keep it configurable). - Tasks are typed contracts, not terminal typing. Running
npm run checkfrom a button = spawn the command with streaming output into a terminal view + a stop button that tree-kills. No keyboard-macro hacks. - Offline-first: the shell is local; no remote shells.
- Verify before claiming: real interactive shell (ls/echo/arrow keys), a long-running task (e.g.
npm run check) with streaming + stop verified in the browser.
What
Phase 8 delivers:
- PTY service (
node/src/services/pty.ts): session registry (id, shell, cwd, status), spawn via node-pty (ConPTY), data pump (pty → WS eventterm:data, WS input → pty.write), resize handling, exit detection (session closed event), tree kill on stop/daemon shutdown (Phase 1 rule). - Terminal UI (browser): xterm.js view with tab bar (new/close), fit addon (resize on container change), theme matching the IDE dark theme, copy/paste (browser clipboard — secure context required; note the http://127.0.0.1 caveat: clipboard API needs secure context, localhost counts as secure), Ctrl+C handling (pty handles it natively — do NOT intercept except for the explicit "stop task" button).
- Task runner (
node/src/services/tasks.ts):runTask { name, command, args, cwd }→ spawn WITHOUT pty (stdio pipes; streaming via WStask:output) OR with pty for interactive tasks; status events (task:statusrunning/succeeded/failed/stopped, exit code); stop = graceful SIGTERM → 3s → tree kill (taskkill /T /F on Windows); output capped per event (Phase 4 rule: 256KB truncation with flag). - Contracts (
common/contracts/terminal.ts+tasks.ts): open/close/write/resize terminal; run/stop/status task. WS channels:term:<id>:data,task:<id>:output,task:<id>:status. - Integration: the RUN view's model/training buttons and the Phase 10 training arena use the task runner; the terminal is the visible window into long jobs.
How
1. node-pty on Windows (verified practice)
- Install node-pty; it ships prebuilt binaries for common Node versions (check
node-ptyrelease assets; if prebuild missing for the installed Node, it needs a native toolchain — avoid by pinning Node to a version with prebuilds). - Spawn:
pty.spawn('pwsh', ['-NoLogo'], { name: 'xterm-256color', cols, rows, cwd, useConPTY: true, env: {...} }). The-NoLogoavoids banner noise;name: 'xterm-256color'makes color apps work. - ConPTY requires a console-aware host; node-pty handles it. If
useConPTY:truethrows (old Windows), fall back tofalsewith a logged warning (winpty path) — Windows 10 22H2+ has ConPTY; this machine is modern. - Data flow:
pty.onData(chunk => ws.send({ channel: 'term:<id>:data', data: chunk }));pty.write(input)from WS messages. NEVER buffer: xterm.js expects real-time bytes; backpressure =ws.bufferedAmountcheck + throttle. - Resize:
pty.resize(cols, rows)onResizeObserver/fit addon events — debounced (e.g. 100ms), resize storms hang ConPTY.
2. PTY lifecycle + hygiene
- Session registry with IDs; close = user closes tab → daemon sends graceful shutdown to the shell (write
exit\ror kill) → wait → tree kill → remove from registry. - Daemon shutdown: tree-kill every PTY child (spawned shell has grandchildren — node-pty's kill kills the shell but NOT its children on Windows; the Phase 1 taskkill /T rule applies).
- CWD: default workspace root; a task can set cwd (containment-checked, Phase 1).
- Env: inherit daemon env +
TERM=xterm-256color,COLORTERM=truecolor; never pass secrets. - Exit detection:
pty.onExit→ session closed event → UI shows exit code + allows restart (keep the last 5000 lines of scrollback in the daemon so a closed session can be re-inspected; session restore keeps the tab with a "process exited" state).
3. Task runner (no PTY for non-interactive)
spawn(command, args, { shell:false, cwd, env }), stdio pipes.- Output: line-buffered chunks → WS
task:output(with ANSI passthrough — tasks may colorize; xterm parses ANSI). - Status: exit code 0 → succeeded; nonzero → failed (code in the event); killed by stop → stopped.
- Stop: SIGTERM → 3s grace →
taskkill /PID <pid> /T /F(Windows tree kill). NEVER leave orphans. - Concurrency: one task per id; start returns CONFLICT if the id exists (Phase 1 idempotence rule).
- Restart: re-run with the same command (new id).
4. Terminal UI (xterm.js)
new Terminal({ fontFamily: <bundled mono>, fontSize, theme: dark, scrollback: 5000 })+ FitAddon; open in the terminal container;term.loadAddon(fit)andfit()on container resize + on tab switch (Monaco view state restore rule from Phase 3 applies to terminal too: remount + refit + restore scrollback from the daemon session buffer on restore).- Input:
term.onData(d => ws.send({ channel: 'term:<id>:input', data: d })); paste = browser clipboard read (async, permission) → send as input data. - Alt-buffer apps (vim, htop) work via ConPTY automatically — do not fight it.
- Selection: xterm handles text selection natively; only add copy button if needed.
5. Tasks in the UI
- RUN view: "Run task" inputs (name, command) + a saved-task list (persisted in config, typed schema) — the verified training-arena pattern (job config JSON) generalizes here.
- Terminal tabs show task output inline (task started from a button opens/attaches a terminal tab showing that task's stream).
Why (research grounding)
- VS Code terminal docs: terminal = xterm.js renderer + node-pty/ConPTY backend with a data pump; the renderer never touches the PTY. This is the proven architecture for browser-rendered terminals.
- node-pty docs: ConPTY is the Windows 10+ backend; useConPTY:true is the documented correct mode; winpty is legacy.
- nodejs.org: spawn with shell:false for tasks; tree kill required on Windows (taskkill /T) — Phase 1 doctrine applies.
- Verified project lessons: the training arena already streams logs + stops cleanly (graceful-then-kill-tree, checkpoint-first); the task runner generalizes that verified pattern.
Dependencies
node-pty (native, prebuilt for the pinned Node), xterm.js + @xterm/addon-fit (local npm, no CDN — xterm CSS must be bundled), Phase 1 process manager, Phase 2 api client, Phase 4 WS channels, Phase 6 (model start/stop share the task/PTY infrastructure for llama servers? NO — model servers keep spawn, not PTY: no terminal semantics needed. Keep them separate.)
Known issues / bugs (watch these)
- ConPTY resize storms: resize floods hang the shell — debounce + only send when cols/rows actually changed.
- ANSI garbage: apps emitting old-school control sequences — xterm's parser handles most; if text looks broken, check
name: 'xterm-256color'was set (TERM=dumb breaks colors). - Backpressure: fast output (training logs!) into a slow UI — WS buffer bloat; cap per-event (256KB truncate flag, Phase 4) + allow the UI to pause/resume the stream.
- Clipboard permission: navigator.clipboard on http://127.0.0.1 — localhost IS a secure context, works; on a packaged WebView (Phase 11) confirm the scheme is treated secure (custom:// may not be — plan for a fallback execCommand path).
- node-pty prebuilds: Node upgrade without matching prebuild = native compile failure (needs VS Build Tools). Pin Node; upgrade deliberately.
- Ctrl+C vs stop button: Ctrl+C goes to the PTY (correct for interactive). The STOP TASK button sends SIGTERM+taskkill — distinct from Ctrl+C; label it clearly or users will wonder why Ctrl+C didn't kill a task.
- Shell quoting in tasks: commands are arrays, never strings (spaces in paths);
npm run check=['npm', 'run', 'check']— on Windows npm is npm.cmd, spawn with shell:false needs the .cmd resolved: useexecFilewith{ shell: true }ONLY for npm/npx (documented npm-on-Windows quirk: .cmd requires a shell or the full path to npm.cmd) — resolve viawhere npmor spawn 'cmd.exe /c npm.cmd ...' — decide once, document in the code, test it. - Scrollback loss: browser refresh loses terminal state unless the daemon buffers — daemon keeps per-session scrollback (cap 5000 lines) for restore.
- Encoding: default UTF-8; chcp issues on Windows console apps — set
cwd+ envCHCPisn't a thing; prefer PowerShell (pwsh is UTF-8 by default; cmd.exe legacy codepages garble — default shell is pwsh for this reason).
Phase 8 audit checklist (applied to the existing terminal work)
- PTY service with ConPTY, session registry, data pump, resize, exit handling, tree-kill on close AND daemon shutdown.
- xterm.js UI: tabs, fit, dark theme, scrollback restore; interactive shell verified (typing, arrow keys, Ctrl+C, a vim/htop alt-buffer app).
- Task runner: run/stream/stop/restart with exit codes; npm task verified on Windows (the .cmd quirk handled and tested); stop leaves no orphan processes (PID scan).
- Contracts terminal.ts/tasks.ts + WS channels in common/; fixtures both sides.
- Offline audit: no CDN, no remote shells; xterm css bundled.
npm run checkgreen.
Signals
- GitHub stars
- 43
- Forks
- 14
- Last commit
- Oct 2026
Advanced
- Item type
- skill
- Key
aide-arch-terminal- Source
- github.com/anonymousnomad/covert-coder
github.com/anonymousnomad/covert-coder
Related picks
Skill · thedaviddias
The pick for JavaScriptmodern-javascript-patterns
Skill · wshobson
The pick for JavaScriptsetup-ts-deep-modules
Skill · mattpocock
The pick for TypeScripttypescript-pro
Skill · jeffallan
The pick for TypeScriptnodejs-backend-patterns
Skill · wshobson
The pick for Noderun-node-tests
Skill · hiroro-work
The pick for Node