Files
AgentHub/docs/PLUGINS.md
T
nntrivi2001 478418f602 fix(macos): scrub parent-session env, survive node upgrades and reboots, store lanes by real path (#22)
What broke (code audit, untested on a Mac):
- Without systemd the server is always spawned from inside a Claude Code
  session, so it inherited CLAUDECODE, CLAUDE_CODE_SESSION_ID,
  CLAUDE_PLUGIN_ROOT, ... and tmux handed them to every lane pane (a codex
  pane even resolved as `claude` in `agenthub`'s harness check).
- The ~/.local/bin/agenthub launcher pinned a versioned node path that
  `brew upgrade`/nvm deletes, leaving the CLI dead until the next bootstrap.
- A discovery entry left over from before a reboot could name a recycled pid,
  so the bootstrap's fast path believed a dashboard was live and
  stopDashboard could signal an unrelated process.
- Lanes were stored under the typed cwd; macOS reports /private/tmp and the
  on-disk case, so sessions never bound to a /tmp or differently-cased lane.

What changed:
- server/index.js deletes a DENYLIST of parent-session variables at startup;
  user config (CLAUDE_CONFIG_DIR, CLAUDE_CODE_USE_BEDROCK, ANTHROPIC_*) stays.
- linkCli's launcher falls back to `node` on PATH when the pinned one is gone.
- liveServers ignores entries whose startedAt predates this boot (60 s margin).
- createLane and POST /api/lanes/ensure store/look up fs.realpathSync.native
  of an existing cwd; the liveness reaper also tries the realpath. Existing
  rows are untouched.
- session-liveness gains an exec seam so the darwin ps+lsof branch is tested.
- plugin-doctor names ~/.zshrc on darwin; INSTALL.md gains a macOS section
  with the Mac verification checklist, mirrored in both READMEs and PLUGINS.md.
No launchd, no macOptionIsMeta, engines stays >=20.
2026-09-25 11:23:59 +07:00

45 KiB
Raw Blame History

AgentHub — Plugin Marketplace

Official Claude Code plugins for the Agent Monitor dashboard. The agenthub plugin is the dashboard — hooks, server and the agenthub CLI, no checkout required. (It shipped an MCP server until c7dbaf2, which dropped it; the dashboard reads Claude Code's MCP configuration in the config explorer but no longer serves one.) On top of it, 10 focused plugins extend Claude Code with skills, agents, slash commands, hooks, and CLI tools for deep analytics, cost guardrails, productivity automation, developer tools, AI-powered insights, session forensics, workflow/fleet intelligence, reliability & SLOs, config & memory governance, and dashboard connectivity.

Every plugin is powered by the local Agent Monitor REST API at http://localhost:4820. They are read-only advisors unless a skill explicitly documents a mutating endpoint (and those preview + confirm before acting).

Quick Start

Add the marketplace

claude plugin marketplace add https://git.smartgift.io.vn/Smartgift-AI/AgentHub.git

Install the dashboard itself

claude plugin install agenthub@agenthub

That is the whole install: no clone, no npm run setup, no npm run install-hooks, no manual npm start. See The agenthub plugin below for what it does on first session start.

Or via the Smartgift skills marketplace

agenthub is also listed as a standalone entry in smartgift-claude-skills — its source still points at this repo's main branch, so the two entries install identically:

claude plugin marketplace add https://git.smartgift.io.vn/Smartgift-AI/smartgift-claude-skills.git
claude plugin install agenthub@sg

Pick whichever marketplace you already have added; installing agenthub from both at once is redundant but harmless (Claude Code treats it as one plugin per marketplace name, not per source).

Install a focused plugin

claude plugin install agenthub-analytics@agenthub
claude plugin install agenthub-cost-guard@agenthub
claude plugin install agenthub-productivity@agenthub
claude plugin install agenthub-devtools@agenthub
claude plugin install agenthub-insights@agenthub
claude plugin install agenthub-sessions@agenthub
claude plugin install agenthub-workflows@agenthub
claude plugin install agenthub-quality@agenthub
claude plugin install agenthub-config@agenthub
claude plugin install agenthub-dashboard@agenthub

Or install locally during development

# From the repo root, test a plugin locally
claude --plugin-dir plugins/agenthub-analytics

Prerequisites

  • Claude Code installed and authenticated
  • Node >= 22.5 when installing via the agenthub plugin. A plugin install has no native better-sqlite3, so the server stores data through node:sqlite, which landed in 22.5. The bootstrap refuses with one line on anything older instead of letting the server crash. (A checkout install still works on Node >= 20.)
  • The Agent Monitor dashboard reachable at http://localhost:4820 — the agenthub plugin starts it for you; a checkout starts it with npm start (see SETUP.md)

Skills and commands are invoked as /agenthub-<plugin>:<name>. Agents are dispatched automatically by Claude Code (or named explicitly).

The agenthub plugin

The marketplace's root entry ("source": "./") is the entire repository, so server/, client/, scripts/ and bin/agenthub.js all land under ${CLAUDE_PLUGIN_ROOT} when Claude Code caches it. That is what makes a checkout unnecessary.

What it installs

Component Where it comes from
The eight event hooks inline hooks in .claude-plugin/plugin.json, each running scripts/hook-handler.js
The dashboard server started detached by the bootstrap, from the plugin cache
The agenthub CLI a launcher written to ~/.local/bin/agenthub
The dashboard UI (/run and every other client route) built into the runtime dir by the bootstrap, so it works the moment claude starts
/agenthub-doctor, /agenthub-update, /agenthub-open plugins/agenthub/commands/
/ship-full, /ship-quick and one command per pipeline node (/intake, /plan, /implement, /tests, /e2e, /review, /qc, /gate, /publishing, /pr-open, /done, …) plugins/agenthub/commands/, one file per name
The skills (ship-feature-lane, ship-feature, repo-onboarding, debug-live-issue, update-project-docs, file-headers) skills/ at the repo root — which IS the plugin root, so they are auto-discovered as plugin skills
The agents (qc-local, senior-gate-reviewer, backend-reviewer, frontend-reviewer) agents/ at the repo root, auto-discovered the same way — exposed as agenthub:<name>

Plugin skills are namespaced: they are invoked as /agenthub:<name>, with the bare /<name> working as an alias unless another skill or command claims that name. This is why skills/ sits at the repo root instead of .claude/skills/ — the latter only loads for a session whose cwd is inside this checkout, which is useless for a lane working in a different repo. agenthub skills install survives as the fallback for a plain checkout without the plugin.

The agents ship the same way, from the same files. agents/ at the repo root holds all four (qc-local, senior-gate-reviewer, backend-reviewer, frontend-reviewer), so the plugin exposes them as agenthub:<name>. agenthub lanes agents install copies qc-local + senior-gate-reviewer from that same directory into a lane's own .claude/agents/ — the highest-priority agent source — which is what makes the bare subagent_type: qc-local in the pipeline skill resolve there. One source file, two ways to reach it; the skill names the bare form first and falls back to the agenthub: form. On a codex lane the same command installs the <!-- agenthub:stage:start --> block in the lane's AGENTS.md instead — Codex never reads .claude/agents/.

Because the plugin ships the hooks itself, npm run install-hooks is not needed for plugin users — and must not be run alongside it. Events carry no id, so two handlers mean every token and cost figure is counted twice. claude plugin install writes the plugin's own hook entries into ~/.claude/settings.json too (${CLAUDE_PLUGIN_ROOT} resolved to the actual cache path) — confirmed against a real install — so those entries also contain hook-handler.js, same as a leftover checkout install. The bootstrap tells them apart by whether the command resolves under ~/.claude/plugins/cache/: only genuine checkout paths are removed (backing ~/.claude/settings.json up as settings.json.agenthub-bak first), never the plugin's own. /agenthub-doctor reports the state using the same check.

First session start

scripts/plugin-bootstrap.js runs from SessionStart. It returns within milliseconds — the real work happens in a detached worker, so a session never waits on an install:

  1. Fast path — recorded state matches this plugin build and a server is live → exit. "Live" means a discovery entry whose pid answers AND whose startedAt is after this boot (60 s margin): an entry left over from before a reboot names a pid the OS may have handed to an unrelated process, and without systemd (macOS) nothing else clears it.
  2. Superseded check — if Claude Code records a DIFFERENT build of this plugin as installed, this one logs a line and does nothing else (see A retired build never acts).
  3. Node gate — refuse below 22.5 with one line (see Prerequisites).
  4. Lock — atomic mkdir lock holding the PID; reclaimed when the owner is dead or the lock is older than 10 minutes, so two sessions cannot race the install or spawn two servers.
  5. Install — npm install --omit=dev --ignore-scripts into the runtime dir (never into the plugin cache, which is garbage-collected and replaced on every update). --ignore-scripts keeps the root postinstall from pulling the whole Vite client toolchain.
  6. Legacy hook cleanup — see above.
  7. CLI — write the ~/.local/bin/agenthub launcher, never clobbering a agenthub the bootstrap did not write. It pins the node that ran the bootstrap and falls back to node on PATH when that binary is gone (a Homebrew Cellar or nvm path deleted by an upgrade).
  8. UI build — client/ is copied into the runtime dir and built there (npm ci --include=dev, falling back to npm install --include=dev, then npm run build), landing in runtime/client-dist — the same directory the server serves from. --include=dev is required, not tidy: the entire build toolchain (vite, typescript, @vitejs/plugin-react, tailwindcss, @types/*) is a devDependency, and npm reads an inherited NODE_ENV=production as --omit=dev. Every bootstrap descended from the running server carries that env — the self-update chain, and any SessionStart fired by a claude inside a tmux pane the server started — so without the flag the install drops vite and the build dies on missing types. Skipped when a bundle for the current version already exists; a failure here does not fail the bootstrap (the API still works, and /agenthub-open can retry) but does mean /run 404s until it's fixed — and when a bundle from the PREVIOUS version is still on disk the failure is quieter still: the dashboard keeps serving the old UI against the new API, visible only as the Settings page's UI build vX (rebuild client to match) line.
  9. Server — on Linux with systemd --user available, install/refresh a agenthub.service unit (see Auto-start on boot) instead of a bare spawn, so the server is supervised and comes back after a reboot with no Claude Code session involved. Everywhere else (macOS, Windows, or no systemd), spawn server/index.js detached, with NODE_PATH at the runtime node_modules and DASHBOARD_CLIENT_DIST at the runtime client-dist — scoped to this session, same as before this fell back to systemd.
  10. Record state — runtime/state.json.
  11. Prune retired cache copies — delete the plugin-cache directories earlier updates left behind (see Pruning the plugin cache). After step 10, so a prune that goes wrong cannot also cost the record of a bootstrap that went right.
  12. Hand over to systemd — only when a unit of ours already owns the server (see Who may stop the server). Deliberately after step 10.

The first run takes a few minutes — most of it is the UI build, which is what makes client-only routes (http://localhost:4820/run, and every other page) work the moment claude starts, with no manual /agenthub-open step. Progress goes to ~/.claude/agenthub/runtime/bootstrap.log; npm run build's own output goes to client-build.log next to it; the server's own output goes to server.log.

A retired build never acts

claude plugin update unpacks the new version into a new cache directory and prints "Restart to apply changes". A Claude Code process that was already running does not: it keeps loading the OLD directory — skills, commands and hooks included — until it is restarted.

That used to be self-inflicting. Every session such a process opened ran the OLD plugin-bootstrap.js, which saw a state.json naming a different root, concluded the server had to be replaced, repointed agenthub.service at itself and restarted the dashboard onto the version the user had just upgraded away from. The dashboard then reported the old version and offered the update again — once per session, forever, while installed_plugins.json and the cache both said the new version was installed. A /agenthub-update from that session "succeeded" and changed nothing.

So the bootstrap now asks first (supersededBy): if Claude Code's ~/.claude/plugins/installed_plugins.json records a sibling directory as the installed build of this plugin, this build logs one line and returns superseded without touching dependencies, the unit, or the server. --force does not override it — the self-update chain runs --force from the NEW directory, which is never superseded, so the only --force this can refuse is one that would deliberately downgrade.

It cannot hand over to the new build either: the process it would have to replace is the one loading it. Restarting Claude Code is the fix, and the log line says so.

Matching is by sibling directory rather than by the <plugin>@<marketplace> key, which holds without parsing a cache path or trusting a name. An entry pointing at a directory that no longer exists is ignored — a phantom must never wedge a bootstrap shut.

Pruning the plugin cache

Claude Code unpacks every update beside the last one and does not reliably remove the old. A machine that tracks releases closely accumulates a full copy of this repo — node_modules and all — per release; a dozen of them is gigabytes.

Step 11 of the bootstrap (pruneRetiredPluginRoots) deletes them. This is the only place anything in the plugin touches the cache, and the rule it appears to break ("never write into the plugin cache") is about the runtime living outside it, not about keeping retired copies forever.

Four independent readings of "still in use" are protected, and nothing matching any of them is ever deleted:

Protected Why
This build It is running.
Every installPath in installed_plugins.json, at any scope Claude Code says it is installed.
The directory agenthub.service names (unitRoot, foreign unit included) A service is executing from it. Not ours to rewrite is still not ours to delete.
Any directory named in the user's settings.json hooks A Claude Code process that has not been restarted is still executing from there — this is the same directory the section above describes, seen from the other side. Deleting it would break that session's hooks mid-flight.

Plus the newest KEEP_RETIRED_ROOTS (1) of whatever is left, as a rollback cushion — one build deep, because a full copy of this repo is ~130 MB. Outside ~/.claude/plugins/cache/ the pruner does nothing at all — for a git checkout the parent directory holds the user's own work. Best effort throughout: a directory that will not delete is left alone, never an error.

Auto-start on boot

On Linux, every plugin bootstrap (not just the first) installs/refreshes a systemd --user service (~/.config/systemd/user/agenthub.service, managed via scripts/systemd-service.js — shared with the checkout path's agenthub service install, see the README). Its ExecStart/WorkingDirectory point at the current plugin cache path, so a plugin update that moves the cache directory rewrites and restarts the unit on the next session start, the same self-healing pattern the CLI launcher already uses. The bootstrap also tries loginctl enable-linger so the service starts on a cold boot before anyone logs in; when that needs elevated rights, it's skipped silently (check ~/.claude/agenthub/runtime/bootstrap.log, or run sudo loginctl enable-linger <user> once by hand). A pre-existing agenthub.service unit not written by this bootstrap is left untouched, and the server falls back to the old per-session detached spawn instead.

On macOS, Windows, or a Linux box without systemd, nothing changes: the server is a detached spawn started fresh on the next SessionStart after a reboot, same as always. That spawn inherits the Claude Code session's env, so server/index.js deletes the parent-session variables (CLAUDECODE, CLAUDE_CODE_SESSION_ID, CLAUDE_CODE_MESSAGING_*, CLAUDE_PLUGIN_ROOT, …) before anything else runs — otherwise tmux hands them to every lane pane. It is a denylist: user configuration such as CLAUDE_CONFIG_DIR, CLAUDE_CODE_USE_BEDROCK and ANTHROPIC_* passes through. There is no launchd agent; see INSTALL.md § macOS.

Who may stop the server

When a agenthub.service unit of ours exists, nothing else may stop the dashboard. The bootstrap that performs a self-update is spawned by the running server, so it lives inside that server's systemd cgroup. SIGTERM-ing the server from there breaks two ways at once:

  • the server exits 0, and the unit's old Restart=on-failure read a clean exit as "meant to stop" — so systemd did not bring it back;
  • KillMode=control-group (systemd's default) reaps every process in the cgroup when the main process exits, including the bootstrap itself — mid-run, before it could repoint the unit at the new plugin root or write runtime/state.json.

The result was a dashboard that went down on every self-update and stayed down until some later Claude Code session happened to bootstrap again, leaving a stale .bootstrap.lock and a state.json still naming the previous version.

So the order is fixed, and scripts/systemd-service.js splits its API to enforce it:

Situation What the bootstrap does
A unit of ours owns the server (unitIsOurs) Never stops it. writeUserService repoints the unit at the new plugin root without starting anything, the rest of the bootstrap runs, state is written, the lock is released — and only then restartUserService asks systemd to restart, with --no-block so being killed by its own request costs nothing.
No unit, or a foreign one Unchanged: stop the old server, then installUserService (or a detached spawn where there is no systemd). Nothing here is inside a unit's cgroup, so the stop is safe.

The unit is written with Restart=always, not on-failure: a graceful SIGTERM from anything at all would otherwise leave the dashboard down for good. An explicit systemctl stop — which is what agenthub service uninstall and the Settings panel do — still stops it.

agenthub service install (the checkout path) keeps using installUserService: it runs from your own shell, outside the unit's cgroup, so it may block and start in one step.

A unit pointing at a retired plugin root repairs itself on the next session. This is the residue an interrupted update leaves behind, and it is invisible while the dashboard is up: the server runs fine, every doctor row reads OK, and then a reboot starts a cache directory Claude Code deleted during the update — so the dashboard never comes back, for a reason nothing recorded. The fast path therefore checks it (unitIsStale, pure fs — it may not spawn a process on every SessionStart) and refuses to short-circuit, and the bootstrap rewrites the unit.

Repairing the unit is not restarting the server: when the running server is current and healthy, the corrected unit is simply left to take effect at the next start (pendingSystemdRestart = systemdOwned && needsServer). Restarting a working dashboard to fix a file that only matters at boot would be churn the user feels for nothing. For the same reason the detached-spawn fallback is guarded by needsServer — entering that branch for a stale unit alone would start a second server onto a port the live one already holds.

systemdOwned requires the unit to be active, not merely present: an installed-but-stopped unit owns nothing, and treating it as the owner would skip the stop and then ask systemd to bind an occupied port — a crash loop, courtesy of Restart=always.

Commands

Command Does
/agenthub-doctor Node version, bootstrap state, runtime deps, server liveness, duplicate hooks, CLI launcher + PATH, systemd (WARN when the unit names a retired plugin root — the dashboard will not survive a reboot — or when it is installed but stopped; no unit at all is fine), tmux (WARN when absent — only the run console, agenthub lanes shell and session reloads need it), skill plugins (see below), UI bundle
/agenthub-update Pull the latest agenthub release via claude plugin marketplace update + claude plugin update agenthub@<marketplace> -y, then reinstall dependencies and restart the server (plugin-bootstrap.js --force). The plugin pull needs a manual /reload-plugins afterward to take effect in the current session — not scriptable from a command.
/agenthub-open Rebuild the UI bundle and print the dashboard URL. Re-runs the bootstrap first when the server is down or still executing a plugin root that a mid-session /plugin update retired, so a fresh bundle never talks to an older server's routes
/ship-full <requirement> Put the lane on the 16-node ship-feature template, then run /agenthub:ship-feature-lane in this session. The in-session twin of agenthub ship-full (which spawns its own claude from a terminal)
/ship-quick <requirement> The same for the 8-node default template and /agenthub:ship-feature — stops at review/gate, no PR, no browser QC
One per pipeline node: /intake, /plan, /implement, /tests, /e2e, /e2e-passed, /review, /qc-plan, /qc, /gate, /publishing, /pr-open, /reported, /watching-pr, /merged, /done Run just that node's own command, resolved through agenthub lanes node <id> --print against whichever template the lane is on (matched by id or alias, so /implement works on default's implement and ship-feature's implementing). A slash-command node is invoked in the current session, never as a nested claude; anything else runs as a shell argv in the lane's cwd. None of them declares a stage

The Skill plugins row

Derived from the loaded pipeline templates, not hardcoded: every /plugin:skill string a template names — as the pipeline's own skill or as one node's command — has to come from an installed, enabled plugin. Today that means superpowers, which /agenthub:ship-feature and /agenthub:ship-feature-lane drive step by step (brainstorming, writing-plans, test-driven-development, verification-before-completion, finishing-a-development-branch). The review node is the exception: it names the bare /code-review, Claude Code's own review skill, which carries no plugin: prefix and so requires nothing to be installed. Install it with claude plugin install superpowers@claude-plugins-official.

The row is a WARN, never a FAIL: the dashboard, hooks and CLI all work without it, and only those two pipeline skills stop partway. A plugin listed but explicitly disabled counts as missing — Claude Code will not resolve its skills. The skills present as plain user skills under ~/.claude/skills/ count as satisfied, so a hand-copied setup is not reported as broken. A custom template in DASHBOARD_PIPELINES_DIR naming some other plugin's command is checked the same way.

Both the derivation and the missing/satisfied rules live in server/lib/skill-plugins.js, shared with the bootstrap below so the row and the install can never disagree about what is missing.

Automatic install, and why it is allowlisted

plugin-bootstrap.js installs the missing plugins itself, at the very end of its detached worker — never in the 10 s SessionStart hook, because the install clones from the network. It runs claude plugin install superpowers@claude-plugins-official --scope user -y; if that fails it registers the marketplace (claude plugin marketplace add anthropics/claude-plugins-official) and retries exactly once. Failure is logged with the manual command and nothing throws — the dashboard, hooks and CLI do not need these plugins.

The result is recorded as skillPluginsSettled in the bootstrap's state.json, which is also part of fastPathOk(): the check runs once per install, then the hot path reads one flag. /agenthub-update (--force) is the retry. AGENTHUB_AUTO_INSTALL_PLUGINS=0 (or false/off) turns it off entirely.

An installed plugin only resolves in the current session after /reload-plugins; a new session picks it up on its own. The log says so, since the worker is detached and cannot tell the session that started it.

Reporting is derived, installing is allowlisted. The row above reads plugin names out of the templates, which is right for a report. Installing from the same source would not be: a template is a file anyone can drop into DASHBOARD_PIPELINES_DIR, so it would turn "edit a JSON file" into "run this vendor's plugin install command on the next session". Auto-install therefore consults AUTO_INSTALLABLE, a fixed map in server/lib/skill-plugins.js, and skips every other requirement — visible in the doctor, never installed. Adding an entry there is a decision to install someone else's code on a user's machine without asking; it belongs in a review, not in a config file.

Where things live

Thing Location Survives a plugin update
SQLite DB, transcripts ~/.claude/agenthub/ yes
node_modules, client-dist, logs, lock, state.json ~/.claude/agenthub/runtime/ yes (re-verified on every session start)
Source, hooks the plugin cache version directory no — re-bootstrapped

The bootstrap deliberately does not set DASHBOARD_DATA_DIR: leaving the default keeps a plugin-run server and a developer's npm run dev server on one data directory, where ingestGroupKey already deduplicates hook ingest to a single port.

Uninstalling

claude plugin uninstall agenthub@agenthub only removes the plugin from the enabled list — verified against a real install/uninstall, not assumed. It does not:

  • stop the running server (it keeps serving from the now-uninstalled cache dir)
  • disable or remove the agenthub.service systemd --user unit (Linux) — it will keep restarting the old server on every reboot, since systemctl knows nothing about claude plugin uninstall
  • remove the cached source under ~/.claude/plugins/cache/.../agenthub/<version>/
  • remove the hook entries claude plugin install wrote into ~/.claude/settings.json (still pointing at that cache dir — they keep firing, and keep working, until the cache directory is eventually GC'd by Claude Code, at which point they silently start failing)
  • remove ~/.local/bin/agenthub or ~/.claude/agenthub/runtime/

For a clean machine, do all of this yourself:

# 1. Stop the server. On Linux, disable the systemd unit FIRST — the unit is
#    Restart=always, so a bare `kill` is always undone by systemd.
systemctl --user disable --now agenthub.service 2>/dev/null
rm -f ~/.config/systemd/user/agenthub.service && systemctl --user daemon-reload 2>/dev/null
# Fallback for a detached (non-systemd) server, or if the unit above was absent:
kill "$(node -e 'console.log(JSON.parse(require("fs").readFileSync(require("os").homedir()+"/.claude/.agenthub.json","utf8")).pid)')" 2>/dev/null

# 2. Runtime state and the CLI launcher
rm -rf ~/.claude/agenthub/runtime    # deps, UI bundle, logs, state
rm -f ~/.local/bin/agenthub

# 3. The hook entries claude plugin install wrote (settings.json is not
#    ours to fully own — back it up first and only drop entries mentioning
#    hook-handler.js)
node -e '
const fs = require("fs");
const p = require("os").homedir() + "/.claude/settings.json";
const d = JSON.parse(fs.readFileSync(p, "utf8"));
fs.copyFileSync(p, p + ".agenthub-bak2");
for (const [type, entries] of Object.entries(d.hooks || {})) {
  const kept = entries.filter((e) => !JSON.stringify(e).includes("hook-handler.js"));
  if (kept.length) d.hooks[type] = kept; else delete d.hooks[type];
}
fs.writeFileSync(p, JSON.stringify(d, null, 2) + "\n");
'

~/.claude/agenthub/ still holds the SQLite database after all of the above — delete that directory too only if you want the recorded history gone.

Available Plugins

1. agenthub-analytics — Analytics & Monitoring

Deep analytics on sessions, token usage, costs, cache efficiency, model mix, and productivity.

Skill Command Purpose
Session Report /agenthub-analytics:session-report Per-model tokens (input/output/cache_read/cache_write + baselines), cost, agent hierarchy, tool activity, timeline
Cost Breakdown /agenthub-analytics:cost-breakdown Per-model cost via the pricing engine, daily trends, cache efficiency, optimization opportunities
Usage Trends /agenthub-analytics:usage-trends 365-day session/event trends, token volume, tool rankings, model distribution, event-type ratios
Productivity Score /agenthub-analytics:productivity-score Weighted scorecard: completion, token efficiency, tool effectiveness, velocity, cost efficiency
Cache Efficiency /agenthub-analytics:cache-efficiency Cache hit rate, write-vs-read reuse, sessions with poor cache reuse
Model Mix /agenthub-analytics:model-mix Share of tokens and cost per model family; expensive models doing cheap work

Commands: /agenthub-analytics:cost-today · /agenthub-analytics:top-spenders · /agenthub-analytics:burn-rate

Agents: analytics-advisor (full advisor incl. workflow intelligence) · token-economist (token economics & reduction tactics)

Hooks: Logs Stop / SubagentStop events. CLI: agenthub-stats — terminal stats (sessions, cost, tokens).


2. agenthub-cost-guard — Budget Guardrails

Spend limits, forecasting, cost alerts, and model-routing savings.

Skill Command Purpose
Budget Set /agenthub-cost-guard:budget-set Define a budget and (optionally) arm a token_threshold alert rule; explains the $→token conversion
Spend Forecast /agenthub-cost-guard:spend-forecast Project week/month-end spend from the daily trend (moving average × remaining days)
Cost Alert /agenthub-cost-guard:cost-alert Review alert rules and fired alerts; explain exactly what tripped
Model Savings /agenthub-cost-guard:model-savings Estimate $ saved by routing eligible work to a cheaper model family
Daily Budget Check /agenthub-cost-guard:daily-budget-check Today's spend vs a daily budget, pace vs target, projected overage

Commands: /agenthub-cost-guard:budget · /agenthub-cost-guard:forecast · /agenthub-cost-guard:overspend

Agent: budget-sentinel — watches spend vs target, projects month-end, recommends cuts. Hooks: fail-safe Stop event POST so budget tracking sees session ends.


3. agenthub-productivity — Productivity & Workflows

Standups, weekly/monthly reviews, sprint tracking, focus analysis, and workflow optimization.

Skill Command Purpose
Daily Standup /agenthub-productivity:daily-standup Standup from recent sessions — work by project (cwd), costs, tools, errors, velocity
Weekly Report /agenthub-productivity:weekly-report Daily session/event trends, per-session costs, token volumes, tool top-20, completion rates
Sprint Summary /agenthub-productivity:sprint-summary Per-project + per-model costs, token efficiency, subagent effectiveness, retrospective data
Workflow Optimizer /agenthub-productivity:workflow-optimizer Tool-flow transitions, effectiveness, delegation, error propagation, concurrency, compaction
Monthly Review /agenthub-productivity:monthly-review Month-over-month sessions, cost, tokens, completion, top projects, notable shifts
Time of Day /agenthub-productivity:time-of-day Activity/productivity bucketed by hour and day-of-week; peak vs low-output windows

Commands: /agenthub-productivity:standup · /agenthub-productivity:whats-next · /agenthub-productivity:focus-report

Agents: productivity-coach (work-pattern review) · focus-analyst (deep-work / focus blocks). Hooks: session start/end timing.


4. agenthub-devtools — Developer Tools

Debugging, data-integrity inspection, event tracing, transcript search, diagnostics, export, and health checks.

Skill Command Purpose
Session Debug /agenthub-devtools:session-debug Full event chain, agent hierarchy, token usage with baselines, workflow intelligence
Hook Diagnostics /agenthub-devtools:hook-diagnostics Hook install, connectivity, handler validation, event delivery, data freshness
Data Export /agenthub-devtools:data-export Export sessions/events/analytics/costs as JSON/CSV/Markdown
Health Check /agenthub-devtools:health-check API, SQLite (WAL), WebSocket, endpoints, hooks, disk, data freshness
Event Trace /agenthub-devtools:event-trace Ordered event timeline for a session, highlighting gaps/failures
Transcript Grep /agenthub-devtools:transcript-grep Search a session transcript for a string/pattern with context

Commands: /agenthub-devtools:doctor · /agenthub-devtools:export · /agenthub-devtools:tail-events

Agents: issue-triager (cross-component triage) · db-inspector (data-integrity inspection). CLI: agenthub-doctor, agenthub-export.


5. agenthub-insights — AI-Powered Insights

Pattern detection, anomaly alerting, forecasting, regression watch, benchmarking, optimization, and comparison.

Skill Command Purpose
Pattern Detect /agenthub-insights:pattern-detect Tool-flow transitions, recurring sequences, agent co-occurrence, delegation habits
Anomaly Alert /agenthub-insights:anomaly-alert Cost/token/event-ratio/complexity outliers (statistical)
Optimization Suggest /agenthub-insights:optimization-suggest Model downgrades, cache optimization, compaction reduction, tool reliability
Session Compare /agenthub-insights:session-compare Side-by-side tokens, costs, complexity, tool-flow, metadata deltas
Regression Watch /agenthub-insights:regression-watch Rising error rate, falling cache hits, growing compaction, climbing cost/session
Benchmark /agenthub-insights:benchmark Benchmark a session vs the rolling average; show percentile

Commands: /agenthub-insights:insights · /agenthub-insights:compare · /agenthub-insights:anomalies

Agents: insights-advisor (strategic analysis) · trend-forecaster (near-future cost/usage projection).


6. agenthub-sessions — Session Forensics

Search, timeline, transcript replay, per-project rollups, and lifecycle management.

Skill Command Purpose
Session Search /agenthub-sessions:session-search Find sessions by project/model/status/date; rank by cost or recency
Session Timeline /agenthub-sessions:session-timeline Ordered timeline of one session's events with durations and tool names
Transcript Replay /agenthub-sessions:transcript-replay Walk a transcript turn-by-turn, summarizing each message
CWD Rollup /agenthub-sessions:cwd-rollup Roll up sessions by working directory: counts, cost, tokens, last-active
Session Cleanup /agenthub-sessions:session-cleanup Identify stale/empty sessions; preview before the cleanup endpoint deletes (confirm required)

Commands: /agenthub-sessions:find-session · /agenthub-sessions:replay · /agenthub-sessions:recent

Agent: session-investigator — end-to-end investigation of a single session.


7. agenthub-workflows — Orchestration & Fleet Intelligence

Multi-agent structure analysis using the workflow intelligence API and Workflow-tool run journals.

Skill Command Purpose
DAG Map /agenthub-workflows:dag-map Orchestration DAG: parent→child subagent edges, depth, fan-out
Delegation Audit /agenthub-workflows:delegation-audit Model delegation + subagent effectiveness; wasted delegations
Concurrency Report /agenthub-workflows:concurrency-report Concurrency lanes, parallelism, serialization bottlenecks
Error Propagation /agenthub-workflows:error-propagation Trace failures by depth and how they cascade across subagents
Fleet Runs /agenthub-workflows:fleet-runs Summarize Workflow-tool fleet runs (no-hook fleets ingested from run journals)

Commands: /agenthub-workflows:workflow · /agenthub-workflows:dag · /agenthub-workflows:runs

Agent: orchestration-analyst — analyzes the 11 workflow datasets + fleet runs.


8. agenthub-quality — Reliability & SLOs

Error monitoring, hook-delivery health, SLO tracking with error budgets, and regression alerts.

Skill Command Purpose
Error Scan /agenthub-quality:error-scan Scan events for APIError + failure signals; group by tool/model; rank by frequency
API Error Report /agenthub-quality:api-error-report APIError detail: counts over time, affected sessions/models, likely causes
Hook Failure Audit /agenthub-quality:hook-failure-audit PreToolUse/PostToolUse balance, missing terminators, stale ingestion
SLO Check /agenthub-quality:slo-check Completion rate, tool success rate, error rate; error budget remaining
Regression Alert /agenthub-quality:regression-alert Compare this period's error/failure rates to the prior period; optional alert rule

Commands: /agenthub-quality:errors · /agenthub-quality:slo · /agenthub-quality:health

Agent: reliability-engineer — treats Claude Code usage as a service with an error budget.


9. agenthub-config — Config & Memory Governance

Audit your Claude Code configuration and curate the file-based memory store via the Config Explorer API.

Skill Command Purpose
Config Audit /agenthub-config:config-audit Counts per surface (user vs project), duplicate skills/agents, shell-running hooks
Memory Review /agenthub-config:memory-review CLAUDE.md + per-project auto-memory files grouped by project; flag stale/oversized facts
Skill Inventory /agenthub-config:skill-inventory Installed skills + contributing plugins; overlap with your own skills
MCP Audit /agenthub-config:mcp-audit MCP servers (user + project): transport, command/args/env names, source file
Hook Inventory /agenthub-config:hook-inventory Hooks across settings + the hooks scripts dir; flag network/arbitrary-command hooks

Commands: /agenthub-config:audit-config · /agenthub-config:memory · /agenthub-config:inventory

Agent: config-auditor — audits config sprawl, duplication, risky hooks, and stale memory.

Memory Review can also edit the per-project memory store: auto-memory files are mutable via PUT/DELETE /api/cc-config/file with { scope: "auto-memory", type: "auto-memory", project, name } (always backed up first).


10. agenthub-dashboard — Dashboard Connector

Quick status, live watch, and endpoint probing.

Skill Command Purpose
Dashboard Status /agenthub-dashboard:dashboard-status Health: API connectivity, session/event counts, hook status, data freshness
Quick Stats /agenthub-dashboard:quick-stats One-line metrics: active sessions, total cost, events, top tool, cache efficiency
Live Watch /agenthub-dashboard:live-watch Poll a few times to show live deltas (active sessions/agents, events, ws connections)
Endpoint Probe /agenthub-dashboard:endpoint-probe Probe each major API route and report reachability/shape

Commands: /agenthub-dashboard:status · /agenthub-dashboard:ping · /agenthub-dashboard:open-dashboard

Agent: dashboard-operator — verifies the dashboard is up and guides start/restart/import. Access: direct tool access to the Agent Monitor API. Settings: default agent model.


Data Model Reference

These plugins query the Agent Monitor API at http://localhost:4820. Key data shapes:

Token Tracking

  • 4 token types: input_tokens, output_tokens, cache_read_input_tokens, cache_creation_input_tokens
  • 4 baselines: baseline_input, baseline_output, baseline_cache_read, baseline_cache_write (preserve pre-compaction tokens)
  • Effective total = current + baseline (the /api/analytics totals are pre-summed)

Cost Calculation

  • Formula: (tokens / 1,000,000) × rate_per_mtok for each token type
  • Model matching: longest model_pattern wins (e.g., claude-sonnet-4-5% beats claude-sonnet-4%)
  • Pre-seeded rates for Opus, Sonnet, Haiku families

Session Metadata (JSON)

  • thinking_blocks: count of extended thinking blocks
  • turn_count: number of conversation turns
  • total_turn_duration_ms: cumulative turn processing time
  • usage_extras: { service_tiers[], speeds[], inference_geos[] }

Event Types

PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, Notification, Compaction, APIError, TurnDuration, ToolError, Interrupted

Workflow Intelligence API (/api/workflows/{sessionId})

11 datasets: stats, orchestration (DAG), toolFlow (transitions), effectiveness (subagent success), patterns (recurring sequences), modelDelegation, errorPropagation (by depth), concurrency (lanes), complexity (score), compaction (impact), cooccurrence (agent pairs)

Alert Rules (/api/alerts/rules)

Rule types: token_threshold ({ total_tokens } — the spend-relevant guardrail), event_pattern, inactivity, status_duration.

Config Explorer (/api/cc-config/*)

Read every Claude Code surface (skills, agents, commands, output-styles, plugins, marketplaces, mcp, hooks, settings, keybindings, statusline, memory). A plugin card's contribution chips are clickable: each one expands to name the skills / subagents / commands / output styles that plugin ships (from contributes.items), so the plugin's contents are readable without opening its install directory. memory includes the per-project file-based store with scope: "auto-memory" (carrying project, name, isIndex, frontmatter); those files plus CLAUDE.md are mutable via PUT/DELETE /api/cc-config/file with always-on timestamped backups. The page also manages plugins and marketplaces: paste a GitHub owner/repo, URL or local path to register a marketplace, then install / enable / disable / update / uninstall its plugins — each button runs the corresponding claude plugin … command on the dashboard host (argv array, never a shell string). Hooks and settings.json keys are editable per layer (user / project / project-local) through PATCH /api/cc-config/settings, a per-key merge that leaves every untouched key — including redacted secrets — exactly as it was.

Plugin Development

To create your own plugins for the Agent Monitor, see the Claude Code plugin documentation.

Plugin structure

my-plugin/
├── .claude-plugin/
│   └── plugin.json          # Required: name (== dir name), description, version
├── skills/
│   └── my-skill/
│       └── SKILL.md         # Skill (description-only frontmatter; uses $ARGUMENTS)
├── agents/
│   └── my-agent.md          # Agent (name == filename, model, tools, instructions)
├── commands/
│   └── my-command.md        # Slash command (description, optional argument-hint)
├── hooks/
│   └── hooks.json           # Event hooks (fail-safe, non-blocking)
├── bin/
│   └── my-cli-tool          # CLI scripts (added to PATH)
└── settings.json            # Plugin settings

Structure is validated by server/__tests__/plugins-marketplace.test.js, which enforces the marketplace↔directory bijection, plugin.json shape, name/dir agreement, and required frontmatter on every agent / skill / command.

Two of those shape rules exist because getting them wrong makes a plugin listed but uninstallable, with no other symptom — the marketplace loads fine and only claude plugin install fails:

  • A subdirectory entry declares "source": "./plugins/<name>", never "path". path is not a source key the CLI accepts (This plugin's marketplace entry is invalid: source: Invalid input).
  • A plugin.json's repository is a string, not npm's { "type", "url" } object (Validation errors: repository: Invalid input).

server/__tests__/repo-links.test.js guards the link side: no GitHub owner/repo marketplace shorthand (it resolves to github.com only — this repo is on Gitea, so the shorthand cannot work and no GH_HOST-style env var redirects it), no raw.githubusercontent.com / *.github.io / GitHub /blob/<branch>/ URLs, no retired repository name, and no stale committed openapi.yaml.

Testing locally

claude --plugin-dir /path/to/my-plugin   # then use /my-plugin:my-skill some args

Troubleshooting

Dashboard not reachable

cd /path/to/AgentHub
npm start        # or: npm run dev

Hooks not installed

cd /path/to/AgentHub
npm run setup

Plugin not found

claude plugin marketplace list
claude plugin marketplace add https://git.smartgift.io.vn/Smartgift-AI/AgentHub.git

License

Internal SmartGift build — all rights reserved.