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
Apps that use the default data directory share one %APPDATA%/Keybinding folder and overwrite each other's profiles #249
Each is Path.Combine(Environment.GetFolderPath(SpecialFolder.ApplicationData), "Keybinding"). That resolves to %APPDATA%\Keybinding on Windows and ~/.config/Keybinding on Linux for every consumer of the library. USAGE_EXAMPLES.md recommends calling AddKeybinding() with no directory.
Failure scenario
Two unrelated apps, A and B, both call services.AddKeybinding() and CreateDefaultProfile(), which uses id "default".
A binds editor.save to Ctrl+S and saves.
B binds game.jump to Space and saves.
JsonKeybindingRepository.SaveProfileAsync runs RemoveAll(p => p.Id == profile.Id), so B's profile replaces A's "default" profile and all of A's bindings.
B also writes its own active profile to the shared active-profile.json.
The command merge in KeybindingManager keeps stored commands it did not load, so A's commands stay in the shared commands.json.
A restarts and calls InitializeAsync:
Ctrl+S is unbound, and the "default" profile holds game.jump on Space.
B's commands appear in A's GetAllCommands, SearchCommands and GetSummary().TotalCommands.
The user's bindings are lost and nothing reports it.
Suggested fix / acceptance criteria
Define the default directory once, for example in Constants, and use that definition at all four call sites.
Make the default app-specific. For example, Path.Combine(ApplicationData, Assembly.GetEntryAssembly()?.GetName().Name ?? "Keybinding", "Keybinding"), or an appName parameter on AddKeybinding/CreateManager. Making the directory required is the other option.
Document the default location in the README.
Add a test: two configurations with different entry or app names resolve to different directories, and the default path contains the app name.
Optional: when the old shared folder exists, log it or migrate from it once, so existing single-app users keep their bindings.
Related but different: #93 proposes moving persistence onto ktsu.AppDataStorage, which would also scope storage per app. This issue is the narrower data-loss bug in the current default.
Priority: High. Any two apps on the same machine that follow the documented AddKeybinding() usage overwrite each other's "default" profile and mix their commands. The user's bindings are lost with no error.
Area / suggested owner: the library's persistence defaults (ServiceCollectionExtensions, KeybindingManagerFactory, KeybindingConfiguration), plus Constants, README and USAGE_EXAMPLES.md.
Note: changing the default path is a behaviour change for existing single-app users, whose bindings would appear to vanish. The optional one-time migration or log in the last checkbox is therefore worth doing, and the release should be at least a minor bump.
Activity
matt-edmondson commentedon Nov 12, 2026
Triage
AddKeybinding()usage overwrite each other's"default"profile and mix their commands. The user's bindings are lost with no error.ServiceCollectionExtensions,KeybindingManagerFactory,KeybindingConfiguration), plusConstants, README andUSAGE_EXAMPLES.md.Generated by Claude Code