Skip to content

Wake

A native desktop app that reads the private session directories of every coding agent on the machine, read-only, and gives them one window: browse by agent or project, full-text search that treats Chinese text and code substrings alike, one-click resume in the original project directory, a bundled MCP server and a command line so the agents themselves can read the history back, and remote hosts mirrored over SSH.

Screenshot of Wake
Editor screenshot, 1 Oct 2026Wake ↗

What it is

A native desktop app that gathers every coding-agent session on a machine into one place. It opens the private directories the agents already write to — read-only, and it never writes back — and turns them into one library that can be browsed by agent or project, searched, and resumed in a terminal at the original project directory. The supported-agent table has 22 rows, and between them they cover JSONL trees, dated rollout directories beside a SQLite state file, three table schemas across two database files from one product, a key-value store, zstd-compressed logs whose file name carries a format generation, and one agent whose transcripts are encrypted and can therefore only be listed as metadata. Search is SQLite FTS5 over a trigram index, so a Chinese phrase and a code substring such as useEffect( take the same path, and a hit opens the transcript at the matched message. The same index is handed back to the agents through a bundled read-only MCP server with five tools, and a command line that prints byte-identical output. Around that sit an Insights statistics page, remote hosts mirrored over SSH, a read-only memory page, and a cleanup page that moves session files to the system trash behind a marker so they stay deleted. Rust on GPUI, MIT, macOS first with experimental Linux and Windows builds.

Who built itAn independent developer whose own main tools are Claude Code and Codex, and who works mainly in Chinese. He wrote 181 of the repository’s 200 commits; the rest come from a GitHub account named claude with 10, YTwsy with three, and five others with one each. Of the 129 co-author trailers, 125 name a Claude model — Fable 5.1 on 63, Fable 5 on 36, Opus 5 on 16 and Opus 5.5 on nine.

How it is put together

The parts · 6

The repository is a two-crate workspace with a deliberate seam through it. wake-core is the data layer with no UI dependencies at all — adapters, the scanner and the file watcher, the SQLite index, the remote-host mirror, the MCP server, the command line and the per-platform services — and wake is the GPUI application above it. Almost every other decision follows from where that seam was put. Because the only source of truth is other tools’ files, opened read-only, the index is a derived cache that can be thrown away and rebuilt, with stars and pins kept in a separate table so they survive; because everything agent-specific is behind one trait, a new data source is a new module rather than a change to the interface; and because the same five query tools answer both MCP and the command line, the CLI’s text can be asserted byte for byte against what a connected agent sees, which leaves one format to document instead of two. The remote-host feature is the same seam used a second way: remote.rs wraps an adapter over a mirrored cache, so nothing above it can tell a remote session from a local one except by the badge.

crates/wake-core/src/adapters/
Twenty-six files: 22 agent modules behind the AgentAdapter trait, plus mod.rs at 61,238 bytes, parse_utils.rs at 41,391, remote.rs for the SSH mirror and sqlite_ro.rs for read-only database access. The largest single adapters are Codex at 59,164 bytes and Cursor at 46,943.
crates/wake-core/src/{scanner,watcher,db}.rs
A single-pass scan that collects metadata and the full-text rows together and then runs incrementally on mtime, a notify-based file watcher for per-file updates, and the rusqlite index in WAL mode with sessions, messages, messages_fts, user_data and tombstones plus location, remote_hosts and schema-meta tables. db.rs is 146,506 bytes and scanner.rs 53,568.
crates/wake-core/src/{mcp,cli} and bin/
A read-only MCP server over stdio with hand-written JSON-RPC and five tools, and a command line whose argv is turned into the same calls. Three binaries ship: scan for a data-layer smoke test, wake-cli and wake-mcp.
crates/wake-core/src/services/
Terminal resume implemented per platform — AppleScript on macOS, argv on POSIX, Win32 with the raw argument API on Windows, across six files — plus export, agent context helpers, filesystem helpers, and an 88,525-byte cleanup module that finds removable sessions, takes a content hash before moving anything, and uses each platform’s own trash.
crates/wake/
The GPUI application. workbench.rs is 388,590 bytes, the largest file in the repository, with settings.rs at 79,160 and main_window.rs at 12,803; theme.rs and ui.rs are the only files allowed to hold colours, font sizes and spacing constants. The Simplified Chinese translation is 24,547 bytes next to a 25-byte en.json, because English is the source language rather than a translation.
DESIGN.md, PRODUCT.md, docs/ and scripts/
Three documents that hold the project’s written memory — 26,541 characters of interface specification, a product record of platforms, constraints and per-adapter provenance, and three references (cli.md at 21,972 bytes, mcp.md at 20,502, session-cleanup-design.md at 7,888) — beside packaging scripts for the app bundle, Linux packages and the Windows zip, and a 34,869-byte script that builds the synthetic home used for every public screenshot.

Choices, and what they beat

  • A data-layer crate with no UI dependencies over parsing and indexing inside the application

    The README’s architecture block labels wake-core a pure data layer with no UI dependencies, and that is what lets the same adapters be driven by the app, by wake-mcp and by wake-cli, and what lets the tests be data-layer tests: continuous integration runs cargo test -p wake-core on all three platforms while the GPUI window layer is only required to compile.

  • Read-only, in every direction over writing back into the agents’ own stores

    The README’s privacy section states that agent data directories are opened read-only, that credential files such as auth.json are never read, and that the only writes go to Wake’s own index and three small preference files. PRODUCT.md records the same rule as a constraint about Codex’s SQLite, and it reaches the remote-host feature too: OpenClaw’s database is excluded from mirroring because it also holds credentials, and only its legacy JSONL is copied.

  • The index is disposable and a command may only build a missing one over treating the database as the record, or letting a tool rebuild one in use

    The README says the index can be rebuilt from scratch at any time, with stars and pins in a separate table that survives a rebuild. wake-cli index is deliberately narrower than that: it scans into a temporary database beside the real one and takes its place atomically at the end, so a killed run can be retried, and it steps aside when the application already holds the index — the GUI and the two writing commands share one lock that is released when the window closes.

  • Classify Codex’s internal threads at the file boundary, and keep spawned sub-agents over filtering them after parsing, or excluding the whole family

    The maintainer’s answer to issue #42 kept guardian auto-review, /review, compaction and memory consolidation out while bringing spawn_agent children back, nested under the session that spawned them, with the copied parent conversation folded into one non-indexed stand-in. The README also states the direction the ambiguity is resolved in: a thread it cannot identify stays visible rather than risk hiding a real conversation.

  • Leave Qoder’s token count unknown instead of filling it with Credits over converting the only non-zero usage field into tokens

    That was proposed in #35 as a rough proxy and turned down in the maintainer’s reply, with the reason written out — it would combine different units in the same statistic. The limitation was documented and covered by regression tests instead, and the sessions stay visible in the Insights views that do not depend on tokens.

  • A synthetic home directory for every screenshot and demo over shooting the author’s real session library

    PRODUCT.md records the decision on 2026-08-19 and the reason: real project names are private. A script builds a fake home directory — 22 synthetic sessions, five invented projects, seven agents lit up — and all outward-facing screenshots use it. The test suite follows the same rule and parses synthetic fixtures only, which the README states explicitly, including for the remote-host test that uses a stand-in ssh and the system rsync against a synthetic home.

Read fromcrates/wake-core/src/adapters/ and the 235-file tree with sizes, the README’s architecture and privacy sections, PRODUCT.md (7,614 characters), DESIGN.md (26,541 characters), docs/session-cleanup-design.md, .github/workflows/release.yml and .github/workflows/ci.yml. The adapter count and the per-file sizes are the repository’s own directory listing; the trait name, the crate split and the index tables are quoted from the README’s architecture block.

Build log

6 stages
  1. 01

    Forty-two versions in forty-one days, and a release line that routed around a proxy

    The repository was created on 2026-08-18 and 0.1.0 shipped the same day with seven agents. In the forty-one days to 0.8.5 on 2026-09-27 the changelog gained 42 version sections, and the 200 commits split 76 in August and 124 in September. The busiest day is 2026-08-25 with five versions; 2026-09-03 carries four, and 2026-09-01 and 2026-09-25 three each. The API list in the recon report stops at twenty entries, from v0.4.2 to v0.8.5, because that is one page; the changelog goes back to the first release. Beside it sit 1,387 stars, 88 forks, 2 watchers, 6 open issues and an MIT licence. Eight accounts have committed: the owner wrote 181, an account named claude wrote 10, YTwsy three, and five others one each. The release workflow is worth reading on its own. Pushing a v* tag creates the GitHub Release with notes cut out of the changelog — the script takes everything between ## [X.Y.Z] and the next version heading — and then three jobs build for macOS, two Linux runners and Windows in parallel. They run on native machines because, in the author’s own comment at the top of the file, GPUI’s shader compilation cannot be cross-compiled. Assets already on a release are skipped and never overwritten, so whatever was uploaded first, including from the maintainer’s own laptop, is the published artifact. The same comment records a workaround: tag pushes and manual dispatch both came back 403 from the proxy the development environment pushes through, so pushing a branch named release/vX.Y.Z triggers the workflow instead and the tag is stripped out of the branch name.

  2. 02

    One trait, twenty-six adapter files, and the formats the agents invented

    The data layer is wake-core, and everything that differs between agents is confined behind one AgentAdapter trait. The README states the payoff in a comment — 「add an adapter, get the whole UI for free」 — and adds that remote.rs wraps any adapter over a synced cache, so remote hosts reuse the same code rather than a parallel implementation. crates/wake-core/src/adapters/ holds 26 files: 22 agent modules plus mod.rs at 61 KB and parse_utils.rs at 41 KB. The formats they absorb have almost nothing in common. Claude Code writes one JSONL per session under a per-project directory. Codex writes rollout-*.jsonl into a dated tree and keeps a parallel state_5.sqlite. Cursor keeps two stores that never meet: CLI transcripts under ~/.cursor/projects, and the IDE’s Chat and Composer history inside state.vscdb, a key-value database where one key gives the ordering and per-message keys give the bodies; a chat that also has a full transcript stays with the transcript so it lands under the right project. OpenCode ships three schemas across two database files, both scanned. DeepSeek Harness writes session[.vN].jsonl[.zstd], where the file name carries a format generation and the logs are decompressed on the way in — exactly the shape that broke in issue #45, where an adapter still looked for the older name and indexed zero sessions out of 112 on disk. Devin is a plaintext two-table database whose visible transcript is a forest walked from main_chain_id back along parent_node_id, with a documented fallback to every node in write order. Cursor’s directory slugs are the smallest and nastiest case: a single - stands for a path separator, a hyphen and a space, so My Project was decoded as My/Project until issue #38.

  3. 03

    What the file boundary keeps, what it hides, and what it leaves visible on purpose

    Codex writes its background threads into the same sessions directory as real conversations, and the first version of Wake indexed them: issue #30 reported guardian auto-review threads appearing as Untitled entries, some of them blank and some showing a reviewer’s approval JSON. Both shapes announce themselves on the first line, in a session_meta record carrying a thread_source and a structured source object, and the decision was taken at the file boundary rather than after parsing, so the watcher and the incremental path reach the same verdict as a full scan. v0.6.6 excluded the whole family. Then issue #42 asked for spawn_agent sub-agents back, noting that codex.rs already carried a comment saying their transcripts were held back for now and could later be reattached through parent_links. v0.8.0 answered it: spawned children are indexed again, nested under the session that spawned them and titled with their task name, the parent history Codex copies into each child is folded into one stand-in so it is not indexed twice, and the guardian, /review, compaction and memory-consolidation threads stay out. The README states the tie-break for anything it cannot classify: such a file stays visible rather than risk hiding a real conversation. The same instinct shows up with Craft Agents, which runs other engines and leaves a copy of each conversation in Claude Code’s own history; Wake lists the Craft session and hides the engine copy only while the original exists, and the copy reappears if the Craft session is deleted.

  4. 04

    Search over every agent, and two reports that turned a session id into a command-line flag

    Search is one SQLite FTS5 table with a trigram index, which is why a Chinese phrase and a query for useEffect( are the same operation; below three code points it falls back to a LIKE scan, and 0.8.0 fixed a crash where a one- or two-character term hit a message containing a character such as Ω or İ before the match. A hit jumps to the matched message rather than the top of the transcript, on a seq contract that the index and the reader both honour, and 0.6.5 added title matching and a small preference for recently active sessions. That same release had to stop an agent’s own wake_* lookups from appearing as hits inside the session that made them. Resume is where the sharpest reports landed. Issue #50 showed that a session id was concatenated into the agent’s command line with no shape validation, and that the quoting helper’s fast path treated - as a safe character, so a session file named --dangerously-skip-permissions.jsonl became a real option on that command line. Issue #49 went the other way: on Windows the Command Prompt path wrapped the id in double quotes without escaping anything inside them and filtered only %, while the ids of several adapters come from a database rather than a file name, so the assumption the code was written on did not hold. 0.8.4 fixed both by validating ids before opening a terminal, opening a desktop app, or copying an SSH command.

  5. 05

    GPUI: no symbols, no zoom, no Dock hiding, and a window layer CI only compiles

    The app is GPUI 0.2 with gpui-component 0.5, and several small constraints follow from that and are written down. GPUI has no SF Symbols, so every chrome icon is a bundled Lucide SVG and every agent identity is a bundled brand PNG rendered in its original colours, never tinted, not even in a selected row. There is no page zoom, because there is no web view: issue #51 asks for readable text and lists what does not exist — no font-size setting, no working Cmd +, and a Window menu zoom that only maximizes the window — and the only workaround offered is macOS Accessibility Zoom, which magnifies the whole screen. Issue #43 found a second closed door: the author had tried LSUIElement in the app bundle to keep Wake out of the Dock, and it does nothing, because GPUI sets the activation policy itself at launch. Two more limits are recorded as rules rather than bugs. A pointer callback must not synchronously dispatch a keyboard event, because opening the search palette from an AppKit mouseUp re-enters GPUI’s event dispatch; the root has to save the current focus before the palette opens, or ⌘K stops working once it closes. And the theme turns the component library’s focus ring off, because that ring is an absolutely positioned child two pixels outside the element’s box and gets clipped by dialog layers and scrolling lists — focus is carried by tinting the border instead, which takes no space and cannot be cut in half. Continuous integration builds the app on macOS, Linux and Windows, but the window layer is gated only by compiling there; the memory page, the cleanup page and the workbench itself ship with no windowed test.

  6. 06

    A design document written as numbers, beside a list of what the author could not verify

    DESIGN.md is 26,541 characters of specification rather than guidance: colours may only change in theme.rs, icons must be registered in assets.rs where a missing file extension is a silent blank, every interactive element gets an .id() before anything is bound to it, and every window root must mount the overlay layers after its content in an order the document calls a contract. Some of it reads like measurement notes. The sidebar’s centreline is the macOS traffic light’s red centre at x = 26.75, and everything else descends from it, down to a 7.75-pixel leading inset; the title inset of 9 was reverse-engineered from the width of the letter W, with a warning that changing the font size or weight invalidates it immediately. One gap was unified at 6 pixels on 2026-09-22 and is deliberately off the four-pixel grid, because brand PNGs carry no padding while Lucide icons carry about 1.5 pixels of it. A third note records that the rasterisation step on a 2x display is 0.5 pixels and that the digits past the decimal point should be left alone: the header inset had been 12.125 and landed at −0.125, and rounding it to 12.25 moved it to +0.375, a different physical pixel. The same document bans rem-based spacing outright after a migration finished on 2026-08-24, because rem is pinned to 14 pixels and the utility classes it replaced rendered at sizes such as 10.5 or 12.25. Underneath that, PRODUCT.md keeps the other kind of record: which adapters were checked against a real session on the author’s machine and which were inferred from source code, that OpenClaw, CodeBuddy and Reasonix had no local sessions to check against at all, that Qoder’s token counters are zero and its Credits are a different unit that will not be converted, and that from 2026-08-19 every screenshot and demo uses a synthetic home directory built by a 34 KB script, because real project names are private.

Adjacent records

All records →