English
Extending KeySteer
Use TOML for shortcuts, speeds, or action sequences. Add a Mode, plugin, or platform capability for a new interaction flow. Choose the entry point below for your change.
Choose an approach
| Goal | Recommended approach | Main entry point |
|---|---|---|
| Change keys, speed, themes, or an application's behavior | Configuration | keysteer.<name>.toml |
| Run several actions in sequence | Action array | [<mode>.bindings] |
| Add a keyboard workflow or targeting method | New Mode | src/modes/ + api::Mode |
| Add a callable host capability | Bundled plugin | src/plugins/ + Manifest |
| Add a cross-platform capability | Shared API + Backend | src/api/, src/platform/ |
| Add a configuration action | Binding + Command | src/api/binding.rs, src/api/command.rs |
The shortest development path
text
Configuration change
└─ TOML → --check → docs/tests
Mode or plugin
└─ ModeEvent → state → Command → Engine → Backend
Platform capability
└─ API trait → Windows/macOS/unsupported implementations → native testsRead Architecture, then use Workflow and tests for the checks relevant to your change.
Add a Mode
A Mode receives events and read-only runtime context, updates its own state, and returns commands for the host.
- Check whether the existing
ModeEventandCommandtypes insrc/api/cover the capability. - Add a state machine under
src/modes/. Store session state there; keep Win32, AppKit, and Backend calls out of it. - Implement
api::Mode, includingid,display_name, andhandle. - Add one catalog entry in
src/app/mode_catalog.rs, converting loaded configuration into the Mode'sSettings. - Test keys, completion, cancellation, configuration reloads, and failure cleanup.
- Update the default TOML, user docs, sidebar, and AI maintenance notes together.
The core shape is:
rust
impl Mode for MyMode {
fn id(&self) -> ModeId {
ModeId::new("my_mode").unwrap()
}
fn handle(&mut self, event: &ModeEvent, ctx: &HostContext<'_>) -> CommandBatch {
// Update state; request host capabilities through commands.
CommandBatch::new()
}
}Let the host perform system operations
Modes update state and return commands. The Engine/Backend handles pointers, windows, threads, and permissions so the same interaction logic can be tested on both platforms.
Add a plugin
Plugins compile with the app
Bundled plugins register at startup. Developing one means changing the repository and rebuilding. See Plugin development for the full interface.
- Implement
Modeundersrc/plugins/. - Declare a stable ID, name, description, verbs, and suggested bindings in a
Manifest. - Return the plugin from
bundled_plugins()insrc/app/mode_catalog.rs; the catalog validates its manifest. - Register the complete set through
RuntimePlanduring startup or reload, rather than assembling it piece by piece in bootstrap. - Configure inheritance, bindings, and plugin-specific
settingsunder[plugin_modes."plugin:<id>"]. Use fields declared byPluginModeConfig; plugins do not inherit the built-in targeting modes'lifecyclesection. - Test verb arguments, user binding precedence, reloads, and exit cleanup.
Plugins and built-in Modes use the same API:
text
ModeEvent + HostContext → plugin state machine → CommandBatchAdd a shared API capability when needed, keeping plugins independent of Engine internals and platform modules.
Add a configuration action
An action such as notify <text> needs changes in four places:
- Parsing: add syntax, argument counts, and errors in
src/api/binding.rs. - Command: add a platform-independent
Commandvariant insrc/api/command.rs. - Execution: handle it in the runtime command path under
src/app/runtime/mod.rs, usingBackendfor native work. - Tests and docs: add unit and integration coverage, then update
keysteer.default.toml, Modes and actions, the simulator's action list, and AI maintenance notes.
Binding parsing rejects typos when configuration loads. Keep errors explicit so users can fix a binding before trying it at runtime.
Add a platform capability
- Define an interface in
src/api/backend.rsthat works for both Windows and macOS. - Implement it under
src/platform/windows/andsrc/platform/macos/. - Check the
unsupportedimplementation so unsupported platforms still compile and report a clear error. - Let the Engine coordinate scheduling, timeouts, and failure cleanup. Modes should not own native objects.
- Test permissions, hooks, input injection, overlays, and multiple displays on the target OS.
Before submitting
bash
cargo fmt --check
cargo check
cargo test --all-features --lib --tests -- --test-threads=1
cargo clippy --all-targets --all-features -- -D warnings
cargo run -- --check -c ./keysteer.default.tomlFor documentation or configuration-model changes, also run:
bash
pnpm docs:check
pnpm docs:buildCheck that examples can be copied, documented defaults match the code, and failures release keys, mouse buttons, overlays, timers, and other owned resources.