Your agent finishes a patch. A fresh reviewer now opens the changed files with none of the conversation that produced them, then returns PASS, FAIL or PARTIAL. You can apply the findings, run another review, or use the verdict as a CI gate. /review works in the desktop app and TUI; --review brings the same check to headless runs.
Parallel agents can work in separate browser tabs without stealing each other's clicks. You can set reasoning effort by lane, open model pickers faster, search chat and Markdown previews, run Empryo on older Windows x64 CPUs, and switch to the new proxySoul Crimson theme.
Review before you merge
`/review` gives the patch to a fresh agent. Add a brief such as /review check the error paths, or run it without one for a general correctness pass.
You decide what happens next. Apply findings to the coder, dismiss them, or re-review. Each tab keeps its last eight verdicts through reloads and session restores.
The reviewer follows the work. It checks the current lane first, then session edits, then uncommitted git changes. New and deleted files count. A clean tree exits without calling a model.
`--review` can gate CI. PASS exits 0, FAIL exits 3, and PARTIAL exits 4. JSON output includes the verdict and report.
Parallel browser work
Each chat tab drives its own pages. Two agents can click and type in the same browser window without taking over each other's tab. Both can read any page.
Agents can inspect modern app layers. Page snapshots reach into shadow DOM, same-origin iframes, and interactive components built from div and span elements.
Browser actions keep your cursor in chat. Agents send input to the target page element. Background tabs keep running and can still capture screenshots.
Control the cost of each job
Set reasoning effort per router lane. Give code and review deeper reasoning while exploration and compaction stay lighter. The desktop app, TUI, and headless runner share the setting.
Choose a separate review model. Use a stronger judge without paying that rate for routine exploration.
Open model pickers faster. Long catalogs render only visible rows, prefetch when you approach them, and put your current provider first.
Desktop changes you'll notice
Find text in chat and Markdown previews. Press Cmd/Ctrl+F to search the document you are reading.
Provider key setup is easier to scan. The drawer groups providers, adds search and filters, shows provider marks and custom icons, and links to each key page.
proxySoul Crimson joins the theme picker. proxySoul themes lead the list with branded cards. Existing proxy-empryo configs keep working.
Markdown lists render cleanly. Wrapped bullets hang under their first line, and task items look like checkboxes.
Terminal paste happens once. Image annotations persist, Linux windows repaint after restore, status chips stop colliding, and open memory or config drawers refresh after agent writes.
Plans and older Windows PCs
OpenCode Go limits show on every surface. See remaining allowance and reset windows beside your other subscription plans.
Plan badges update when you switch model, tab, or lane.
Windows installers support x64 CPUs without AVX2. The installer selects the compatible baseline build after checking the CPU.
Notes
This is a beta. macOS, Linux and Windows builds are on the downloads page.
Know what your agents cost, then pay less for the same work
Empryo has a Cost Center now: one page for every dollar you spent, which model spent it, and how much prompt caching saved you. Building it meant staring at our own numbers, and the numbers were embarrassing. Caching was broken on half the providers we support, and nothing on screen said so. We fixed that too, so the savings figure on that page went up on its own. Also in this one: diagrams that draw themselves in your terminal, a tab strip you can read from across the desk, and browser and terminal panels that park and pop out instead of squatting on your workspace.
The Cost Center
What you paid leads. What you might have paid is the footnote. Most usage dashboards show list price and leave the arithmetic to you. This one puts the amount that left your account first, with the full API rate and your caching leverage underneath. A burn-rate chart, a spend-by-model table and a per-provider split sit below that.
Plans and quotas share a room with per-token spend. Subscription windows, reset times and remaining allowance live on the same page as metered billing, so a Claude Max seat and a pay-as-you-go key stop occupying separate corners of your brain.
Three ways to hide your account. Masked (ou•••@g•••.com), fully hidden, or visible. Pick it once from the status bar or the Cost Center rail and every open surface follows on the spot. Your screen-share thanks you.
Click a provider, filter the table. Every row carries its cache hit rate and the dollars that hit saved you.
Pay less for the same work
The savings number moved because caching finally works everywhere. We measured every one of these on a live session instead of assuming it.
OpenAI-family models cache within a session again. The cache key was going out as a header, which does nothing. Moved into the request body, a GPT session over the proxy went from a flat 3,456 cached tokens to 21,900 and climbing.
OpenRouter caches the tail. Its SDK ignores a request-level cache mark, so Empryo now stamps the last message of every request instead. Cached reads advance turn over turn rather than sitting still.
Subagents stopped paying for the cache twice. One tool showed up only for background agents, which split the prompt prefix into two variants and bought two separate 27k writes. Every subagent now carries the same tool belt.
A warm session appends, a cold one rebuilds. Idling past the cache window used to glue a stale snapshot onto a warm prefix. Empryo now spots the tab going cold, refreshes what it knows about your code, and takes the one write it was always going to owe.
When caching breaks, Empryo tells you. A big write with zero reads on a request that should have landed warm now prints a notice in the chat instead of billing you in silence.
Prices you can trust. We checked every effort ladder and reasoning setting against its vendor, and a rate we cannot verify now says so instead of guessing.
Diagrams, in both apps
Mermaid renders on the desktop as real SVG you can zoom, pan and blow up full-screen. It waits for the fence to close and the turn to settle, so nothing lurches while the model is still typing.
And in the terminal. Flowcharts and sequence diagrams drawn in box characters, no browser anywhere near it. Architect and plan modes know they can draw now, so go ahead and ask for one.
Also new
A tab strip you can read at a glance. The selection is one pill that travels: it tweens to the tab you picked, squashes with its own speed, and retargets mid-flight if you keep moving. A working lane sweeps and bobs its mode icon off-beat; a finished lane goes green with a check and a rail.
Minimize, dock, pop out, fullscreen. The terminal and the embedded browser each park to a status-bar pill and come back on demand. The workspace grid slides to make room for a panel instead of teleporting.
Code execution, resolved per provider. Anthropic's sandbox on the models that support it, OpenAI's code interpreter on the Responses lane, off behind gateways that can run neither.
The model picker fills in as answers arrive rather than making every provider wait for the slowest one. Routing through the proxy also reads its live model list, so the newest ids show up with the context windows they really have, 1M included.
⌘L jumps to the composer from anywhere, including out of a focused browser page. The idle placeholder mentions it until you learn it.
Links in chat are links, and a GitHub URL becomes a chip with the avatar on it.
Ask exchanges stay in the transcript. The question and the answer you picked sit together in the thread instead of evaporating the moment you click.
Screenshots go somewhere. Send one to the chat, copy it, or save it to a file.
Reveal in Finder (or Explorer, or your file manager) from any row of the file tree.
Faster
Long markdown opens instead of stalling. A 186KB document cost 1.5 seconds to parse in one piece. Split into chunks it costs 260 milliseconds, character for character identical.
Switching tabs no longer rebuilds the conversation. Lanes stay mounted, so a tab flips into view instead of reconstructing its entire transcript.
The browser console holds 5,000 lines and renders 17 of them. It follows live output, then holds your place the second you scroll up to read something.
Fixed
Your scroll position survives. Leave a tab pinned to the bottom and it re-pins when you come back. Leave it up in history and it stays there.
A renamed tab keeps its name through restarts and session reloads, in both apps.
Parking the browser stopped destroying your loaded tabs. Minimizing used to leave it on screen swallowing clicks, too.
Run waits for your dev server. It used to flash a connection error a heartbeat later and give up seven seconds in. Now it waits for the port to accept, which matters when a Vite app with a codegen step ahead of it needs 15 seconds to bind.
Editing a message in one split stopped replacing the draft in every other split.
A fresh session clears every tab, and restoring the same session twice no longer doubles your lanes.
Headless stopped dropping your tool flags. Code execution, computer use and the text editor were set everywhere except there.
Empryo clamps the output ceiling per model. One gateway checks that ceiling and rejected every single turn with a 400, because we asked for 64k from a model capped at 32,000.
The code map skips dot-directories..github, .claude and the rest stopped being indexed the moment your project was a git repo.
Organize imports works, and code actions on the last line of a file stopped being unreachable.
Installing a skill survives a slow registry instead of giving up early with an error too long to read.
A slash command stays highlighted when you shift+enter onto a second line.
A missing session says which directory it searched, so a resume from the wrong folder explains itself.
Empryo's memory number means something now. Raw RSS counts pages Bun has already handed back, so the old figure tripped guards over nothing.
Linux windows read the real display backend, so a Wayland session gets Wayland behaviour.
Notes
This is a beta. macOS, Linux and Windows builds are on the downloads page.
Open every project at once, split any tab in two, and stop losing sessions to a memory leak
You have three repos open in three editors, two of them are the same repo on different branches, and you have lost track of which terminal is which. We know, because we do it too. So this release makes Empryo hold all of it at once: a window per project, worktrees as first-class citizens, and splits everywhere — desktop and terminal both. Then we went back and killed the two bugs everyone kept hitting: sessions that quietly ran out of memory after a long day, and a terminal UI that let long text spill onto the row below it.
Bring the whole shelf, not one book at a time
A window per project. Open a second project without shutting the first. Every window keeps its own tabs, models, agents and layout, and has them back exactly as you left them next launch. Closing one plays the full swap instead of leaving half the old project smeared on screen.
Worktrees, properly. Create, list and switch git worktrees from inside Empryo, and give any of them its own window. The branch you are gambling on sits beside the branch you are shipping. Per-project state anchors to the main checkout, so five worktrees share one memory and one map — not five amnesiac copies of the same project.
Split any tab, in either app. Two conversations side by side, in the terminal as well as on the desktop. Stack tabs into groups, nest splits inside splits, and build the layout your actual task has, not the one a tab bar allows.
Hours nine through twelve
The long-session failures. These are the ones that made you restart and lose your thread.
The terminal stopped leaking. RSS used to climb all day until the app silently disappeared. Growth is bounded now, and an idle session sitting at the high-water mark quietly recycles itself in place: same session, same history, fresh process. You will not notice, which is the point.
Auto-compaction actually fires. On providers that do not report token usage it never triggered at all, and one failed attempt disarmed it permanently. Long conversations hit the wall instead of compacting. It now estimates its own occupancy, counts the system prompt it kept forgetting about, and keeps the recent tail by size rather than by a message count that treated a one-word reply and a 400-line diff as equals.
A stalled turn wakes itself up. The stall watchdog is on by default. No more staring at a spinner wondering whether to hit Ctrl-C.
A refused option no longer kills the turn. When a model or a proxy rejects a setting, Empryo drops that one setting and carries on — mid-stream too, and in the desktop app and headless mode, not just the terminal.
The terminal stopped eating its own letters
If you have ever watched a model id, a file path or an error string smear across the row underneath it, this is the release you wanted.
Every fixed-height row clips now. A row that promised to be one line tall keeps that promise. Long labels stop wrapping into their neighbours. It was the most visible glitch in the whole terminal UI and it is gone.
Lists follow your selection again. Arrowing down a picker used to walk the cursor off the bottom while the list sat still. Scrolling now waits for the row to exist before deciding it is already visible.
Popups fit their window. The prompt deck caps its height and scrolls inside itself, the command picker sizes to its content, the intro modal takes arrow keys, and cards stop hanging off the edge of narrow terminals.
A crash stays where it happened instead of taking the screen with it.
The transcript is clickable. Copy chips on the rows worth copying, click-to-open, one consistent caret vocabulary for what folds and unfolds — and a folded row that tells you what it is hiding rather than just vanishing.
Stop one tool, keep the turn. Kill a runaway command on its own. Shell timeouts are clamped, so nothing hangs forever waiting for a prompt that is never coming.
Faster, quieter, more honest
Syntax highlighting got quick. Highlighting lands in waves against pre-warmed grammars, and the desktop editor keeps its native tokenizer for languages it already knows. Big files open instead of stalling the pane.
Onboarding shows you the app, not a form. Coach marks on the real interface replace the setup wizard. First thing you see is Empryo.
The map runs on your terms. Pick its GPU, flip Fast/Eco on the map itself, and it drops to an idle tier the moment you look away.
Dropped `cd` prefixes are explained once per session, so a command that reads differently from what you typed is never a mystery.
Ask and Goal prompts land in the pane you asked from. Language servers and file locks survive sibling windows on the same machine. Background agents appear once in the inspector, not once per report. A tool row never unfolds into an empty box.
Notes
This is a beta. macOS, Linux and Windows builds are on the downloads page.
Compile your prompts, remember across sessions, and run agents in the background
This release is built around three ideas. Marionette turns a rough request into a compiled prompt before the model ever sees it, and shows you the work. Memory was rebuilt against a benchmark instead of intuition, so recall actually finds the thing you meant. And agents now run background-first — fan out several at once, steer them mid-flight, and stop babysitting a single blocking turn. Alongside that: subscription quota meters for Anthropic and Copilot plans, a redesigned TUI transcript that folds old turns out of your way, and a long list of fixes.
New
Marionette, the prompt compiler. Give Empryo a vague goal and let it compile: Marionette runs a short survey pass, drafts a sharper prompt, and hands you the result to accept or discard. Use /marionette in the CLI, the compile strip in the desktop app, or the --steps / --time flags to cap how much effort it spends. It picks a lane based on what you are doing, and the fast lane now ships the settings that won our benchmark passes rather than defaults someone guessed. There are guided tours and intro popups the first time you meet it.
Memory that was tuned against a benchmark. Cross-session recall got a ground-up overhaul: a sanitizer that strips noise before storage, keyword and semantic scoring blended together, a maintenance pass that keeps the store healthy over time, a local embedder so recall does not depend on a network call, and distillation that compresses what it keeps. Recall now weights files by how distinctive their path is, so a hit in an obscure module counts for more than one in a file everyone touches.
Background-first agents. Delegated work no longer blocks your turn. Fan several agents out at once, watch them on the tasks strip, and steer any of them while it runs. Empryo also picks the delegate from what you are actually doing next rather than a static preference.
See your subscription limits, not just your spend. If you route through an Anthropic subscription or a Copilot seat, Empryo now reads the real per-model caps and monthly allowances and draws them as meters in the status bar, usage panel and headless output — including which window is currently gating the model you are on. Subscription routing is documented as use-at-your-own-risk.
Real computer use. The computer-use tool is implemented and gated per lane and per model, so only the models that genuinely support it can reach for it.
A transcript that folds. The TUI transcript was reworked: older turns collapse into clickable scars you can reopen, ^O unfolds them, one turn stays open at a time, and the tool rail is aligned to a proper cell grid. Tasks collapse into a well with a tally of changed files on the ground line.
Ten tabs, with a context gauge. The tab cap rose to 10 in both the TUI and the desktop app, and each tab shows how full its context is.
Branch a conversation into a new tab. Fork any point of a chat into its own tab instead of destroying the original thread.
See-through windows on Linux and Windows. The desktop app's translucent chrome is no longer macOS-only.
The embedded browser moved to real guest views, with a shared network-policy cache and load errors that actually surface as an action you can take.
Improved
Sessions restore without stepping on your work. Restoring is additive, tab numbers stay stable across restarts, renames are written to the session log the moment you make them, and the log itself is durable.
The proxy sidecar is a shared daemon. It is no longer killed and respawned on every provider switch or spawned once per host, which removes a class of dropped-connection stalls.
Quota and usage formatting is consistent across the badge, the drawer and the status bar, drawn in the same visual vocabulary as the context gauge.
Search results say where they came from, and repeated code edits fold into one grouped row, so a large refactor reads as a single entry instead of fifty.
Composer and layout polish. Slash-command tokens are tinted as you type, command names stay intact at narrow widths, free-text fields wrap instead of scrolling sideways, composer hints degrade based on measured fit, and the cursor lands at the end after tab completion.
Toasts stack instead of stacking up — bottom-anchored with overlap, fanning out when you hover.
Fixed
Agents stopped prefixing `cd <project root>` to your commands. Shell commands run in the right place without the redundant prefix that broke quoting and chained commands.
A turn's answer is never swallowed. When the final response step was skipped, the actual answer could vanish; turns are also only called silent when they genuinely said nothing.
Deleted memories stay deleted. Deduplication could resurrect a memory you had soft-deleted. It no longer does, and recall deduplicates across scopes correctly.
File paths in memory work on Windows. File-reference paths are normalized, so file affinity scoring is not silently dead on Windows.
`list_dir` reads the filesystem live instead of answering from a stale view.
Tool child processes are reaped. Long-running project tools no longer leave orphaned process trees behind.
Modals keep their keyboard. The CLI stopped swallowing keys destined for modals that own keyboard input, and subagent docks stay scoped to the tab that spawned them.
Edits land where they should. A targeted edit now finds its anchor no matter how the surrounding code is indented.
Provider switching is cleaner. Stale provider-executed search blocks are stripped as matched call/result pairs and stay replayable, and a dead reasoning setting is no longer sent to MiniMax.
Desktop config writes resolve in order, so a write no longer completes before the config invalidation it depends on.
Desktop display fixes. One marionette on stage at a time and confined to the conversation box, the maze search dropdown draws above the HUD instead of behind it, and selected text in the composer stays visible.
Successful edit rows dropped the redundant "Edited x" line — the diff already says it.
Notes
This is a beta. Downloads for macOS, Linux and Windows are on the downloads page.
See exactly what your AI coding sessions cost — and what caching saved you
Empryo now answers the question most AI coding tools quietly avoid: where did the money go? /usage opens a live breakdown you can steer — spend and tokens per model, per day or per week, how long each step actually took, and how much prompt caching saved you versus paying full price for every token. This release also brings a real file tree with drag-to-chat, branch switching from the status bar, and a fix for the classic "works in my terminal, broken when I launch the app" bug.
New
`/usage`, now interactive. Instead of one flat total, you get a breakdown you can move through: cost and tokens per model, grouped by day, week or all time, with average step latency so you can see which model is actually slowing you down. Models that exist on several providers are labelled with the provider they ran on, so a cheap route and an expensive one never get averaged together. The same view is in the desktop app's usage drawer.
What caching saved you, in real numbers. Alongside your spend, Empryo now shows the counterfactual: what the same work would have cost with no prompt caching at all. It turns an invisible optimization into a number you can point at.
A file tree worth using. The sidebar tree gained a toolbar — sort, and toggle dotfiles and gitignored files in or out. Gitignored files now show up in @-mention pickers too (dimmed and marked, so you always know what you are pulling in), and you can drag a row straight from the tree onto the composer to insert it as a mention.
Switch branches from the status bar. Click the branch name in the desktop status bar and pick another branch — no terminal detour.
Your edits get syntax-checked as they land. After Empryo edits a YAML or JSON file, it re-parses it on the spot and tells you immediately if the result is broken, instead of letting you discover it at deploy time.
The goal bar names the reviewer. In closed-loop runs you can now see at a glance which model is reviewing the work, not just which one is writing it.
Improved
Reasoning controls follow the model you picked. Effort levels and thinking settings are now derived from what the active model genuinely supports, so non-reasoning models stop offering knobs that do nothing, and models with unusual ladders show their real options.
The context map behaves. The panel under your chat folds away when you want the room back, its detail card scrolls when the content is long, and fullscreen no longer leaves a stray backdrop behind.
Smaller edges, smoothed. Keyboard navigation in @-mention lists keeps the highlighted entry in view, the composer resizes correctly when the window rewraps or a font finishes loading, zoom shortcuts respect the current layout, and the tree toolbar stays on one row even at the narrowest pane width.
Fixed
Launching the app from the dock no longer breaks your environment. If Empryo worked when started from a terminal but misbehaved when launched as a desktop app — wrong language and encoding, missing tools, commands that could not find your setup — that gap is closed. A GUI launch now recovers your real shell environment and locale before anything else runs.
Relative links in chat are clickable again. Links pointing at files and paths in your own project were being rewritten as [blocked]. They render and work normally now.
A corrupted memory database can be salvaged instead of blocking you. When Empryo's cross-session memory store could not be opened — most often on Windows, where a lingering file handle kept the damaged file locked — it got stuck in a loop it could not recover from. It now releases the handle, sets the bad file aside and continues with a fresh store, and it no longer quarantines a database that was merely busy rather than broken.
The file watcher no longer crashes the app. On the runtime Empryo ships with, the fast native watcher could corrupt memory and take the whole process down under heavy file churn. It is now switched off on affected runtimes and falls back to a safe watcher — file search, glob and grep are unchanged and still native.
Agent runs end cleanly. A step that produced no tool calls could leave the loop spinning instead of finishing the turn. It now ends where it should.
Switching between providers mid-conversation is safe. Reasoning content produced by one provider is now cleaned up before it is sent to another, so moving a conversation across models no longer trips an error.
A crash on startup and a runaway process on exit — both fixed
A focused stability patch. Two ways Empryo could misbehave around the edges of a session — freezing moments after it started, or refusing to let go when its terminal went away — are gone. If you hit either, this is the update you want.
Fixed
Empryo no longer freezes right after startup. On some shells the terminal could lock up seconds into a session — the window would stop responding and, in a few setups, get pushed to the background in an unusable state. The culprit was a routine check Empryo runs at launch to learn your shell's PATH; it now runs fully isolated so it can never reach back and stall the session that started it.
A dead terminal no longer leaves Empryo running. If the terminal Empryo was attached to closed or crashed, the process could keep spinning in the background at full tilt, burning a CPU core until you hunted it down and killed it. It now notices the terminal is gone and exits cleanly on its own.
The map settles down. A creature in the map beneath your chat could jitter mid-move, and stray connector lines occasionally flickered across it. Both are smoothed out.
Every tab is its own workspace now — its own model, its own reasoning effort, its own agents
Open a tab, point it at Opus on high effort for the refactor. Open another, drop it on a cheap fast model to answer a question. They don't fight, they don't share settings, and both survive a restart exactly as you left them. This release makes the tab the unit of configuration in Empryo — model, effort, routing, agents, even the map — and rebuilds the router into a real settings surface for pointing every lane at the model it deserves. On top of that: a subagent overhaul that turns delegation into an actual conversation.
Every tab, configured its own way
Reasoning effort is per tab. The effort dial used to be one setting shared everywhere. Now it belongs to the tab, and it remembers the right levels for each model you switch to instead of carrying over a setting that doesn't apply. It's saved with the tab and restored when you reopen it. /effort in the terminal, a slider in the desktop composer.
Model choice is per tab, and it sticks. Pick a model anywhere — topbar, router, or a per-tab override — and it survives a reload and a session restore. Reopen a saved session and it really is running on the model it says it is.
Refresh your model list from any picker, not just the Keys screen.
Your tabs stop bleeding into each other. Scroll position is remembered per tab. The context pane's Edited list only shows the tab you're looking at. Map activity, fog and compaction are per tab. Two conversations, two worlds.
The router is a settings page now
A nav rail instead of an endless scroll — Routing, Custom agents, Behaviors, Failover — each with a live status line, and your scope and save path pinned to the bottom so you always know what you're editing.
Lanes are compact cards, grouped by job: main agent, subagents, quality passes, housekeeping. Each shows honest per-lane spend — and hides the number entirely when a model has no published price, rather than inventing one.
Custom agents get their own pane, with a model picker per agent. Choosing one rewrites just that agent's model: line and leaves everything else exactly as you wrote it.
Concurrency goes to 16, matching what the engine will actually run.
Subagents, overhauled
Delegation used to be a one-way door: send the work off, wait, read the report. Now it's a conversation.
Agents report in while they work. Background agents post progress, questions and blockers upstream. Progress just appears; a question or blocker *wakes you* — because those are the ones where waiting silently wastes everybody's time.
You answer without breaking the run. Reply to a working agent and it picks your message up at its next step, keeping everything it had already worked out. Or stop it. Or take the job over yourself. The choice shows up at the moment you need to make it — on the desktop too, pinned to the tab you sent it from.
Agents can create agents. An agent can define a new custom agent and hand it work straight away, no restart needed. And if you've defined two agents with the same name in different places, Empryo tells you which one it's using instead of silently picking one.
Your own custom agents run in the background. Previously only Empryo's built-in agents could be sent off to work in the background. Now any agent you've defined can, while you carry on.
You can see who's talking. Agent badges run through the terminal UI, the desktop and headless output, so parallel work stops reading as one anonymous voice.
The transcript stopped narrating its own paperwork. Agent tools read as plain labels, and the status-polling tool went quiet — it was printing a line every time it checked on something, which is not news.
New here? Custom agents are yours to define — drop one in .empryo/agents (or .claude/agents, .opencode/agent, .gemini/agents) and set its model, tools and effort, with the body as its system prompt. Browse them with /agents, or just describe a task and let dispatch pick the right one.
The maze became an aquarium
The map under your chat was already alive. Now it has a cast.
Your subagents are sharks — each stationed at the cell its real agent is working in, tool-tinted glowing eyes, dive-travel between files. Background agents are ghost sharks. Click any creature for a card: who it is, its task, its current tool.
Your code grows from real diffs. Cells swell and shrink against the actual line-set change, edits leave deposits, touched files glow hot and cool over about four minutes.
Fog of war. Light pools around everything alive, so exploring a codebase is something you can literally watch happen.
Web work flies to a spinning globe instead of pretending to be file activity.
Achievements grow body parts. Spore-style, with an unlock burst. We're not sorry.
Language servers install themselves
Empryo now spots which language servers your project needs and installs them for you on startup, telling you when it does. It also checks they actually work rather than just assuming they're there, and empryo lsp gives you control of them from the command line for the first time. On Windows, errors and warnings simply weren't showing up for TypeScript projects — they do now.
Desktop reliability
Big streamed answers render. A long reply could stop painting partway through. It doesn't.
Closing the window closes the app. Launched from a terminal, Empryo used to linger after its last window. It quits — and handles Ctrl-C properly.
Cmd/Ctrl+S stashes your draft, matching Alt+S in the terminal, for when a thought needs to wait.
The browser behaves: overlays hide when they should, pages can be forced light or dark, refused local loads retry, local certificates stop being a wall.
The terminal grew hands — copy/paste via context menu, Ctrl+C or Insert; real exit codes; correct reflow on Windows; and reopening a pane re-adopts its terminal instead of losing it.
Windows
A whole class of Windows-only bugs, swept. Empryo used to trip over Windows file paths — backslashes, drive letters, and capitalisation that Windows treats as the same but Empryo didn't. Privacy rules that silently failed to match, refactors that wrote broken imports, files Empryo thought were two different files. All fixed.
Commands with quotes in them work. Running a command containing quotation marks no longer mangles it.
Empryo lets go of your files on exit. Closing a project could leave it holding the workspace database, so the next launch complained the file was in use.
The installer wears its own icon instead of a generic one.
Also in this release
Web search got more honest. When a search is blocked, Empryo says it was blocked instead of quietly reporting an empty web. On providers that can search for themselves, it now uses that directly — fewer round trips, better results.
Lighter on your machine. Faster codebase scans, and language servers you've stopped using shut themselves down instead of sitting on memory all session.
Empryo starts on Windows again — our loading spinner had been shouting a 32,000-character command at it
If Empryo flat-out would not start on Windows, that was us, and it was a silly one. The spinner on the splash screen handed its artwork to a helper process the laziest way imaginable: as one giant command-line argument, about 32,306 characters of it. Windows hangs up at 32,767. Install into a folder with a slightly longer path and you crossed the line — Empryo died before printing a single word, and reinstalling could never fix it. The artwork travels down a pipe now. Argv carries code and nothing else.
Windows
A spinner that fails can no longer take the app with it. It used to throw from the top of the file. Empryo is not, in fact, dependent on a spinner.
Boot crashes read like sentences. The crash handler was registered about 800 lines too late, so anything that broke during startup — hydration, native probes, the console switch, the splash — printed a wall of minified Bun internals and no report. It's the first statement in the file now: readable message, crash-report file. (This is exactly how the bug above hid for so long.)
`empryo doctor` stops dying mid-report. It was loading a graphics addon that segfaults on Windows. The terminal UI has skipped it there for ages; doctor now honours the same rule and says "skipped".
`Failed to create TextBuffer` finally names its cause — UI tree too large, handles retained after unmount, or the allocator refusing — and warns at 70% of the limit, while you can still do something about it.
Panes you can actually arrange
Dock the browser, the map and the chat together. A wide screen fits all five panes, each resizable, and chat never trades away its floor.
Too narrow? Panes get demoted, not deleted. Columns shrink toward their minimums first, then side panes float instead of vanishing.
Resize with the keyboard. Arrows on a grip (Shift for bigger steps), Home/End for the ends, Enter to reset.
The widths in between are reachable. Every screen used to land on the same hardcoded 640px, because "no stored width yet" could never actually happen.
Pane headers wrap instead of shoving their own collapse button off the edge.
The window looks the way you set it
See-Through is see-through. The shell was painting an opaque layer *under* every pane, so the entire slider range did nothing. The same alpha was also stacked five times over — 0.58 five times composites to ~0.99, which is a wall. The frame is painted once now.
Windows translucency is back. Mica never shows what's behind the window; acrylic does. We went back to acrylic.
Opacity floors, re-measured against a window that can genuinely see through. They'd been shaved to nothing while chasing a bug that lived somewhere else entirely.
Chrome stays legible over a backdrop it can't trust — including a clear window, where the titlebar text was sitting directly on your wallpaper.
One "Around panes" control, with sliders that don't stick, and a frame that follows each pane's curve instead of ruling a straight band across it.
A restart is only asked for when one is genuinely needed. Blurred ⇄ Solid changes live; only crossing into or out of See-Through needs a new window.
A thinner titlebar with one pane on the right — Context, Memory, Errors, Tools and Diffs are tabs now, and the ⌘K button is gone, since ⌘K already exists.
Small stuff
The update dialog's forge idles while it waits, then extends into the download instead of restarting the scene.
"What's new in v3.5.2-beta" no longer appears above some older release's notes.
Change an appearance setting against a stale main process and it tells you, rather than storing it nowhere.
Quieter diff wash, evener memory rows.
If Windows calls this a virus
It isn't. The installer is unsigned — certificates are a recurring cost — and Defender's ML has taken to tagging fresh unsigned builds (Trojan:Win32/Wacatac.B!ml). That's a guess about a file nobody has downloaded yet, not a finding. Every artifact ships with an RSA-4096-signed SHA256 manifest on dl.empryo.com, and the installers check against it before anything runs.
The desktop terminal is now GPU-rendered, searchable, and no longer types junk into your shell
The terminal in the desktop app got the round of work it needed. It renders on the GPU, it can find text, it can hand a selection straight to the chat, and — most importantly — it stopped doing two things it should never have done: spitting escape-sequence garbage at your prompt when you opened a tab, and leaving processes alive after you closed it. Alongside that, the embedded browser no longer hangs on screen while a window closes, and the model picker can no longer hide the model you're actually running.
The terminal stops fighting you
No more junk at the prompt. When you opened a terminal tab, the replayed scrollback could contain escape sequences that ask the terminal a question. xterm dutifully answered them — into your shell's standard input, where the answers landed as garbage at the prompt. Those queries are stripped from the replay now, and the backlog is trimmed at a line boundary instead of halfway through an escape sequence.
Closing a terminal actually closes it. The whole process group is taken down on close — SIGTERM, then SIGKILL if needed, and taskkill on Windows — so a shell with background children doesn't leave them running.
Your shell gets a clean environment. On Linux, the AppImage runtime was leaking its own mount paths into your shell, so tools resolved against the app bundle instead of your system. That's scrubbed, and Empryo's own control variables (ELECTRON_RUN_AS_NODE, EMPRYO_*, VITE_*) no longer show up in your shell either.
New in the terminal
GPU rendering. The terminal draws through WebGL, with bounded recovery if the graphics context is lost and careful teardown so contexts can't leak as you open and close tabs.
Emoji and CJK line up. Character widths follow Unicode 11, so powerline prompts stop drifting out of alignment.
Find with Cmd/Ctrl+F. A find bar over the terminal buffer.
Selection to chat with Cmd/Ctrl+Shift+A. Highlight output, send it straight to the composer.
Tabs tell you what's running. Each tab shows its current command with a busy dot while it's working.
The black band at the bottom is gone. xterm hardcodes a black viewport, and fitting the terminal to the pane left an unpainted remainder below the last row.
Browser
Closing a window no longer leaves the browser floating on top. Native views are detached before the renderer tears down, so the embedded browser goes away with everything else.
Reopening a window brings the browser back. After closing and reopening a window on macOS, the browser could come back invisible.
Links from the terminal go somewhere sensible. Localhost and workspace files open in the in-app browser; public links go to your system browser when the embedded one is scoped to local-only. file: navigation is limited to real files inside the workspace you have open.
Models
The picker can't hide the model you're running. A custom provider's declared models stay in the list even when its API key is missing, and if no provider claims your current model — a deleted provider, a renamed model, an unresolved listing — it's surfaced under "Running now" instead of vanishing from the picker.
Per-tab routing overrides survive a reload. The drawer said "Tab routing updated" and then quietly dropped it on restart. It persists now.
Empryo stops leaking processes and memory — the mystery freezes, the orphaned editors, and the sessions that wouldn't reopen are all fixed
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.
The genome now learns as you work, and the terminal UI is reborn — plus custom agents, first-class skills, and background subagents
This is the big one. All this time you've wanted your coding agent to actually understand your codebase — this is where it comes together. Empryo's genome — the graph that knows how your code fits together — stops being a static snapshot and becomes a system that gets better the more you use it. And the terminal UI is rebuilt from the ground up around a single living idea, so what you see finally matches how the work actually flows. On top of that: custom agents you define in markdown, skills as a first-class part of every prompt, background subagents that wake you when they're done, and a per-model effort dial.
The genome grows with you
Until now the genome read your code — the syntax tree, the symbol graph, who calls whom. That's still there, and it's sharper. But 3.5 adds something new: the genome now learns from how you actually work, and it keeps learning every session.
It mines your git history. Files that truly change together are surfaced with PMI scoring — so a real coupling stands out while a "changes with everything" hub file scores near zero. It's rename-aware (a git mv never orphans what it learned) and it skips the noise (release bumps, lockfile-only sweeps are process, not coupling). The mining window went from 300 commits to 2,500, so it stops missing the bulk of your history.
It learns from your sessions. Every session's actual tool walk is distilled into behavioral trails the static graph can't see: files that get read together, the file you always open *before* editing another, and the reads that turned out to be dead ends. Successful sessions reinforce their trails; at the end of each one a judge marks what actually paid off, and trails that prove out repeatedly graduate into confirmed knowledge.
It calibrates to your model. The hint economy is derived from each model's own follow-through — if a model keeps ignoring a class of hint, those hints tighten automatically; when it starts acting on them, the gates open back up. Files you actually open from a search result feed a click-through signal back into ranking, so your clicks become part of the ranking.
It heals itself. When a tool can resolve what you meant from the symbol index, it returns something useful instead of a bare failure — visibly, and logged as a bug report against its own schema so the rough edge gets filed.
The effect, measured on Empryo's own repo: co-change coverage went from 86 to 3,239 file pairs, the edit-advisory pool from 14 to 444, and a mis-ranked side-app formatter that used to rank #1 across the whole repo dropped to #103. The whole subsystem shipped behind a 13-finding adversarial review and a 3,831-test suite that passes clean.
Genome stays off for workspaces where you've disabled it, and every engine upgrade forces a clean re-index so stale data can never strand you.
A new terminal
The terminal UI is reforged around one metaphor — a living strand of work — and it's now what you get on a fresh boot.
Your prompts live above the work, forever. A prompt deck pins every prompt you've sent (last few, then folded) at the top; the transcript below only ever grows. The old "two views showing the same thing" duplication is now structurally impossible — the live turn renders inside its own transcript group, so there's exactly one copy of everything.
Subagents are a living constellation. Dispatch a few agents and they render as breathing "critter" faces in a SwarmDock, each tagged with its routed model, connected by cache-talk arrows — click a face to open its inspector. Background agents collapse into a single dock line you can expand.
Your history is a star-map. A checkpoint crown turns your session into a clickable constellation (latest, edits, reads, what you're viewing) with a routing chip — persistent from your very first checkpoint. Click a star to view or rewind.
It's frameless and soft. No rounded box, no scrollbar — the strand *is* the landmark. Tasks, plans, and ask-surfaces get a soft-depth "well" skin instead of four-sided borders, there's an inline effort slider in the composer, honest single-source thinking indicators, and a jump-to-bottom pill.
The splash paints your real logo. On kitty, Ghostty, and WezTerm the boot splash reveals the actual Empryo artwork over the graphics protocol with a rune-decode animation, degrading gracefully to a mosaic persona and then half-blocks on plainer terminals. There are boot, restart, and shutdown tiers.
A render error can't blank your terminal anymore. A three-tier crash boundary (transcript / modal / root) catches React render throws, and every surface writes to a durable errors.jsonl you can actually read.
Prefer the classic look? /presentation (and the /v2 alias) toggles between organic, normal, and zen.
Custom agents, defined in markdown
Drop a markdown file in .empryo/agents (or .claude, .gemini, .opencode, .agents) and you've defined an agent: frontmatter sets its name, model, tools, skills, and effort; the body becomes its system prompt. Dispatch a task to it by name, browse them in the TUI /agents panel or the desktop Agents drawer, or run one headless with --agent <name>. Project definitions win name collisions with global ones, and the tool allow/deny lists act as a real execute-time guard.
Background subagents that wake you
A solo `explore` tool — one read-only delegate for "go find out," no dispatch ceremony, foreground or background, with its own display chrome and a router slot.
Background report-back, delivered exactly once. Send an agent to the background and its report wakes the tab that spawned it — atomically, journaled, never double-injected — across the TUI, headless, chat, and desktop. A compact marker shows in the transcript while the full report rides the model's context.
`web_search` can run detached and wake you when the research is in.
Skills, first-class
Type `$` in the composer — on every surface — to pick skills: a caret-aware, multi-select float with your installed skills first and live registry results below. Space installs, Enter collapses your picks into a [skills: …] chip that expands into a clean "use these skills" block on submit. (This release also makes that picker's list scroll with the cursor, just like ⌃R history.)
Empryo remembers your skills per session — active skills restore when you reopen a session, pinned skills auto-load, and installs from another terminal announce themselves mid-session without disturbing the cached prompt.
Effort, per model
An inline effort slider (· ∙ ● ◉ ◈ ✶) on both the TUI and desktop composers lands on each model family's native reasoning knob — Claude, OpenAI, Google, xAI, DeepSeek — and applies to your next turn. There's /effort <level> and a headless --effort too, and it's gated to models that actually support it so the API never rejects your turn.
Desktop
A project-wide Search panel off the warm file index — literal, regex, or fuzzy, with smart-case, glob scope, and open-at-line in the editor (⌘⇧F).
A faster file watcher (the resident engine replaces the native @parcel/watcher), git-badged file/dir results in the @-mention picker, and a cumulative cache-hit-rate meter in the usage drawer.
Cost & caching
"Is caching actually working?" now has an answer: a 30-day cumulative prompt-cache hit-rate bar in /usage and the desktop drawer, plus cache-miss surfacing in headless via --events.
Long-lived (1-hour) cache writes are now costed at their real 2× rate, and main-turn spend finally reaches the usage ledger on every surface (it had been landing for roughly 1 event in 145).
Fixed
Invalid tool pairings and oversized images can't be sent. Message sanitization is now total (strict 1:1, in-order tool-call/result pairing), which kills the replayed-tool-id error, and images clamp their pixel dimensions — a tall 1200×12000 screenshot no longer 400s.
Genome ranking poisoning — a generic-word floor stops short, plain-word exports from minting false provenance, and upgraded databases migrate the stale resolutions out.
Inline kitty images stopped blanking, terminal identity is read from TERM/TERM_PROGRAM only (a parent terminal's leaked env no longer makes Terminal.app paint tofu), and the embedded desktop browser's blank-until-reopen bugs are fixed.
A cluster of dispatch/deferred-tool activation bugs, a proxy bounce that could signal sibling sessions, Windows hearth dispatch through compiled binaries, and the boot-flash on organic startup — all fixed.
Under the hood
The image pipeline moved to Bun.Image — no more shelling out to sips/ffmpeg/magick, so it works on Windows and bare Linux and survives bun --compile.
Mature genome databases shrink about 47% (100 MB → 53 MB in under a second on the live DB), and the file engine is upgraded to 0.10.1.
Live end-to-end coverage grew: background-wake tested on the real TUI (pyte) and desktop (Playwright), tool-pairing exercised on all three surfaces.
Every build is still executed before it ships — empryo doctor loads the native runtime and parses real code inside a Linux container, under Wine for Windows, and under Rosetta for Intel macOS.
Your DevPass plan status is now live in Empryo — see your premium allowance and credits as you work
If you're on a DevPass plan through the LLM Gateway, Empryo can now show you exactly where you stand: how much of your weekly premium allowance is left, how many monthly credits remain, and a live meter that tells you the moment you've hit the weekly premium cap. No more guessing or checking a separate dashboard — it's right there in the app while you work.
New
Live DevPass plan status, everywhere. The Gateway now exposes a key-authed plan endpoint, so Empryo surfaces your subscription state directly: a weekly premium-allowance meter and a monthly credit meter in the Usage drawer (desktop) and under /usage (TUI), plus an ambient meter chip in the statusbar/footer showing percent used. It only appears when you're actually on a Gateway model with a DevPass connection, and it degrades silently to the local usage ledger whenever you're offline or unauthenticated.
A clearer "no plan" state. When a Gateway key has no active DevPass plan, you now get a plain "No active DevPass plan" note with a subscribe link, instead of a bare budget selector that told you nothing.
Fixed
Premium cap no longer stalls your conversation. When your weekly premium allowance runs out mid-conversation, the model-fallback chain now routes to a standard model automatically, and the meter flips to a paused "standard only · resets in Xd" state right away — so work keeps flowing and you can see exactly why.
Under the hood
The terminal chat's diff renderer now accepts the desktop-only "off" diff style without complaint, keeping the diff-style contract consistent across surfaces.
Terminal chat renders formatted text again, the desktop zooms end to end, and model prices are accurate to the day
A focused follow-up to the last beta. The biggest fix: in compiled builds the terminal chat could show raw markdown — literal # headings and backticks — instead of formatted text, because the highlighter's grammar and worker weren't being bundled into the binary. They are now, so chat reads the way it should. On the desktop you can zoom the entire interface with a keystroke, model pricing is refreshed and pulled live so cost estimates stay honest, and the release itself is safer to ship: every Windows build is now executed and self-checked before it goes out.
Fixed
Chat renders formatted text again. In compiled builds the terminal chat could display raw markdown instead of rendered headings, code blocks, and emphasis, because the syntax grammar and the parser worker that drive highlighting weren't embedded in the binary. They're bundled now, so formatting shows up correctly in every packaged build.
Desktop menus read as solid. A lone floating menu or popup could look semi-transparent and hard to read. Their opacity is now unified with the rest of the desktop, so they render solid.
New
Zoom the whole desktop interface. Press Cmd/Ctrl with +, -, or 0 to scale the entire app — layout and all, crisply re-rendered rather than just bumping the font size. Your zoom level is remembered across launches.
`empryo doctor` now checks the whole stack. The self-check goes beyond the core runtime: it drives the chat-markdown highlight pipeline, spawns the embedded genome and io workers and round-trips them, and binds the fff and ghostty native engines. If a subsystem is broken, doctor tells you before it bites you mid-session.
Under the hood
Model prices are accurate to the day. Tiered model pricing now flows through the live models.dev catalog, with rates refreshed as of 2026-07-18, so the cost figures Empryo shows track what providers actually charge.
Windows builds are smoke-tested before they ship. The Windows executable is now run and self-checked at build time, closing the gap where a Windows-only breakage could ship unnoticed from a non-Windows release machine.
Every macOS and Linux build is still executed before it ships — empryo doctor must load the native runtime and parse real code inside a Linux container, and under Rosetta for Intel macOS.
The live agent map is rebuilt, the desktop runs smoother and steadier, and web search gets its own drawer
This is a big one. The live "maze" map that shows your agents at work has been rebuilt: subagents now have real identity, stay tethered to the agent that spawned them, and move legibly between work stations, while the camera glides, the water calms, and the heads-up display collapses into a few clean islands with a zoomable minimap. The desktop app also gets a broad reliability-and-speed pass — the renderer's hot path is faster, reconnects and checkpoints survive a reload, and a whole class of lag where the display trailed behind what the agent was actually doing is gone. Web search gains a dedicated drawer and a new Tavily backend, long headless runs compact themselves so they don't overflow, and a crash that could hit custom providers mid-run is fixed.
The live agent map, rebuilt
Subagents are real characters now. Background agents get distinct identities and their own live work stations, stay tethered to the agent that dispatched them with animated links, and roam legibly instead of teleporting. Their role tags now survive a graph rebuild.
A calmer, smoother stage. The camera glides instead of snapping, water and motion are gentler, rebuilds are frame-coalesced, and both the docked and fullscreen maps now run at a full 60fps.
A decluttered HUD. The heads-up display collapses into a few clean islands, and a new minimap lets you zoom and jump around large graphs.
Frame rate is yours to set. Choose a frame rate per surface — the docked and fullscreen maps can run at different rates to match your machine.
New
A dedicated Web Search drawer. Web search moves into its own desktop drawer that shows which provider is handling a query and whether each provider's key is set.
Tavily joins web search, with automatic fallback. A new Tavily backend leads a priority chain that falls through to the other providers, so a search still resolves when your first choice is down or unconfigured.
Long headless runs compact themselves. Extended headless chat sessions now auto-compact and carry full tool memory across turns, so they no longer overflow the context window or lose earlier tool results.
Fixed
No more crash on custom providers mid-run. A tracker in the AI SDK could crash when a model returned tool calls with sparse or gapped indices — common with some custom OpenAI-compatible providers. Empryo now patches that path so those turns complete cleanly.
Headless compaction keeps your tool turns. Compaction in headless mode now preserves tool turns and computes the compaction boundary correctly, so nothing is silently dropped mid-conversation.
Steadier maze teardown. Animations are cancelled cleanly when the map closes, and the drone separators are legible again.
Desktop
A faster, steadier renderer. A renderer hot-path sweep, typed bridge event fan-out, and an appearance ready-handshake make the app quicker and more reliable, and reconnects recover cleanly.
The display keeps up with the agent. A class of lag where the transcript trailed behind what the agent was actually doing — with buffered deltas occasionally dropped — is fixed, so what you see matches what's happening.
Checkpoints survive a reload. Checkpoint git tags now persist across a session reload and re-join correctly even when history shifts, so undo and redo still work after you reopen a session. Checkpoint slug guarding, a draft-restore race, and appearance retries are hardened too.
Live tool rows in Details. The Details view now windows live tool rows for parity with the terminal UI, so long tool streams stay smooth.
A better genome download and update dialog. Downloading the genome engine shows a DNA-style animation and can be cancelled before closing, and the update dialog is bigger, resizable, and actually shows the release notes.
Webapp
Shareable release pages. Each release now has its own shareable page with a flip-card changelog, plus a branded release-card generator for Discord.
Under the hood
Leaner TUI and headless hot paths. The verbose live rail is windowed, reminder scans are incremental, and a round of hot-path and reliability fixes from an audit landed across the CLI.
Storage keeps only the newest releases. After each upload the release process prunes old versions, keeping the three most recent.
Toolchain and dependency refresh. Electron 43.1.1 with Vite 7 and electron-vite 5, the AI SDK at 7.0.31 with the latest providers, and OpenTUI 0.4.5.
Every macOS and Linux build is still executed before it ships — empryo doctor must load the native runtime and parse real code inside a Linux container, and under Rosetta for Intel macOS.
Custom OpenAI-compatible providers now find their models automatically
If you point Empryo at your own OpenAI-compatible endpoint, it now discovers the models on its own. Some servers only answer at /v1/models (vLLM, openference) and others expect a bare /models (LiteLLM, llama.cpp) — Empryo now tries both, so either kind lights up without you typing model names by hand. Custom-provider edits also take effect immediately and the endpoint is checked the moment you save, so you know right away whether it worked.
New
Custom providers auto-discover their models. Model discovery asks {baseURL}/models first and, if that comes up empty, retries with /v1 stripped from the path. Strict servers that only serve /v1/models and permissive ones that serve /models both populate their model list with no manual entry.
Save now probes the endpoint. When you add or edit a custom provider it's contacted on save and reports back the number of models it found — or a plain connection error if it can't be reached — instead of failing silently later.
Nicer custom-provider setup. Pick an icon for a custom provider, see clear "no models" empty states when a server returns nothing, and providers are now visually separated in the model pickers with a more legible remove control.
Fixed
Custom-provider edits apply live. Changing a custom provider's URL, key, or models now takes effect on the current session — no restart needed.
No more crash on the send after a stop or failover. When a turn was stopped or a model failover left a tool-call without its matching result, the next send could crash. Empryo now heals that trailing orphan tool-call while cleaning up history, so resuming, continuing, and high-availability model-fallback retries pick up cleanly.
Huge reasoning traces no longer freeze the TUI. Expanding a very large thinking trace used to lock up the terminal; its rendered size is now bounded. The desktop app gets the same huge-reasoning speedups plus grouped thinking phases.
Desktop
Long user messages collapse instead of dominating the transcript.
Softer user-message bubble on dark themes.
Clearer topbar wording — "More panels" and "Models & routing".
Webapp
A new sponsors section and a featured LLM Gateway card.
"AI coding agent" now appears in the hero for search.
A Lighthouse performance pass: inline critical CSS, self-hosted avatars, and a smaller webp logo.
Decorative icons are hidden from screen readers for cleaner accessibility.
Under the hood
Every macOS and Linux build is still executed before it ships — empryo doctor must load the native runtime and parse real code inside a Linux container, and under Rosetta for Intel macOS.
Desktop API keys you add are now the ones your requests actually use
A focused fix for anyone who brings their own API keys into the desktop app. A key you pasted was being saved under one name while the request path looked it up under another, so a freshly added key was quietly ignored — your requests kept using the old one and came back unauthorized — and deleting a key could leave a second, hidden copy behind that made it seem to come back. Keys now save under a single canonical name, deletes remove every copy, and installs that were already in this state heal themselves the first time the key is read, with nothing to re-enter.
Fixed
Desktop keys are saved, read, and deleted under one name. API keys added in the desktop app were stored under a different spelling than the one requests read, so a new key was ignored — you'd get stale-key 401s — and deleting a key could leave a hidden copy that made it reappear. The desktop app now stores and removes keys under the same canonical name every other surface already uses: new keys take effect immediately, deletes purge every copy, and there are no leftover spellings hiding in your keychain.
Existing broken keys heal on their own. If a key was already saved the old way, the secrets layer recognizes the old spelling, uses it, and collapses it into the canonical name the first time it's read. Affected installs recover on next use — you don't have to re-paste anything.
Under the hood
Every macOS and Linux build is still executed before it ships — empryo doctor must load the native runtime and parse real code inside a Linux container, and under Rosetta for Intel macOS.
Model routing you can see and price, and models that fail over on their own
This release rebuilds how you pick and pay for models. The desktop app's routing drawer becomes a Models & routing dialog: three presets — Best, Balanced, Frugal — that resolve against the keys you actually have and are priced live from the models.dev catalog, next to a map of where every lane's tokens go and what each one cost you over the last month. Underneath, every surface learns to fail over: hand a model a fallback chain and Empryo rides it down on its own when a provider falters, resuming mid-stream without dropping what already streamed. The desktop app also starts notifying you properly and wears real provider logos, and the website it deploys alongside is largely new.
New
Models & routing, redesigned. (desktop) The routing drawer is now a Models & routing dialog built around a single dial — Best, Balanced, or Frugal. The presets aren't hardcoded model names; they're relationships to your chat model, resolved live against the keys you've configured and priced from the models.dev catalog, so they work for any provider — including LLM Gateway's full catalog. A token flow map shows where each lane's tokens go — chat, the subagents it dispatches, on-demand web research, after-edit cleanup and review, the goal-loop judge, and background work — with price bands and 30-day spend per lane. Routing, Behaviors and Failover each get their own tab.
Automatic model failover, on every surface. Give a model a fallback chain and Empryo fails over on its own: it orders the candidates by health, resumes mid-stream without losing streamed output or completed tool calls, and sends permanent provider errors (401, 400, 404) straight down the chain instead of retrying a lost cause. A user abort always wins. Configure no chains and nothing about your setup changes.
Notifications that reach you. (desktop) Delivery is now platform-correct, background turns can chime when they finish, and a short what's-new recap greets you after an update.
Provider brand marks throughout. (desktop) Real provider logos now appear in the topbar model trigger, every picker, the wizard steps, and the routing and failover chips — lazy-loaded, so boot stays light. Alongside them: dialogs and drawers are lighter glass, selection rings are crisp insets, pickers are roomier, and list surfaces take type-to-search.
Smaller conveniences./cost is now an alias for /usage. The stash janitor prunes anything older than 30 days and caps the store at 200 rows. And a debug bundle plus a hang sampler make a stuck run far easier to report.
Fixed
Desktop polish. The restore toast and the message composer each got a round of fixes.
Under the hood
empryo.com ships with this release. The deploy brings a new Spore landing page, the benchmarks program with console-verified round pages and two accompanying blog posts, site-wide ⌘K search, live GitHub star counts, a providers page that leads with LLM Gateway, and raw-markdown mirrors of every docs and blog page plus an llms-full.txt so agents can read the site directly. It also fixes a hydration error on the documentation pages that has been live in production.
Every macOS and Linux build is still executed before it ships — empryo doctor must load the native runtime and parse real code inside a Linux container, and under Rosetta for Intel macOS.
Your session history stops going missing, and the desktop app catches up to the terminal
Session persistence used to be spread across a handful of files that could fall out of sync — a crash, a fork, or a save taken mid-turn could quietly drop part of your history. This release moves every surface — the terminal, the desktop app, headless runs and the background daemon — onto a single append-only session log, so what you see is what was saved. The desktop app also grows into the terminal's equal: a live Concise view, the same narration fold, and a send gate that waits for the code graph. And prompts get cheaper — a set of cache fixes stops silently throwing away the reusable prefix.
New
One append-only session log, across every surface. Sessions now persist as a single append-only event log that the terminal, desktop app, headless runs and the background daemon all write to and restore from — folding that log is the *only* restore path. The old design spread state across several files that could disagree, so a crash or a save taken mid-turn could lose part of a conversation. Existing saves are migrated on first load.
A live Concise view in the desktop app. The desktop chat gains a ground-up Concise mode with a forge status header and ghost narration, plus a two-way narration fold that matches the terminal exactly. One "Concise | Details" control switches between the running summary and the full transcript.
The desktop app waits for the code graph before it sends. A message typed while the genome is still indexing is now parked until the graph is ready, then sent — the same send gate the terminal already had, so an early send no longer misses codebase context.
`/export api` captures the real request and response. Exporting now records the actual bytes sent to and received from the provider, not a reconstruction — the thing you want when you're debugging a provider or filing a report.
Faster search over large trees. grep's count mode is served straight from the FFF index instead of re-reading files, and symbol outlines are memoised on content. Pasted images can now be forwarded to /goal, running tool icons animate, and the desktop titlebar keeps its panel toggles visible at all times.
Fixed
Prompts stop throwing away their cache. A prefix-invalidating bug meant the reusable part of each request was being rewritten every turn, so the provider's prompt cache kept missing and you paid full price for tokens that should have been cached. The prefix is now stable, the child render cache is gated correctly, and the "cache miss" warning only fires when a miss actually cost you tokens — not on the harmless ones.
Restored sessions match what you saw. On load, the restored UI is now guaranteed to be a superset of the model transcript, and gaps left by a save taken mid-turn are repaired — so resuming can't crash the next request or show less than was there.
The background daemon stops wiping session metadata. A hearth save path could flush metadata in a way that erased it; it now flows through the session log like everything else.
The plan tool stops hijacking the turn. An approved plan no longer ends the turn before it runs, a second plan call can't start while one is executing, and the mode banner is actually injected — so plan and architect runs behave.
Streaming markdown stops flickering. Both the terminal and the desktop chat showed raw markdown for a frame before formatting it as text streamed in; that flash is gone.
`empryo doctor` reads correctly on Windows. Its output no longer staircases down the screen.
grep and glob agree whether the index is on or off. Path-pattern globs that returned nothing with FFF disabled, and corpus differences between the two modes, are fixed.
Desktop polish. Follow-ups from the widget migration: low-contrast segmented controls and inputs, wizard cards painting outside their box, rows overflowing under the overlay scrollbar, and a workspace picker that went invisible under "reduce motion".
Linux clipboard images are validated. Image reads now check the PNG signature before trusting the bytes.
Under the hood
The desktop app's hand-rolled widgets were replaced with a shared shadcn primitive set — buttons, inputs, Kbd and the rest — so the UI is consistent and easier to extend.
The boot screen was unwedged and made diagnosable, with an optional live logs console behind --debug.
Tool verbs and categories now come from one source of truth, and TUI-only tools are scoped out of the desktop agent's belt.
The website's features page was rebuilt in the cosmos language, and the blog index gained a lead story with centered page headers.
Every macOS and Linux build is still executed before it ships — empryo doctor must load the native runtime and parse real code inside a Linux container, and under Rosetta for Intel macOS.
Four reported bugs, fixed — including two that failed silently
Every fix here came from a bug report, and three of them shared a habit: they failed quietly. Model fallback didn't fire, embeddings never reached your provider, and syntax colours ignored your theme — none of it announced itself. This release fixes all four, and makes the remaining failure paths say what went wrong.
Fixed
Model fallback now fires on a rate limit, however the provider words it. Failures were classified by reading the error *message*, and the HTTP status never made it into that text. So a textbook 429 whose body said something like *"Prepaid credit balance is exhausted"* — naming no status and no rate limit — was treated as permanent, and the turn died instead of swapping to your fallback model. The status now decides: 408, 429 and any 5xx always retry and fail over. Auth rejections still never burn the retry budget. The same rule now covers the terminal, the desktop app and subagents, which each had their own copy of the old one.
Memory embeddings actually use your provider now. Setting memory.embeddingModel did nothing: the model id was handed to the AI SDK as a plain string, and a bare string always resolves through the Vercel AI Gateway — so every embedding call went there, wanted a gateway key you don't have, failed, and fell back to the offline embedder without a word. Embeddings are now built from your own provider and your own key. Local embedders (Ollama, LM Studio) work too, with no key at all. If one still can't be wired, /memory → Settings tells you exactly why instead of just reading offline.
Reasoning models work on strict backends. We sent reasoning_effort and reasoning: { effort } in the same request, on the theory that an API ignores keys it doesn't recognise. Strict ones don't — they reject the whole request ("pass either, not both"), making those providers unusable. Empryo now sends the single flat OpenAI field. Custom providers that genuinely need the nested shape can ask for it with reasoning.effortStyle.
`/theme` finally reaches your code. Syntax highlighting in code blocks, diffs and tool results used a fixed dark palette that was built once and never rebuilt, so changing themes did nothing to it — and on a light theme, comments and ordinary text were close to invisible. Colours are now drawn from the active theme and follow it when you switch.
Grok
`/grok login`, `status`, `logout` and `switch` exist now. The commands were missing entirely, even though the model picker told you to run /grok login — and there was no way to sign out of Grok on any surface.
The desktop app can find the Grok CLI. It installs to ~/.grok/bin, which only reaches your PATH through your shell profile — so an app launched from the Dock reported "grok CLI not found" and greyed out sign-in even when it was installed.
Under the hood
The reported problems came with source-level diagnoses. Thanks to the people who wrote them up that carefully.
Stop really stops, diffs stop lying, and the desktop app grows up
Three fixes in this release reach every surface — the terminal, headless runs and the desktop app all share the same tool belt, and all three had a way of quietly doing the wrong thing. Stop could leave a runaway process alive, a diff could report "no changes" when there were changes, and resuming a session could crash the next turn. On top of that, the desktop app gets its largest upgrade yet.
Fixed
Stop now kills the whole process tree. Shell commands were started without their own process group, so stopping a turn only killed the shell wrapper — anything it had spawned kept running. A hung grandchild could survive indefinitely and Stop appeared to do nothing. Commands now run detached and are reaped as a group (Windows kills the tree via taskkill /T).
`git diff` no longer hides real changes. A dedup cache suppressed any diff identical to the previous one, so asking twice reported "No changes since last diff" even when the working tree was clearly dirty. The cache is gone — a diff now always shows what's actually there.
Resuming a session no longer crashes the next turn. If a session was saved while a tool call was still in flight — or you stopped mid-turn — the restored history contained a tool call with no result, and the next request failed outright. Those gaps are now repaired on load.
New
Kill one tool without ending the turn. A single running tool can be stopped by itself now; the agent keeps going with everything else.
A real desktop app. The chat is virtualized and stays anchored while it streams, with syntax-highlighted markdown and a shared diff renderer used by both the transcript and the inspector. There's a live file tree that follows changes on disk, tabs that show cost and edits at a glance, a model picker that opens on first launch if no model is set, subagent detail views, and a Stop button that is a genuine hard cancel — the turn, its subagents and any background agents, all at once.
Under the hood
Goal-loop runs report the phase they're actually in (no more bars stuck on "planning"), and the reviewer's tokens and cost are folded into the tab total.
Every macOS and Linux build is still executed before it ships — empryo doctor must load the native runtime and parse real code inside a Linux container and, for Intel macOS, under Rosetta.
The terminal app stops breaking when you also install the desktop app
If you used the TUI and then installed the desktop app, the TUI could stop launching entirely — dying with opentui is not supported on the current platform, even though nothing about your platform had changed. This release fixes that, adds a one-command way to check your install, and makes every Linux and macOS build prove it actually runs before it ships.
Fixed
The TUI no longer breaks after you use the desktop app. Both apps share ~/.empryo, and the desktop's startup refresh was deleting native libraries it doesn't ship but the TUI depends on. The desktop is now fully self-contained — it reads its runtime from inside its own app bundle and never writes to the shared directory. Each surface now owns only the files it installs.
Installs repair themselves. The installer keeps a pristine copy of the native runtime, so a TUI whose libraries were already wiped restores them on the next launch instead of staying broken. This also protects you if you're still running an older desktop build.
A missing runtime finally says so. Instead of the misleading "not supported on the current platform", you get the exact file that's missing and how to fix it — and the crash report keeps the full message rather than a bare Error.
New
`empryo doctor` — checks that the native runtime loads and that tree-sitter parses, then prints OK or the precise failure. Run it any time an install misbehaves; it's also what our release now runs against every build.
Under the hood
Every macOS and Linux build is now executed before release — Linux inside a container, Intel macOS under Rosetta — and must load its native library and parse real code, not merely print a version number. A stale or mismatched native library can no longer reach a download link.
Live code-intelligence on the desktop, sharper genome, and the site opens to everyone
The desktop app now surfaces code-intelligence the way the TUI does, the genome understands more languages, and empryo.com is out of coming-soon — anyone can download.
Desktop
Code-intelligence surfaces live. A late-ready genome rebuilds one agent mid-session instead of degrading the whole session; toggling genome, instructions, or skills rebuilds running lanes; and project-scoped cache / token-budget settings now apply on every host.
`/genome` and `/context` are in the command palette.
Genome
Wider language coverage — TSX/JSX, PHP, and C++ headers/includes parse cleanly, with sharper TSX signatures and known gaps closed.
Site
empryo.com is public. The coming-soon gate is gone — downloads for macOS, Windows, and Linux are open to everyone, and there's a new /benchmarks page with a console-verified head-to-head.
Anonymous, opt-out usage telemetry and configurable desktop terminals
3.4.2 adds a small anonymous usage beacon so we can see which platforms, surfaces, and models to prioritise — and gives the desktop terminal real shell profiles. The telemetry is privacy-first and easy to turn off.
New
Anonymous usage telemetry. On session start Empryo sends one tiny beacon — version, OS, surface (TUI / headless / hearth / desktop), install method, provider + public model name, agent mode, terminal, runtime, theme, and a random install id used only to count distinct installs. Never prompts, file paths, code, keys, IPs, or anything that could identify you. Turn it off any time: set "telemetry": false in your config, or DO_NOT_TRACK=1 / EMPRYO_TELEMETRY=0 in the environment. A one-time notice explains this on first run.
Desktop terminal shell profiles. The embedded terminal now supports VS Code-style shell profiles — pick your shell and args per platform instead of being stuck with the default login shell.
Fixed
The desktop terminal failed to spawn in packaged builds — the bundled app now resolves the shell correctly, so the terminal opens in the shipped DMG / installer as it does in dev.
A redesigned task router, live task visibility, and a first-boot freeze fixed
A quick follow-up to 3.4.0 with a reworked task router, a live view into what the agent's doing, and a first-boot freeze fixed at the root.
Desktop
Task router redesign. Grouped lanes, icons, effective-model hints, and segmented concurrency controls; targets a single tab's session override when more than one tab is open; changing the topbar model now keeps the router's default slot in sync, and the model dropdown scrolls correctly inside the drawer.
See what the agent's doing, live. A tasks panel above the composer streams the agent's task list as it updates; the goal reviewer's report text now reaches the desktop instead of being dropped; GoalBar gets a toggle for the reviewer's live steps and past verdicts.
Maze choreography. Agent hops read as a fast swim instead of a teleport, dispatch and background workers hatch from and return to the organism instead of orbiting as static dots, the main agent perches while a swarm or the reviewer works nearby, and the camera eases in during review.
Fixed
A first-boot freeze. Migrating settings into place could hang the TUI on a fresh install when the filesystem couldn't clone files in place — regenerable data now skips cleanly instead of blocking, runtime files like a stale pid or lock never migrate, and a corrupt memory database is quarantined and recreated instead of bricking startup.
The boot sequence stopped teleporting. Brand, picker, and version text now hand off on one shared clock instead of racing separate entrance animations; the workspace no longer replays its entrance after indexing; the logo no longer flashes when the halo settles.
The genome popup showing 0 files after the map format overhaul — the parser now follows the directory-folded layout and groups files under their directory with a blast-radius heat bar.
A loading state instead of a blank flash on the maze, browser, setup wizard, and full genome view while they lazily mount.
Fast file search everywhere, session import from Claude Code & Codex, and a smarter long-session brain
A big minor: a resident file-search engine now powers the app end to end, your Claude Code and Codex history can move in with you, and the machinery behind long sessions — compaction, memory, the code graph — got a serious upgrade.
Fast file search (fff)
@-mentions are instant and get smarter as you use them. The picker (TUI and desktop) runs on a resident native index: results are frecency-ranked, every pick teaches it, and a bare @ now surfaces your hot files — the ones you've been touching — instead of an alphabetical wall.
The agent's search tools ride the same engine. Warm greps for "does X exist" answer in well under a millisecond, glob matches skip the process spawn, and everything still falls back to ripgrep/fd when it must — complex regexes, scoped paths, or the first seconds while the index warms.
It ships in every install. macOS, Linux, and Windows binaries (both architectures) carry the engine and set it up on first launch — nothing to install. On by default; /fff off (TUI) or Settings → General (desktop) turns it off per project or globally.
Bring your sessions with you
Import from Claude Code and Codex. The desktop wizard gained an Import step (also /import) that scans ~/.claude and ~/.codex, shows what it found, and migrates transcripts into Empryo's session store — each session imported individually with live status, so one odd file never sinks the batch.
Long sessions got cheaper and sharper
Compaction keeps more of what matters. Summaries are genome-aware (files the map already covers collapse to one line), subagent work survives into the parent's working state, aged edit results fold down to their status line, and truncated lists say so — the model knows when it's seeing a tail.
Compaction no longer torches your prompt cache. Prior summaries are carried byte-identically and the genome snapshot is preserved when the head survives, so compacting mid-session stops guaranteeing a full-price re-read.
Memory learns from being ignored. Recalled-but-never-used memories decay and eventually archive themselves; the ones you act on rise. Near-duplicate writes auto-supersede the older note instead of piling up.
The code map leans toward your question. Identifiers in your prompt pull their defining files up the map, LSP call-hierarchy now corrects the call graph for the hottest symbols, and standalone-LSP enrichment runs itself after every scan — no more "LSP off" until you poked settings.
Desktop
A proper hello and goodbye. A brand splash plays on launch (click to skip, respects reduced motion), the workspace selector is a redesigned two-column instrument with a manageable recent list, and quitting masks the teardown instead of flashing it.
Live turn timing where you're looking. The active tab shows a ticking timer from the instant you hit send; durations across the app read as humane 5m 12s instead of 312.0s.
Wizard polish. Model search matches across separators, the mode step breathes, and the first Keys panel opens fast — the keychain probes warm in the background during the splash.
Fixed
Nested `app/` directories were invisible. An unanchored .gitignore pattern hid every nested app/ dir from git and the code graph.
fff grep matches ripgrep line-for-line. Multiple hits on one line no longer produce duplicate rows.
Docked maze clears the right-side panels, and the titlebar divider sits where it should.
Correct version in About, a tidy workspace picker, and a clean quit
A quick follow-up to 3.3.6 with the small fixes that make the desktop app feel right — the version you're actually running, control over your recent list, and a quit that doesn't flash.
Fixed
The "can't click anything" freeze. Confirming a delete (file tree, storage) could leave the whole app unclickable — the modal's focus-return target had just been deleted, wedging an invisible pointer lock. A global safety net now releases it the moment no modal is actually open, across every dialog, drawer, and menu.
Sending while indexing works. Sending a message during the initial codebase scan errored with "Agent not initialized"; now your message shows immediately with a live status and sends itself the moment indexing finishes.
Composer hints stop colliding. Squeeze the center column and the keyboard hints now shed their labels, then hide entirely — instead of being clipped under the buttons.
Tab chips drop the redundant model label when a tab uses the workspace default model.
About shows the version you're actually running. It reported Electron's version in development builds; it now bakes in the real Empryo version at build time and shows it as a badge next to the title.
Manage your recent workspaces. The picker now has a per-item remove (hover a row) and a Clear-all — no more permanent list of folders you opened once.
No flash when you quit. On Linux especially, closing the window briefly flashed the app content before it vanished; the window now hides instantly, so the shutdown animation is the last thing you see.
New
The file tree keeps up. When the agent creates a file it now appears in the sidebar automatically, and the tree header gains three buttons — New file, New folder, and a manual Refresh — right beside the hide control.
Every language highlights, errors finally make sense, and Grok behaves
Syntax highlighting grew from a handful of languages to the entire grammar registry — lazily, so the app doesn't get heavier — and the Errors panel stopped shouting stack dumps.
New
332 languages highlight now. Chat code blocks and the editor share one highlighter: core languages preload, everything else (Astro, Svelte, Vue, Zig, Prisma, GraphQL, Haskell, Nix, …) loads the first time it appears — nothing to install, works offline. The editor gains real TextMate grammars for languages it never had, themed to match the app.
Languages panel./languages (or More tools → Languages): every language with live status — core, loaded this session, on-demand, or off — per-language toggles that persist, and a hand-off to the Language-servers panel for completions and diagnostics.
`/about`, with the version, lineage, support links — and the titlebar wordmark opens it on click.
Fixed
The random TUI freeze. The terminal renderer could lock up mid-session — opening a picker, moving a cursor, sometimes for no visible reason — with the process still alive underneath. The rendering engine is upgraded to a release that guards against exactly this (destroyed-renderable lifecycle loops, FFI pointer lifetimes, render-tree corruption). If you ever see a freeze again, please report it — we're watching this one closely.
The Errors panel reads like a log you'd want. One failure used to land three times wrapped in minified stack dumps; entries now dedupe, titles are readable, embedded JSON pretty-prints on expand, and a copy-all button sits beside clear. Raw text is preserved — nothing is paraphrased away.
Grok (subscription CLI). Failures surface the CLI's own message instead of a source-code dump, and the model list now comes from grok models live — so ids that vanished from your plan (looking at you, grok-4.3) stop being offered.
File preview crash on the second open ("Theme forge not found") — the editor and the highlighter now agree on theme names, and highlighting failures degrade gracefully instead of reaching the error screen.
Linux: windows associate with their launcher entry properly (taskbar icon, pinning) via WM_CLASS alignment.
Genome view panels stopped blending into the modal backdrop; the Settings button tooltip says Settings.
Empryo updates itself now — signature-verified, on every platform
The desktop app gains a real self-updater, the update feed that silently froze is fixed for good, and the macOS first-launch fix is now impossible to miss.
New
Self-updating desktop app. When a new version ships, Empryo tells you — a dialog on launch (once per version, Skip respected), /update on demand, a light 4-hourly background check, and an OS notification if the window is in the background. On Windows and Linux (AppImage) one click downloads, verifies, installs silently, and restarts. On macOS (unsigned builds can't self-install) it downloads and opens the verified DMG — and because the download never touches a browser, there's no quarantine flag and no "damaged app" dance on updates.
Trust before bits. Every update is checked against the release's RSA-4096-signed checksum manifest with a key pinned inside the app — the same chain the install scripts use. A tampered or spoofed feed can't get a single unverified byte executed.
Support Empryo. The About dialog now says the quiet part: the app ships unsigned because certificates are a recurring cost. If Empryo helps you, GitHub Sponsors and PayPal links live there — appreciated, never expected.
Fixed
A missing API key can no longer brick the app. If your configured model's key isn't set (or no model is configured at all), the workspace now boots normally — genome, files, and the Keys panel all work, the Errors panel explains what's missing, and chat shows the same actionable message per send until you add a key or switch models. Previously this failed the whole bridge at the workspace picker.
Linux gets its icon back. Installs shipped the icon only into an unregistered 1024px slot, so Mint/Cinnamon menus showed nothing — a full 16→1024 size set now lands in the right places, and the window/taskbar icon ships as a real resource instead of a path that only existed in dev.
The update check told everyone they were current. The release feed gated on a changelog file nothing was updating, so it froze at 3.0.1 and every newer install compared against it and answered "up to date". The feed now includes every release no matter which pipeline wrote it — and empryo.com/changelog shows the full history again.
Slash commands the composer forgot. Commands declared in the shared manifest (like /update and /usage) ran from the ⌘K palette but were invisible to the chat composer. The composer now reads the same manifest and runs them through the same bindings.
macOS install hint you can actually see. The xattr -cr first-launch fix is now a bold amber callout with one-click copy, sitting directly under the download buttons — on the download page, the wizard, and the docs.
Docs accordions were rendering empty. A markdown-renderer bug dropped content nested inside tabs and accordions — the "Other install methods" section on the installation page was blank on the live site. Fixed.
Memory tab's scope controls are labeled, readable fields now; select dropdowns app-wide slimmed down with a consistent chevron; wizard download labels no longer vanish in light theme.
A real file manager, a genome you can read, and glass that finally behaves
The biggest desktop UX pass since launch — the file tree became a file manager, the genome became a browsable interface, the titlebar got out of its own way, and transparency stopped turning menus into ghosts. Plus two real intelligence bugs fixed under the hood.
New
File manager in the tree. Right-click (or keyboard) to create, rename, duplicate, copy/cut/paste, and delete files and folders — with drag-and-drop moves, inline rename, and a confirm dialog for deletes. The tree also stopped hiding things: dotfiles (.github, .env…) show, and deep folders load on expand instead of being silently truncated.
Draggable panels. The sidebar, context pane, and inspector all resize by dragging, with sane min/max widths, double-click to reset, and the layout persists across restarts. Both side panels collapse and reopen from the titlebar.
A genome you can actually read. The genome view now parses our own structure into a real interface — a stats bar, dependency pills, and a searchable grid of file cards showing blast-radius, exported signatures, and clickable :line links — with Structured / Markdown / Raw modes. Open it full-screen from the context pane.
Sessions, reorganized. The sessions menu leads with search (focused on open) and a New-session button that names and starts a fresh conversation; saving is a secondary action.
A calmer titlebar. Twelve occasional tools fold into one More tools menu, narrow windows collapse the rest into it, provider rows show live readiness dots with a Refresh button, and Zen mode has a one-click toggle.
Fixed
Transparency behaves on every theme. With transparency on, menus, pills, tabs, dialogs, and toasts now use a fixed-opacity frosted glass (blurred, but readable) instead of going see-through at low window opacity — and light themes no longer turn murky. Opaque mode is unchanged.
Language servers stop dying. A second Empryo process (a TUI beside the desktop, a relaunch) was killing the first instance's language servers, which then showed as stuck "starting…" forever. The reaper now only touches genuinely orphaned servers, and dead servers are reported honestly.
The genome stopped lying about itself. A fully enriched genome could display "semantic: off" if a background task hiccuped — the status now comes from the database, and the mislabeled lsp: line (actually symbol enrichment) reads enriched:.
Creating a new file in a workspace behind a symlink (macOS /tmp, /var) no longer fails with "path escapes workspace".
Scrollbar no longer overlaps toggles in drawer lists; the model picker's right-side reopen button no longer hugs the window edge.
The desktop model picker shows every live model — gateway providers were stuck on a hardcoded list
One targeted fix, big visible difference: on desktop, gateway-style providers never showed their real catalogs.
Fixed
Desktop model picker: live catalogs for grouped providers. LLM Gateway, OpenRouter, Copilot, GitHub Models, opencode-zen, the local proxy, and Vercel AI Gateway all listed only a short hardcoded fallback set on desktop — regardless of your key or login. The picker's probe asked these providers the wrong question (their flat model call intentionally returns nothing; the grouped catalog is the real one). It now fetches the grouped catalog: LLM Gateway shows its full ~232 models, OpenRouter ~347, and DevPass logins see everything their plan allows. The TUI was never affected.
The TUI-crash fix — stale native libraries can never survive an upgrade again
The root cause of "the TUI keeps crashing" on Linux, Windows, and Intel Macs: builds since the OpenTUI 0.4.2 upgrade shipped a two-versions-old native render library next to new code, and on upgraded machines the old library could survive in ~/.empryo/native indefinitely. Both halves are fixed, and a set of production-hardening guards landed with them.
Fixed
TUI startup crash (`Symbol "dumpOutputBuffer" not found`). The build now verifies every platform's native OpenTUI library against the exact JS version and fetches the right one from the registry when the local copy is stale — a lockstep gate in the release pipeline makes shipping a skew impossible. If you hit this: reinstall, or rm -rf ~/.empryo/native and relaunch.
Upgrades fully refresh the runtime. A version marker forces ~/.empryo/{native,wasm,opentui-assets} to be rebuilt whenever the binary version changes, files are swapped atomically (a running Empryo never sees a torn library), and dropped files can't linger.
Addons survive upgrades. Installing a new version no longer wipes opt-in addons (proxy, Neovim) — they stay installed and linked.
Installs verify themselves. The installer now runs the freshly installed binary before declaring success — wrong-CPU downloads (SIGILL) and corrupt archives fail loudly with the exact fix, and EMPRYO_ARCH=x64-baseline can force the no-AVX build explicitly.
Updates behave. Beta users are offered the final release of the same version, and empryo update no longer times out at 60 seconds and orphans a half-finished installer.
Under the hood
Build-time smoke tests run every host-compilable binary before packaging.
TUI renderer-init failures now write a crash report and, when the cause is a stale native runtime, say exactly that instead of blaming your terminal.
A fast patch for Linux users hitting crashes on 3.3.0. If Empryo went black, invisible, or down in flames on your machine yesterday — this one's for you.
Fixed
Wayland black window / render-loop crash. Chromium 144's new wp_color_manager path is broken on KWin/Plasma-family compositors (endless "Unable to set image transfer function", invisible windows). The feature is now disabled — the desktop renders correctly on Wayland again. On an affected 3.3.0 build: --disable-features=WaylandWpColorManagerV1.
GPU crash-loops self-heal. Three GPU-process crashes in a run and the desktop relaunches itself with hardware acceleration off and remembers the choice — a broken driver no longer reads as "the app keeps crashing".
TUI crashes leave evidence. Fatal TUI/CLI errors now write a crash report to ~/.empryo/logs/crash-tui-*.txt (mirroring the desktop's ~/.config/@empryo/desktop/logs/), so "it crashed" comes with a file.
Clean piped output.empryo … | jq and friends no longer risk truncated output or stray terminal escapes on exit.
Notes
On Ubuntu 23.10+ prefer the .deb over the AppImage — Ubuntu's AppArmor blocks the AppImage's Chromium sandbox by design; the .deb installs a proper AppArmor profile. The new Linux troubleshooting docs cover all of this.
Crash-proof desktop with real logs, Linux .deb/.rpm packages, and a faster everything
The reliability release. The desktop app can no longer die silently — every early failure now surfaces with the logs you need to report it — Linux users finally get native packages, and a Chromium-generations Electron jump plus the React Compiler make the whole app quicker.
Highlights
Crashes now show themselves. A global crash guard catches every fatal error — even before the window exists — and shows a dialog with the full story: copy the logs, save them to a file, open the log folder, restart, or close. No more blank-screen deaths on Linux (or anywhere).
Persistent logging, finally. Main-process, bridge, and interface errors all land in a rotated log file (~/Library/Logs/Empryo on macOS, ~/.config/Empryo/logs on Linux), so a GUI-launched app no longer discards its own diagnostics. Fatal errors also write a standalone crash report.
Linux gets .deb and .rpm. Alongside the AppImage, native packages for Debian/Ubuntu and Fedora-family distros — x64 and arm64 — built and checksum-signed by the same release pipeline, on the download page now.
Electron 43 + React Compiler. Ten Chromium generations newer (and back in the security-support window), with the interface auto-memoized by the React Compiler — snappier long chats without a single hand-written memo.
LLM Gateway, three ways in. Log in with your browser to account credits or straight into your DevPass subscription (/login llmgateway, /login llmgateway-devpass), or paste an API key — on desktop, in the TUI, and headless. Empryo now identifies itself as Empryo on the consent page.
Know what you're spending. A new Usage view — desktop drawer and TUI /usage — with today/week/month spend, per-model breakdowns, a 30-day sparkline, and a DevPass budget ring showing exactly how much is left until reset. Powered by a local ledger, so it works offline and for every provider; it switches to live gateway numbers automatically once the gateway ships a key-scoped usage API.
Fixed
A stopped turn no longer waits out the full retry backoff before actually stopping, and a closed tab can no longer wedge itself mid-send.
Checkpoint restore no longer corrupts binary files and no longer strips trailing newlines from text files; Windows paths restore correctly.
--timeout in headless runs now also bounds background agents; piped --json output can no longer be truncated on exit; a failed --login exits non-zero; Ctrl+C keeps its documented exit code on Windows.
The TUI no longer sprays escape sequences into pipes or logs when stdout isn't a terminal, and a clean quit can no longer terminate the shell wrapper that launched it.
On Linux, bridge child processes (git and friends) now find per-user installs (~/.bun/bin, ~/.local/bin) when launched from the desktop.
Under the hood
Conversation-history sanitizing now skips arrays it has already proven clean — per-turn cost stays flat instead of growing with session length.
Renderer errors, unhandled rejections, and React error-boundary crashes are reported to the same log file over IPC, rate-limited so a hot loop can't flood it.
If Empryo ever breaks on your machine now, it will tell you — and hand you the logs to make it our problem instead of yours.
Desktop gets real memory, full session management, and deep settings parity with the TUI
The biggest desktop update since launch. The app now remembers across turns, manages sessions the way the TUI does, and exposes the provider and task-router controls power users have been asking for — all running through one unified bridge instead of a growing pile of one-off wiring. Alongside it: a full provider pricing refresh and a run of composer polish.
Highlights
Real cross-turn memory + compaction. The desktop app now keeps genuine conversation memory across turns and compacts it automatically as context fills up, with a UI to watch it happen — no longer a TUI-only feature.
Session management, for real./continue, /new, rename, and a full diagnostic session export now work on desktop exactly like the TUI — pick up where you left off, or hand off a session for debugging.
Provider Settings, deepened. Per-provider reasoning-effort overrides, context-management controls, capability toggles, key-priority ordering, and advanced request-shaping — desktop Settings now covers what the TUI's /provider-settings has for a while.
Task router gets teeth. Per-model fallback chains, a dedicated goal-review model slot, and searchable model pickers make routing different work to different models something you configure, not just read about.
One command palette, two hosts. TUI and desktop now share the same command manifest — a new slash command shows up in both automatically.
Zen mode, and a redesigned composer. A focus mode that strips the chrome away, plus several rounds of composer polish — ToolTrace tool-call rendering and new Chat FX treatments — for a calmer conversation view.
Under the hood
Every desktop feature that talks to the backend now goes through one unified bridge-invoke seam instead of a bespoke protocol case per feature — git, memory, skills, LSP, checkpoints, diagnostics, and more all moved onto it this release.
Refreshed pricing, model catalogs, and reasoning/effort capabilities across every supported provider: new models (Grok 4.5, Gemini 3.5 Flash, and more), corrected context windows, and a couple of real capability bugs fixed — Claude Sonnet 5 was silently missing its full effort range.
Fixed a genome-indexing freeze on large backends, clamped prompt-cache breakpoints to Anthropic's 4-block limit, and closed a race between a new turn starting and an in-flight compaction.
Same graph engine, same workshop — now with a desktop app that remembers, and a TUI that isn't the only one with the good settings.
The desktop app grows a browser, clickable file mentions, and a Markdown preview
The v3 beta's biggest desktop update yet. Empryo's desktop app gains a real embedded browser, turns the agent's file references into things you can actually click, and learns to render Markdown — plus a long list of smaller refinements across chat, the maze, settings, and the workspace picker.
Highlights
An embedded browser, built in. Preview your dev server without leaving Empryo — a tabbed, local-only browser lives right inside the app, so the thing you're building and the agent building it share one window.
Clickable file mentions. When Empryo names a file, it's now a link. Click to open it in place (desktop) or jump straight there from the terminal (CLI). Only real files in your indexed codebase light up, so a mention is never a dead end.
Markdown, prettified. The file peek can render Markdown instead of only showing source — hit the prettify toggle to read a doc the way it's meant to look, headings, code, and all.
Choose your prompt-cache window. Settings now expose the prompt cache TTL (5 minutes or 1 hour), so you can trade freshness for cost on your terms.
Smoother all over
The maze opens zoomed in with a clearer HUD, gives each agent a distinct color, and keeps links off by default so it reads at a glance.
The workspace picker scrolls and filters your recent projects, so getting back into a codebase is one keystroke.
Settings grew a dedicated Providers tab, a clearer workspace-scope toggle, and tabs that scroll when they need to.
Resuming a session brings back the full transcript — agent messages and tool cards included — instead of a bare outline.
Steadier chat streaming, reliable glass transparency, framed image lightboxes, sharper themes on dark backgrounds, and a tidier titlebar round it out.
Under the hood
The download page now builds its links from a tracked manifest, and a release refuses to finish until empryo.com is actually serving the new version — no more dead download buttons.
Every artifact here — CLI, TUI, and the desktop app for macOS, Windows, and Linux — is built, signed, and shipped straight from a Mac. No CI in the loop.
Same graph engine, same workshop — now with a window onto the web and fewer dead ends.
A calmer first launch — you pick the workspace, Empryo asks for less
A focused follow-up to the v3 beta that makes the desktop app's first moments calmer and more predictable — and asks your OS for a lot less.
Highlights
Always start at the workspace picker. The desktop app no longer reopens your last project on its own. You choose the workspace on every launch — recent ones are one click away — so your codebase graph indexes exactly the folder you meant, and nothing else.
Far fewer permission prompts. Empryo doesn't touch a single file or open the network until you pick a workspace, and it no longer asks macOS or Windows for local-network access it never used. It only ever asks for what it actually needs, when it needs it.
The right theme from the first frame. The picker and loading screen now follow your system light/dark setting instead of briefly flashing the wrong palette.
Under the hood
The bundled agent sidecar now ships with a stable, hardened identity instead of an anonymous one, so the file access you grant is attributed to Empryo cleanly.
Same graph engine, same workshop — just a gentler way in.
The Empryo era. SoulForge becomes Empryo — same engine, new name, and a much wider surface: a native desktop client, a real website at empryo.com, and binary-first distribution straight from the source. Versioning continues from SoulForge v2 — this is v3, not a restart.
Features
brandrebrand SoulForge → Empryo across CLI, desktop, and web; migrate ~/.soulforge config to ~/.empryo
webappempryo.com on TanStack Start — owned docs (dropped Mintlify), blog pipeline, download page, glass UI
genomestable symbol monikers, polyglot structural-edit tool, trigram search with gitignore + hash CAS
cli--cwd plumbed through a single global; Empryo brand splash on boot/landing/shutdown
distbinary-first releases via dl.empryo.com (Cloudflare R2) — signed SHA256SUMS, install.sh / install.ps1, Homebrew + WinGet channels
Bug Fixes
releaseredact builder paths from compiled CLI/bridge binaries; mandatory leak audit before ship
releaseone arch per desktop job; native fpm for arm64 .deb; square 1024² app icon
headlesswire full agent capabilities into setupAgent
llmcorrect app-identity headers for OpenRouter and LLM Gateway
Performance
desktopstop maze RAF teardown on every hover/link/target change; reduce-motion guard
clifix react-compiler bailouts and cut render-path allocations
Documentation
point install/download references at dl.empryo.com, not GitHub Releases
document package architecture; refresh README, getting-started, and project guide
Tooling
workspace-wide lint/format/typecheck/build coverage across all packages and apps
manual-only package publish workflow; pack rehearsal without npm auth
3.0.0-betaJul 2, 2026
release
Empryo v3 — SoulForge, reborn
Meet Empryo — the coding agent that treats your codebase as code, not text. It's the successor to SoulForge v2: same graph-powered engine, a whole new form. SoulForge lived in your terminal. Empryo is the entire workshop — a polished TUI, a native desktop app, and empryo.com. Versioning continues where SoulForge left off, so we open at v3, and the whole line is a public beta.
Highlights
A real desktop app. Native on macOS, Windows, and Linux — multi-tab sessions, a live map of your codebase, and every tool a click away.
A TUI that feels crafted. Rebuilt from the ground up: soft depth, fluid panels, an agent dock, an inspector, and a fast command palette.
It understands your code. Empryo parses your whole repo into a dependency graph and edits by symbol and line — AST surgery and LSP rename, not find-and-replace.
Your models, your way. Bring any provider, or sign in with the ChatGPT, Grok, or Copilot subscription you already pay for.
Always current. A built-in changelog and one-command updates keep the CLI and desktop fresh.
Under the hood
Cross-platform binaries — signed, checksum-verified, and installed by a single curl … | bash (or irm … | iex on Windows).
memoryannotate buildMemoryIndex locals with MemoryIndex type
memorysurvive concurrent sf SQLite I/O errors
Documentation
changelogadd sponsors shoutout to 2.16.2
promptsrewrite commit-boundary rule to clarify set_lockin timing
Features
presetsload shareable config bundles by name, URL, or path
Miscellaneous
update readme
update readme
update readme
update readme
Refactor
promptspositive framing + naturalize memory
promptsper-family tuning + tighter answer voice
2.16.2May 20, 2026
💜 sponsors
💜 Sponsors
[LLM Gateway](https://llmgateway.io/dashboard?ref=6tjJR2H3X4E9RmVQiQwK) ([@theopenco](https://github.com/theopenco)) — one API for OpenAI, Anthropic, Google, and 30+ providers. Up to 30% off frontier models, real-time analytics, BYOK. Now wired into Empryo as the llmgateway provider. Thanks for keeping the forge lit. 🔥
Bug Fixes
lockininvalidate commit when tools land after set_lockin
read-highlightrender unknown-lang files plain in multi-file reads
Documentation
sponsorsadd BACKERS.md + README sponsor wall with LLM Gateway
use HTML formatting inside sub tag in README image table
Features
clipboard image paste support (#3)
Miscellaneous
update workflow
2.5.0Apr 5, 2026
release
Bug Fixes
warn agent when auto-format changes line count after edit
complete async migration and bug fixes for soul_vision
smart video fallback — animated GIF for Kitty, static frame for others
remove Konsole from Kitty Unicode placeholder support
render reasoning blocks with Markdown component
Features
auto mode bypasses all permission prompts, use hardRestart for updates
cap soul_vision image height, retry flaky video-to-GIF, update README
async video pipeline with live progress UI
restore Kitty images on session resume
restore Kitty images on session resume
soul_vision tool for inline image display
Refactor
clean up soul_vision for performance and reusability
Testing
add image rendering and terminal detection tests
2.4.0Apr 5, 2026
bug fixes
Bug Fixes
custom providers not showing in Ctrl+L model picker
eliminate unsafe casts on LLM data, add Zod validation for plan output
Documentation
fix features SVG — drop animations, use static opacity for GitHub compatibility
fix features SVG visibility, remove prompt caching and sandboxed execution
expand features SVG with 16 pills, fix header spacing
update README and assets
Miscellaneous
readme overhaul
2.3.0Apr 4, 2026
release
Features
add LM Studio provider; fix non-nerd-font icons for ollama, lmstudio, and custom providers
2.2.1Apr 4, 2026
bug fixes
Bug Fixes
add Java/JVM LSP support and fix health check hangs (#8)
2.2.0Apr 4, 2026
release
Bug Fixes
resolve stream stall watchdog deadlock and surface retry messages
show FREE tag in model picker, drop sub-group rearrangement
accurate OpenRouter cost reporting and free model detection
improve Ctrl+L model selector performance and fix handleNewSession hoisting
track and kill all child processes on exit
handle SIGHUP to clean up child processes on terminal close
correct free Qwen model ID in Headless Forge workflow
Features
add /session new command to start fresh session
add Groq, DeepSeek, Mistral, Bedrock, and Fireworks providers
Miscellaneous
remove stale tea_test file
update gitignore
update README badges and rename workflow
bump all actions to latest (checkout v6, artifact v7, setup-node v6)
bump actions to v5 for Node.js 24 compatibility
add Headless Forge workflow for end-to-end testing
2.1.1Apr 4, 2026
bug fixes
Bug Fixes
x64-baseline bundle uses wrong native addon paths
2.1.0Apr 4, 2026
release
Bug Fixes
make headless test TTY-independent
detect brew install when ~/.soulforge/bin shadows PATH\n\nBrew's post-install copies the binary to ~/.soulforge/bin/, which\nshadows the brew symlink at $HOMEBREW_PREFIX/bin/soulforge in PATH.\nThis caused detectInstallMethod() to fall through to \"binary\".\n\nFix: directly check if $HOMEBREW_PREFIX/bin/soulforge exists as a\nsymlink — the one artifact only brew creates.
accordion behavior in model selector — expanding a provider collapses others
update prompt-content test to match shell guidance heading
apply default transparent theme on first launch
strip mismatched provider options from subagents
git commit messages with literal \n instead of real newlines
npm pack tar extraction on macOS, tolerate published versions
use npm pack for cross-platform native deps, retry uploads
patch dynamic platform import in bundled JS before compile
cross-platform bundle — stub native libs for compiled binaries
use available CI runners for all platforms
npm registry, publish workflow, and build plugin fixes
dead barrel detection for Python packages\n\n- isForbidden() returned truthy when uninitialized, causing collectFiles()\n to skip all files and break repo map indexing in tests\n- Dead barrel edge check now excludes sibling files within the same\n package directory (e.g. core.py → __init__.py is internal, not external)\n- Fallback ref check also excludes refs from files inside the barrel dir
worker thread missing initForbidden — scan found 0 files
wait-for-repomap UX + timeout increase
sync symbol cache on IntelligenceClient for buildSymbolLookup
shell guard no longer blocks code strings in node -e / python -c
token-budget-only pruning for forge, z.preprocess coercion for numeric tool params
enable pruning
TabBar mode label reads stale registry on Ctrl+D cycle
project format action uses dedicated formatter instead of lint+fix
StatusDashboard bar alignment and popup width
StatusDashboard data matches topbar, bar style improved
remove startTransition from streaming flush — was deferring UI updates indefinitely causing frozen display
tasks always resolve — complete on success, reset on error/abort, taskId for per-agent updates
auto-complete in-progress tasks when agent finishes streaming
Ctrl+X abort preserves partial chat content instead of clearing it\n\nSnapshot liveToolCallsBuffer and streamSegmentsBuffer before abort()\nclears them, so the catch block can reconstruct in-flight tool calls\nand partial assistant messages. Previously the buffers were empty by\nthe time the catch block ran, causing content to vanish on cancel.
alphabetize /help and autocomplete commands, add 7 missing entries to help
dispatch UI freeze — mark toolCallsDirty on agent stats + multi-agent events so streaming display updates during dispatch
steering flush includes in-progress tool calls — shows progress before steering message
StatusIcon shows warning for failed tool results
dedupe installed skills by name, prefer project-scoped over global
project tool reports lint warnings as failures — agent sees issues and can auto-fix
SystemBanner useMemo exhaustive deps
SystemBanner hooks after early return, rename icon to bannerIcon
lint — move biome-ignore comments to correct lines
wrap all raw numbers in String() for OpenTUI text compatibility
wrap hiddenCount in String() — OpenTUI rejects raw numbers as text children
nudge-aware tokenStop eliminates race condition where a single step could jump past both nudge threshold and stopWhen budget
complete modal stacking fix for toggleModal and openCommandPicker
modal stacking, transient renders, keyboard early returns, scan throttle
show dark red border on input during loading/compaction instead of invisible gray
ContextBar token reset on modal open, repo-map picker live updates, scan progress labels
health check readSymbol probe picks valid identifier name
tree-sitter grammar for ALL typescript/tsx files — no tree-sitter-typescript.wasm exists
tree-sitter tsx grammar lookup in findImports/findExports/getFileOutline + wider diagnose popup
tree-sitter tsx grammar mismatch + smarter health check readSymbol probe
improve steering message injection — drain all queued messages at once, stronger framing
ASCII fallback icons for all providers, remove hardcoded Nerd Font glyph
teach subagents to use startLine/endLine when task provides line ranges\n\nAdds WORKFLOW hint to explore and code agent prompts: when the dispatch\ntask includes line numbers, use read_file with startLine/endLine to\nbypass the 500-line truncation cap and get exact content.\n\nAlso removes fixresearch.md — all fixes verified as implemented.
dispatch UI — late agent seeding, broken tree connectors, render storms
strip contextManagement from subagent provider options
theme system, UI rebrand, docs refresh, and headless color updates
add ASCII visualization guidance to plan & architect modes\n\n- Architect mode now instructs use of dependency graphs, comparison\n tables, box diagrams, and flow charts for design analysis\n- Plan mode (both full and light) presents visual file change summaries\n and dependency diagrams before calling the plan tool
tab bar UX improvements and subagent fix\n\n- Hide model label in tab when it matches the default model\n- Restyle tab model labels with brackets and move after edit count\n- Fix explore subagent provider options not being stripped for mini-forge
v2 compaction, git branch/stash ops, SSRF protection, agent bus hardening, and comprehensive test suite
context compaction, plan view overhaul, persistent system messages, and broad refinements
repo map intelligence, compound tools, web scraper, and Ink → OpenTUI migration
multi-tab chat, parallel agent dispatch, and provider config system
Miscellaneous
add SHA256SUMS.txt checksum generation to release workflow
untrack .agents/skills, remove stale homebrew/ copy
wrap tab bar indicators in brackets\n\n- Edited file count, unread dot, and error markers now use bracket styling\n- Consistent visual language across all tab bar indicators
upgrade deps
remove completed/obsolete improvement docs
add HTML coverage report script
add test coverage reporting + lcov artifact upload
biome formatting — normalize imports, indentation, line wrapping
fix lint formatting across refactored files
fix lint errors from dead code removal (trailing blank lines, let→const)
delete PlanView.tsx (dead file), remove dead exports from splash.ts and types/index.ts
remove 43 dead exports, delete highlight.ts (fully dead file)
remove 10 dead files (780 lines)
fix biome formatting across 5 files
remove JetBrains Mono from bundle, keep Symbols Only
UI polish, context bar simplification, repo map token budget, worker memory tracking, lint fixes & test updates
collapse re-export symbols in repo map render
remove shell search redirect gate\n\nRemove checkSearchAntiPattern and the blocking redirect layer that\nprevented shell from running grep/cat/find commands. This gate was\noverly aggressive and incorrectly blocked legitimate git and shell\noperations. The softer post-success hints in shell.ts are retained.
clean up stream options, subagent tools, tab instance, and context manager\n\nCo-Authored-By: SoulForge <soulforge@proxysoul.com>
fix dumb tests, reduce plan eagerness, clean up truncation messages