Originally submitted to the Logitech x Devpost hackathon on Devpost.
The Speed Editor for Agentic Development.
AI agents run faster than you can watch them. The bottleneck is DevLT: minutes of developer attention per trusted change. Runbook turns the MX Creative Console into a physical instrument that optimizes for DevLT. Arm a prompt on the keypad. Dispatch on the dialpad. Scroll evidence with the dial. The device shows confirmed agent state from first-party lifecycle events. No scraping. No polling. No lies.
Inspiration
In January I generated 3 million lines of code using AI agents. The bottleneck was never speed. It was attention.
Directing an AI coding agent right now is Level 3 autonomous driving. The car handles the road, but you sit there with your hands near the wheel, watching, ready to intervene. Full attention on something that’s supposed to save you attention.
The keyboard is the wrong instrument for Level 5. Same insight as the DaVinci Speed Editor: give the operator a dedicated physical instrument for the actual job. Runbook is that instrument for agentic development. Two surfaces: dispatch intent, navigate evidence. The device tells you what the agent is doing so you don’t have to watch.
What It Does
The MX Creative Console ships as a two-piece kit. Runbook uses both pieces for what they’re built for.
The keypad is your intent surface. Each LCD key maps to a repo-specific playbook: Prep PR, Break Task, Run Gates, Write Spec. These are markdown files committed to the repo, not macros. Press a key and the prompt is armed on the device display. It does not fire. You can’t accidentally burn tokens by bumping a button.
The dialpad is your execution and navigation surface. Thumb rests on Enter. Press it to dispatch the armed prompt. While the agent runs, the large dial scrolls terminal output and diffs. The roller cycles between terminal sessions. Four buttons handle the high-stakes actions: Enter, Esc, Export, and Hard Interrupt.
The loop:
- Press “Prep PR” on the keypad. Device shows ARMED: PREP PR.
- Press Enter on the dialpad. Prompt dispatches. Device shows RUNNING.
- Agent finishes. Device shows WAITING (needs approval) or COMPLETE.
- Dial scrolls to the diff. Review hunks. Accept or reject.
- Press “Run Gates.” Tests pass. Device shows PASS.
That entire sequence happens without touching the keyboard. Every accidental dispatch burns the context window and $3-5 in compute. Every alt-tab to check agent status is attention that doesn’t come back. DevLT drops because the operator stops context-switching and starts responding to signals.
How I Built It
The intelligence isn’t in the keystrokes. It’s in the lifecycle wire.
Two layers connected by a local daemon.
Layer 1 — Agent plugin. The agent runtime exposes a first-party hooks API: structured JSON events fired at each stage of the agent loop. Runbook registers a small Rust binary (runbook-hooks) as a hook consumer. When the agent starts a task, requests permission, completes work, or errors out, the binary receives the event and forwards it to the daemon.
Layer 2 — Logitech Actions SDK plugin. The daemon translates agent lifecycle state into device actions: LCD label updates, haptic confirmations, state indicators. Packaged as .lplug4 for the Logitech Marketplace.
The state machine is the bridge:
| Agent Event | Device State | What You See |
|---|---|---|
| Prompt submitted | DISPATCHED | Label updates to prompt name |
| Tool executing | RUNNING | Active tool indicator |
| Permission needed | WAITING | Physical signal — authorize now |
| Task done | COMPLETE | Result ready |
| Session ended | RESET | Device returns to baseline |
No terminal scraping. No VS Code polling. The device reflects confirmed agent state because it consumes first-party lifecycle events. If the hook doesn’t fire, the device doesn’t update. It won’t lie to you.
Hardware safety is deliberate. The dialpad’s top-left button is physically concave. That’s where Hard Interrupt (Ctrl+C) lives. You feel the hollow before you commit the highest-cost action. Three protection layers: physical seek, tactile confirmation, and the agent runtime’s own null-first-press gate.
Accidental interrupts burn the context window and force a restart. The hardware prevents them without software guards.
Stack: Rust (hooks consumer, daemon), C# (Actions SDK plugin), TypeScript (VS Code extension bridge), Markdown (prompt commands).
Challenges
The concave button is a bet. I mapped the highest-cost action to the physically hardest-to-reach button, relying on a tactile concavity I designed around but haven’t held yet. If the reach or the feel is wrong, the safety architecture needs remapping. Day-one physical validation when hardware arrives.
Keeping the Logitech layer thin. The daemon handles all state logic. The Actions SDK plugin only renders and captures. That boundary is deliberate: the state machine is testable independent of the device, and the Logitech code stays small enough to maintain as the SDK evolves. But “thin” means the plugin can’t compensate if the daemon gets state wrong. All reliability pressure sits in the Rust layer.
Prompt libraries as repo infrastructure. The keypad prompts live as committed .md files in .claude/commands/. Versioned, reviewable, shared across the team. Clone the repo, the keypad populates. That’s closer to CI configs than keyboard shortcuts. The challenge: making that feel instant, not “install a plugin and configure it.”
What I’m Proud Of
The hook wire. Most plugins fire macros. Runbook consumes actual structured JSON from the agent lifecycle. First-party, documented API. If the device says WAITING, the agent is actually waiting. If it says COMPLETE, the output is ready to review. That’s the part nobody else has: the device knows what the agent is doing after dispatch.
The ARMED state is table stakes done well. Two-gesture dispatch (arm, then fire) is just good UX: confirm before you commit. The competitors skipped it and went straight to “button fires macro.”
The ARMED state matters because it’s the entry point to the lifecycle loop: arm → dispatch → RUNNING → WAITING → COMPLETE. Without the hook wire, it’s just a confirmation step. With it, it’s the start of a stateful conversation between the operator and the agent.
Clean degradation. The primary runtime gets full hooks, permission gating, state reflection. Everything else degrades to a reliable navigation surface. Keystrokes and scroll, no broken states. I’d rather show nothing than show wrong.
What I Learned
The value is post-dispatch, not dispatch. Pressing a button to send a prompt is trivial. Knowing what the agent is doing after you press it is the hard part. The hook wire solves the right problem: not “how do I send commands faster” but “how do I stop watching the terminal and start responding to confirmed state changes.” That reframe changed everything about the design.
The bottleneck is navigation, not generation. Agents generate fast. Humans evaluate slow. The physical dial is gross motor (low fatigue) vs. mouse wheel fine motor (high fatigue) across thousands of lines of output per session. The operator’s job is reading the instrument panel, and the instrument panel should be a dial, not a scroll wheel.
Physical state display eliminates polling. Without the device, developers alt-tab to check if the agent is done, waiting, or errored. With it, the answer is always visible on the desk. The human stops monitoring and starts responding to signals. DevLT drops because you reclaim the minutes spent asking “is it done yet?”
What’s Next
Marketplace submission. The plugin is scoped narrow: arm, dispatch, navigate, reflect state. .lplug4 packaged, MIT-licensed, targeting Logitech Marketplace review.
MX Master 4 + Actions Ring. The Actions Ring as an ambient state indicator — ring color reflecting IDLE, RUNNING, WAITING — is a zero-architecture-change addition. Extends the device story to the right hand without touching the daemon.
LCD telemetry during runs. Keypad tiles shift from prompt buttons to live build status during active runs: test counts, pass/fail, token burn rate. The device becomes a dashboard without opening a browser.
Open source. Daemon, hooks consumer, and VS Code bridge are public. The Actions SDK plugin targets Marketplace distribution.
Built With
- Rust (hooks consumer, daemon, state machine)
- C# (Logitech Actions SDK plugin)
- TypeScript (VS Code extension bridge)
- Markdown (prompt command library)
- Claude Code Hooks API (first-party agent lifecycle events)
- Logitech Actions SDK
Try It Out
- Devpost Submission
- runbook.rs
- GitHub — runbook-rs (Rust daemon + hooks consumer)
- GitHub — runbook-actions (Logitech Actions SDK plugin)
- GitHub — runbook-vscode (VS Code extension bridge)