Usage panel (status bar):
- every account shows its plan (Claude subscriptionType, Codex
chatgpt_plan_type, Cursor membershipType, Grok subscriptionTier)
- new quota rows: Cursor CLI (cursor.com usage-summary), Antigravity
(`agy --print /usage`, two model pools; AGENTHUB_AGY_USAGE=0 never runs
agy), Grok Build, Kimi Code, OpenCode Go — each login read from the tool's
own file, sent only to its own host while valid, never refreshed
- in-flight quota reads are shared between tabs
AI Tools catalog: Grok Build (`grok`) and Kimi Code (`kimi`) added;
Gemini CLI, Hermes and OpenClaw removed.
Also: Quit AgentHub (#65, `agenthub stop`), status-area icon, Add to Chat
on an editor selection, Settings in three groups, JetBrains-style Changes
panel (ticked files/hunks, ignore, blame, file history), terminal font.
--no-verify: :3000 is taken by another dev server (lane-detect tests);
both suites run by hand — server 2636/2639 (the 3 are :3000), client
1131/1131.
AI Proxy (was AI Router):
- server/lib/ai-proxies.js, proxy-apply.js, routes/ai-proxies.js mounted at
/api/ai-proxies and the old /api/ai-routers; `router` still accepted on the
start routes; profiles move to <CLAUDE_HOME>/agenthub-proxies/
- dashboard_runs.router renamed in place to proxy: an older build on the same
DB fails on that column, so dev and prod sharing one DB update together
- a proxy's baseUrl stored as its root (a typed /v1 made /v1/v1/messages);
Test probes Claude /v1/messages and Codex /v1/responses
- Settings → AI Proxy (/settings/ai-router redirects), ProxyPicker
Updates:
- every tab reloads onto the new UI build when its WebSocket reconnects to a
server of another version (lib/newBuildReload.ts, once per version)
- Update now stops waiting on a plugin chain that failed or pulled nothing
(the old server never goes down), and reloads as soon as a new version answers
Also:
- a pane whose command exits at once says so (EPANEEXITED) instead of
"Command failed: tmux set-option … mouse on"
- the pane drag preview draws where the pane actually lands
- Settings → About → "Start AgentHub automatically" (AutostartSettings.tsx,
GET/PUT /api/settings/autostart, server/lib/autostart.js). The switch is
the systemd --user unit's / LaunchAgent's enabled state: on writes a unit
for the running server when none exists and enables it, off disables it;
neither starts or stops the server. A foreign unit is never touched
(409 EFOREIGN)
- The plugin bootstrap no longer installs a unit on every install: it
installs or starts one only while the user has it enabled, and a rewrite
keeps the enabled state (writeUserService({ enable })). An install that
already had the unit enabled stays on. A stale-but-enabled unit beside a
live detached server is repointed, no longer started onto the bound port
- unitIsEnabled / setUnitEnabled in systemd-service.js and launchd-service.js
Also:
- fix(workspace): status bar no longer covers the chat box below md (#61)
Analytics parity phases 2–7 (docs/plans/analytics-parity/), built on
138e706 and ported onto v2.3.1:
- Cost by AI tool (?tool= on cost/analytics/stats/workflows, by_tool,
Codex fast/priority and flex tiers, agenthub_cost_usd_total{tool,model})
- Date ranges (from/to) on cost/analytics/workflows; Analytics range select
with Today / This week (Monday) / This month (1st) / 7d / 30d / 90d / All /
Custom; workflow filters carried into workflow-stats.js (read worker)
- Budgets and cost alerts as alert rule types (alert_rules rebuilt without
its rule_type CHECK), GET /api/budgets/status, rule preview, spend pace,
status-bar budget chip; rules stay editable in place
- Query Explorer (/query, allowlisted sort, CSV/JSON export) and scheduled
reports (report_definitions/report_runs, Settings → Reports)
- Session Replay tab and immutable snapshots (session_snapshots, /snapshot/:token)
- Remote Codex sync, push ingest with a hashed token, privacy redaction and
ignored folders (Settings → Data), Cursor sessions (no cost)
- Read-only MCP server, statusline, Grafana/Prometheus files
Also: resizable sidebar, pet run/wave animations, the workspace home keeps a
half-typed prompt, and the pre-commit hook runs only the related tests for a
small commit.
- Changes panel: a working file opens in a CodeMirror editor with its diff
inline (DiffEditor.tsx, @codemirror/merge, lazy-loaded); Changes folds the
unchanged lines, Whole file shows them; side by side at 50/50 and full
width; a Revert per block; original from HEAD or the branch's merge base
(`mergeBase` on GET /git/changes?range=branch)
- Every diff: green = line added whole, red = removed whole, blue = edited
in place (--diff-mod)
- History drawn as a commit graph (#58: `parents` on GET /git/log,
--date-order; lib/commitGraph.ts)
- Per-workspace never-stage list, drawn orange in the Files tree (--kept);
closed Terminal rows past three deleted
- Status bar plan quota for Claude (per account) and Codex
(GET /api/pricing/quota, server/lib/quota.js); compact hover panel that
stays open, Refresh button with a spinner
- Settings → Appearance holds language, theme and pet; Ctrl+Shift+C copies;
compact sidebar navigation and short session times
- EditorModal loads once per path (a parent re-render no longer reloads the
file over the user's typing), refuses Save after a failed load, opens a
truncated (>256 KB) file read-only, and asks before overwriting a file
that changed on disk or could not be re-read.
- Settings/Hooks editors unset only keys from the snapshot taken at Edit,
warn when the file changed underneath, keep a renamed key's value, and
refuse a new key named like a redacted one (env) or a read-only hook
event, which used to replace the secret/hooks.
- Project scope shows its resolved folder and is disabled inside the
plugin cache. Account-profile, pricing-row and pet deletes confirm;
two-click actions disarm after 3 s; unsaved drafts ask before closing.
- Search indexes every Claude Code / Codex sub-tab, opens it via ?tab= and
scrolls to + highlights the row; the active config tab is in the URL.
- General splits into General / Data / About; Pricing moves to a Cost
group with one shared load; config tabs group as Content / Extensions /
Config with arrow-key roving; Promise.allSettled per tab.
- Data: browser-preferences export/import (allowlisted keys), per-section
reset, housekeeping dry-run first, clear-all behind a typed phrase.
Server: purge days must be a whole number >= 1 (INVALID_PURGE_DAYS) and
dry_run returns exactly what the real run would delete.
- Alerts can be edited; webhooks/alerts/remote-source failures toast;
copies go through copyText; modals get dialog roles and useDialog.
- Sagi: Ctrl/Cmd+B only when shown and not typing, default spot clear of
row controls, arrow keys move it, reduced motion honoured; the dead
/run launch link goes to the workspace.
Settings -> Pet (/settings/pet, PetSettings.tsx): show/hide, speech
bubbles, size with a live preview, and the pet grid - Sagi, featured
codex-pets.net pets (downloaded on first pick), your own (deletable) -
with image upload and .codex-pet.zip import. The Sagi block leaves
General; the mascot menu's Pet settings opens the page. PetMenu and the
page share components/Sagi/usePets.ts.
Workspace sessions (docs/plans/desktop-parity, phases 1-5 and 7):
- sessions.lane_id: a workspace lists only the sessions its panes held,
stamped by bindRunSession (first writer wins, nested `claude -p`
excluded); GET /api/sessions?lane=&archived=
- session row state dot, double-click rename, archive (sessions.archived_at,
hides only); the activity bar's duplicate Sessions tab removed
- Fork beside Resume (--fork-session, Claude only), Ctrl/Cmd+click a live
session opens it in a second pane, a diff line's comment is pasted into
the workspace's last-focused pane (lib/panePaste.ts)
dashboard_runs stability:
- a pane's previous run is archived as <pane>@<started_at> instead of being
overwritten by INSERT OR REPLACE
- a run is flagged abandoned only once its tmux session is gone, at boot and
on the run-heal beat (panes outlive a server restart)
UI:
- sidebar: no footer, language or theme block; small collapse button in the
brand corner; version + update check in the connection details modal, a
status-bar dot while a release is out; language in Settings -> General
- one Switch component for every switch, the themed Checkbox for every
checkbox (no native checkboxes)
Also: AI Tools catalog trimmed to 10 built-ins (custom-file prompt modes
tested through fixtures), and the workspace plans under docs/plans/ (the
multi-user server plan lives in the AgentHub-Server repo).
Settings moves from a tab bar to /settings/<section>: a left nav grouped
General / Agents / Routing / Git / Projects (a select on narrow screens), a
search box over every section (Ctrl/Cmd+F, Enter opens the first match), and
row primitives. Each AI tool has its page under agents/<id>, the AI Tools
modal becomes the Agents page, Pricing shows every vendor, Git → Worktrees
sets which untracked worktrees the sidebar lists, and each project gets a
page with its own worktree override and Forget all. ?tool= and #ai-tools
links redirect to the path form.