Skip to content

feat(dev): hot-reload the web UI from disk + live reload (debug only)#154

Merged
edwin-zvs merged 2 commits into
mainfrom
webui-hot-reload
May 23, 2026
Merged

feat(dev): hot-reload the web UI from disk + live reload (debug only)#154
edwin-zvs merged 2 commits into
mainfrom
webui-hot-reload

Conversation

@edwin-zvs

Copy link
Copy Markdown
Contributor

Fast change→refresh loop for the web client. Asks: "give me options to hot-reload webui changes" → implemented disk serving + live reload, runtime-settable so an already-running daemon can be pointed at a worktree's assets (no rebuild/restart), exposed as a debug-only MCP tool.

The problem

crates/daemon/assets/index.html + static/* are include_str!/include_bytes!'d into the daemon, so editing the web UI means: edit → cargo build (~20s) → restart daemon → reconnect browser. The recompile dominates.

What this adds (all #[cfg(debug_assertions)]-gated)

  • Disk serving: when a dev-assets dir is set, the web server serves index.html/static/* from it instead of the embedded copies (web_asset / web_index_html), falling back to embedded per-file.
  • Live reload: the served index.html gets a tiny poller injected that hits /dev/version (a combined mtime fingerprint of the served files) every 700ms and location.reload()s on change. Edit → save → browser reloads itself.
  • Runtime-settable (the key ask — works against an already-running daemon, no restart):
    • webui_hot_reload(<dir>) MCP tool (debug only) — any dev session in any worktree can point the daemon at its own crates/daemon/assets; dir: null reverts to embedded.
    • dev.set_assets IPC method / client.dev_set_assets().
    • AGENTD_ASSETS_DIR=<dir> at boot.

So the loop becomes: build a debug daemon once, then iterate on index.html forever with just an auto-refresh.

Safety

Release builds ignore the env var, treat the IPC override as a no-op, drop the /dev/version route and the MCP tool, and always serve the embedded, tamper-proof assets. No arbitrary-path serving in production.

Tests

  • web_asset_prefers_dev_dir_then_embedded, web_index_html_injects_livereload_only_from_disk, dev_assets_version_tracks_mtime (daemon); webui_hot_reload_tool_is_debug_only (mcp).
  • Verified end-to-end over HTTP against a live daemon: set dir → custom HTML + poller served, /dev/version changes on edit, revert → embedded. Full workspace green (the one failing test is the pre-existing debug-only timing flake many_pinned_sessions_resize_within_budget).
  • Documented in AGENTS.md.

🤖 Generated with Claude Code

edwin-zvs added 2 commits May 22, 2026 17:16
Editing the web client meant recompiling the daemon (assets are
`include_str!`'d), restarting it, and reconnecting the browser. Now a
running debug daemon can serve `index.html` + `static/*` from a worktree's
assets dir, with a live-reload poller injected so browser edits show up on
save — no rebuild, no restart.

- `webui_hot_reload(<dir>)` MCP tool (debug builds only) so any dev session
  on any worktree can point the daemon at its own assets; `dir: null`
  reverts to embedded. Backed by the `dev.set_assets` IPC method /
  `client.dev_set_assets()`; `AGENTD_ASSETS_DIR` sets it at boot.
- The web server prefers the dev dir over the embedded copy when set
  (`web_asset` / `web_index_html`); the injected poller hits `/dev/version`
  (a combined mtime of the served files) every 700ms and reloads on change.
- All of this is `#[cfg(debug_assertions)]`-gated: release builds ignore
  the env var, reject the IPC override (no-op), drop the `/dev/version`
  route and the MCP tool, and always serve the embedded, tamper-proof
  assets.

Tests: web_asset disk-vs-embedded + missing-file fallback; index injection
only when served from disk; version tracks mtime; MCP catalog gates the
tool to debug. Verified end-to-end over HTTP (set dir → custom HTML +
poller served → /dev/version changes on edit → revert → embedded).
Documented in AGENTS.md.
web_asset already serves the embedded copy per-file when a file is
missing; keep the live-reload poller injected whenever dev mode is on
(even on the embedded fallback) so the page auto-recovers to the dev
assets the moment the file reappears — handles editor atomic-saves and a
removed/empty worktree without leaving the page stuck.

Test covers: dir with index.html (dev + poller), removed file and
nonexistent dir (embedded + poller), dev off (embedded, no poller).
@edwin-zvs
edwin-zvs merged commit 7d48354 into main May 23, 2026
1 check passed
@edwin-zvs
edwin-zvs deleted the webui-hot-reload branch May 23, 2026 00:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant