Devlog · Nov 10
1. Schema checks at every edge of ThinkRail: 22 PRs, still on my fork
ThinkRail has many boundaries: browser ↔ host, host ↔ files on disk, host ↔ gh, MCP, PostHog and pi session files. Today a lot of the data crossing them is trusted and cast to a type. My stack parses it once, at the edge where it arrives. Yesterday went mostly into deriving the schemas from their source packages instead of writing them by hand, so a schema can't drift from the type it checks.
What it gets:
- All 193 request methods checked at dispatch, with no cast left
- 33 push channels typed from one schema map, checked by the web before the UI sees them
- A missing or wrong check fails
tsc - A broken state file is kept as a
.corruptcopy instead of being overwritten with defaults - A workspace id passed as a session id fails
tsc
What it costs: +25 KB gzip of web JS, +17 ms host startup, +4.7 MB idle memory. Not ready yet. Stack overview: #135

2. Agent mockups you can actually click
When the agent shows an HTML mockup in chat, it used to be a static picture: no scripts, buttons removed. Now mockups take the app theme, fit their content, and run their scripts in a sandboxed frame. Tabs switch, charts draw, and even Freedoom plays inside a chat card. On macOS the desktop app runs them too, after an upgrade to Electrobun 2.0.6. Stack: #205, #206, #210

3. One keyboard focus ring for every control
Each control drew focus its own way, in 96 separate class strings. The chat composer barely showed focus at all: APCA contrast Lc 8, where a UI indicator needs 45. Now one ring is defined once, and its lowest contrast in the dark theme is Lc 64.5. #1306
4. Turbo cache for type checks and tests
ThinkRail ran every type check and unit test from scratch, even when nothing changed. Turbo now caches both, and the cache key covers files that tests read from outside their package. When nothing changed:
- Type check: 10.3 s → 0.9 s
- Unit tests: 5 min → 0.2 s
5. Smaller things
- Tried the new cn package in place of clsx + tailwind-merge: about 2× faster on real class strings, not 30×. It needs a build step to generate its tables, so I'm not sure it's worth it yet (#213)
- Filed 3 ThinkRail issues: focus indicators, a note field that breaks arrow keys, and an unclear error when a subagent's model is set to "inherit"
- Shipped this Devlog section on my site