A calm, thread-based terminal for AI-era workflows. Electron + TypeScript + React + xterm.js.
Weft organizes the terminal around threads of work: a named, color-dyed group holding one
Claude Code session and the satellite terminals that belong to the same task — instead of a flat
row of anonymous tabs. See DESIGN.md for the full product & design plan.
npm install # once
npm run rebuild # once — builds node-pty against Electron's ABI
npm run dev # launchnpm run typecheck checks both processes; npm run build typechecks + bundles.
- Threads (⌘N) group tabs around a task. Each thread gets a chalk hue that dyes the whole interface — indicator, prompt glyph, focus rings — so you always know which task you're holding.
- The composer is a real text editor for the prompt line: click anywhere, select, edit, ⇧⏎ for multi-line. History on ↑/⌃R, fish-style ghost suggestions (→ accepts), Tab completes paths against the tab's live cwd. It auto-hides when a full-screen app (vim, htop, Claude) takes over, and auto-masks password prompts.
- Claude tabs (⇧⌘T) launch your
claudecommand with a ✳ badge and busy/waiting status. Pin one to a split (⌘) and watch it work while you drive the other tabs. - Send to Claude (⇧⌘A): select any output — an error, a diff — and it lands in the thread's Claude tab as a paste.
- When a Claude tab goes quiet after working and you're elsewhere, Weft can send a macOS notification; clicking it jumps straight to that tab.
| ⌘P | command palette |
| ⌘N / ⌘T / ⇧⌘T | new thread / tab / Claude tab |
| ⌘W | close tab |
| ⌘1–9 · ⇧⌘[ ] | switch tabs |
| ⌥⌘↑ ↓ | switch threads |
| ⌘\ | toggle split (pinned tab right) |
| ⇧⌘A | send selection (or draft) to Claude |
| ⌘F / ⌘K | find / clear |
| ⌘J / ⌘I | composer off–on / focus composer |
| ⌃R | fuzzy history (in composer) |
| ⌘↑ ⌘↓ | jump between your commands |
| ⌘B | sidebar |
| ⌘± 0 | terminal text size |
Double-click any thread or tab name to rename it in place. Right-click everything — terminals, tabs, threads all have real menus (thread menu includes the hue picker).
src/main Electron main: node-pty + flow control, JSON persistence,
cwd via lsof, native menu, notifications, screenshot harness
src/preload sandboxed typed bridge (window.weft)
src/renderer React app: zustand store · terminal registry (xterm outside
React) · components · design tokens
src/shared contracts shared by all three
Session state persists to Electron userData (threads, layout, per-thread history).
Claude tabs restore as shells with claude -c pre-filled — resuming is a choice, not a surprise.
WEFT_DEMO=1 seeds art-directed fixture threads (never touches real state).
WEFT_SHOT=/path.png captures a screenshot and exits; WEFT_SHOT_STATE=palette|settings|light|welcome
poses the UI first. Used for design QA.
Packaging/installers, shell-integration blocks (OSC 133), PATH completions, N-way splits, Windows/Linux polish.