Every user-visible string in Empryo now comes out of a translation catalog. 5,482 of them, Arabic complete, switchable while the app is running. That turned out to be the smaller half of this release. The terminal also learned three ways to draw a conversation, everything a running agent does moved into one strip under the transcript, and the number in your status bar finally means the same thing on all three surfaces. I also closed five ways a tool could reach past the workspace, one of which let a redirect decide where a preset came from.
Pick a language, keep working- The catalog covers the engine too, not just the two apps. Boot steps, quota lines and MCP timeouts paint through the same keys as the chat, so a translated Empryo is translated all the way down.
/languagein the terminal repaints in place. Settings then Language on the desktop reloads the window. Neither asks you to restart.- Arabic is at 100%, with real ICU plurals rather than a count glued to a noun. Hebrew and Arabic lay out right to left per block, in chat and in the composer.
- Turn on
liveTranslationsand Empryo pulls newer catalogs from the public repo between releases, validated by the same security gate before a single string reaches your screen. localizedCommandsaccepts translated slash commands, so/لغةruns/language. Off by default, because your muscle memory is in English.- Translators work in proxysoul/Empryo: one JSON file, PRs welcome, and the build fails if the English catalog is stale.
/chat-stylepicks speakers, rail or bubbles. Speakers is the default and names who is talking. Rail runs a single spine down the left of the turn. Bubbles wraps your prompts, clamped to 70% of the lane so text stops spilling under its own frame.- Everything alive sits in one strip under the transcript. One frame per activity, one dispatch group per parent call, and a queued worker is visible while it waits instead of appearing only once it starts.
- A custom agent carries its own name, model and colour while it runs, on both surfaces. Background agents show the name you gave them, not the
bg-3handle. - The agent pane reads like the transcript: chips, a tool strand, markdown, and a framed well for steering the child mid-run.
- A review says itself once. A stamped row in the thread, an apply that folds, and a chip on the composer that tells you findings are waiting.
- The tool rail holds still. Thinking spends one of the five slots rather than adding a sixth, so the list stops growing and shrinking under a working agent.
- Colour got quieter. Category tints on the strand are held on a leash, and only a genuine failure wears red.
- Input means the total prompt on every surface, with cache reads and writes beside it and the uncached part derived. The status bar and the usage panel had been quoting two different conventions.
- The desktop prices each step as it arrives, so tokens, cost and context move during the turn rather than after it.
- Headless emits the same split, including the running cost on every
--eventsstep and the cache write on a resume. - A dispatch child's cache writes are priced at the cache rate, which they always were on the invoice and were not in ours.
- New price rows for grok-4.6 and MiniMax M3, DeepSeek carrying its 2026-08-17 peak rates, and static matching that only accepts a model at a version boundary so
grok-4.7reads as unknown instead of quietly billing like a 4.3.
ast_edit,structural_editandmove_symbolcould write anywhere on disk unattended. The outside-cwd gate needs a tool in two lists and they were in one, or neither.fetch_pagenow pins the address it resolved, so a hostname cannot answer a second time with an internal one.- A preset URL that redirects off
https://is refused rather than followed. $IFSand friends no longer smuggle a forbidden path past the shell gate. Variables are dropped and what remains is checked again.- The desktop parks outside-cwd and destructive approvals on the ask card in every mode that has approvals. Auto mode bypasses them by design on every surface, which is policy, and now says so.
- A reloaded desktop session keeps its thinking blocks where they happened, instead of collecting them into one lump at the top (#182).
- Opening a session in single-window mode swaps the window on the reveal, not on a
showevent that macOS never fires (#179). - A global behaviour toggle survives a project config layer and de-shadows it everywhere (#178).
- Julia gets its language servers driven through the
juliabinary (#169). - An unknown subcommand is reported instead of running its parent.
/session bogusused to open the session browser and say nothing about the word it threw away. - The desktop git drawer stops calling a folder that is not a repository a clean working tree.
- An oversized request is shrunk rather than discarded.
- The diff viewer shows the change instead of the file twice.
/goal clearends the loop and keeps the turn you are in. Ctrl-X is still the abort.- The stall watchdog is off by default, and when you turn it on it no longer reads a slow pre-pass or a quiet stretch of reasoning as a stall.
- A refusal wider than your terminal keeps its tail, so you see what would have been right.
- Kitty graphics write as one buffer, so a renderer frame cannot tear an image in half.
- A wedged splash child is killed before the first frame instead of hanging the boot.
- Bun is pinned back to 1.3.14. 1.4.0 still carries oven-sh/bun#37284, which segfaults under the JSC GC on all three platforms.
- Tree-sitter grammars that
tree-sitter-wasmsdoes not publish are now built here, Julia included. - The QA immune system schedules in pools by phase, reports against a time budget, names the five cells eating it, and reaps by process tree. Thirty seeds that could not have failed were rewritten to be able to.
- empryo.com serves an agent surface: a discovery catalog at
/.well-known/ai-catalog.json, JSON indexes, content negotiation for markdown, and Lighthouse 100 on the pages that matter. - The download page counts real installs, live.
Two people started sponsoring Empryo this cycle: 3utterfly3ffect at the ember tier, and Praneeth Merugu (@PraneethMerugu) at spark. Nothing but sponsors funds this project, so both of them paid for part of what is in this release. Thank you.
