aboutsummaryrefslogtreecommitdiff
path: root/packaging
AgeCommit message (Collapse)Author
2026-10-23raise the terminal window that holds the tmux clientIgor Soarez
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_<tty>, 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.
2026-10-23restore, step 3: offer it in the panel, menu, and status lineIgor Soarez
when tmux stops (and its sessions are missing from the running server, or no server runs), the daemon publishes the restore offer: offer.json for the menu bar app and @dingger_restore for the status line, withdrawn once restored or dismissed. - panel: a first row "↺ Restore 9 sessions · 22 agents" with when it was saved and how many agents were mid-turn; clicking restores, "Not now" dismisses. an offer shows the panel like a waiting agent; off stays off. - menu: the offer on top; restore all, one session, or not now. - status line: a clickable blue ↺N before the clock. - restore runs through the user's login shell, as a terminal starts tmux, so restored panes get a real environment, not launchd's; --report writes restore.log and notifies a summary. restore --dismiss. - commands log only warnings by default; SIGPIPE ends them quietly. e2e: the offer through the real menu bar binary, the summary notification, the offer clearing, a restore with no tmux running, and not now staying dismissed when a terminal starts tmux. the second test daemon is started directly (it leaked through a function's $! before, and dozens of leaked daemons fought over the test socket and loaded the machine); each run uses its own socket and checks its daemons stop.
2026-10-20rebuild the status model as herdr's state machine, event-driven and testedIgor Soarez
the seen logic was inverted: first observations were marked done and real completions idle, so the menu showed teal for agents that did nothing and green for agents that finished, and attending changed nothing visible. - watcher::advance is herdr's apply_pane_state_change + mark_active_tab_seen as a pure function, unit-tested against herdr's own cases; attendance is window-level like herdr's active tab - hook reports are events applied in order, so a turn shorter than a poll is still a completion - event-driven: hook reports, dingger focus, and tmux focus hooks wake the watcher; notifications are delivered off-thread (the macos call blocked ticks for 2+ seconds) after the pane options are written - all per-pane state persists in tmux pane options, so restarts and deploys lose nothing, including the authoritative hook state - every click goes through dingger focus: the menu bar shells out to it and the status-line binding runs it; it picks the right client, skips the window already shown, and activates the terminal app hosting the client - the ready queue is ordered like the menu (blocked first, then oldest done) - menu bar and tmux segment render herdr's symbols in herdr's palette - tests/e2e.sh: 60 assertions against an isolated tmux server with a real client, a 30s poll interval, and a slow fake notifier
2026-10-19menu bar app: live agent states from tmux pane optionsIgor Soarez
single-file appkit status item (menubar/main.swift, LSUIElement) polling @agent/@agent_state pane options every 2s: counts in the bar, per-pane rows with click-to-focus via switch-client. daemon now also writes an @agent label per pane so the menu bar and tmux status-right can render agent names without duplicating identification logic.
2026-10-19wait for tmux at startup, force utf-8 for tmux clients, add launchd packagingIgor Soarez
running under launchd, the tmux client defaults to the c locale, which makes tmux mangle tab-separated -f output into underscores, so every pane parsed as one field and the watcher silently saw nothing; invoke tmux with -u so format output is locale-independent. drop the startup fail-fast: the watcher now waits for a tmux server and attaches when one appears, which is the right shape for a login agent. ship the launchd plist under packaging/launchd.