<feed xmlns='http://www.w3.org/2005/Atom'>
<title>dingger.git/crates/dinggerd/src/terminals.rs, branch master</title>
<subtitle>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
</subtitle>
<id>https://git.soarez.net/sz/dingger.git/atom?h=master</id>
<link rel='self' href='https://git.soarez.net/sz/dingger.git/atom?h=master'/>
<link rel='alternate' type='text/html' href='https://git.soarez.net/sz/dingger.git/'/>
<updated>2026-10-25T04:41:34+00:00</updated>
<entry>
<title>terminals: ask Ghostty only once focus has settled</title>
<updated>2026-10-25T04:41:34+00:00</updated>
<author>
<name>Igor Soarez</name>
<email>igor@soarez.org</email>
</author>
<published>2026-10-25T04:41:34+00:00</published>
<link rel='alternate' type='text/html' href='https://git.soarez.net/sz/dingger.git/commit/?id=b77427190408cbe3ebea5677cd67bce53e73f313'/>
<id>urn:sha1:b77427190408cbe3ebea5677cd67bce53e73f313</id>
<content type='text'>
across a Space switch (a full screen window) tmux sees the new client
focused about 0.3 s before Ghostty's front window changes, so learn paired
the client with the terminal that had focus. live, raising a full screen
window and back crossed the two pairings, and from then on every jump
raised the wrong window (old binary: 0 of 10 jumps right).

learn now waits a second before asking Ghostty, then still requires the
client to be focused. it also drops pairings of clients no longer attached,
which piled up with every closed window.

e2e step 20: Ghostty lagging behind tmux's focus, crossed pairings healing,
pruning; the old learn fails all five. live, two Ghostty windows, one full
screen: 16 of 16 jumps right, starting from crossed pairings.
</content>
</entry>
<entry>
<title>raise the terminal window that holds the tmux client</title>
<updated>2026-10-23T16:11:23+00:00</updated>
<author>
<name>Igor Soarez</name>
<email>igor@soarez.org</email>
</author>
<published>2026-10-23T16:11:23+00:00</published>
<link rel='alternate' type='text/html' href='https://git.soarez.net/sz/dingger.git/commit/?id=e4d3bc242bd3d18aa83a76f25dcbe5cb7a2ced78'/>
<id>urn:sha1:e4d3bc242bd3d18aa83a76f25dcbe5cb7a2ced78</id>
<content type='text'>
a jump (any click, a shortcut, search) activated the terminal app, which
raised whichever window was used last. now:

- the client: the named one (a status-line click), else one already on a
  session holding the agent's window (several terminal windows can show
  one session; it shows the agent without switching, and keeps its own
  session in a session group), else any; the focused one first, then the
  one used last (its last input or focus).
- Ghostty (1.3+, scriptable by terminal id, not by tty): dingger learns
  which terminal holds each client when it gains focus. tmux's
  client-focus-in hook runs `dingger terminal focused`, which asks Ghostty
  for its focused terminal and records it in @dingger_terminal_&lt;tty&gt;, but
  only if the client is still focused once Ghostty answered (a fast switch
  must not pair the wrong terminal); a terminal holds one client, so an
  older pairing with it is dropped. `focus` raises the exact terminal
  (window, tab, split) through `tmux run-shell`: Apple Events from the tmux
  server count as Ghostty's own, so no permission prompt. a terminal that
  is gone is forgotten and the app activated, as without a pairing.
- in a hook, #{client_name} can be another client (the previous event's);
  the snippet's hook uses #{hook_client}.

e2e step 20: two nested clients on one session, focused by typing focus
reports into their outer panes, a fake osascript as Ghostty, a fake open
(tests never activate a real app); it loads the snippet's own hook line.
each rule has a negative control that fails.
</content>
</entry>
</feed>
