diff --git a/README.md b/README.md
index d3a7d6f..bfdf72c 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
**A desktop workbench for the Pi coding agent.**
**Workspace-first, not chat-first.**
-[Quick Start](#quick-start) · [Architecture](docs/openpi-architecture.md) · [Project Brief](docs/openpi-project-brief.md) · [Pretext Deep-Dive](docs/openpi-pretext-deep-dive.md)
+[Quick Start](#quick-start) · [Architecture](docs/openpi-architecture.md) · [Design tokens](#design-tokens) · [Docs](docs/openpi-project-brief.md)
[](https://github.com/echohello-dev/pidex/actions/workflows/ci.yml)
[](https://www.electronjs.org/)
@@ -16,80 +16,26 @@
## Why this exists
-Daily coding-agent work means juggling repos, branches, and sessions, and the current tools are chat-first: the primary screen is a conversation, not your work. pidex flips that. It is a kitchen bench where every active repo, its branch, its sessions, and what has gone stale are visible at a glance.
-
-| The pain, observed daily | pidex's answer |
-|---|---|
-| Workspace switching takes too many clicks | One dashboard of every repo with Pi sessions, sorted by last activity |
-| Losing the thread when resuming | Repo, branch, and session state as first-class UI, not buried chat history |
-| Long sessions get sluggish | [Pretext](https://github.com/chenglou/pretext) measures multiline text off the DOM hot path, ~600x faster than browser measurement |
-| Worktrees feel unreliable | Git and worktree state surfaced directly, no chatting with the agent to switch branches |
-
-pidex is a personal project: learn by building, sharpen day-to-day DX, and share a cleaner local-first harness pattern for coding agents. Not a commercial product, not an OpenCode clone. Install, BYOK, and provider wiring belong to its sibling, Weldable; pidex focuses entirely on the daily coding workflow.
-
-> A developer's kitchen bench, not a chat pane.
-
-
-
-
-
-
+Daily coding-agent work means juggling repos, branches, and sessions, and the current tools are chat-first. pidex is the kitchen bench: every active repo, its branch, its sessions, and what's stale, visible in one glance.
## Quick Start
-You need [mise](https://mise.jdx.dev/) and the [Pi CLI](https://pi.dev/). The dashboard reads existing sessions from `~/.pi/agent/sessions`, so run `pi` in a repo or two first if you want it to light up.
+You need [mise](https://mise.jdx.dev/) and the [Pi CLI](https://pi.dev/). The dashboard reads existing sessions from `~/.pi/agent/sessions`.
```bash
$ git clone git@github.com:echohello-dev/pidex.git && cd pidex
$ mise install
$ bun install
-154 packages installed [2.61s]
-
-$ mise run dev
+$ mise run dev # starts Vite + Electron
```
-That starts Vite on :5173 and launches Electron against it. For a production build:
-
-```bash
-$ mise run build
-[build] $ bunx tsc -p tsconfig.main.json
-[build] $ bunx tsc -p tsconfig.preload.json
-[build] $ bunx vite build
-vite v8.0.11 building client environment for production...
-✓ 29 modules transformed.
-✓ built in 760ms
-
-$ mise run start
-```
-
-## Features
-
-### Shipped today
-
-| Feature | What you get |
-|---|---|
-| Workspace dashboard | Every repo with Pi sessions: branch, session count, last activity |
-| Session resume | Reopen any past session from its `.jsonl` transcript |
-| Streaming transcript | Token-by-token text with tool-call cards, one tab per session |
-| Pi over RPC | Each session is a supervised `pi --mode rpc` subprocess |
-| Pretext measurement | Row heights and line counts computed without touching the DOM |
-
-### Built on
-
-| Layer | Choice | Why |
-|---|---|---|
-| Shell | Electron 41 | Native window, context-isolated, typed `window.openpi` preload bridge |
-| UI | React 19.2 + Vite 8 | HMR in dev, fast renderer bundles |
-| Text measurement | `@chenglou/pretext` | ~15KB, DOM-free, built for virtualised text-heavy lists |
-| Language | TypeScript 6 | Strict types across main, preload, and renderer |
-| Package manager | Bun | Fast installs, frozen lockfile in CI |
-| Toolchain | mise | Node and Bun versions pinned, every command via `mise run` |
+For a production build: `mise run build` then `mise run start`.
## Architecture
```
┌────────────────────────────────────────┐
-│ Renderer (React 19 + Pretext) │ ← dashboard, session tabs, timeline
+│ Renderer (React 19) │ ← dashboard, session tabs, timeline
└───────────────────┬────────────────────┘
│ typed IPC (window.openpi)
┌───────────────────▼────────────────────┐
@@ -101,58 +47,37 @@ $ mise run start
└────────────────────────────────────────┘
```
-The renderer draws. The main process owns the workspace registry and every Pi subprocess, and normalizes agent events before they cross the bridge. Preload exposes a narrow typed API, so renderer code never touches Node.
+Pi runs out-of-process over RPC so the UI survives a runtime crash. Pretext handles text measurement so virtualized lists stay smooth in long sessions. Full detail in [docs/openpi-architecture.md](docs/openpi-architecture.md).
-Pi runs out-of-process over RPC instead of being embedded via SDK. That keeps the UI alive when a session crashes, makes restart supervision simple, and leaves the door open to non-Node clients later. The full decision matrix is in [docs/openpi-architecture.md](docs/openpi-architecture.md).
+## Built on
-## Philosophy
-
-1. **Workspace-first, not chat-first.** The primary screen is work state, not the latest conversation thread.
-2. **Fast by default.** Compounded multi-second delays are real cognitive drag.
-3. **Repo-aware.** Branch, dirty state, last commit, and worktree are first-class concepts.
-4. **Work-aware.** Task context belongs next to the session, not in another app.
-5. **Local and extensible.** Pi's minimal runtime stays intact; the richness lives in the UI layer.
-
-## Roadmap
-
-Shipped:
-
-- [x] Workspace dashboard over `~/.pi/agent/sessions`
-- [x] Session resume and streaming transcript with tool cards
-- [x] RPC session supervision
-- [x] Pretext-backed text measurement
-
-Next up:
-
-- [ ] **Diff viewer**, virtualised summaries with file-level change previews
-- [ ] **Session fork**, branch sessions visually
-- [ ] **Worktree switching** from the UI
-
-Long term:
-
-- [ ] Richer git and PR context in the dashboard
-- [ ] Task tracker awareness alongside sessions
-- [ ] Optional adapters for other agent runtimes
+| Layer | Choice |
+|---|---|
+| Shell | Electron 41, context-isolated, typed `window.openpi` preload bridge |
+| UI | React 19.2, Vite 8 with HMR |
+| Text | [`@chenglou/pretext`](https://github.com/chenglou/pretext), DOM-free |
+| Language | TypeScript 6 |
+| Package manager | Bun |
+| Toolchain | mise, all commands via `mise run` |
## Design tokens
-The workbench inherits its palette from the [Pi coding agent](https://pi.dev) so the desktop harness feels like part of the same family as the runtime it drives. Source of truth: [`scripts/_design.py`](scripts/_design.py), hexes pulled from `pi.dev/style.css`.
+The workbench inherits its palette from the [Pi coding agent](https://pi.dev) so it feels like part of the same family as the runtime. Source of truth: [`scripts/_design.py`](scripts/_design.py), hexes pulled from `pi.dev/style.css`.
| Token | Hex | Role |
|---|---|---|
-| warm-black | `#13110f` | Primary window background |
-| bg-deep | `#0d1116` | Deepest surface |
+| bg-deep | `#0d1116` | Window background |
| bg-canvas | `#161d27` | Canvas surface |
-| panel | `#212730` | Sidebar / panel surface |
+| panel | `#212730` | Sidebar / panel |
| panel-soft | `#252f3d` | Card surface |
| parchment | `#dacbc2` | Named cream, primary mark and text |
-| moonstone | `#ebe7e4` | Lighter cream, lit facet |
-| driftwood | `#5c5752` | Warm mid-gray, shadow facet |
+| moonstone | `#ebe7e4` | Lighter cream |
+| driftwood | `#5c5752` | Warm mid-gray |
| terracotta | `#844f3b` | Warm bronze accent |
-| terracotta-light | `#b86b52` | Accent highlight, status dots |
-| sunkissed | `#e1b06e` | Warm gold accent |
+| terracotta-light | `#b86b52` | Status dots |
+| sunkissed | `#e1b06e` | Warm gold |
| sage | `#a3a473` | Sage accent |
-| accent-blue | `#6a9fcc` | Links, focus rings |
+| accent-blue | `#6a9fcc` | Links, focus |
Regenerate assets after a token edit:
@@ -161,26 +86,20 @@ uv run --with fonttools python scripts/build-icon.py # assets/icon, mark
uv run --with fonttools python scripts/build-screenshot.py # docs/assets/screenshot
```
+## What's next
+
+- [ ] Diff viewer with virtualised summaries
+- [ ] Session fork, branch sessions visually
+- [ ] Worktree switching from the UI
+
## Documentation
| Doc | What it covers |
|---|---|
-| [docs/openpi-project-brief.md](docs/openpi-project-brief.md) | The thesis, pain points, positioning, MVP slice |
-| [docs/openpi-architecture.md](docs/openpi-architecture.md) | Process boundaries, IPC schema, SDK vs RPC matrix |
-| [docs/openpi-pretext-deep-dive.md](docs/openpi-pretext-deep-dive.md) | Why DOM-free text measurement, and where it applies |
-
-## Project Status
-
-Alpha. A personal workbench, not a product that ships. Expect sharp edges and breaking changes. Pushes to `main` tag calendar-versioned releases (`YYYY.MM.DD`) with notes generated from merged PRs.
+| [docs/openpi-project-brief.md](docs/openpi-project-brief.md) | Thesis, pain points, positioning, MVP slice |
+| [docs/openpi-architecture.md](docs/openpi-architecture.md) | Process boundaries, IPC schema, SDK vs RPC |
+| [docs/openpi-pretext-deep-dive.md](docs/openpi-pretext-deep-dive.md) | Why DOM-free text measurement |
## License
-No license chosen yet. Personal project, shared in the open.
-
----
-
-
-
-Made with Electron, Pi, and an unreasonable attachment to fast text layout.
-
-
+No license chosen yet. Personal project, shared in the open.
\ No newline at end of file
diff --git a/docs/assets/banner.png b/docs/assets/banner.png
index 4328c9a..c0a3fe6 100644
Binary files a/docs/assets/banner.png and b/docs/assets/banner.png differ
diff --git a/docs/assets/screenshot.png b/docs/assets/screenshot.png
index c23b4cf..7dbb4a4 100644
Binary files a/docs/assets/screenshot.png and b/docs/assets/screenshot.png differ
diff --git a/docs/assets/screenshot.svg b/docs/assets/screenshot.svg
index 7ec5d0f..e84180d 100644
--- a/docs/assets/screenshot.svg
+++ b/docs/assets/screenshot.svg
@@ -11,12 +11,23 @@
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
@@ -32,11 +43,17 @@
- pidex
+ pidex
-
+
+
+
+
+
+
+
-
+
diff --git a/scripts/build-screenshot.py b/scripts/build-screenshot.py
index 04de711..b651480 100644
--- a/scripts/build-screenshot.py
+++ b/scripts/build-screenshot.py
@@ -1,12 +1,16 @@
-"""Build a faithful pidex dashboard mockup SVG (and PNG) using the Pi
-(pi.dev) design tokens. Layout mirrors what the renderer ships: warm-black
-window with a panel-toned workspace sidebar on the left, session pane on
-the right, input pill at the bottom. Apple-style soft drop shadow under
-the window.
+"""Build a faithful pidex dashboard mockup SVG (and PNG) using the actual
+app design tokens (src/renderer/design-system/tokens.css), which mirrors
+pi.dev. Layout mirrors what the renderer ships: dark window with the
+blueprint grid, panel-toned workspace sidebar on the left, session pane
+on the right, input pill at the bottom. Apple-style soft drop shadow.
Output:
docs/assets/screenshot.svg
docs/assets/screenshot.png (1440x900)
+
+This is a structural render rather than a live capture: it uses the real
+tokens (--bg-deep, --panel, --parchment, --terracotta-light) and the real
+blueprint grid pattern so the visual language matches the running app.
"""
from __future__ import annotations
@@ -21,11 +25,11 @@
sys.path.insert(0, str(Path(__file__).resolve().parent))
from _design import ( # noqa: E402
- WARM_BLACK,
+ BG_DEEP,
+ BG_CANVAS,
PANEL,
PANEL_SOFT,
PARCHMENT,
- MOONSTONE,
TERRACOTTA_LIGHT,
pi_path,
)
@@ -44,8 +48,14 @@
SIDE_BG = PANEL
SIDE_PAD = 22
-# Warm neutral ground that complements the warm-black window
-BG = "#E2D8CC"
+# Warm neutral ground that complements the dark window.
+# Set to None to render on a transparent canvas (useful when the PNG will be
+# composited over a backdrop, e.g. the README banner).
+BG = None
+
+# Blueprint grid colors (from tokens.css --grid-minor / --grid-major)
+GRID_MINOR = "rgba(255,255,255,0.025)"
+GRID_MAJOR = "rgba(255,255,255,0.06)"
def svg() -> str:
@@ -53,10 +63,9 @@ def svg() -> str:
gx = (bbox[0] + bbox[2]) / 2
gy = (bbox[1] + bbox[3]) / 2
- # Sidebar π mark + pidex wordmark
mark_cx = WX + 36
mark_cy = WY + 44
- mark_scale = 0.036 # ~37px tall
+ mark_scale = 0.036
mark_transform = (
f"translate({mark_cx} {mark_cy}) "
f"scale({mark_scale} -{mark_scale}) "
@@ -106,12 +115,29 @@ def svg() -> str:
pill_y = WY + WH - 64
pill = (
- f''
- f''
- f''
- f''
+ f''
+ f''
+ f''
+ f''
+ f''
)
+ # Blueprint grid pattern (matches tokens.css body background)
+ # Clipped to the main pane area (not sidebar), so the grid is the
+ # distinctive app-chrome look in the session view.
+ grid_id = "blueprint"
+ grid_def = f"""
+
+
+
+
+
+
+
+
+
+ """
+
return f"""