feat: Muse Code and Devin CLI agents, OpenCode sqlite history, OpenCode quota accounts
Summary
-
OpenCode history was silently empty. OpenCode 1.x keeps every session in
<data>/opencode/opencode.dband no longer writes thestorage/messageJSON tree the collector scanned. The collector now reads the database read-only (better-sqlite3, joined tosessionfor cwd and title) and keeps the JSON scan only for pre-1.x installs. -
OpenCode logins show as quota accounts.
auth.jsonholds Anthropic and OpenAI OAuth logins on the same OAuth clients Claude Code and Codex use, so the existing quota endpoints answer. A new OpenCode section in the quota panel shows one card per provider login. -
Muse Code (Meta's terminal agent) becomes a built-in agent and joins token history.
muselaunches the interactive session (prompt as positional arg),muse resume <uuid>resumes,muse execis the headless one-shot; registered in the Add-agent catalog, icon picker, settings search, README tables, docs and the marketing compatibility strip. A new collector reads its JSONL session logs; Muse is priced at Meta Model API list rates, attributed to a newmetamodel provider, and drawn as an eleventh series with the Meta mark as its icon (Meta blue on light, white on dark; Meta publishes no Muse-specific vector). -
Devin CLI becomes a built-in agent with lifecycle hooks and usage history.
devin --permission-mode dangerouslaunches, the prompt rides after--,--resume <id>resumes,devin -p --respect-workspace-trust falseis headless. Devin's hooks follow Claude Code's contract, so agent-setup merges Superset's notify hook into~/.config/devin/config.jsonand ships adevinwrapper; token history comes from~/.local/share/devin/cli/sessions.db. Icon is Cognition's Devin mark. -
Both new agents get Superset lifecycle hooks (working indicator, completion chime, session binding). Devin's config takes Claude's nested hooks block. Muse runs hooks with a cleared environment, so its settings-block hooks never see
SUPERSET_*; Superset instead owns$SUPERSET_HOME_DIR/hooks/muse/hooks.json, points Muse'smanaged_hooks_pathat it and allowlists the notify script's variables viamanaged_hooks_env_vars.
How It Works
history/opencode.tschecks foropencode.db; when present it dynamically importsopencode-db.ts(better-sqlite3 is a Node-only native binding the Bun unit suite cannot load) and maps rows through the pureopencode-rows.ts. The message JSON in thedatacolumn is the same shape as the old files.claude.tsandcodex.tsnow exposefetchClaudeSubscriptionQuota/fetchCodexSubscriptionQuota(token in, quota out).opencode-quota.tsparsesauth.json, classifies each OAuth entry as live / stale (lapsed access token, refresh token present — OpenCode renews it on its next request) / expired, and calls the matching fetcher.type: "api"entries become pay-per-token cards without the key ever being read.history/muse.tswalks<data>/muse/sessions/YYYY/MM/DD/<id>/session.jsonl. Each line is an envelope (recorded_atin microseconds); the run stream is mirrored in asruntime.sessionrecords whoseevent.kind === "model_completed"carriesusage.{input_tokens, output_tokens, cached_tokens, reasoning_tokens}(input includes the cached share, as with Codex). cwd and model come fromruntime.session.metadata, the label from the run'sstartedprompt. Entries dedupe onsource_run_record_idbecause a child run can be mirrored into both its own and its parent's log.agent-setup/agent-wrappers-devin.tsregisters SessionStart/SessionEnd/UserPromptSubmit/Stop/PostToolUse/PermissionRequest in Devin's config (it drops the wholehooksblock on an unknown event name, so only accepted names are written) and keepsversion: 1, which Devin requires.history/devin.tsreads assistantmessage_nodeswhose JSON embedsmetrics(input, output, cache-read tokens) andgeneration_model; the streamed and committed copies of a message share arequest_idand dedupe on it. Devin's own SWE models have no published token price and take the approximate fallback.agent-setup/agent-wrappers-muse.ts:managed_hooks_pathis single-valued, so a path Superset does not own is never replaced (a previous Superset home is). Teardown removes only the pointer and Superset's env names. Events: SessionStart, SessionEnd, UserPromptSubmit, Stop, StopFailure, PostToolUse, PermissionRequest.- Desktop:
QuotaCapableAgentgainsopencode(section, label,opencode auth loginre-auth hint);AGENT_CHART_CONFIGgains Muse with a palette-validated rose. The stale-token hint is now worded per agent (it was hardcoded to Claude Code), with the new string translated in all 16 locales.
Manual QA (dev desktop over CDP, this worktree, signed in as kiet@superset.sh)
Screenshots and measurements: https://app.superset.sh/page/usage-tab-muse-opencode-verification-pd01op
- Settings → Usage renders an OpenCode section: Anthropic login as stale (token expired months ago, refresh token present), OpenAI login with plan
pro, weekly window, credits balance — matches a direct call to the ChatGPT usage endpoint with the same token. - OpenCode history line reads
$0.18for 30d, which is exactly the 14 assistant turns / 142,845 input tokens the sqlite store holds for that window at thegpt-5list rate; the legacy JSON tree has 0 files in that window, so the number can only come from the database. - Three synthetic Muse session logs (shaped like a real
muse execlog, with nonzero usage) dropped under~/.local/share/muse/sessionsappear as a Muse Code legend row with a cost after a refetch; removed afterwards. - Real Muse session. Muse Code 1.1.1 signed into a Meta account and ran one
muse execturn. Its log carriesmodel_completedwithusage.{input_tokens 28316, output_tokens 22, cached_tokens 0, cache_write_tokens 0, cache_read_tokens 0, reasoning_tokens 11}andmodel: "muse-spark-1.3-contributor"; the collector yields exactly that entry priced at the contributor rate, and the usage tab shows it asMuse Code · 28Kin Tokens mode. The record is pinned inmuse.test.ts. - Muse as an agent. Settings → Agents → Add agent lists Muse Code with its icon; adding it creates the device row with command
museand resume argsresume; the workspace launcher bar shows it and launching opens a pane runningmuse(trust prompt, then the TUI boots onmuse-spark-1.3-contributorand accepts a typed prompt; the model call itself returned Meta's 402 "Billing verification failed" for this account, which is the account's billing state, not the launch). The headlessmuse execturn earlier the same evening did complete and is what the history collector was verified against. The usage legend row now carries the icon. - Devin as an agent. Two headless
devin -pprobes with a hook-capturing config confirmed the payload shape (hook_event_name,session_id,prompt,tool_name) on every registered event, in print mode too. In the dev app: Add agent lists Devin with its icon; adding creates the row with commanddevin --permission-mode dangerous, prompt args--, resume args--resume; the dev host-service merged Superset's hooks into~/.config/devin/config.jsonat boot (alongside another tool's existing hooks) and created the wrapper; launching from the workspace bar opened a pane, Devin's first-run Git wizard was skipped, a typed prompt ran to completion on SWE-1.6, andterminal_agent_bindingsrecorded the terminal asdevinwith the real session idlonghaired-fileandStart/Stopevents from the hook chain. Usage legend shows the probe sessions asDevin · 46Kin Tokens mode with the icon. - Muse hooks. Env-dumping probe hooks proved settings-block hooks get 13 variables and no
SUPERSET_*, whilemanaged_hooks_pathhooks get the allowlisted ones. In the dev app after boot: Muse's settings carry the pointer and allowlist, the managed file exists, and a pane launched from the workspace bar producedterminal_agent_bindingsrows Attached → Start (with Muse's real session id) → Stop, with the amber working dot on the tab and pane while the turn ran. Muse's notify stderr shows the host-service receiving each post. - Stale-token hint on the OpenCode card reads "Refreshes when OpenCode next runs." (was "…Claude Code…" before the last commit).
- Real-data collector run under Electron's Node: OpenCode 250 rows → 246 entries, 30 labels, ~180 ms; Muse collector finds the seeded logs.
Testing
bun run typecheck(host-service, desktop)bunx biome checkon changed filesbun test src/trpc/router/usage(host-service, 123 pass) — new:opencode-rows.test.ts,opencode-quota.test.ts,muse.test.tsbun test src/agent-command.test.ts(shared, 31 pass) — new Muse and Devin registration casesbun test src/agent-wrappers.test.ts(agent-setup, 79 pass) — new Devin config and Muse managed-hooks cases- host-service usage suite now 126 pass incl.
devin-rows.test.tsbuilt from a captured real record bun run typecheckalso clean for shared, ui, marketingbun test src/renderer/routes/_authenticated/settings/usage(desktop, 43 pass)bun run check:i18nclean
Known Limitations
- Whether Muse's
input_tokensincludes the cached share could not be observed (the real call hadcached_tokens 0); the collector assumes it does, as Codex reports, so a cached call can only be under-counted. The binary exposes no quota endpoint, so Muse has no quota card. - Eleven categorical series is past what the palette validator can fully satisfy; the rose is the best remaining slot (≥ 9 ΔE from every other hue for normal vision, bands and contrast pass in both modes). The pre-existing Antigravity/Grok adjacent pair already fails the CVD check.
https://claude.ai/code/session_012R8eHx1CdbVXNJveeGA2dV
Summary by cubic
'2027'
Summary by CodeRabbit
-
New Features
- Added full Devin support, including terminal launching, managed setup, icons, usage history, charts, model attribution, and pricing.
- Added full Muse Code support, including terminal launching, icons, usage history, charts, model attribution, and pricing.
- Added OpenCode usage tracking for database and legacy records.
- Added OpenCode quota visibility for Anthropic and OpenAI logins, including token status and subscription details.
- OpenCode now appears in usage ordering and account displays.
-
Localization
- Added translated OpenCode usage refresh messaging across supported languages.
-
Documentation
- Added Muse Code and Devin to supported-agent documentation and product listings.