Imported from mthines/lorekit (
.claude/skills/command-coverage/SKILL.md). Install upstream withnpx skills add mthines/lorekit --skill command-coverage. Copyright stays with the author (MIT).
Command Coverage
Ensures every place a user can navigate to and every action they can
take in packages/web is exposed consistently in two surfaces:
- The command palette (⌘K / Ctrl+K), and
- A keyboard shortcut that follows Linear's conventions.
The skill crawls the web app, builds two inventories (what exists vs. what is
registered), diffs them into a coverage matrix, recommends a Linear-style
binding for each gap, and — in apply mode — writes the missing
useCommand({...}) registrations behind a confidence gate. It reads and
writes LoreKit memory so the approach (conventions, decisions, prior gaps)
compounds across runs.
This
SKILL.mdis a thin index. The crawl procedure, the Linear key map, the auto-wire mechanics, the LoreKit protocol, and the concrete palette API contract live inrules/*.mdandreferences/*.md— load only what the current phase needs.
Mode Detection
Parse $ARGUMENTS. First token selects the mode; --scope narrows the crawl.
| Mode | Default | Trigger |
|---|---|---|
audit |
yes | Default. "check coverage", "audit palette", or no mode argument. |
apply |
"wire up", "fix the gaps", "apply", or $ARGUMENTS starts apply. |
--scope (default all): dashboard (routes + actions behind auth),
docs (the public /docs palette), blog (the public /blog palette), or
all.
State the detected mode and scope in one line before continuing:
Mode: audit
Scope: all
apply runs the full audit pipeline first — it never wires blind.
Workflow
| Phase | Name | Rule / reference | Gate |
|---|---|---|---|
| 0 | Recall | rules/lorekit-memory.md |
Prior conventions + decisions loaded from LoreKit |
| 1 | Inventory | rules/crawl-inventory.md |
Nav targets, actions, and the command registry all enumerated |
| 2 | Diff | rules/crawl-inventory.md |
Coverage matrix built (target × {palette, shortcut}) |
| 3 | Recommend | rules/linear-shortcuts.md |
Every gap has a proposed binding; no token collisions |
| 4 | Report | this file (Report format) | Matrix + recommendations presented to the user |
| 5 | Wire (apply) | rules/auto-wire.md |
Registrations written only at confidence ≥ 90% + user OK |
| 6 | Record | rules/lorekit-memory.md |
New insights/decisions written back to LoreKit |
audit stops after Phase 4 and still runs Phase 6. apply runs all phases.
Required Reading by Phase
Load on demand — do not preload.
| Phase | Files |
|---|---|
| 0, 6 | rules/lorekit-memory.md |
| 1, 2 | rules/crawl-inventory.md, references/palette-api.md |
| 3 | rules/linear-shortcuts.md |
| 5 | rules/auto-wire.md, references/palette-api.md |
The concrete packages/web palette contract (the Command type, the
useCommand hook-position rules, existing bindings, id-prefix conventions)
lives in references/palette-api.md. Read it
before crawling or wiring so the skill never re-derives — or drifts from —
the real API.
Report format (Phase 4)
Emit one coverage matrix, then the recommendations. Group by surface scope.
## Coverage — dashboard
| Target / action | Route / trigger | Palette | Shortcut | Warrants shortcut? | Gap | Proposed shortcut | Proposed palette | Prio |
| ---------------------- | ---------------- | ------- | -------- | ------------------ | ---- | ----------------- | --------------------- | ---- |
| Overview | /overview | ✅ nav-overview | ✅ g o | yes | — | — | — | — |
| Lore Explorer | /lore | ✅ nav-explorer | ✅ g e | yes | — | — | — | — |
| Settings → Plan | /settings/plan | ✅ settings-plan | ❌ | no — occasional | — | — | — | — |
| Filter (Explorer) | FilterMenu open | ❌ | ❌ | yes | both | `f` | "Filter lore…" (Lore) | P1 |
| Focus search (Explorer)| search input | ❌ | ❌ | yes | both | `/` | "Search lore…" (Lore) | P1 |
| Keyboard help | (none) | ❌ | ❌ | yes | both | `?` | "Keyboard shortcuts…" | P3 |
Rules for the matrix:
- One row per navigation target AND per page-level action.
Palettecites the registering commandidwhen present,❌when absent.Shortcutcites the key sequence when present,❌when absent.Gapis frequency-aware, one of:—covered — has a palette entry, and either has a shortcut or does not warrant one (occasional/destructive/deep). A palette-only settings page is—, NOT a shortcut gap.palette— missing its palette entry (always a real gap; the floor).shortcut— passes the shortcut test but has no shortcut.both— missing the palette entry AND warrants a shortcut.
- Include a
Warrants shortcut?judgment per row (yes/no — occasional/no — destructive/contextual) so a palette-only row reads as a decision, not an oversight. Proposed shortcut/Proposed palette— the suggested binding for a gap row (fromrules/linear-shortcuts.md), or—for a covered row. Every gap row MUST carry a proposal so the user can challenge each one individually. When a proposal is blocked (e.g. a handler must be lifted first, or a token collides), append the blocker inline — e.g.`f` ⚠ lift FilterMenu handleror`g o` ✗ taken → `g m`.PrioisP1–P4(P1 = high-frequency, both surfaces missing).- Never invent coverage: a target counts as covered only if a real
useCommandregistration is found in the crawl (Phase 1). - The separate prose "Recommendations" list is now redundant with the
Proposed*columns — keep only cross-cutting notes (new features, ordering) below the table, not per-row repeats.
Core Principles
- Palette is the floor; a shortcut is earned. EVERY navigable target and
real action gets a command-palette entry — that is the discoverability
baseline and its absence is always a gap. A keyboard shortcut is the
accelerator layer, added ONLY when the target passes the shortcut test
(frequent + global + flow-critical — see
rules/linear-shortcuts.md). A low-frequency destination with a palette entry and no shortcut is correctly covered, not a gap. Shortcuts are a scarce, memorable resource — spending one on a rarely used page devalues the whole keymap. - Follow Linear, do not invent.
gprefix is reserved for navigation; single letters (F, L, C, …) are context actions; ⌘K opens the palette. Reuse the repo's existing bindings before adding new ones. - Table-driven truth. Navigation is already driven by
DOCS_SECTIONS,SETTINGS_SECTIONS, andBLOG_SECTIONS; register from those tables, never a hand-copied list that can drift. - Never wire blind.
applyonly writes after theauditmatrix and aconfidence ≥ 90%gate; show the diff and get explicit user confirmation. - Compound the approach. Read LoreKit at the start, write decisions and newly-found conventions at the end, so the next run is smarter.
Anti-patterns
- Registering commands inside a
.map()— breaks React hook order. Wrap each item in its own component (see theDocsCommandItempattern). - Reusing a key token already bound (checked against the live registry).
- Binding a single-letter action that fires globally without respecting the input/textarea/contenteditable guard.
- Claiming a target is covered from the route table alone without finding its
useCommandregistration. - Adding a nav command with a
g-prefix that collides withg o/e/s/g.
Definition of Done
- Mode + scope stated in one line.
- LoreKit recalled (Phase 0) and recorded (Phase 6).
- Coverage matrix covers every route, section-table entry, and page action.
- Every gap has a proposed Linear-style binding with no token collision.
-
applyonly: each new registration passed the confidence gate, the user confirmed, andpnpm nx typecheck webis green. - One-line summary of the coverage delta delivered to the user.