Skip to content

Add live hotkeys to control a running session#30

Merged
karava merged 1 commit into
mainfrom
claude/compassionate-mccarthy-hn7hla
Jun 18, 2026
Merged

Add live hotkeys to control a running session#30
karava merged 1 commit into
mainfrom
claude/compassionate-mccarthy-hn7hla

Conversation

@karava

@karava karava commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Makes devflow start interactive: single keypresses change things on the fly without restarting the session.

Why it's clean

start already owns the timer, music, and UI in one process, and already runs stdin in raw mode capturing every keystroke (it just swallowed them). This wires that handler to mutate the session's own state directly — no new infrastructure.

Keys

Key Action
space pause / resume
n next channel
m toggle mascot
v toggle voice
+ / - volume up / down
? show hints
Ctrl+C stop

All single keys do safe, reversible things; quitting stays on Ctrl+C/Ctrl+D, so a stray keystroke (wrong tmux pane) can never end a session.

Implementation

  • channel, mascot, voice, and volume are now mutable; the next tick (mascot/voice) or a best-effort mpv IPC call (volume) applies changes live. Switching channel also restarts the now-listening heartbeat and respawns the stream (when music should be playing).
  • New setVolume() mpv IPC helper in player.ts.
  • devflow pause (SIGUSR1) now shares the same togglePause() path as the space key (dedup).
  • Startup prints a dim hints line; actions report via a dim status line — the same pattern the existing pause/music handlers use, so the countdown resumes below it as a clean log.
  • README: documented the flag (--mascot/--no-mascot) and a Live controls table.

Verification

  • pnpm typecheck + pnpm build pass.
  • Drove a real --demo session through a pseudo-terminal feeding keystrokes: confirmed m shows + animates the runner, n cycles the channel, +/- adjust volume, v toggles voice, space pauses/resumes, ? reprints hints, and Ctrl+C stops — with the countdown staying live throughout.

Note

This input layer is the groundwork for the richer vim-style command bar (option B from the feasibility investigation) and can be reused by #17's in-session feedback hotkey.

🤖 Generated with Claude Code


Generated by Claude Code

Make `devflow start` interactive: single keypresses change things on the fly
without restarting. Reuses the existing raw-mode keystroke handler (which
previously just swallowed keys) and mutates the session's own state directly,
since `start` already owns the timer, music, and UI.

Keys (all safe + reversible; quitting stays on Ctrl+C so a stray keystroke
can't end a session):
  space  pause/resume      n  next channel      m  toggle mascot
  v      toggle voice      +/-  volume           ?  show hints

- `channel`, `mascot`, `voice`, and volume are now mutable; the next tick / a
  best-effort mpv IPC call applies the change live. Channel switch also restarts
  the now-listening heartbeat.
- New `setVolume()` mpv IPC helper in player.ts.
- `devflow pause` (SIGUSR1) now shares the same togglePause() path as the space
  key (dedup).
- A dim hints line is printed at startup; actions report via a status line, the
  same pattern the pause/music handlers already use.
- README: documented the flag and a Live controls table.

Feasibility groundwork for the richer command-bar idea (#17's in-session
feedback hotkey can reuse this input layer).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013BGajYfJGLkYwBWbgoKcjM
@karava karava merged commit c16eae5 into main Jun 18, 2026
knox661 pushed a commit that referenced this pull request Jun 19, 2026
Two bugs reported after #29/#30:

1. Ctrl+C exits but music keeps playing. The player tracked only the
   latest mpv via a single proc. play() is async (awaits the mpv lookup)
   and runs from overlapping paths (watchdog, channel-switch, revive),
   so a second mpv could spawn that proc never tracked; on exit, stop()
   killed only the tracked one and the other orphaned. Now every spawned
   mpv is tracked in a Set and stop() kills them all (and the mpv path is
   cached to shrink the double-spawn window).

2. The mascot hotkey (and pause) were advertised in free-flow mode,
   where there's no timer/progress bar so they do nothing. The key hints
   are now mode-aware: timer-only keys are dropped in free flow.

Verified: SIGINT now leaves 0 mpv; free-flow hints omit pause/mascot
while timed modes keep them. typecheck + build pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants