Two independent systems: learned keyboard mappings saved inside the set, and MIDI with its own connection, learn, pickup and feedback rules.
Keyboard
What can be learned
Four kinds:
| Kind | Behaviour |
|---|---|
| Clip | Triggers the captured clip |
| Column | Triggers the captured column |
| Parameter | Sets one fixed numeric value each press |
| Cue | Jumps to a captured cue on its captured clip |
The Parameter kind is the important distinction - a keyboard parameter key is not a continuous controller. It writes the value that was captured when you learned it. Six parameters are offered:
Layer opacity · Master opacity · Crossfader · BPM · Clip speed · Clip playhead
Each has the same range the control API enforces: layer opacity 0…1, master opacity 0…1, crossfader −1…1, BPM 20…300, clip speed −16…16, clip playhead 0…1.
Learning
Settings → Keyboard → Learn a keyboard shortcut. The note warns you correctly: "Select the intended clip, column or layer in the console. The Learn action captures that target; later selection changes do not redirect it."
- Choose Shortcut scope: Composition-wide or Current bank only.
- Press Learn selected clip, Learn selected column or Learn parameter key.
- The first press learns only - it never triggers. The prompt says so:
"Press a key for
. The first press learns only. Escape cancels." - Escape cancels. If the set or target changed across an undo, nothing is learned and you are told to learn again.
- Learning works while the console window has focus, or while Settings is showing the Keyboard section with learn armed. Saved mappings only fire in the console window.
Cue keys and MIDI notes
In Clip → Transport → Cue points, use a cue row's Learn key or Learn MIDI note. The first press/note only learns. A later press jumps immediately to the captured cue; it is not quantized and does not activate an idle clip. Cue Note Off leaves playback state unchanged, and repeated Note On is suppressed until release. MIDI learning requires a connected source.
These row actions learn composition-wide mappings, independent of the Settings scope picker. Mappings retain clip/cue identity in the set; a removed cue is unavailable rather than redirected. Cue keys count toward 192 keyboard mappings; cue notes count toward 64 note mappings.
Modifiers
Captured: Shift and Option only. A given physical key with Shift or Option is a separate mapping.
Reserved: any Command or Control combination cannot be constructed at all, so it can never collide with menus. Text editing, sheets and panels are excluded entirely.
Physical keys and conflicts
Identity is the native macOS virtual key position; the letter you see is a display-only label captured at learn time. A Mac with a different physical layout still works as long as the position matches.
- The same key in the same scope replaces the previous mapping, preserving its ID - one undo step.
- A bank-scoped mapping overrides the same key's composition-wide mapping only while that bank is selected. The global key stays live in every other bank.
- Maximum 192 mappings, with globally unique IDs and addresses; exceeding the cap makes a set unloadable rather than silently truncated.
- Decoding is strict - unknown fields are rejected rather than reinterpreted.
Built-in keys (no learning needed)
Digits 1–9 and 0 trigger columns 1–10 of the selected layer as held presses. A learned mapping on the same digit overrides this default behaviour. Repeats while held are ignored, and key-up releases that exact captured owner.
Focus loss and app quit release everything - there is no latching mode anywhere.
Keyboard mappings save with the set and participate in undo/redo. See Keyboard and menu reference for every menu shortcut.
MIDI
Connecting a source
Settings → MIDI → Connect MIDI, choosing from available sources.
The rule that governs everything here is identity is unique-ID-only; names are never used to match a device. A different endpoint with the same display name will not satisfy a reconnect. The settings note states it plainly: "The saved MIDI source is unavailable. Choose a source explicitly; names are not used to match devices."
- Sources must be available and have a verified, non-zero unique ID to be selectable.
- Identity is re-verified at least once per second while connected, plus on every topology change.
- Reconnect only ever targets the previously requested ID, retried about once a second.
- `MIDI input starts disconnected at every launch. Your ID is remembered for pre-selection only; nothing auto-connects.
- Disconnecting cancels the reconnect request but still remembers the preference. Source removal releases held notes and retires the whole queued callback generation, so delayed callbacks cannot inject stale events.
Only Note On, Note Off and Control Change are accepted. Note On with velocity 0 is treated as Note Off. CC 120 and 123 act as an all-off panic and can never be learned. Anything else is dropped before it becomes a show command.
Learning
Nothing can be armed while disconnected. Targets are exhaustive:
| Learn | Binds |
|---|---|
| Learn selected clip | A note to the selected clip |
| Learn selected column | A note to the selected column |
| Learn parameter CC | A CC to one of the six parameters above |
| Cue row → Learn MIDI note | A note to that clip and cue |
The first gesture learns only - it creates the binding without dispatching anything. Prompts say so
explicitly, e.g. "Play a note for
Targets are captured at learn time and survive you navigating away afterwards. CC 120 and 123 can never be learned.
Clip notes follow the clip's own trigger style and quantization; column notes trigger their captured column once per press, and note-off deliberately does not stop playback for a column note.
Encoder modes
Five choices for controller mappings:
| Mode | Definition |
|---|---|
| Absolute | CC 0–127 maps to the saved minimum–maximum range |
| Absolute · pickup | Waits until the fader reaches (within half a CC step) or crosses the current value |
| Relative · two's complement | 0 = unchanged; 1–63 = increase; 64–127 = value minus 128 |
| Relative · binary offset | 64 = unchanged; each value moves by value minus 64 steps |
| Relative · sign magnitude | 0 and 64 = unchanged; 1–63 = increase; 65–127 = 64 minus value |
Relative modes need a step, expressed as a fraction of the saved range and constrained to (0, 1]. Presets are offered: Fine · 0.1% of range, Standard · 1/127 of range, Coarse · 3.125% of range, plus Saved · N% for any other value.
Relative input always reads the live target value at dispatch, applies nudge × step × range, and clamps into the saved range. It never integrates its own history, which is why it cannot drift. Zero deltas and turning against an already-clamped endpoint produce no edit at all.
Encoding and step are editable after learning, with undo/redo. Saved rows display their range.
Pickup
Pickup tolerance is exactly half a CC step: (maximum − minimum) ÷ 254.
Acquisition is runtime-only and never persisted - reopening a set re-arms it. It re-arms on:
- changing bank;
- any native change to that target - UI edits, undo/redo, or REST/OSC writes;
- input overflow;
- disconnect or reconnect;
- removing or editing the mapping.
While unacquired, status reads "Waiting for pickup: move CC N to
Feedback output
Feedback uses a separate, explicitly connected destination - Connect feedback /
Disconnect feedback. It starts disconnected and remembers only the destination's unique ID. A source can
never be used as a destination.
- Running clips send Note On velocity 127; inactive or retired rows send Note Off velocity 0. A column note reflects whether any clip in that column is running.
- Changes coalesce at up to 10 Hz, with newer values replacing queued ones.
- A maximum of 256 words is published at a time.
- Explicit disconnect sends Note Off 0 for every owned lit note.
- If the destination disappears, feedback stops and waits for you to reconnect explicitly - returning devices are not auto-adopted.
- CC values are read from live state and sent clamped 0–127; fixed ranges (max == min) send nothing.
Which mappings send CC
Each CC row has a CC feedback picker: Input mode default, Off, Absolute 0–127.
- Input mode default keeps relative mappings silent and enables absolute/pickup mappings.
- Off never sends.
- Absolute 0–127 always sends current positions regardless of input mode.
Feedback never emits relative movement deltas. Choosing output requires set format 4 or later, while the existing defaults keep format 3.
Limits
| Limit | Value |
|---|---|
| MIDI mappings | 192 total: ≤ 64 note, ≤ 128 controller |
| Inbox capacity | 256 events; overflow releases held input |
| Per-drain budget | 64 events and 2 ms per tick |
| Feedback rate | 10 Hz |
| Feedback words per publication | 256 |
Exceeding the mapping counts makes a set unloadable rather than truncated.
Not verified
- Whether the local keyboard monitor shadows AppKit's menu key-equivalents for unmodified Space, T, R and the digits, and therefore whether a learned mapping on those keys can be reached at all.
- Real hardware behaviour. Every MIDI claim above is verified against virtual CoreMIDI endpoints in the app's own test suites. No physical controller, LED ring or motorized fader was exercised, and device-specific LED colours and protocols are explicitly out of scope.
- Whether note velocity other than 0 influences anything besides Note On/Note Off.