1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
# dingger
macOS agent watcher for tmux panes. dingger watches every pane in your tmux
server, detects which AI coding agent is running in each one (claude, codex,
pi, gemini, and 19 others), tracks its state (idle / working / blocked), and
sends a macOS notification — with sound — when an agent needs attention or
finishes.
dingger owns no terminals. It is a client of your tmux server: `capture-pane`
for screen text, `#{pane_title}` for OSC titles, and `#{pane_pid}` plus a `ps`
tree walk for agent identity. The detection engine and rule manifests are
extracted from [herdr](https://github.com/herdrdev/herdr) (Apache-2.0), so
detection quality matches herdr's screen-matching engine. herdr's manifests
use the same terminal-screen regions (`capture-pane` output maps 1:1); OSC
progress sequences are not re-exposed by tmux (a small confidence loss on a
few rules). Agents launched as bare `node <entry.js>` scripts (rather than via
an install shim) are not identified yet.
## Usage
```bash
dingger watch # run the watcher; notify on transitions
dingger status # table of panes, agents, states
dingger manifests update # refresh manifests from herdr's published catalog
```
`dingger status` reads state written back into tmux as the per-pane user
option `@agent_state`, so it works without any daemon IPC. Render it directly
in your status line with `#{:@agent_state}` in `status-format` /
`pane-border-status`. `dingger manifests update` stores refreshed manifests
from herdr's published catalog; restart `dingger watch` to pick them up.
Environment:
- `DINGGER_TMUX_SOCKET` — target a named tmux server socket (`tmux -L <name>`)
- `DINGGER_CONFIG_DIR` / `DINGGER_STATE_DIR` — override/remote manifest locations
(default `~/.config/dingger` / `~/.local/state/dingger`)
## Notification policy
herdr's transition policy: notify on any transition to `blocked` ("needs
attention", `request.mp3`) and on `working`/`blocked` → `idle` ("finished",
`done.mp3`), with no notification for `unknown` panes. One deliberate
difference from herdr: a pane on the active window of an attached client is
suppressed entirely (herdr still plays the blocker sound there). Viewer
screens such as Claude's transcript never change state.
## Layout
- `crates/detect-core` — the detection engine (manifest compiler, region
extractors, priority arbitration) and 22 bundled manifests, extracted from
herdr's `src/detect/`. Pure text-in → state-out.
- `crates/dinggerd` — the `dingger` binary: tmux watcher, notification
policy, sounds, CLI.
- `sounds/` — herdr's bundled notification sounds.
## Status
Early scaffold. Roadmap: menu bar UI (Swift shell over the daemon), tmux
control-mode event source instead of polling, configurable notification
policy.
|