EmpryoEmpryo.beta
‹ all releases
3.5.1-betaJul 25, 2026

3.5.0 was the big feature release. This one is the cleanup crew. Long sessions were quietly accumulating things they never let go of — editor processes, memory, and a session log that grew far faster than the conversation in it — and a few of those turned into the kind of total freeze where the terminal just stops and no amount of waiting helps. All of that is closed here, along with a cluster of history bugs that could lose your work when a turn died, and a solid round of desktop polish.

Nothing leaks anymore

The theme of this release: every leak we found was a limit that already existed but was never actually measured.

  • Orphaned editors stop piling up. A stalled Neovim plugin install had no timeout, so it left the editor running forever — one machine had accumulated 127 orphaned processes holding 725 MB, the oldest three days old. Installs now have a real timeout, own their process group so the whole tree gets cleaned up, and the reaper finally recognises Empryo's own editor instead of walking past it. It matches strictly on Empryo's own config path and socket, so your personal nvim is never a candidate.
  • Empryo proves a process is its own before killing it. Child processes are recorded when they're spawned, so a stray one gets cleaned up the day that kind of child is introduced rather than the day someone notices it leaking. A process younger than its own registry entry is treated as an impostor — a recycled process ID can't trick it into killing something that isn't ours.
  • Two whole classes of total freeze are gone. Asking for diagnostics on one file used to type-check your entire program to answer — 2,134 MB and 818 ms, down to 557 MB and 233 ms for identical results. And any tool that shelled out could hang forever waiting on a pipe rather than on the process, so a child that outlived the command (a lingering formatter server, a watcher, a test worker) would wedge the tool indefinitely. Both are fixed; a real end-to-end run went from 2,272 MB to 915 MB peak.
  • Heavy work gets declined under memory pressure instead of hanging. Past a memory ceiling the runtime can end up collecting a nearly-all-live heap forever, and once that starts nothing can interrupt it — no timeout saves you. So the answer is refusing to *start* the expensive work rather than trying to free memory after the fact. The ceiling is 1536 MB and EMPRYO_MEMORY_LIMIT_MB overrides it.
  • Your session log stopped bloating. Crash checkpoints were being written every single step, each one a full snapshot of the turn in flight — 51.7 MB of a 66.5 MB session log, against 12 MB of actual conversation. Only the newest is kept now and a completed turn writes none at all, which took one real session's log from 22.7 MB to 1.6 MB. The crash path still works: it's flushed on the way out.

empryo doctor now checks for this directly — it reports leaked child processes and memory against the ceiling, using the exact same detection the cleanup uses, so the two can never disagree. It runs on every build before release, which is where these get caught from now on.

Your work survives a turn that dies
  • A dead turn keeps its work. If a turn was interrupted or hit a provider error, the tool calls it had already completed were being thrown away and replaced with "(interrupted)". They're committed to the real history now, with their full output, on both desktop and the terminal.
  • Attached images survive a session restore. An image attached to a message validated fine while the session was live, but the way it was written to disk meant restoring that session threw an error — permanently, with no way to reopen it. Images are now stored in a form that round-trips, covered on all four surfaces.
  • Compaction fires on the limit that actually bites. Context is now budgeted against the real input ceiling and the transport size cap rather than a token estimate against the window — a 1 MiB request cap reads as only ~25% full on a token gauge, which is how you get a rejected turn that looked like it had plenty of room. It's checked every step instead of once after the turn settles, and there's one shared implementation across desktop, terminal, and headless instead of three drifting copies.
  • Restored sessions also keep their tabs, and history-rewriting flows (rewind, edit-and-resend) no longer disturb the real conversation.
Desktop
  • The embedded browser grew real debugging tools. Network recording for every request (status, size, timing, cache state, failures), connection and CPU throttling that survives navigation, an audit covering Core Web Vitals, page weight, accessibility and SEO, and a wait tool so screenshots stop landing mid-load. There's an element picker and element-scoped screenshots, and the browser can expand to fill the workspace.
  • Git decorations in the file tree. Staged and unstaged changes are told apart (a file you staged and then edited again correctly reads as modified), per-file ±line counts on hover, folders rolling up to "N changed files · +A −B", and a change-count pill on the Files pane. It's a toggle in Settings › General, and turning it off skips the git query entirely.
  • Scrolling and clicking behave. Scrolling up through a settled chat no longer slides itself back down, switching tabs doesn't scroll the transcript into place, expanded tool cards stay open across remounts, and press feedback can no longer swallow a click on a wide button.
  • Full memory details in the memory popup, tighter composer controls, even separators in the status bar, and Bun stack traces grouped into a single Errors row instead of flooding the transcript.
Terminal

Tool rows in the live strand log open mid-turn now — you can expand a running tool and see its output while the turn is still going, instead of waiting for it to land. The unfolded log hangs off the row frameless, matching the rest of the organic UI.

Under the hood
  • Tool schemas across the belt now match what the code and the description actually require, so the model stops being told one thing and validated against another.
  • Per-tab model changes stay isolated to that tab and persist immediately, and provider model lists handle key parity properly with temperature gated off on reasoning models.
  • The website picks up a cookieless pageview beacon — no cookies, no consent banner, and it emits nothing at all until a token is deliberately configured.
  • Documentation and blog posts got a pass to strip machine-written cadence, plus a refreshed terminal screenshot and a fix so the changelog stops competing with the docs in search.