all repos — dingger @ 943fc940d9c387916708cb3fdc912323c92ef6dc

Watches the AI coding agents in your tmux panes on macOS and tells you which need you, from the menu bar, a floating panel, the status line and notifications; jumps to them, and restores tmux sessions and agents after a crash

write @agent_state on attendance changes, not just transitions

the seen demotion (done -> idle when the user focuses the pane) only
updated the daemon's internal track; @agent_state stayed done forever,
so the menu bar and status line never reflected attendance. the display
status is now written whenever it differs from the pane option,
regardless of what triggered it.
Igor Soarez igor@soarez.org
Tue, 20 Oct 2026 12:06:03 +0300
commit

943fc940d9c387916708cb3fdc912323c92ef6dc

parent

3509e48c5776c4153d8f90aff83a796c6d383208

1 files changed, 12 insertions(+), 4 deletions(-)

jump to
M crates/dinggerd/src/watcher.rs → crates/dinggerd/src/watcher.rs

@@ -232,13 +232,21 @@ );

} if transition { debug!(target = %pane.display_target, ?prev_state, ?new_state, seen, "state change"); - let display = display_status(&self.tracks[&pane.pane_id]); - if let Err(err) = tmux::set_agent_state(&pane.pane_id, display.label()) { - warn!(target = %pane.display_target, %err, "failed to write @agent_state"); - } let _ = tmux::clear_ack(&pane.pane_id); } else if seen != prev_seen { let _ = tmux::ack(&pane.pane_id); + } + let display = display_status( + self.tracks + .get(&pane.pane_id) + .unwrap_or(&PaneTrack { state: new_state, seen, ready_since: None }), + ); + // @agent_state mirrors the display status on both transitions and + // attendance changes (done → idle when the user focuses the pane). + if pane.written_state != display.label() { + if let Err(err) = tmux::set_agent_state(&pane.pane_id, display.label()) { + warn!(target = %pane.display_target, %err, "failed to write @agent_state"); + } } if new_state == AgentState::Unknown { // The agent is gone; its last hook report must not outlive it.