feedBack/docs/plugin-keyboard-shortcuts.md
Miguel_LZPF 1214a6c0a0
docs: extract plugin contracts into modular docs and slim CLAUDE.md
CLAUDE.md had grown to 545 lines / 50 KB — most of it plugin-author
content that other AI tools (Cursor, Copilot, Codex, Aider) and humans
without AI never reach. Extract the plugin surface into 10 focused
docs and a JSON Schema for plugin.json, then slim CLAUDE.md to a
156-line navigable index.

New docs (~999 lines total, all self-contained):

  docs/PLUGIN_AUTHORING.md            — entry point and quickstart
  docs/plugin-manifest.md             — plugin.json field reference
  docs/plugin-visualization-contracts.md — setRenderer / overlay / note-state
  docs/plugin-audio-mixer.md          — fader registration
  docs/plugin-logging.md              — context["log"] + env vars
  docs/plugin-diagnostics.md          — server_files / callable
  docs/plugin-keyboard-shortcuts.md   — registerShortcut + scopes
  docs/plugin-sibling-imports.md      — load_sibling pattern
  docs/websocket-protocol.md          — /ws/highway message reference
  docs/testing-plugins.md             — pytest fixtures + Playwright

  schema/plugin.schema.json           — Draft 2020-12 schema for
                                        plugin.json; license enum
                                        mirrors CONTRIBUTING's curated
                                        allowlist. Backs CI validation
                                        and the plugin-validate skill.

CLAUDE.md slim (581 lines changed, -485):

  - Removed ~300 lines of plugin-author prose (now in docs/).
  - Kept architecture quick reference, running the app, testing,
    git workflow, versioning, song formats, frontend/backend
    conventions, plugin authoring INDEX (table → docs/), first-hour
    pitfalls, "For AI agents" footer.
  - Anchor stubs preserved next to the new index entries so deep
    links from specs/001-slopsmith-platform/analyze.md still resolve.

Verification:
  python -c "import json,glob,jsonschema; s=json.load(open('schema/plugin.schema.json')); [jsonschema.validate(json.load(open(p)), s) for p in sorted(glob.glob('plugins/*/plugin.json'))]"
  # ok — validates highway_3d, app_tour_library, app_tour_settings
Signed-off-by: Miguel_LZPF <mgcdreamer@gmail.com>
2026-06-18 00:38:50 -07:00

2.7 KiB

Plugin keyboard shortcuts

Plugins can register keyboard shortcuts via the global window.registerShortcut() function. Shortcuts appear in the ? help panel.

Registration

window.registerShortcut({
    key: 'k',                       // key value (e.key) or key code (e.code)
    description: 'Toggle my view',  // shown in the help panel
    scope: 'player',                // 'global' | 'player' | 'library' | 'settings' | 'plugin-{id}'
    condition: () => _isMyViewActive, // optional guard
    handler: (e) => _myAction()      // called when shortcut triggers
});

Scope

Scope controls when the shortcut is active:

  • global — works on any screen
  • player — only on the player screen
  • library — only on the home/favorites screens
  • settings — only on the settings screen
  • plugin-{id} — only when your plugin's screen is active

Panel-scoped shortcuts

For plugins that create multiple panels (e.g., splitscreen), shortcuts are automatically scoped to the active panel. Use const panel = window.createShortcutPanel(id) to create a panel (keep the returned reference so you can call panel.clearShortcuts() during cleanup) and window.setActiveShortcutPanel(id) to switch between them. Each panel has its own shortcut registry, so multiple panels can have the same key without collisions.

Condition

condition is an optional guard function. If it returns false, the shortcut is skipped even if in scope.

Key matching

The handler matches against both e.key (character produced) and e.code (physical key). Use e.key for letters/symbols that depend on keyboard layout, and e.code for special keys (e.g. Space, ArrowLeft).

Cleanup

Clean up with window.unregisterShortcut(key, scope). You must pass the same scope you registered with — the default is 'global' and won't match player/library/settings/plugin-* bindings.

For panel-scoped shortcuts, prefer panel.clearShortcuts() over per-key unregister calls.

Built-in shortcuts

Key Description
? Show keyboard shortcuts panel (global)
Space Play/Pause (player only)
/ Seek ±5 seconds (player only)
Escape Back to library (player only)
[ / ] Audio offset ±10ms (Shift: ±50ms) (player only)

Don't override these. The ? panel is the canonical reference for users.

Debugging

Open the browser console and type _listShortcuts() to inspect every registered shortcut, its scope, and its source plugin.