4.8.4 — The notification body, and Japanese in the terminal
A snapshot as of 4.8.4 (released 2026-08-15). It will go stale as the app moves on — that is expected, and the living reference is the guide each section links to.
npx mulmoterminal@latest
There is nothing to configure. This release only fixes things, so this page says what was broken and how to tell, on your own machine, that you have the fix.
A push whose body was the prompt you had just typed
Before. Opening a notification, the body was sometimes the prompt you had just sent, word for word. It happened on finished turns (✅) and on blocked ones (❓). Reading your own words back tells you nothing about what the turn did.
Why. The body is built from the agent’s reply — but the reply was re-read from the transcript file, and the last resort when that read came back empty was “the last prompt”. Empty reads are real: a turn you stopped with ESC, or one that ended on a tool call, has no reply to find.
If you use /clear, it happened on every turn afterwards. After a /clear, Claude starts writing to a different file, so our copy stays frozen on the conversation you ended. The mark that says “frozen” never lifts, so every later finished push in that session fell to the last resort.
Now. The reply comes from the value the hook that reports the turn already carries. No file is re-read, so nothing races the write and the /clear freeze does not apply. And the prompt is gone from the fallback chain — on no path can your own words become the body again.
The body is now decided like this:
| Notification | Body |
|---|---|
| Finished (✅) | the turn’s reply; failing that the session title, failing that “the task finished” |
| Waiting (❓) | what the agent is asking for; failing that “waiting for input” |
How to tell you have it. With phone push on (notification settings), run one turn in a cell and read the body that arrives. If it opens with the reply, the fix is in. The same holds in a session you have /cleared. An interrupted turn says “the task finished”, and that is correct — that turn has no reply to report.
Terminal Japanese arriving as runs of _
Before. An agent’s Japanese output sometimes arrived as __________. Box-drawing characters (─│) and · still looked right, which made it look like a font problem.
Why. Neither the font nor the renderer: tmux was substituting on write. When a tmux client finds no UTF-8 name in its locale (LC_ALL / LC_CTYPE / LANG), it replaces every character it has no fallback for with one _ per cell — and a full-width character is two cells wide, so one character became __. A process launched from a GUI can carry no locale variables at all (launchctl getenv LANG was empty on this machine), which is exactly that case.
Now. The tmux client is pinned to UTF-8. That is not a guess about your terminal: the reader of this client’s output is our own xterm.js, which is always UTF-8. On macOS, a LANG of en_US.UTF-8 is also supplied — only when the environment named no locale at all. An environment that already sets LANG=ja_JP.UTF-8 is left alone.
How to tell you have it. The _ substitution happens in the tmux client, so an existing session is fixed the next time you open it. Ask an agent for some Japanese. If it is still _, the cause is a different one — see when it doesn’t work.
The supplied locale name applies only when a session is created, so it does not reach a process that is already running. If you need that half (a curses TUI or Python deciding its output is ASCII), open a new session.
Shared apps: publish handed out a URL that does not open
Publishing an app returns the address to give visitors. It read /{name}, but the public page lives at /a/{name}. The author passes that string straight on to people, so this was not an awkward message — it was a URL that does not open.
Addresses for the roster and participant pages were printed as the placeholder /m/{name} and are now filled in with the name we know. The participant page did not name an address at all.
To check, open the address the next publish hands you.
Shared apps: the public view’s link refusal did nothing on Windows
Files the public view reads are opened so that symlinks are not followed. That defence rested on one flag, O_NOFOLLOW — and Windows does not have it. A missing value counts as zero, so the defence silently degraded to a plain read, with no error and no warning.
This affects you only if you serve a shared app’s public view from Windows. Nothing to configure.
Everything fixed here
| Fix | Issue |
|---|---|
| The notification body was your own prompt | #1696 |
Terminal Japanese arriving as runs of _ | #1634 |
| A shared app’s public URL did not open | #1697 |
| The public view’s link refusal did nothing on Windows | #1709 |
What the previous release added is in the 4.8.3 guide.