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
Multi-chord phrases (e.g. "Ctrl+K, Ctrl+C") can be parsed but never bound, looked up or executed #135
Phrase is a public type with parsing support: Phrase.Parse, Phrase.FromStrings and IKeybindingService.ParsePhrase. The binding model, though, only holds single chords:
Profile.Chords is a Dictionary<string, Chord> (Keybinding/Models/Profile.cs:73).
Every KeybindingService bind, find and execute API takes a Chord.
The JSON repository stores one chord per command.
Nothing can bind a phrase to a command or match input against one. There is also no way to track a partially typed sequence, where a prefix chord is pressed and the next chord is awaited.
The documentation says otherwise:
CLAUDE.md says profiles "Store mappings from CommandId to Phrase".
README.md:239 says the demo shows "Phrase binding and lookup".
Keybinding.Demo/MusicalDemo.cs:37-39 builds Ctrl+R, R and Ctrl+K, Ctrl+C phrases, but it only prints them.
Why it matters
Chord sequences such as VS/VS Code-style Ctrl+K, Ctrl+C are the headline example for the Phrase type. A consumer who follows the docs will find they can't be used. #134 (a phrase string silently parsed as a single chord) makes this worse, because the attempt fails without any error.
Suggested scope / acceptance criteria
Store a Phrase per command. A single chord is a one-chord phrase, so existing chord APIs keep working as thin wrappers.
Add BindPhrase(commandId, phrase), FindCommandByPhrase(phrase), and a way to execute a phrase.
Optionally, add prefix matching so a host can tell "sequence in progress" from "no match".
Serialise bindings as a list of chords, and keep reading the existing single-chord {"notes":[...]} format.
If this isn't planned, correct the CLAUDE.md, README and demo claims instead.
Category: Feature Request. It is partly a documentation bug, because the README, CLAUDE.md and the demo claim that phrases can be bound.
Priority: Medium. Chord sequences are the headline use of Phrase, but single-chord bindings work. The documentation mismatch should be fixed either way.
Area / suggested assignee: binding model and persistence (Profile, KeybindingService, JSON repository). Owner: @matt-edmondson. The scope needs a design decision: phrase storage with backward-compatible serialisation, plus optional prefix matching.
Next step: decide whether phrase binding is planned. If it is, implement per-command Phrase storage while still reading the existing {"notes":[...]} format. If not, correct the docs and demo.
store a Phrase per command, with single chords as one-chord phrases so the existing chord APIs remain thin wrappers
add BindPhrase, FindCommandByPhrase and phrase execution
add prefix matching, so a host can tell "sequence in progress" from "no match"
serialise bindings as a list of chords while still reading the existing {"notes":[...]} format
Next reader: land #134, then implement the above. Coordinate the serialisation change with #93, which is moving persistence to ktsu.AppDataStorage with a format migration, so there is one format change rather than two. Make the demo exercise real phrase binding.
Activity
matt-edmondson commentedon Sep 27, 2026
Triage
Phrase, but single-chord bindings work. The documentation mismatch should be fixed either way.Profile,KeybindingService, JSON repository). Owner: @matt-edmondson. The scope needs a design decision: phrase storage with backward-compatible serialisation, plus optional prefix matching.Phrasestorage while still reading the existing{"notes":[...]}format. If not, correct the docs and demo.Generated by Claude Code
matt-edmondson commentedon Sep 28, 2026
Decision (maintainer, 2026-09-28)
Phraseper command, with single chords as one-chord phrases so the existing chord APIs remain thin wrappersBindPhrase,FindCommandByPhraseand phrase execution{"notes":[...]}formatNext reader: land #134, then implement the above. Coordinate the serialisation change with #93, which is moving persistence to
ktsu.AppDataStoragewith a format migration, so there is one format change rather than two. Make the demo exercise real phrase binding.Generated by Claude Code