Agent codenames for parallel session coordination
Status: Partially implemented
Problem
jackin' operators routinely open three, four, or more tabs inside a single Capsule session — each running the same agent with the same provider, pointing at the same workdir, working on the same branch. This is intentional: parallel agents explore the problem space faster than a single agent can. The problem is that none of the agents know who they are relative to the others. They share JACKIN_AGENT, JACKIN_INSTANCE_ID, and every other environment variable identically. A Claude Code session in tab 2 and a Claude Code session in tab 5 are indistinguishable from inside the container. That anonymity makes self-organized coordination impossible: when agents want to divide a large refactoring across tabs — claiming subsets of a task list, avoiding file conflicts, announcing completions — they have no stable identity to claim under, and no way to say "I already started this; pick another one."
The identity gap also breaks across context-window resets. When an agent's context window fills and the process is restarted, the agent loses all memory of what it was doing and which work it owned. Any coordination state stored inside the agent's context is gone. An environment variable survives process restarts because it is attached to the tab, not to the process: when the replacement process starts in the same tab, it inherits the same env and can recover by looking for its own codename in whatever shared state the agents are using.
What jackin' provides
jackin' provides two things: a stable identity for each tab, and a read-only registry that any agent can query. How agents use these is up to the operator and role author.
Per-tab codename. Each tab is assigned a unique single-word codename at creation time — drawn from a small curated wordlist embedded in jackin-capsule. The codename is injected into the environment of every process spawned inside that tab as JACKIN_AGENT_CODENAME. It is stable for the lifetime of the tab: if the agent's context window fills, the agent process is restarted, or the operator sends a new session via the same tab, the replacement process still has the same JACKIN_AGENT_CODENAME — because it is a tab property, not a process property.
Agent registry command. jackin-capsule agents is an in-container binary subcommand that outputs the complete session registry for the current container: every tab ever opened in this container lifetime — active and exited — with its codename, agent type, provider, start time, exit time, and status. Any process inside the container can call it at any time. The registry is owned and maintained exclusively by the capsule daemon; agents can read it but cannot write to it.
An agent that needs to orient itself in a multi-agent session runs jackin-capsule agents, reads the output, and immediately knows who it is, who else is currently running, and which agents were running before it. The two surfaces answer complementary questions: $JACKIN_AGENT_CODENAME answers "who am I?" without a subprocess call; jackin-capsule agents answers "who is everyone and what is their full identity?"
jackin' does not prescribe a coordination format, a communication pattern, or a task-tracking mechanism. That is the operator's and role author's concern. jackin' provides the identity infrastructure — the stable, machine-readable codename and the authoritative registry — and nothing more.
Prior art on infrastructure-assigned identity
Docker's container naming system generates adjective_surname pairs (agitated_torvalds, bold_turing) at container creation time. The rationale is explicit: cryptographic IDs are correct but hostile to human operations; memorable names let operators refer to containers without looking up 36-character strings. The petname library (Dustin Kirkland, used in Ubuntu MAAS and LXD) formalizes this into adjective-noun pairs drawn from large wordlists, designed to satisfy Zooko's Triangle: human-meaningful, no central registry, practically unique at two words.
JACKIN_AGENT_CODENAME follows the same infrastructure-assigned model. The agent does not pick its own name; the multiplexer assigns it. This is the correct choice for a multiplex where tabs may run any combination of agents and providers — a name chosen by the agent would depend on the agent knowing it was running in a multi-agent scenario, which is a prompt-engineering concern rather than an infrastructure one.
Codename infrastructure
Wordlist design
The wordlist is compiled into jackin-capsule as a static &[&str] slice. Design goals: human-memorable and pronounceable (single syllable or common two-syllable words), unambiguous when spoken aloud (crane not grain), drawn from a small number of semantic families so operators can orient quickly, and large enough that any realistic tab fleet — up to ~20 simultaneous tabs per container — draws from a clearly uncrowded pool.
Recommended families and target counts: animals (~60 words — badger, crane, falcon, gecko, heron, ibex, jackal, kite, lynx, mink, newt, otter, puma, quail, raven, stoat, teal, vole, wren, yak, and roughly 40 more); landforms (~50 words — arch, bay, bluff, cape, cliff, crag, delta, dune, fjord, gorge, gulch, inlet, isle, knoll, ledge, mesa, moor, peak, reef, ridge, scarp, shelf, shoal, sill, spit, spur, steppe, swale, talus, tor, vale, and roughly 20 more); weather and celestial (~40 words — aurora, cirrus, frost, gale, haze, mist, nimbus, squall, storm, surge, tide, veil, zephyr, and roughly 27 more). A total of ~150 words gives ~150 × 149 = 22,350 ordered pairs before any collision, far exceeding any realistic tab fleet.
The wordlist is fixed at compile time and embedded verbatim — no runtime file read, no external process, no OS entropy at tab-open time. Codename assignment cycles through the list starting from a random offset seeded once at daemon startup. Codenames are never reused within a container lifetime. Once a codename has been assigned to any tab — even if that tab has since been closed — it is permanently retired for the remainder of the session. This is the critical property: an agent that reads badger in a shared file and later sees a new badger in the tab strip could mistake the new tab for the old one. Permanent retirement eliminates that ambiguity entirely.
Because codenames are not recycled, the effective pool shrinks as tabs are opened and closed. With ~150 words, the pool supports ~150 distinct tabs opened over a session before exhaustion. In practice, the number of tabs opened over a typical jackin' session is well below this ceiling. When the pool is exhausted, the daemon falls back to <word>-N combinations (e.g. badger-2) drawn from the same semantic families, ensuring the name remains human-readable and unambiguous without recycling any previously seen bare word.
Daemon changes
The Tab struct in crates/jackin-capsule/src/tui/layout.rs gains a codename: String field assigned at construction. The Multiplexer in crates/jackin-capsule/src/daemon.rs holds two sets: live: HashSet<String> for codenames currently assigned to open tabs, and retired: HashSet<String> for codenames that have ever been assigned and must never be reused. On tab creation the daemon picks the next word from the wordlist that is absent from both sets, inserts it into live, and stores it on the Tab. When a tab is closed, its codename moves from live to retired — it is never available for assignment again.
The daemon also maintains a history: Vec<AgentRecord> — an append-only ordered log of every tab ever opened in this container lifetime. Each AgentRecord stores the codename, agent slug, provider label, started_at timestamp, and an optional exited_at timestamp (set when the tab closes). This history is the sole data source for jackin-capsule agents and for the tab hover tooltip. It is never pruned during a container lifetime; both live and retired sets are consistent with it at all times.
Environment injection
build_agent_command() in crates/jackin-capsule/src/session.rs already injects JACKIN_AGENT from the session's agent slug. Adding JACKIN_AGENT_CODENAME follows the same pattern: the function receives the tab's codename as an argument (passed from the dispatch path in daemon.rs that already knows which tab the new session lives in) and calls cmd.env("JACKIN_AGENT_CODENAME", codename). All processes spawned in a tab — the primary agent session, split-pane secondary sessions in the same tab, and shell sessions — receive the same codename. Pane splits that open in a different tab receive that tab's codename, not the source tab's.
JACKIN_AGENT_CODENAME is added to the reserved runtime env list in crates/jackin-core/src/env_model.rs alongside the existing JACKIN_* vars so role authors cannot override it via [env.JACKIN_AGENT_CODENAME] declarations in their manifest.
TUI display
The Capsule tab strip label does not change. Codenames are intentionally not shown in the tab strip at rest — adding them there would increase visual noise without benefit, since the codename is not something the operator needs to see on every glance at the tab bar.
Tab hover tooltip. When the operator moves their mouse cursor over a tab cell in the strip, the multiplexer renders the codename as a coloured pill (dark background, phosphor green text) at row 3, directly below the tab strip with one blank row of breathing space. This is the only place the codename appears in the TUI. The label is painted inside compose_chrome_hover_frame using the existing ANSI save/restore cursor sequence, left-aligned to the hovered tab cell's column from StatusBar::tab_regions. Entering or leaving a tab hover triggers a full frame repaint so the label is never left on screen after the operator moves away. The Some(_) => PointerShape::Pointer arm in pointer_shape_at already handles HoverTarget::Tab — no separate arm is needed.
Agent registry command
jackin-capsule agents is a subcommand of the in-container capsule binary that queries the daemon over the control socket at /jackin/run/jackin.sock and renders the complete session history. Any process running inside the container can call it.
The registry is always present for the lifetime of the container. The first tab opened creates the first record; every subsequent tab open or close appends to or updates the log. An agent that calls jackin-capsule agents at any point during the session gets the full picture of who has ever run in this container, regardless of whether those agents are still active.
Output format
The command renders structured output that is both human-readable in a terminal and reliably parseable by an LLM in a tool call:
jackin' agent registry
You are: badger (claude · anthropic)
codename agent provider started exited status
──────────────────────────────────────────────────────────────────────────────────
badger claude anthropic 2026-06-04 10:15:02 — active ← you
falcon claude anthropic 2026-06-04 10:16:30 — active
reef codex openai 2026-06-04 10:17:45 — active
crater claude anthropic 2026-06-04 10:12:00 2026-06-04 10:40:11 exitedThe ← you marker on the calling agent's own row is rendered using the caller's JACKIN_AGENT_CODENAME env var — the command reads its own env to identify itself and annotate the output accordingly. Active agents appear first, sorted by start time; exited agents follow, also sorted by start time. The — placeholder in the exited column for active agents makes the table fixed-width and easy to parse without conditional logic.
Machine-readable flag
jackin-capsule agents --format json outputs the same registry as a JSON array for tooling and scripting:
[
{"codename": "badger", "agent": "claude", "provider": "anthropic", "started_at": "2026-06-04T10:15:02Z", "exited_at": null, "status": "active", "is_self": true},
{"codename": "falcon", "agent": "claude", "provider": "anthropic", "started_at": "2026-06-04T10:16:30Z", "exited_at": null, "status": "active", "is_self": false},
{"codename": "reef", "agent": "codex", "provider": "openai", "started_at": "2026-06-04T10:17:45Z", "exited_at": null, "status": "active", "is_self": false},
{"codename": "crater", "agent": "claude", "provider": "anthropic", "started_at": "2026-06-04T10:12:00Z", "exited_at": "2026-06-04T10:40:11Z", "status": "exited", "is_self": false}
]Why read-only
Agents can read the registry but cannot write to it. The capsule daemon is the sole authority on which tabs exist, which codenames are assigned, and which tabs have exited. An agent that could write to the registry could falsify identity records, impersonate another agent's codename, or poison the shared identity surface that other agents depend on. The read-only constraint is enforced by design: jackin-capsule agents is a query to the daemon over the control socket, not a write to a file.
Design questions
Should the wordlist be extensible by role authors? The compile-time static slice is the simplest implementation. A wordlist file under /jackin/runtime/ baked into the role image, falling back to the compiled list, would let role authors customize codenames for their domain. Deferred to implementation.
Should the registry survive container restarts? The current proposal keeps the registry in daemon memory, which resets on container restart. Persisting it to a file under /jackin/state/ would let operators review the full session history after a restart. The tradeoff is added I/O on every tab open/close and a schema-migration concern. Deferred.
Should codenames be operator-assignable? The current proposal generates them automatically. Allowing jackin new-tab --codename badger adds control but requires uniqueness validation and a clear error when the name is already used or retired.
What does the tab hover tooltip show for split panes? A tab can contain multiple split panes, each running a different session. The tooltip for the tab strip cell should show the primary session's identity and summarize the pane count. Per-pane identity is a Phase 3 design question.
Should jackin status on the host report codenames? Yes — the host-side jackin status command should show per-instance agent lists with codenames, agent types, providers, and timestamps, making it a richer view than jackin-capsule agents (which is scoped to one container). This work is tracked in Operator CLI Hygiene Phase 2, which already owns jackin status / jackin ps. That item's output schema will be extended to include per-agent codename rows when the registry data is available from a running container.
Future direction: inter-agent messaging
This section captures a future vision, not an implementation plan. No work on inter-agent messaging is scheduled or designed for any current phase.
The codename and registry infrastructure described above is the first layer. It gives agents identity and fleet awareness. The natural next layer — which this roadmap item does not design or implement — is direct inter-agent communication: an agent addressing a message to another agent by codename, and jackin' routing it through the capsule daemon.
A rough future shape: jackin-capsule send falcon "I finished my tasks, you can start on the remaining ones" sends a message to the tab running falcon. The falcon tab receives the message through an inbound queue the daemon manages. Each tab would have an inbound message queue, and agents could poll it or block on it. The sending agent addresses by codename; the daemon resolves routing; no session ID or PTY address is needed.
This direction has clear precedent in the agent orchestration ecosystem — Batty's maildir-style inboxes, CrewAI's task hand-off model — and it is the natural extension of the identity infrastructure here. It is not being designed yet because the identity and registry layer must ship and prove useful first. Premature messaging infrastructure before agents reliably use codenames would be building on an unvalidated foundation. When the time comes, this item and agent workflow orchestration should be designed together, since a workflow runner that routes work between agents via codename messages is a structured version of the same concept.
Phases
Phase 1 — Codename infrastructure and registry command
Deliverables:
- Embedded 150-word curated wordlist in
jackin-capsule. codename: Stringfield onTab; assigned at tab creation from the wordlist.live: HashSet<String>andretired: HashSet<String>inMultiplexer.history: Vec<AgentRecord>append-only log inMultiplexer— stores codename, agent, provider,started_at,exited_atper tab; the sole authoritative data source for the registry command and tab tooltip.JACKIN_AGENT_CODENAMEenv injection inbuild_agent_command().JACKIN_AGENT_CODENAMEadded to the reserved runtime env list incrates/jackin-core/src/env_model.rs.jackin-capsule agentssubcommand — queries the daemon via the control socket, renders the full registry with← youannotation and timestamps, supports--format json.- Tab hover tooltip: coloured codename pill (dark bg + phosphor green text) rendered at row 3, one blank row below the tab strip; left-aligned to the hovered tab cell's column; full frame repaint on hover enter/exit clears stale labels. Tab label itself unchanged.
Phase 2 — Operator documentation
Deliverables:
- This roadmap item updated to
Partially implementedafter Phase 1 lands. - Operator guide page
guides/parallel-agent-coordination.mdxexplainingJACKIN_AGENT_CODENAME,jackin-capsule agents, and--format json— with practical examples of how operators and role authors can use the identity infrastructure for parallel session work.
Phase 3 — Integration (deferred pending operator feedback)
Deferred until Phase 1 and 2 have shipped. Candidate work:
- Registry persistence across container restarts under
/jackin/state/agent-registry.json. - Configurable wordlist override in the role manifest.
- Host-side
jackin statuscodename integration is tracked separately in Operator CLI Hygiene Phase 2.
Related work
- jackin' Capsule control plane — the in-container multiplexer that owns tab lifecycle, pane tree, and environment injection. Phase 1 of this item is a direct extension of Capsule Phases 1–3.
- Operator CLI Hygiene — owns
jackin status/jackin ps(Phase 2). That item's output will be extended to include per-agent codename, agent type, provider, and timestamps sourced from the in-container registry, giving the host operator a richer fleet view thanjackin-capsule agentsalone. - Agent runtime status authority — classifies whether an agent is
working,blocked,done, oridle. Codenames give agents a stable per-tab identity; runtime status gives the operator visibility into what each identified agent is currently doing. Together they form the per-tab observability pair: who is this tab, and what state is it in. - Agent workflow orchestration — the longer-term vision for jackin'-driven multi-agent workflows. Codenames and the registry are the identity substrate the workflow runner will build on; the future inter-agent messaging direction described above is the direct precursor to the runner's session-routing model.
- Persistent storage and workspace memory layer — a future durable storage surface relevant to Phase 3 registry persistence.
- Terminal observation and automation — the typed read/wait/send Capsule API that a coordination-aware workflow runner would use alongside codename routing.