4.8.1 — A server that stops running out of terminals
A snapshot of 4.8.1 as released on 2026-08-10. It will go out of date as the app moves on; that is fine and expected. For the reference that is kept current, follow the links to the living guide in each section.
npx mulmoterminal@latest
There is nothing to configure in this release. The headline is a bug that only showed itself after the server had been up for days, and the way to benefit from the fix is to restart onto this version. The rest is the per-folder collection work from 4.8.0 moving forward.
If your server stopped being able to open new terminals
This is the one to read.
The symptom. After a few days of continuous uptime, every new session fails to start. The cell shows:
[forkpty: Device not configured]
Nothing you do in the app helps — closing sessions does not free anything up, and the sessions already running keep working, which is what makes it look like a display problem rather than a resource one. Restarting the server clears it completely, and then it comes back a few days later.
What was happening. Every terminal MulmoTerminal opens is a pseudo-terminal, and macOS allows a fixed number of them machine-wide (511 by default). The library we use to spawn them, node-pty, was failing to give two of them back per terminal on macOS — one file descriptor it opened and never closed, and one whole pseudo-terminal allocated and abandoned. Because a session takes one on each spawn, the count only ever went up.
The rate-limit gauge is what made it fast: it starts a hidden Claude session every ten minutes while a browser is watching, so a machine left with the grid open climbed steadily whether or not anyone was using it. One report reached 498 of the 511 in five days.
The fix. MulmoTerminal now runs node-pty 1.2.0-beta.15, which closes both. This was measured rather than assumed, on a real server: with the old version, six terminal sessions opened and closed left six pseudo-terminals held forever; with the new one, zero.
Raising the limit with sysctl kern.tty.ptmx_max was never a fix — it only moves the day it happens.
How to tell you have the fix
You do not need to do this, but if you were affected it is satisfying to watch.
With MulmoTerminal running, find the server process and count the pseudo-terminals it holds:
pgrep -f "mulmoterminal|server/index" | head
lsof -p <that pid> | grep -c /dev/ptmx
Run it, use the app for a while — open and close a few cells — and run it again. The number should track how many terminals are actually open, and come back down when you close them. Before this release it only rose.
If you would rather not use lsof: the honest answer is that you will notice this fix by not noticing anything, several days from now.
A restart is required, and npx will not do it for you. A running server keeps the old library loaded in memory no matter what is on disk — stop it and start it again.
A project folder’s collection now refreshes on schedule
4.8.0 shipped the Collections pane and then asked you not to move data into a project folder yet. Two of the four reasons are now gone.
Scheduled refresh works per project. In 4.8.0 a collection that refreshes by dispatching an agent could not be scheduled in a project folder at all — the worker would have started in the workspace and written a project’s records into the workspace’s same-named collection. The shared library now carries the root through to the worker’s working directory, so a refresh scheduled for a project lands in that project.
The calendar sync stays workspace-only on purpose: a Google grant belongs to the user, not to a folder, so a per-project sync would need a per-project answer to “which account” that nothing has yet.
A card stays with the project it was made in. Previously a card built while looking at project A would show project B’s records once you moved the app somewhere else — same slug, same title, different rows, nothing on screen saying so. Cards now carry their own project binding.
For what a collection is and how an agent authors one, see Features overview in the living guide.
Still not ready
Two of the four caveats from 4.8.0 stand, so the advice has not changed: keep your collections in the workspace for now.
- The phone still cannot reach a project’s collection. The host can now list which projects exist (
listCollectionProjects), and every command that takes a project resolves one — but the phone has no picker, so it sees the workspace and only the workspace. - The pane has still not had a live browser check the way the full-screen overlay has.
Nothing here affects a collection already in the workspace.
Also in this release
- An agent is told when it makes a collection unclonable. The portability check has had a route and a button since 4.7.6, and both need a person to think of pressing them. A successful
putSchemanow reports the verdict back to the agent that just wrote the schema — the one that chose the storage kind and is holding the file open. It is quiet when there is nothing wrong. - A feed’s ignored records are a warning, not a blocker. Running the check over a real workspace flagged three feed collections as unclonable because the managed workspace ignores
feeds/by design. A feed’s records are a cache the clone can re-fetch, so the cost is a refresh, not the data. Ordinary collections keep the blocker — there, the records are the data. - A newly saved directory starts watching immediately. Adding a working directory used to wait out a 60-second reconcile before its collections were watched, which read as broken rather than as pending.
- Header chips follow the directory’s text colour. With a strongly coloured
headerColor, the model/context badge and the usage chip stayed on the theme’s dim ink and could become unreadable, while the path and title beside them followed correctly. - The Collections door in the toolbar wears the pane’s own icon, so the two places you can open collections from look like the same thing.
@mulmoclaude/coremoved to 3.2.0, the shared library MulmoTerminal and MulmoClaude both run on.
How to tell you have it
- Restart MulmoTerminal (
npx mulmoterminal@latest). - Open Settings from the gear in the toolbar. The version sits directly under the Settings heading, at the top of the dialog. It should read 4.8.1.
If it still says 4.8.0, the old process is still running — stop it and start it again. npx will not swap the version out from under a running server. For this release that matters more than usual: the pseudo-terminal fix lives in a native library that is loaded once at startup.
If the restart itself is the part that goes wrong, see Getting started.