Request
From operator testing of tt chat: when the operator messages an agent (@codex ...) and that harness is not currently running tt wait (its model turn ended, it isn't in tt standby), the message just sits in the room. tt chat reports "not listening right now; it will see the message on its next wait", but nothing prompts the harness to take that next wait. The agent should be woken so it notices the message.
What exists today
tt standby --wake cmux registers a cmux surface; directed messages/assignments to a standby member trigger one cmux send + Enter wake (src/wake.ts, queueStandbyWake).
--interrupt messages can use a registered wake endpoint; normal directed messages to a non-standby, non-listening member resolve to pending/unreachable and wake nothing.
tt claude-stop-hook already runs on Claude Code's Stop event, but only guards stick ownership.
Directions to evaluate
- Harness hooks at turn end. Claude Code's Stop hook (and equivalents: Codex notify, Grok session hook, OpenCode plugin events) fire when the agent tries to stop. If the member has unread directed messages (or joined a room with an operator chat open), the hook blocks the stop with a message like "You have 1 unread message from the operator; run
tt wait --json." This covers "agent ended its turn instead of re-entering the wait". It does not cover a session that has been idle for a long time.
- Auto-register a wake endpoint at join. When a harness joins from a cmux surface, record the endpoint automatically, not only at
tt standby. Then any directed message to a non-listening member can take the existing one-shot wake path. Keep one wake per unread message, rate-limited. Consider a tmux send-keys transport for non-cmux terminals.
- Delivery status in chat. Show
woken vs queued in the tt chat notice so the operator knows whether a wake was attempted.
Acceptance
- Operator sends
@agent msg while that agent is idle, not waiting and not in standby. The agent resumes and reads the message without manual intervention, at least on Claude Code and Codex inside cmux.
- Room broadcasts still don't wake anyone. Wakes are at most once per message and never loop.
tt chat shows whether the recipient was listening, woken, or only queued.
Target: next release after 0.15.0 (tt chat).
Request
From operator testing of
tt chat: when the operator messages an agent (@codex ...) and that harness is not currently runningtt wait(its model turn ended, it isn't intt standby), the message just sits in the room.tt chatreports "not listening right now; it will see the message on its next wait", but nothing prompts the harness to take that next wait. The agent should be woken so it notices the message.What exists today
tt standby --wake cmuxregisters a cmux surface; directed messages/assignments to a standby member trigger onecmux send+ Enter wake (src/wake.ts,queueStandbyWake).--interruptmessages can use a registered wake endpoint; normal directed messages to a non-standby, non-listening member resolve topending/unreachableand wake nothing.tt claude-stop-hookalready runs on Claude Code's Stop event, but only guards stick ownership.Directions to evaluate
tt wait --json." This covers "agent ended its turn instead of re-entering the wait". It does not cover a session that has been idle for a long time.tt standby. Then any directed message to a non-listening member can take the existing one-shot wake path. Keep one wake per unread message, rate-limited. Consider atmux send-keystransport for non-cmux terminals.wokenvsqueuedin thett chatnotice so the operator knows whether a wake was attempted.Acceptance
@agent msgwhile that agent is idle, not waiting and not in standby. The agent resumes and reads the message without manual intervention, at least on Claude Code and Codex inside cmux.tt chatshows whether the recipient was listening, woken, or only queued.Target: next release after 0.15.0 (
tt chat).