Settings → System → Maintenance. Two buttons that are deliberately not a pair.
── Rebuild: real, and free ──
The same `rebuildFrontend` a plugin install already runs. `Bun.build` reads source
from disk on every call and writes `build/`, and the server serves that directory by
reading each file per request — so a rebuild lands on the next page load with no
process restart, no dropped websocket and no chat session lost.
── Restart: the only way to load server code, and it costs ──
Bun caches modules for the life of the process. Measured rather than assumed: editing
a file and re-importing returns the ORIGINAL export, and a cache-busting query picks
up that one specifier while everything it imports stays cached. So `rebuildHonoApp`
— which install already does — re-wires the same module instances into a new tree and
cannot see a backend edit. Busting the whole graph would duplicate singletons: two
database clients, two session maps, one process.
There is therefore no third button, and the screen says why. A "remount the API"
control would look like it reloaded the backend and would not.
The restart answers BEFORE it schedules itself, because the process serving that
request is the one being replaced. It refuses outright when PM2 does not know this
process — in development the platform runs under `bun --watch`, where the restart
would fail into a promise nobody awaits while the button reported success.
Verified: `POST /rebuild-frontend` → 200, 3.0s, 3 outputs; anonymous → 401. The
restart button is deliberately untested from here — pressing it would end the session
this was written in, which is the same reason it needs a label that says so.
tsgo clean, frontend builds, 914 pass / 7 fail unchanged.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>