Single source of truth for open work across spec/. Each item points back
at the originating spec section for rationale and shape — this file only
tracks what's outstanding.
If you ship something, mark it ✅ here and (where relevant) update the corresponding spec section. If you discover new work, add it here, not inline in another spec.
Last reviewed: 2026-05-16 (hooks.events drawer cross-reference shipped, then expanded into a structured matcher-groups view + hook details modal; see Inspector polish § Shipped for both).
A digest of what's open across the four tracks below — pick from here, then jump to the relevant section for shape and rationale.
- Generalize value-conditional drawer annotation (inspector
polish) — the annotation that ships today only fires for
permissions.defaultMode. Other multi-value enums (effortLevel,teammateMode,viewMode, ...) would benefit but lack a structured per-value source upstream. Tracked at #7; solution space and a recommended starting step (model-config.mdforeffortLevel) live in the issue body. - Rail navigability decision (inspector polish) — spec question, not coding work; needs a fork-vs-fork call before any UI lands.
- Inventory canonicalization —
inventory.md:15flags §3 env-vars and §5.1 hook-events as gaps. Separately, the[!verify]conventionCLAUDE.mddescribes is unused (zero tags in the inventory) — decide whether to re-tag unverified rows or retire the convention. - New sync scripts (catalog sync) — slate complete for now.
(
sub-agents.md,mcp.md, andpermissions.mdshipped 2026-05-07;keybindings.mdandcli-reference.mdshipped 2026-05-08; see catalog-sync section below.) - CI / drift hardening (catalog sync) —
$refresolution policy; staleness signal. (Cron-driven sync with PR-on-diff shipped 2026-05-06.)
Recently shipped (2026-05-13): Attach mode pivots the inspector
to grounded inspection — see attach-mode.md
and the "Attach mode" section below for the shipped surface.
Closes #11 + #12. Other deferred items unchanged: goals view,
cross-cutting surfaces, landing page, nomenclature — see "Design
surfaces" further down.
Phase numbering matches the spec.
- Phase 2 — file-based managed sources. ✅ shipped 2026-05-05.
managed-settings.json+ alphabetic last-wins merge ofmanaged-settings.d/*.json(within-tier; the cross-layer array-concat-dedup post-pass still runs). OS roots resolved perinventory.md:46-48. A malformed file in the managed tier fails the whole layer with the offending path named — admins should see their policy isn't loading rather than a silently-skipped file. Sibling read ofmanaged-mcp.jsonexposed on the snapshot asmanaged_mcp(UI surfacing shipped 2026-05-06 as the topbar pill). Plist / registry policy sources shipped 2026-05-06 in Phase 6. - Phase 3 — env vars + array-merge. ✅ shipped 2026-05-05.
Phase 3a: array-concat-dedup with per-element provenance for the known
array-merged paths;
array-mergedchip activated. Phase 3b:envlayer reads process env via the hand-curated mapping atcatalog/env-settings-map.json(eight v1 mappings —ANTHROPIC_MODEL,CLAUDE_CODE_*). Mapping is extensible by JSON edit; future PR can migrate to a description-prose-derivedenvfield on each settings catalog entry once upstream schema gains structured metadata. - Phase 5 — drawer catalog cross-reference. Mostly shipped
2026-05-05.
✅ Description / type / default in the drawer header (default shown
inline as "default: X" when the entry has one and the row isn't
unset).
✅ Default-layer flow-through — unset rows already pull
valuefrom catalogdefaultand tag withwinner: "default"; the waterfall surfaces it as the winning row. ✅ Per-element waterfall (Phase 3a). ✅ Related-knobs section —findRelatedKnobs(keyPath)insrc/lib/catalog.tsreturns immediate siblings under the same parent; drawer renders them as clickable rows; clicking navigates the drawer + list cursor in lockstep. Outstanding: deprecation copy. The settings catalog has no structureddeprecatedfield — only one entry (includeCoAuthoredBy) mentions it informally in description prose. Either lobby upstream JSON Schema for a flag, or build a description-prose matcher when more entries gain that copy. Not slated. Known minor limitation: clicking a related knob that's currently filtered out (chip / search) snaps to the first visible row instead of clearing the filter. Acceptable for v1; track if it bites. (§ "Phase 5".) - Phase 6 — OS-policy managed sources. ✅ shipped 2026-05-06.
macOS
com.anthropic.claudecodeplist read via theplistcrate (macOS-only[target.'cfg(...)']dep). Per-user MDM (/Library/Managed Preferences/<user>/...) takes precedence over system MDM (/Library/Managed Preferences/...); a present plist shadows the file-based source even when it fails to parse — admins see the broken policy rather than have a different layer silently take over. Plist paths added to the file watcher and to theopener:allow-open-pathscope so the rail's path-note remains clickable. WindowsHKLM\SOFTWARE\Policies\ClaudeCode\SettingsandHKCU\SOFTWARE\Policies\ClaudeCode\Settings(REG_SZ JSON) read via thewinregcrate (Windows-only target dep). Per-tier order is HKLM > file-based > HKCU perinventory.md:50— HKCU is intentionally lowest because per-user policy is admin-overridable by file-based, which is in turn overridden by HKLM. Same "present-but- malformed wins" rule as macOS plist. FrontendWaterfallRow.PathNotedetects registry-style paths and renders them as a non-clickable label (the opener plugin can't do anything with a registry path). Round-trip Windows test writes to a uniqueHKCU\SOFTWARE\Knobs-CC- Test\<unique>subkey to avoid clobbering real policy locations on a shared CI runner. (§ "Phase 6".) - Phase 7 — refresh / watch / diagnostics. ✅ shipped 2026-05-05.
Manual refresh shipped earlier (
Rkey + topbar button). Phase 7 added: ✅ File watcher vianotify(not the fs plugin — capability surface stays atcore:default+opener:defaultplus a tightly-scopedopener:allow-open-pathallowlist; no fs/shell/process/dialog/updater plugins). Watches each settings dir non-recursively, filters by filename, emitssettings-changedto the main window; the frontend debounces by 250ms and re-runsread_settings_layers. ✅ Per-layer error promotion — layer-level parse / IO errors now appear in the diagnostics dock alongside snapshot-level diagnostics (HOME/cwd unresolvable). Previously the dock said "Diagnostics · 0" while a rail row was red. ✅ Better empty-state copy when a file-based layer has no resolvable path (user→ "$HOME not set",project/project_local→ "no project root"). The bare "—" was uninformative. Existing empty states (managed / cli / env / default) continue verbatim frominspector-ui.md:131-139. (§ "Phase 7".)
✅ shipped on branch 2026-05-13. Grounded inspection is now the
product — attach-mode.md is the
implementation contract. Closes
#11 and
#12.
- ✅
sysinfocrate dep +runtime.rsmodule +read_runtime_layerTauri command (cwd / argv / environ for same-UID claude processes). - ✅
read_settings_layersacceptsattached_pid/project_root_override;ProjectSourceenum routes the three grounding modes.#[tauri::command(rename_all = "snake_case")]required so JS snake_case args deserialize to Rust snake_case params (Tauri 2 defaults to camelCase). - ✅ Frontend:
SessionPilltopbar UI with 4-state picker (loading / 0 / 1 / 2+ claudes, plus unsupported on Windows), session-grounding derivation, window-focus refresh, path-picker fallback viatauri-plugin-dialog. - ✅ Rail: project / project_local rows grounded against the
chosen session's cwd or picked root; cli row populated from
attached argv via
catalog/cli-settings-map.json(5 starter flags); env precedence layer reads attached environ when available. - ✅ EnvVarsPanel:
attachedcolumn alongsideshell, withΔper-row badge when values diverge. NewattachedandΔ difffilter chips appear when attached. - ✅ MERGED chip refined to only fire for genuine multi-source
array merges; single-contributor array paths render as
normal
setrows with the contributor's badge. - ✅ Capability surface change:
dialog:allow-opengranted for the path picker. No other new JS-side plugin permissions.
Known follow-up (deferred to a maintenance issue): watcher.rs
still watches knobs.cc's own cwd/.claude rather than the attached
/ picked project dir. Manual refresh + window-focus cover it
operationally; dynamic watch-target rebinding is a focused
improvement, not a blocker.
- Hooks pass #2. ✅ shipped 2026-05-08.
scripts/sync-hooks.jsnow walks the page heading-aware (h2..h5) and extracts three additional artifacts on top of the lifecycle table: (1) handler-fields tables under### Hook handler fields—common,command,http,mcp_tool, andprompt_and_agent(the doc collapses prompt + agent into a single shared section because both types accept the same fields), each{field, required, description}; (2) the### Common input fieldstables (the section has two stacked tables — main + the--agent/subagent extras — both belong to it, so they're concatenated into a singlecommonInputarray of{field, description}, 8 fields total); (3) per-event input/output schemas keyed by event name, each{inputFields, inputExample, outputFields}.inputExampleis the verbatim body of the first```jsonfence inside#### <Event> input;outputFieldspulls from either#### <Event> decision controlor#### <Event> output, whichever the upstream doc uses for that event. The new envelope lands as{source, fetchedAt, count, events, handlers, commonInput}; existingeventsshape is preserved, just enriched with the three new per-event fields. Required two upstream-driven parser refinements: GFM-awaresplitCellsthat handles\|escapes (load-bearing for theEdit\|Writematcher fixture) and a heading-aware table walker that reset deeper levels when a higher heading reopens. Out of scope for pass #2 (tracked as future passes): per-tool nestedtool_inputtables under#### PreToolUse input(Bash / Edit / Write / Read / Glob / Grep / WebFetch / WebSearch / Agent / AskUserQuestion — 4-colField | Type | Example | Descriptionshape, deliberately skipped because pass #2 captures only the shared 2-col shape); the### Matcher patternscross-reference table (different fields per event); the### JSON outputuniversal-fields table (could become acommonOutputarray in a future pass); exit-code-2 behavior, HTTP response handling, prompt-hook response schema, async-hook config — all prose-rich. Wired throughread_catalogashookson the wire (no UI consumer yet — Rust loads it asserde_json::Value, so the new keys flow through transparently). Cron sync covers the new shape. UI consumer tracked at #17 (umbrella #10). - New sync scripts. Each gets one script + one catalog file + one test, per the recipe. No remaining candidates from the documentation index — every page that exposes a canonical tabular artifact is now synced.
- CLI reference catalog (commands + flags). ✅ shipped 2026-05-08.
scripts/sync-cli-reference.jsreadshttps://code.claude.com/docs/en/cli-reference.md's two top-level reference tables and writescatalog/cli-reference.json(20 commands + 63 flags at time of writing). Both tables share a 3-col| X | Description | Example |shape and are extracted by the same parser parameterized over the header pattern. The page's### System prompt flagssubsection usesFlag | Behavior | Example(notDescription) and is deliberately skipped — its four entries are a re-statement of flags already in the main table. Required two upstream-driven parser refinements over the keybindings template: tighterstripBackticks([^]+body) so multi-span flag names like--continue,-ckeep their inline code formatting, and unescaped-pipe-aware splitting so thecat file | claude -p "query"row parses cleanly. Wired throughread_catalogascli_reference(snake-case on the wire to matchenv_vars/sub_agents); no UI consumer yet — tracked at [#21](https://github.com/AlteredCraft/knobs-cc/issues/21) (umbrella [#10](https://github.com/AlteredCraft/knobs-cc/issues/10)). Cron sync covers the new script. Future use: this catalog is load-bearing for the deferred runtime introspection feature ([#11](https://github.com/AlteredCraft/knobs-cc/issues/11)) — each documented flag is a candidate input the eventual flag-name → settings-key mapping (parallel tocatalog/env-settings-map.json`) will draw on. - Keybindings catalog (contexts only). ✅ shipped 2026-05-08.
scripts/sync-keybindings.jsreadshttps://code.claude.com/docs/en/keybindings.md's## Contextstable and writescatalog/keybindings.json(20 records —Global,Chat,Autocomplete,Settings,Confirmation,Tabs,Help,Transcript,HistorySearch,Task,ThemePicker,Attachments,Footer,MessageSelector,DiffDialog,ModelPicker,Select,Plugin,Scroll,Doctor). The page is rich (per-context action tables, keystroke syntax, reserved shortcuts, terminal conflicts, vim-mode interaction) but the contexts table is the single canonical artifact most directly consumable: it enumerates every value thecontextfield accepts inside abindingsblock of~/.claude/keybindings.json. Wired throughread_catalogaskeybindingson the wire (no UI consumer yet — tracked at #20, umbrella #10; blocked on a new read path for~/.claude/keybindings.json). Cron sync covers the new script. Future passes: per-contextAction | Default | Descriptionaction tables (would need to be associated with their owning### foo actionsheading), reserved shortcuts and terminal conflicts tables, keystroke-syntax modifier rules. - Permissions catalog (modes only). ✅ shipped 2026-05-07.
scripts/sync-permissions.jsreadshttps://code.claude.com/docs/en/permissions.md's## Permission modestable and writescatalog/permissions.json(6 records —default,acceptEdits,plan,auto,dontAsk,bypassPermissions). The page is structurally rich (rule syntax, tool-specific patterns, path-prefix table, managed-only settings table, working-directories table) but the modes table is the single canonical artifact most directly consumable: it enumerates every valuepermissions.defaultModeaccepts with prose richer than the short blurbs in the settings JSON Schema. Wired throughread_catalogaspermissionson the wire; UI consumer landed as the drawer's value-conditional annotation forpermissions.defaultMode. Cron sync covers the new script. Future passes: the path-pattern table (### Read and Edit's//path/~/path//path/pathprefixes), the managed-only-settings annotation table (which would let the app flag managed-only settings catalog entries), and the per-tool rule-syntax tables. - MCP catalog (installation scopes). ✅ shipped 2026-05-07.
scripts/sync-mcp.jsreadshttps://code.claude.com/docs/en/mcp.md's## MCP installation scopestable and writescatalog/mcp.json(3 records — Local, Project, User). The page is heterogeneous and most of it lives in prose-heavy###/####sections; the scopes table is the single canonical tabular artifact. Each record carriesname,loadsIn,shared(preserved verbatim — "No" / "Yes, via version control" / "No"), andstoredIn(preserved verbatim, code-spans intact). Wired throughread_catalogasmcpon the wire (no UI consumer yet — tracked at #18, umbrella #10). Cron sync covers the new script. Future passes: transport types (HTTP / SSE / stdio), managed-mcp.json exclusive-control + allowlist/denylist semantics, OAuth credential handling, tool-search deferral thresholds. - Sub-agents catalog (frontmatter pass). ✅ shipped 2026-05-07.
scripts/sync-sub-agents.jsreadshttps://code.claude.com/docs/en/sub-agents.md's#### Supported frontmatter fieldstable and writescatalog/sub-agents.json(16 fields —name,description,tools,disallowedTools,model,permissionMode,maxTurns,skills,mcpServers,hooks,memory,background,effort,isolation,color,initialPrompt). The catalog is wired throughread_catalogassub_agents(snake-case on the wire to matchenv_vars); no UI consumer yet — tracked at #19, umbrella #10; blocked on a new read path for~/.claude/agents/*.md. Cron sync covers the new script. Future pass: built-in subagent identities (Explore / Plan / general-purpose / etc.) and the operational rules around tool restrictions and hooks. read_catalogTauri command. ✅ shipped 2026-05-05. Rust now ownscatalog/{settings,env-vars,hooks}.jsonviainclude_str!and serves them throughread_catalog. The frontend'ssrc/lib/catalog.tsis now async-hydrated (loadCatalog()at boot, sync accessors thereafter); a vitest setup file feeds the same JSON intohydrateCatalogForTesting()so unit tests skip IPC. The env-vars and hooks catalogs are exposed on the wire but not yet consumed by the UI — Phase 5 and inspector polish will pick them up. Unblocks Phase 5.$refresolution policy. Settings catalog preserves$refstrings; decide whether consumers expand them at sync time or via a sibling$defsblock.- Staleness signal. ETag or content-hash on fetch — useful once we want change-detection beyond raw diff.
- Cron CI for catalog drift. ✅ shipped 2026-05-06.
.github/workflows/catalog-drift.ymlruns the sync scripts every Monday 09:00 UTC (and onworkflow_dispatch). Detect step normalises out the always-changingfetchedAtfield; if only the timestamp moved, the working tree is restored and no PR opens. Real drift opens (or updates) a singlechore/catalog-driftPR viapeter-evans/create-pull-request@v8(bumped from v7 alongsideactions/checkout@v5andactions/setup-node@v5for the 2026-06-02 Node 24 cutover). (§ "Automation" incatalog-sync.md.) - Coverage thresholds.
--test-coverage-lines/-branchesfloors on the sync test suites. Premature now. - Inventory's long-term role. Once catalogs cover the same ground,
decide what
inventory.mdis for — reference doc, contribution surface, or retire. (Open question carried incatalog-sync.md§ "Open questions".)
Open work (what to pick up next within this track):
- Rail navigability — undecided. Spec is silent. Either keep the rail informational (current behavior) or wire layer-click → centre list filtered to keys won by that layer. Needs an explicit decision before any work — surface as a question, not a ticket.
- Generalize value-conditional drawer annotation. Today's
annotation only fires for
permissions.defaultModebecause permissions.md upstream has a structured per-mode table. Other multi-value enums (effortLevel,teammateMode,viewMode,env.CLAUDE_CODE_DEBUG_LOG_LEVEL, ...) would benefit but lack a structured per-value source upstream. Tracked at #7 — solution space (sync more upstream tables vs. hand-curated overlay vs. description-prose parser vs. ship as-is) and a recommended starting step (model-config.mdforeffortLevel) live in the issue body. Surfaced by live smoke of the permissions.modes drawer wire-up. mcp.scopesenrichment for the managed-mcp pill. Lower-bar follow-up: the pill currently shows server count and links toopenInEditoron the JSON file. The MCP catalog's 3-recordscopesarray (Local / Project / User, each withloadsIn/shared/storedIn) could fold into a tooltip or popover so users see scope semantics without leaving the app. Smaller surface than the two drawer items above; pick up only if there's a clear UX win — the existing "open the file" affordance may be sufficient.
Shipped:
- Hooks structured drawer view + details modal.
✅ shipped 2026-05-16 (same day as the header cross-reference
below — the two passes are one commit's worth of work in
practice). The drawer's EFFECTIVE block now renders
1 matcher group · command(or2 matcher groups · command, http) for hooks rows instead of the useless generic[N] {…}thatformatValueproduced. A new Matcher Groups section in the drawer body lists each group as a clickable button (01 · matcher: "Bash" → 1 command); clicking opens a newHookDetailsModalmodeled onHelpViewthat carries the full impl — preformattedcommand/url/promptbodies, timeout, full handler shape — plus the event schema lifted from the hooks catalog (inputFields,outputFields,inputExample). First UI consumer of the per-event schemas from hooks-sync pass #2 (2026-05-08). Parsing helpers insrc/lib/hooks.tsare defensive against malformed settings.json — partial groups, missing fields, non-array roots all degrade gracefully rather than throw. Handler- type-aware impl picker:command→commandfield,http→url,mcp_tool→server::tool,prompt/agent→prompt. Modal state lives inInspectorShell(keyed by keyPath so the file watcher's snapshot rebuilds flow through); Esc closes alongside the other modal panels (help / errors / env-vars). Demo scenariotests/07-hooks/updated to walk through the new surfaces. Closes the bulk of #17. - Drawer cross-references
hooks.eventsforhooks.<EventName>. ✅ shipped 2026-05-16. When a row's keyPath matcheshooks.<EventName>and the event is documented incatalog/hooks.json(29 events at time of writing), the drawer header surfaces the event'swhencadence instead of the thinner settings-catalog description. The hooks-catalog prose is consistently event-semantic ("Before a tool call executes. Can block it") rather than knob- framing ("Hooks that run before tool calls"); a handful of events (PreToolUse,Stop,StopFailure,Setup, ...) carry semantics upstream that the settings catalog doesn't capture, and the first-line truncation makes them roughly equivalent for the few events where the settings catalog is richer (ConfigChange,FileChanged). Joins throughfindHookEvent(name)insrc/lib/catalog.ts(name-indexed Map built at hydration time) andhookEventNameFromKeyPathinKeyDrawer.tsx, parallel to the env-vars pattern. Case-sensitive lookup — event names are PascalCase ASCII and case-folding would feed false matches for user typos. Type shape for the hooks catalog tightened fromunknownto a typedHooksCatalogFilewith optionalinputFields/inputExample/outputFieldsper event, so a future detail-panel pass can pull those without re-typing. Third drawer-side consumer of a non- settings catalog after env-vars and permissions.modes; further validates the seam.hooks.<EventName>rows hold matcher-group arrays —formatValuealready renders these as[N] {…}(same shape aspermissions.allow), so no value-rendering changes were needed. Detail panel withinputFields/outputFields/inputExampledeferred per the roadmap's "scope back to header- only" guidance; tracked at #17 (umbrella #10). - EnvVarsPanel — SSOT for env vars. ✅ shipped 2026-05-10. The
inspector-side
envsettings-precedence layer only projects 8 mapped OS env vars (catalog/env-settings-map.json) onto settings keys; the upstream env-vars catalog has 220 entries, so ~95% of documented env vars never showed up in the inspector at all. The new topbar-pill-driven panel (modeled onErrorPanel/HelpView) lists every cataloged env var as a row with: shell-set value (read via the newread_shell_env_varsTauri command), settings.jsonenv.<NAME>contributors per layer in precedence order, an effective-value badge (shell wins when both routes set the same name), and fullpurposeprose on click-expand. Names matching/key|token|secret|password/imask their value to•••••••• abcd(last 4 chars) until clicked — demo-safe by default. Filter chips:all/set/shell/settings.json/unset; substring search across name and purpose. Non-catalog entries — names users set underenv.<NAME>insettings.jsonthat aren't in the upstream catalog — surface at the top of the panel in their own group with anon-catalogchip, so explicit user intent that's invisible everywhere else gets first-class billing. Shell-set names that aren't in the catalog are deliberately not surfaced (a user's shell carries hundreds of unrelated vars; only settings.jsonenvis treated as Claude-Code-specific intent). Sister structural change:env.*rows are now filtered out of the inspector entirely (buildRowsskips theenvsubtree) and a one-line banner above the inspector's column header points users at the panel — closes #6. Caveat surfaced in the panel footnote: knobs.cc reads its own process env, which usually matches the user's shell but can differ for Finder/Spotlight launches that use LaunchServices' env. Tracked at #11 (runtime introspection — reads anotherclaudeprocess's environ to ground- truth the panel). - Drawer cross-references
permissions.modesforpermissions.defaultMode. ✅ shipped 2026-05-08. When a row's keyPath ispermissions.defaultModeand the row's effective value (set orcatalog.defaultfor unset) matches one of the 6 cataloged modes, the drawer surfaces that mode's specific prose as a value-conditional annotation below the EFFECTIVE block — keeping the header description ("Default permission mode.") tied to the knob itself, not its current value. The structural separation matters: a header that silently changes prose when the value changes would be misleading; an annotation labelled by position (under EFFECTIVE, prefixed→) makes it obvious the prose describes the value. Joins throughfindPermissionMode(name)insrc/lib/catalog.ts(name-indexed Map built at hydration time) and a newresolveValueAnnotation(row)helper inKeyDrawer.tsx, parallel toresolveDescription. Case-sensitive lookup — mode names are camelCase ASCII and case-folding would feed false matches for user typos. Defensive: only attempts the lookup whentypeof row.value === "string", so a malformed settings.json with a non-string value renders no annotation rather than misleading prose. Undocumented enum values (delegate— experimental agent-team only, in the JSON Schema enum but not in the upstream permissions docs) also render no annotation. The annotation preserves the full multi-line catalog prose (no first-line truncation) since it lives in its own block — qualifiers like "Currently a research preview" stay visible. Second drawer-side consumer of a non-settings catalog after env-vars; further validates the seam forhooks.eventsnext, where the same value-vs-knob distinction will apply. - Drawer cross-references env-vars catalog. ✅ shipped 2026-05-07.
When a row's keyPath is
env.<VAR>and<VAR>is documented in the env-vars catalog (220 entries upstream), the drawer header surfaces the env-var'spurposeprose instead of the generic parent-envdescription the settings-catalog walk-up returns. This is the first drawer-side consumer of a non-settings catalog —findEnvVar(name)insrc/lib/catalog.tsjoins to a name-indexed Map built at hydration time;resolveDescription(row)andenvVarNameFromKeyPathinKeyDrawer.tsxare pure helpers exported for unit testing. Case-sensitive on lookup (env-var convention is upper-case ASCII; case-folding would feed false matches for user typos). Validates the seam for future drawer consumers —permissions.modesforpermissions.defaultMode,hooks.eventsforhooks.<EventName>,mcp.scopesfor the managed-mcp pill. - In-app error log + per-OS capability split. ✅ shipped 2026-05-07.
src/lib/errorLog.tsis a 50-entry in-memory ring buffer withsubscribe/reportError/markAllSeen/clearErrorsand aninstallGlobalHandlersbridge forwindow.onerrorandunhandledrejection.openInEditor's catch now routes toreportErrorinstead of silentlyconsole.error-ing. The Topbar surfaces a rederrorspill (visible only when entries > 0, glows red while there are unseen entries); clicking opens anErrorPanelmodeled onHelpViewthat lists timestamp / source / message / detail with aclearbutton. Diagnostics (config-side) and runtime errors (UI-side) stay as separate pills so users can tell "my config is broken" from "the inspector is broken." Surfaced an existing bug:opener:allow-open-pathwas failing every call on macOS because Tauri compiles every scope glob on every target, and a Windows backslash pattern (C:\Program Files\ClaudeCode\**) fails to compile on macOS/Linux. Fix: splitcapabilities/default.jsoninto cross-platform +default-macos.json/default-linux.json/default-windows.jsongated viaplatformsso each pattern is only compiled on its own target. managed-mcp.jsontopbar pill. ✅ shipped 2026-05-06.describeMcpPolicy(snapshot.managed_mcp)(src/lib/managedMcp.ts) drives a small clickable pill in the topbar that only renders when the file is present (status: "ok"or"error"). Reports the server count from the parsedmcpServersobject ("3 servers"/"1 server"/"0 servers"for present-but-empty); error state surfaces the parse error in the tooltip and renders a red dot. Click opens the JSON viaopenInEditor— addedC:\Program Files\ClaudeCode\**toopener:allow-open-pathso Windows users get click-through too (pre-existing gap, surfaced now that the pill makes the path actionable). Drill-down into the parsed contents stays out of scope — the file's small enough that opening it in the user's editor is the right primary action.- Path-notes click-through. ✅ shipped 2026-05-06 (per-OS capability
split followed 2026-05-07 — see "In-app error log" above for the why).
Path notes in the drawer waterfall are now clickable; click invokes
@tauri-apps/plugin-opener'sopenPathto open the file in the OS default editor. Required addingopener:allow-open-pathto the capability files (default opener perms cover URLs + reveal-in-dir but not path-open) and scoping the grant to a whitelist of settings-file globs ($HOME/.claude/**,**/.claude/settings.json,**/.claude/settings.local.json) plus per-OS managed-tier paths gated byplatforms(macOS/Library/Managed Preferences/*/...plist/Library/Application Support/ClaudeCode/**; Linux/etc/claude-code/**; WindowsC:\Program Files\ClaudeCode\**). Without a scope the runtime denies every call; the scope keeps the v1 boundary tight by limiting the webview to opening only the files we surface. Line targeting (:7) is deferred —openPathdoesn't take a line, and adding avscode://fileURL scheme would expand the capability surface for VS-Code-only users.
- Related-knobs section. ✅ shipped with Phase 5
(
KeyDrawer.tsxRelatedKnobs). - Per-element waterfall for array-merged fields. ✅ shipped with
Phase 3a (
KeyDrawer.tsxElementList). - Real
errorrail row. ✅ shipped with Phase 2 — managed-file parse failures now produce anerrrow in the rail. (Project / user files have producederrorsince Phase 1; Phase 2 closed the last layer that couldn't.)
- §3 env-vars gaps. Top-of-file note (
inventory.md:15) flags this section as a known canonicalization gap; cross-check against live docs. - §5.1 hook-events gaps. Same — flagged at line 15.
[!verify]convention.CLAUDE.mddescribes the tag as a contribution surface, but the inventory currently contains zero such tags. Decide: re-tag unverified rows, or drop the convention fromCLAUDE.md.
These are deferred / open-ended; track here so they don't get lost.
- Goals view. Mocked at
mocks/03-goals.html. Reframes the Inspector's data by user intent (speed / cost / safety / quality / privacy). Best done after the catalog produces structured tags. - Cross-cutting surfaces. Hook graphs, plugin hierarchies, MCP runtime state. Don't fit a flat list; no concrete plan.
- Landing page (
knobs.cc/). Leaning "live inventory" — renderspec/inventory.mdas a styled static site for the pre-release period. - Nomenclature. "Knob" vs "setting / option / control"; "surface / category / group" for the top-level taxonomy. Listed as open.