You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
User rebinds and unbinds are undone on every launch: the documented startup re-applies app defaults over stored bindings, and there is no defaults layer or "unbound" marker #175
The startup flow in README "Basic Usage" and USAGE_EXAMPLES.md calls BindChord unconditionally after InitializeAsync. Profile.SetChord overwrites the stored binding (Keybinding/Models/Profile.cs), so the app's defaults replace whatever the user stored.
An app can guard each call with HasChordBinding, but that only protects rebinds. A command the user deliberately unbound has no stored entry, so it looks exactly like "never bound", and the default comes back. The library has none of the following:
a defaults layer;
a "bind only if not customised" API (the OverwriteMode enum already exists in Models/Enums.cs but isn't usable for this);
Launch 1. Run the README flow, which binds file.save to Ctrl+S and edit.copy to Ctrl+C. The user then rebinds file.save to Ctrl+Shift+S and unbinds edit.copy, and the app calls SaveAsync. profiles.json correctly holds only file.save: Ctrl+Shift+S.
Launch 2. Run the same README flow. GetChord("file.save") returns Ctrl+S and GetChord("edit.copy") returns Ctrl+C. Both customisations are lost, and the next SaveAsync persists the loss.
Why it matters
User-customisable shortcuts are the library's core purpose, yet following its own Quick Start discards customisations on every restart. The obvious workaround, if (!HasChordBinding(id)) BindChord(...), still brings back commands the user unbound.
Suggested fix / acceptance criteria
Provide a way to declare default bindings separately from user bindings. Either:
a RegisterCommand(command, defaultChord) overload or a SetDefaultChords(...) method, or
BindChord(..., OverwriteMode.DoNotOverwrite) plus a persisted "explicitly unbound" state.
Resolve a binding in this order: user binding, then explicit unbind, then app default. A "reset to default" path then comes naturally.
README and USAGE_EXAMPLES show the defaults API in the startup flow.
A test runs the two-launch sequence above and checks that both the rebind and the unbind survive launch 2.
Category: Improvement. It is labelled enhancement because the fix needs new API, a defaults layer plus an unbind marker. The visible effect behaves like a bug.
Priority: High. Following the library's own Quick Start throws away user customisations on every restart, and customisable shortcuts are what the library is for.
Area / suggested owner:Profile and KeybindingManager binding resolution and persistence, plus the README and USAGE_EXAMPLES startup flow.
Activity
matt-edmondson commentedon Oct 7, 2026
Triage
ProfileandKeybindingManagerbinding resolution and persistence, plus the README and USAGE_EXAMPLES startup flow.RegisterCommand(command, defaultChord)/SetDefaultChordsAPI andOverwriteMode.DoNotOverwritecombined with a persisted unbind.Generated by Claude Code