feat: workspace aliases, tab groups of split panes, native path picker (v2.1.0)
- /api/workspaces and `agenthub workspace(s)` / `--workspace` as aliases of /api/lanes and `agenthub lanes` / `--lane`; old names print one stderr note. REPL `help lanes|workspace|workspaces` resolves through the aliases. - A workspace holds up to ten sessions (slots 0-9); every console tab is a group of 1-4 split panes (PaneGroups, agenthub.workspace.paneLayout); parseGroups keeps the stored active tab when an earlier one is dropped. - Browse button beside path fields: POST /api/lanes/pick-path opens the OS picker on the server's desktop — loopback only and no forwarding header (EREMOTE), a display failure is ENODIALOG not a Cancel, the dialog is killed when the request closes, a folder field falls back to the in-app browser on any failure. - Changes rail counts chip, image viewer (/git/raw), status bar session counts and per-day cost (`date=` on /api/pricing/cost). - /agenthub-open and /agenthub-doctor run from the INSTALLED build (supersededBy), doctor offers fixes behind two confirmations; plugin-open treats a locked bootstrap as non-fatal. - New-terminal shell waits for the first attach (issue #55). - repo-onboarding / debug-live-issue skills removed. - OpenAPI: pick-path, lane/date on /pricing/cost, tool on /run/history, /api/workspaces mount.
This commit is contained in:
@@ -1,41 +1,81 @@
|
||||
---
|
||||
description: Diagnose a plugin-installed AgentHub — Node, npm, disk, bootstrap, server, hooks, CLI, systemd, tmux, UI build
|
||||
description: Diagnose a plugin-installed AgentHub — Node, npm, disk, bootstrap, server, hooks, CLI, systemd, tmux, UI build — and offer to fix what it finds
|
||||
---
|
||||
|
||||
Run the diagnostic and report what it found. Do not fix anything unless the user
|
||||
asks.
|
||||
## 1. Diagnose
|
||||
|
||||
Every command here runs from the plugin build that is installed NOW (`ROOT`):
|
||||
a session not restarted after an update still names the old build in
|
||||
`${CLAUDE_PLUGIN_ROOT}`, which would warn about itself forever. The shell does
|
||||
not keep `ROOT` between commands, so each command block below resolves it
|
||||
again:
|
||||
|
||||
```bash
|
||||
node "${CLAUDE_PLUGIN_ROOT}/scripts/plugin-doctor.js"
|
||||
ROOT=$(node -e 'console.log(require(process.argv[1]).supersededBy() || "")' \
|
||||
"${CLAUDE_PLUGIN_ROOT}/scripts/plugin-bootstrap.js")
|
||||
ROOT="${ROOT:-${CLAUDE_PLUGIN_ROOT}}"
|
||||
node "$ROOT/scripts/plugin-doctor.js"
|
||||
```
|
||||
|
||||
Print the output verbatim, then add at most three lines of guidance based on the
|
||||
`FAIL` and `WARN` rows:
|
||||
Print the output verbatim. If every row is `OK`, stop there — no summary of
|
||||
things that passed.
|
||||
|
||||
- `FAIL Node` → the installed Node is too old for `node:sqlite`; the server
|
||||
cannot start until Node is upgraded.
|
||||
- `FAIL Hooks` → duplicate hook entries double every token and cost figure.
|
||||
Starting a new Claude Code session removes them automatically (the bootstrap
|
||||
backs the file up as `settings.json.agenthub-bak` first).
|
||||
- `FAIL Server` → run `/agenthub-update`, then check
|
||||
`~/.claude/agenthub/runtime/bootstrap.log` and `server.log`.
|
||||
- `FAIL Runtime deps` → the install is incomplete, not merely absent. Delete
|
||||
`~/.claude/agenthub/runtime/node_modules` before running `/agenthub-update`;
|
||||
reinstalling over the broken tree is what let it survive.
|
||||
- `FAIL npm` or `FAIL Disk` → nothing else in the report can be trusted until
|
||||
these are fixed; both silently truncate installs.
|
||||
- `WARN agenthub CLI` → print the exact `export PATH=...` line from the output.
|
||||
- `WARN systemd` → when it says the unit names a **previous plugin version**,
|
||||
the dashboard is running now but will NOT come back after a reboot. Starting
|
||||
a new Claude Code session repairs it; print the `--force` command from the
|
||||
output as the immediate fix. "installed but not running" just needs
|
||||
`systemctl --user start agenthub`.
|
||||
- `WARN tmux` → only the run console, `agenthub lanes shell` and the
|
||||
session-reload keystrokes are affected; monitoring, workspaces and the CLI are not.
|
||||
Print the install command from the output. If the row says `ok` but Start Run
|
||||
still fails, the server has a different PATH than this check — ask it directly
|
||||
with `curl -s localhost:4820/api/run/tmux`.
|
||||
- `WARN Dashboard UI` → run `/agenthub-open` to build the bundle. When the row
|
||||
quotes a build error, report that error — it is the actual problem.
|
||||
## 2. Offer to fix
|
||||
|
||||
No preamble, no summary of things that passed.
|
||||
If any row is `FAIL` or `WARN`, say in one line per row what is wrong (use the
|
||||
guide below), then ask with `AskUserQuestion`: **"Tự động sửa các lỗi trên?"**
|
||||
(answer in the user's language) — options "Có, cho tôi xem danh sách việc sẽ
|
||||
làm" and "Không". On "Không", stop.
|
||||
|
||||
## 3. Show the plan, get approval
|
||||
|
||||
Build the plan from the table below: only the rows that are not `OK`, in the
|
||||
table's order, each with the EXACT command you will run. Merge duplicates — one
|
||||
`plugin-bootstrap.js --force` covers every row marked *bootstrap*. Rows marked
|
||||
*report only* go in a separate "cannot fix automatically" list. Print the plan
|
||||
as a numbered list, then ask with `AskUserQuestion`: **"Thực hiện các bước
|
||||
trên?"** — "Đồng ý" / "Không". Do nothing until the user agrees.
|
||||
|
||||
Detect what the commands need before printing them: the OS (`uname -s`), the
|
||||
package manager (`apt-get`, `dnf`, `pacman`, `brew`), a Node version manager
|
||||
(`nvm`, `fnm`, `volta` — check with `command -v` or `~/.nvm/nvm.sh`), the
|
||||
user's shell rc file from `$SHELL`, and whether `sudo -n true` works.
|
||||
|
||||
| Row | Fix |
|
||||
|---|---|
|
||||
| `FAIL Node` / `FAIL npm` | Install Node ≥ 22.5 (it ships npm). Prefer the user's version manager (`nvm install 22 && nvm alias default 22`, `fnm install 22 && fnm default 22`, `volta install node@22`); else `brew install node` (macOS) or the distro's package (`sudo apt-get install -y nodejs` only when it is ≥ 22.5 — otherwise propose nvm). Then run the *bootstrap* step with THAT node's absolute path, since the `agenthub` CLI launcher pins the node that ran the bootstrap. |
|
||||
| `FAIL Disk` | *Report only.* Show what is large (`du -sh "<Data dir>"/* 2>/dev/null`, the `Data dir` row's path); never delete user data. |
|
||||
| `FAIL Runtime deps` | `rm -rf "<Data dir>/runtime/node_modules"` (the `Data dir` row's path), then *bootstrap* — reinstalling over the broken tree is what lets it survive. |
|
||||
| `WARN Runtime deps`, `WARN Bootstrap`, `FAIL Server`, `FAIL Hooks`, `WARN agenthub CLI` "no launcher", `WARN systemd` "previous plugin version" | *bootstrap* (it reinstalls deps, removes the duplicate hook entries after backing up `settings.json` as `settings.json.agenthub-bak`, rewrites the CLI launcher and the unit, and restarts the server). |
|
||||
| `WARN agenthub CLI` "not on PATH" | Append the exact `export PATH=...` line from the row to the shell rc file — only if that file does not already contain it. |
|
||||
| `WARN systemd` "not running" | `systemctl --user start agenthub` (Linux) / `agenthub service install` (macOS LaunchAgent). |
|
||||
| `WARN systemd` "not written by AgentHub" | *Report only* — it is the user's unit. |
|
||||
| `WARN tmux` "not found" | `sudo apt-get install -y tmux` / `sudo dnf install -y tmux` / `sudo pacman -S --noconfirm tmux` / `brew install tmux`. |
|
||||
| `WARN tmux` older than 3.7 | macOS: `brew upgrade tmux`. Linux: *report only* — building tmux from source is the user's call; quote the row's instructions. |
|
||||
| `WARN tmux` "running tmux server is" | *Report only* — it clears once every tmux session has closed. Never run `tmux kill-server`. |
|
||||
| `WARN Dashboard UI` | the *bootstrap* step's `ROOT` lines, then `node "$ROOT/scripts/plugin-open.js" --force`, as ONE command — skip it when this doctor run was started by `/agenthub-open` (it re-runs the build itself). |
|
||||
|
||||
The *bootstrap* step, run as ONE command so `ROOT` survives (it runs from the
|
||||
plugin build that is installed now — an older build's bootstrap refuses):
|
||||
|
||||
```bash
|
||||
ROOT=$(node -e 'console.log(require(process.argv[1]).supersededBy() || "")' \
|
||||
"${CLAUDE_PLUGIN_ROOT}/scripts/plugin-bootstrap.js")
|
||||
ROOT="${ROOT:-${CLAUDE_PLUGIN_ROOT}}"
|
||||
node "$ROOT/scripts/plugin-bootstrap.js" --force
|
||||
```
|
||||
|
||||
## 4. Fix, then verify
|
||||
|
||||
Run the approved steps in order, one at a time, and stop at the first one that
|
||||
fails: quote its decisive error line (for the bootstrap, from
|
||||
`<Data dir>/runtime/bootstrap.log`) and ask how to continue.
|
||||
|
||||
- Run nothing that is not in the approved plan. If a step turns out to need
|
||||
something else, ask again first.
|
||||
- A `sudo` command when `sudo -n true` failed cannot be typed from here: ask
|
||||
the user to run it themselves as `! <command>`, wait, then continue.
|
||||
- A shell rc change only reaches new terminals — say so.
|
||||
|
||||
Finish by running the diagnosis again (step 1's command, `ROOT` lines included) and printing it verbatim, then at most
|
||||
three lines on what is still not `OK` and why.
|
||||
|
||||
@@ -1,14 +1,23 @@
|
||||
---
|
||||
description: Rebuild the dashboard UI and print its URL
|
||||
description: Rebuild the dashboard UI and print its URL — runs the doctor when it fails
|
||||
---
|
||||
|
||||
Rebuild the dashboard bundle, then print the URL. Always forces a rebuild so a
|
||||
stale bundle (e.g. after a fix commit landed but the bootstrap's build predates
|
||||
it) never serves silently. Also finishes the build if the bootstrap's own
|
||||
attempt failed (check `~/.claude/agenthub/runtime/client-build.log`).
|
||||
attempt failed (check `client-build.log` in the runtime dir — `<data dir>/runtime`,
|
||||
by default `~/.claude/agenthub/runtime`).
|
||||
|
||||
Run it from the plugin build that is installed NOW, as ONE command so `ROOT`
|
||||
survives — a session not restarted after an update still names the old build
|
||||
in `${CLAUDE_PLUGIN_ROOT}`, whose bootstrap refuses to run (`superseded`) and
|
||||
whose client would be built over the new one:
|
||||
|
||||
```bash
|
||||
node "${CLAUDE_PLUGIN_ROOT}/scripts/plugin-open.js" --force
|
||||
ROOT=$(node -e 'console.log(require(process.argv[1]).supersededBy() || "")' \
|
||||
"${CLAUDE_PLUGIN_ROOT}/scripts/plugin-bootstrap.js")
|
||||
ROOT="${ROOT:-${CLAUDE_PLUGIN_ROOT}}"
|
||||
node "$ROOT/scripts/plugin-open.js" --force
|
||||
```
|
||||
|
||||
Install + build takes a few minutes if the client toolchain isn't already
|
||||
@@ -19,7 +28,14 @@ re-runs bootstrap first and prints `Server restarted on the current plugin
|
||||
version.` (without it, the fresh bundle would call routes that old server
|
||||
never had).
|
||||
|
||||
Then help the user open it:
|
||||
**If it exits non-zero** (a failed build, or a bootstrap that did not bring the
|
||||
server up): quote its error line, say you are running the doctor, then read
|
||||
`$ROOT/plugins/agenthub/commands/agenthub-doctor.md` (the `ROOT` resolved above)
|
||||
and follow it from step 1 — diagnose, offer to fix, show the plan, fix only what
|
||||
the user approves. After the fixes, run the `plugin-open.js --force` command
|
||||
above once more; if it fails again, report its error and stop.
|
||||
|
||||
On success, help the user open the URL:
|
||||
|
||||
```bash
|
||||
uname -s
|
||||
|
||||
@@ -23,29 +23,31 @@ else
|
||||
fi
|
||||
```
|
||||
|
||||
That downloads the new version into `~/.claude/plugins/cache/` but does not
|
||||
take effect in *this* session — Claude Code only re-resolves `${CLAUDE_PLUGIN_ROOT}`
|
||||
on `/reload-plugins` (a REPL-only action, not scriptable from a command). Say
|
||||
so plainly: **tell the user to run `/reload-plugins` now**, then either
|
||||
re-run `/agenthub-update` (this time the bootstrap step below runs against the new
|
||||
version) or just start a new session — `plugin-bootstrap.js` compares the
|
||||
recorded state against the current plugin version on every `SessionStart` and
|
||||
rebuilds automatically if they differ.
|
||||
|
||||
Then, whether or not a plugin update was just pulled, refresh the runtime
|
||||
against whatever `${CLAUDE_PLUGIN_ROOT}` currently resolves to. This stops the
|
||||
running dashboard server before starting the new one. Say so, then run:
|
||||
That downloads the new version into a NEW directory under
|
||||
`~/.claude/plugins/cache/`, while `${CLAUDE_PLUGIN_ROOT}` in this session still
|
||||
names the old one — and the old build's bootstrap refuses to run once a newer
|
||||
build is installed (`supersededBy`). So refresh the runtime from the build that
|
||||
is installed now: the new directory when one was just pulled, else this one.
|
||||
This stops the running dashboard server before starting the new one. Say so,
|
||||
then run:
|
||||
|
||||
```bash
|
||||
node "${CLAUDE_PLUGIN_ROOT}/scripts/plugin-bootstrap.js" --force
|
||||
ROOT=$(node -e 'console.log(require(process.argv[1]).supersededBy() || "")' \
|
||||
"${CLAUDE_PLUGIN_ROOT}/scripts/plugin-bootstrap.js")
|
||||
ROOT="${ROOT:-${CLAUDE_PLUGIN_ROOT}}"
|
||||
echo "Refreshing the AgentHub runtime from $ROOT"
|
||||
node "$ROOT/scripts/plugin-bootstrap.js" --force
|
||||
node "$ROOT/scripts/plugin-doctor.js"
|
||||
```
|
||||
|
||||
It runs in the foreground and can take a few minutes on a cold cache. When it
|
||||
finishes, verify:
|
||||
Run it as ONE command (the shell does not keep `ROOT` between commands). The
|
||||
bootstrap runs in the foreground and can take a few minutes on a cold cache;
|
||||
the doctor that follows verifies the result.
|
||||
|
||||
```bash
|
||||
node "${CLAUDE_PLUGIN_ROOT}/scripts/plugin-doctor.js"
|
||||
```
|
||||
If a new version was pulled, tell the user the dashboard already runs it, but
|
||||
this Claude Code session still loads the old plugin's commands and skills until
|
||||
they run `/reload-plugins` or start a new session.
|
||||
|
||||
Report the final state in a few lines. If the bootstrap failed, quote the
|
||||
decisive line from `~/.claude/agenthub/runtime/bootstrap.log`.
|
||||
decisive line from `bootstrap.log` in the runtime dir (`<Data dir>/runtime` —
|
||||
the doctor's `Data dir` row; by default `~/.claude/agenthub/runtime`).
|
||||
|
||||
Reference in New Issue
Block a user