jifeng15
dsh-web-restart
True hot-loading for dsh web: safely auto-restart after installing plugins, editing config, or upgrading dsh. DSH plugin/skill, tmux-hosted safe restart. 让 dsh web 实现真·热装载:装插件/改配置/升级本体后自动安全重启,不用再手动去命令行重启。
- Stars
- 0
- Language
- Shell
- Created
- Aug 15, 2026
- Updated
- Aug 16, 2026
Introduction
dsh-web-restart
True hot-loading for dsh web: after installing plugins, editing config, or upgrading dsh itself, see the effect immediately — no more manually restarting from the command line.
English | 简体中文
Changelog
v2.0.0 (hot install, no restart)
- 🎉 Hot install/uninstall — installing/removing plugins no longer restarts.
Bundled
dsh-web-hothost plugin hot-applies patch rows viainclude.updateat runtime; the PID never changes. - ✨ New commands:
dsh-web install <spec>(hot first, fallback to safe restart),dsh-web remove <pkg>(hot first, fallback to safe restart). - 🛡️
dsh-web session: report the resolved tmux session (auto-discovered, never assumesdsh-web). - 📦 Module-level code updates still require a restart (Node require cache) — structural limit, falls back automatically.
v1.0.0 (safe restart)
- First release: tmux hosting + tmux-server independent delayed restart, covering plugin changes, config edits, and dsh upgrades.
- Crash auto-restart with a 3-strike circuit breaker; port/session auto-discovery; bilingual README.
The problem it solves (what we actually hit)
While using dsh web, I found that DSH has three kinds of changes that require a process restart to take effect — installing/removing/updating plugins (bundle layers are composed at startup), editing profile config (cordis.patch.yml), and upgrading the dsh package itself.
Every time, I had to leave the conversation, go to the command line, re-type dsh web, and refresh the page to see the effect:
- ❌ Not timely: can't see plugin effects right after installing
- ❌ Manual: even when an agent installed the plugin in conversation, I still had to open a terminal
- ❌ Fragile: killing the process directly also kills the running agent session ("many rounds never finished")
This skill syncs "hot reload" and "hot restart" — things that DSH already hot-reloads (skills, AGENTS.md, settings) keep hot-reloading; plugin installs now hot-apply without a restart, and everything that genuinely must restart (config edits, dsh upgrade) is restarted safely and automatically by the agent. dsh web becomes truly hot-loadable: install a plugin in conversation, it's active immediately — no more manual restarts.
Quick Start
Three ways to install, pick any:
① Install via conversation (recommended) — say this in a DSH conversation (include the repo URL so the agent knows where to install from):
The agent installs and loads the skill automatically (skills are hot-loaded — ready immediately, no restart needed).
② One-line install — in your own terminal:
npx -y skills add https://github.com/jifeng15/dsh-web-restart -g -y -a universal --copy
③ Clone & manual install — if you want to inspect the source first:
git clone https://github.com/jifeng15/dsh-web-restart.git && cd dsh-web-restart
bash install.sh
Ready after install (see "Two Usage Scenarios" below).
Two Usage Scenarios (both supported)
Scenario A: Via conversation (recommended) — you type nothing
After installing this skill, say in conversation "install plugin XX for me" (XX = any other plugin, e.g. dsh-market) or "upgrade dsh for me". The agent will:
- Load this skill automatically
- Install the plugin / upgrade dsh
- Automatically call
dsh-web installfor plugins (hot install, no restart) ordsh-web upgradefor dsh itself — the agent calls the script directly, you never touch the command line - For hot installs, the plugin is active immediately; for upgrades, you just refresh the page
For: users who manage plugins through DSH conversations. This is the skill's primary scenario — it's designed for agents.
First use note: the very first time you hot-install, the agent automatically installs the hot-install component and restarts once (so it can load) — you just refresh that once. After that, every plugin install is no-restart.
Scenario B: Manual command line — full control
If you prefer the terminal, install/remove plugins with the hot commands (no restart), and use restart for everything else:
dsh-web install <spec> # Install plugin: hot install (no restart) if available, else safe restart
dsh-web remove <pkg> # Remove plugin: hot uninstall if available, else safe restart
dsh-web restart # Fallback/other: safe restart after config edits, dsh upgrade, or when hot apply is unavailable
dsh-web session # Report the resolved tmux session (auto-discovered)
dsh-web status # Check status anytime
Hot first, safe restart as fallback:
install/removetry the bundled dsh-web-hot (no restart, PID unchanged). If hot apply is unavailable (plugin not loaded, module-level code update, or the change can't be hot-applied), they fall back to a safe restart automatically.restartremains the unified command for config edits, dsh upgrade, and migration.Why the "extra step" is unavoidable: the skill's automation trigger is the agent — when you install via conversation, the agent is present and auto-invokes it; but when you install from your own terminal, no agent is involved, so you must run it manually once. This one-time step is worth it: it migrates dsh web into tmux hosting, and after that everything (conversation-driven) is fully automatic.
For: CLI users, script automation, and agent-internal calls. All commands automatically handle tmux hosting, port discovery, and session discovery — no preparation needed.
At a Glance: What It Can / Can't Do
| ✅ Can | ❌ Can't |
|---|---|
| Hot install/uninstall plugins via bundled dsh-web-hot — no restart (falls back to safe restart if unavailable) | Agent continuing seamlessly after restart — restart briefly disconnects, you refresh (structural limit) |
| Auto-restart dsh web after plugin changes, config edits, or dsh upgrade — no manual commands (conversation) | Hot-apply module code updates (Node require cache — must restart) |
reload takes effect after editing profile config (cordis.patch.yml) | Auto-recover after reboot (you re-run dsh-web start once) |
| No tmux? Auto-installs it (macOS/Linux package managers) | Auto-upgrade non-npm/pnpm dsh installs (only hints) |
| dsh web running in a plain terminal? Auto-migrates into tmux | Skill additions, AGENTS.md edits, etc. (these already hot-reload; not needed here) |
Session not named dsh-web? Auto-discovers the hosting session | Crash auto-restart is a separate opt-in (run-loop) |
Port not 3080? Auto-discovers (incl. --port 0 random ports) | — |
| All terminals closed — dsh web keeps running, restartable anytime | — |
In one line: install/uninstall plugins without restarting (hot), and for everything that genuinely must restart (config edits, dsh upgrade, migration), it restarts safely and keeps dsh web resident — you just refresh after the brief disconnect.
Commands
dsh-web install <spec> # ★ Install plugin: hot install (no restart) if available, else safe restart
dsh-web remove <pkg> # ★ Remove plugin: hot uninstall if available, else safe restart
dsh-web restart # ★ Fallback/other: unified safe restart after plugin changes, config edits, or dsh upgrade
dsh-web start # Start / auto-takeover (create session if none, migrate into tmux if unmanaged)
dsh-web stop # Stop
dsh-web status # Check session/port/PID/logs
dsh-web attach # Enter tmux for troubleshooting
dsh-web autostart-on # Enable autostart at login (default OFF, user opt-in; launchd/systemd)
dsh-web autostart-off # Disable autostart
dsh-web autostart-status # Check autostart status
Hot install first, safe restart as fallback:
dsh-web install/removetry the bundled hot-plugin (dsh-web-hot) first — installing/uninstalling plugins without a restart. If hot apply is unavailable (plugin not loaded, or the change can't be hot-applied), it falls back to a safe restart automatically.dsh-web restartremains the unified command for everything else (config edits, dsh upgrade, migration).
Autostart is optional and OFF by default — the skill never enables autostart on its own. Run
dsh-web autostart-onwhen you want dsh web to start in tmux after login.
Port notification policy: after
start/restart, the actual port is written to~/.dsh/logs/last-port.txt. If the port is the default (3080), no notification (everyone knows it); if non-default (occupied/random), a system notification shows the actual port — especially useful for unattended autostart.
Conventions & Boundaries
| Item | Default | Override |
|---|---|---|
| tmux session name | dsh-web (auto-discovered if not found) | DSH_WEB_SESSION |
| Port | auto-discovered (explicit config > process --port > process listen port > node scan > default 3080) | DSH_WEB_PORT |
| Launch command | dsh web | DSH_CMD |
- Port auto-discovery: works even if you launched dsh web with
--port 8080or--port 0(random) — the script parses the actual port from the process command line or listening socket. - Closing all terminals is fine: tmux server is a daemon, detached sessions keep running, auto-restart still works.
- After reboot /
tmux kill-server: reopen dsh web however you like —dsh-web startis easiest (creates tmux + starts + hosts in one step); plaindsh webalso works, firstrestartauto-migrates into tmux (one extra migration, then fully automatic). - If tmux can't be auto-installed, platform-specific manual commands are printed.
How It Works (30-second version)
tmux run-shell -b "sleep 3; tmux send-keys -t dsh-web C-c; sleep 2; tmux send-keys -t dsh-web 'dsh web' Enter"
tmux server is an independent daemon — it doesn't depend on dsh web being alive. Even if the caller (agent) dies with dsh web, the restart still completes.
Architecture & Data Flow (technical)
Components
| Component | Role |
|---|---|
scripts/dsh-web.sh | Main CLI (start/restart/install/remove/upgrade/status/session/autostart-*) |
hot-plugin/ (dsh-web-hot) | Host plugin: hot install/uninstall via include.update (no restart) |
scripts/run-loop.sh | Crash auto-restart loop (3-strike circuit breaker) |
scripts/install-tmux.sh | Cross-platform tmux auto-install |
install.sh | One-shot install (skill + CLI + hot-plugin + tmux) |
Hot install (no restart) data flow
dsh-web.sh install <spec>
→ POST /dsh-web-hot/install {spec}
→ pnpm add <spec> (profile dir, official registry)
→ read bundle's dsh.bundle.patch → patch rows
→ write cordis.patch.yml (user patch layer, persistent)
→ include.update (hot apply, PID unchanged)
→ record dsh-web-hot.state.json
→ {"ok": true}
Safe restart data flow
dsh-web.sh restart
→ resolve_session (discover actual session, e.g. "0")
→ tmux run-shell -b "sleep 3; C-c; sleep 2; 'dsh web'"
→ tmux server executes independently (completes even if agent dies)
→ 5-8s later dsh web restarts; user refreshes
Environment dependencies
| Dep | Use | If missing |
|---|---|---|
| tmux | hosting + independent restart | auto-installed |
| pnpm | plugin install (via dsh-web-hot) | hot install degrades to safe restart |
| dsh CLI | install.sh hot-plugin install | hot-plugin skipped |
| curl/lsof/ps/pgrep | probing | — |
Pitfalls We Hit
- Synchronous restart = kills the host process = command interrupted → use
tmux run-shell -b nohup ... &background tasks get cleaned up when the caller's turn ends → use tmux server- GitHub tarball URL plugin installs leave pnpm lockfile missing
integrity→ usegithub:owner/repo#ref
License
MIT