Architecture
TrueDeck is a desktop app: Electron main owns processes and data, preload exposes a typed IPC API, and the renderer is a React + xterm Studio UI. The Rust truedeck-backend is the main session engine.
High-level stack
| Layer | What runs there |
|---|---|
Renderer (src/) | React, zustand store, xterm panes, TaskBoard, Settings |
| IPC | contextBridge / preload (window.truedeck) |
Electron main (electron/main/) | App lifecycle, pty-manager, tasks, mcp-hub, memory, agents, session layout |
| Session engine | Rust truedeck-backend (required) |
| Agents | Real CLIs in ConPTY / PTY under the project root |
Process roles
Main (electron/main/)
| Module | Responsibility |
|---|---|
index.ts | App lifecycle, BrowserWindow, settings IPC, session restore orchestration |
pty-manager.ts | Session map, spawn/write/resize/kill, rust vs node-pty backend |
resolve-command.ts | PATH / known-path CLI resolve; blocks Cursor IDE |
agents.ts | Default agent presets + agents.json merge |
session-layout.ts | Persist/load pane tree; max 16 tabs |
tasks.ts / task-dispatch.ts / runs.ts | Kanban store, dispatch to PTY, run records |
mcp-hub.ts | Unified MCP config write/sync to agent clients |
memory-service.ts / memory-providers.ts / mempalace.ts | Auto-context, env inject, providers |
agent-frame.ts | Wrap spawn in truedeck-frame.mjs when enabled |
backend-bridge.ts | JSON-RPC stdio to truedeck-backend |
utf8-carry.ts | Shared UTF-8 chunk decoding for ConPTY streams |
paths.ts | App data and memory directory helpers |
projects.ts | Project list CRUD |
first-run.ts / onboarding.ts | First-run / onboarding flow |
Preload (electron/preload/index.ts)
Exposes window.truedeck methods (spawn, settings, MCP, tasks, restore, …) via contextBridge. Renderer never gets raw Node APIs.
Renderer (src/)
| Area | Role |
|---|---|
App.tsx | Shortcuts, project/session lifecycle, palette, board/settings chrome |
components/TerminalPane.tsx | xterm instance, fit, write IPC, shortcut filter |
components/PaneWorkspace.tsx / lib/pane-layout.ts | Nested split tree, drag targets, max panes |
components/TaskBoard.tsx | Kanban UI |
components/SettingsMenu.tsx | Settings tabs |
store.ts | Lightweight client state (zustand) |
Shared types (electron/shared/types.ts)
Single source for AgentPreset, AppSettings, SessionInfo, SessionLayout, Task, MemoryProviderConfig, etc.
PTY backends
| Backend | Build | Docs |
|---|---|---|
| truedeck-backend | npm run build:backend | RUST-BACKEND.md |
Env overrides:
| Variable | Purpose |
|---|---|
TRUEDECK_BACKEND_BIN | Path to truedeck-backend executable |
| TRUEDECK_DATA_DIR | Override app data directory (also used by hub MCP) |
Every session gets terminal identity env: TERM=xterm-256color, COLORTERM=truecolor, TERM_PROGRAM=TrueDeck.
Pane layout
Runtime layout is a tree of leaves (groups with tab lists) and splits (row | column + ratio).
Persisted form (SessionLayout):
version: 2withpaneTreewhen multi-pane is usedtabs[]as agent/command snapshots (not live PTY ids)- Indices map tree leaves back to restored session order
Helpers live in src/lib/pane-layout.ts (renderer) and electron/main/session-layout.ts (disk clamp/sanitize).
Session restore
- Renderer loads settings; if
reopenLastProject, callsessions:restore - Main loads
session-layout.json, clamps tabs (max 16), filters install helpers - For each tab, resolve agent + spawn PTY (memory env, agent frame when enabled)
- Renderer rebuilds pane tree from saved structure + new session ids
Memory inject
| When | What happens |
|---|---|
| Project open | Ensure .memory/, warm MemPalace, write auto-context.md |
| Agent spawn | onAgentSpawnFast sets TRUEDECK_* env and MCP pointers as configured |
See memory-providers.md. Env bag includes TRUEDECK_PROJECT, TRUEDECK_REPO_MEMORY, TRUEDECK_PALACE, TRUEDECK_AUTO_CONTEXT, and related keys.
Agent frame wrap
If agentFrameTui is enabled (default true), pty-manager wraps the CLI with:
node truedeck-frame.mjs --agent <id> --name … --cwd <root> -- <resolved CLI> …
Shell / cmd-* panes only wrap when frameShellPanes is true. See Agent frame.
MCP hub
mcp-hub.ts merges:
- Built-in truedeck-hub (
resources/mcp-server/truedeck-mcp.mjs) - Memory-provider MCP servers
- User servers in
mcp-servers.json
Then injects the same stdio set into Cursor / Claude Code / Grok / Codex / Gemini configs and project .mcp.json. See MCP.
Task dispatch
task-dispatch.ts:
- Write
.truedeck/tasks/<shortId>.md+.truedeck/current-focus.md - Spawn agent with
TRUEDECK_TASK*env - Start a run record; mark task
running - Best-effort seed prompt into PTY after ~1.2s
- On session exit → task moves toward
review(or blocked on failure)
TUI mode
tui/ is a separate entry (npm run tui) that reuses agent resolve / sessions concepts without Electron’s renderer. Packaging and most docs focus on Studio.
Packaging
electron-builder packs out/**/* plus extraResources:
resources/bin(Rust binaries if present)resources/mcp-serverresources/agent-frame- icons
See Development.
Related deep dives
- Fast PTY - PTY-only Rust sidecar
- Rust backend - full native service protocol
- Agents - resolve and spawn policy