tmux-team · git:20260906.47eaa36 · 2026-09-06 · sha256 987d5d8d5f7b8286
tmux-team git:20260906.47eaa36A
Immutable. This exact content is served forever at /api/v1/blob/987d5d8d5f7b8286.
---
name: tmux-team
description: Communicate with other AI agents in tmux panes through the tmt CLI.
---
# tmux-team
Use `tmt` (the short alias for `tmux-team`) when the user asks you to communicate with another agent in a tmux pane.
SQLite owns durable identities and profiles independently of the working
directory. Active presence also requires matching live tmux binding metadata.
## Delivery safety
Normal delivery pastes a tmux buffer, waits for the configured paste-to-Enter
delay, then sends Enter to submit the message.
`talk` converts ASCII `!` to fullwidth `!` on both normal and fallback input
paths to protect coding-agent shell/bash-mode shortcuts. Line breaks are
preserved, but text such as `if (!ready)` is not delivered byte-for-byte. Do not
assume bracketed paste or an agent's identity name makes literal `!` safe.
`DELIVERY_UNCERTAIN` (exit 1) means input or Enter may already have reached the
pane. JSON includes the failed `stage`. Do not automatically resend: inspect
with `tmt check <target>` and establish whether work started before deciding
what to do next. Missing visible output is not proof that nothing executed.
Successful submission also does not guarantee exactly-once agent processing.
`talk` waits for the complete durable reply by default. It never treats terminal
markers, idle output, a summary, or process exit as completion. A cooperating
recipient must invoke `tmt reply`; otherwise there is no final result yet.
`check` is only a diagnostic snapshot, not correlated result retrieval.
Its positional count or `--lines` accepts integers from 0 through 2147483647;
zero captures the visible pane. Invalid counts are rejected, not clamped.
Invalid configured capture counts also fail before target lookup or capture.
## JSON results and failures
With `--json`, parse the entire stdout as one JSON document. Errors contain
`error.code` and `error.message`; stderr is reserved for optional diagnostics.
Check the exit status too: missing targets use 3, timeout 4, and conflicts 5.
Successful commands without a detailed result return `{ok:true}`.
Timeout returns `status: "timeout"`, `requestId`, target/pane correlation and
`error: {code: "TIMEOUT", message: "..."}` (exit 4). There is no partial response,
nonce, end marker or truncation flag. Use `tmt result <request-id> --json` later.
Timeout and interruption end only the observer, never recipient work. A
`CLEANUP_ERROR` does not undo effects; preserve the request ID and inspect before
retrying. Missing visible output is not permission to resend.
`help`, `version`, `completion` and `learn` are text-only and reject
`--json` with `JSON_UNSUPPORTED`; run them without that flag. `upgrade`
also rejects JSON mode because it streams installer output.
## Durable replies and results
When TMT supplies an exact receipt, submit the complete result through the
storage-only adapters:
```bash
tmt reply <request-id> --receipt <receipt> --message 'Review complete.'
tmt reply <request-id> --receipt <receipt> --file response.md
tmt reply <request-id> --receipt <receipt> --stdin < response.md
tmt result <request-id> --json
```
Use `--message` for short replies, including an explicit empty string. Quote
the body for your shell; use `--message='-leading text'` for a leading hyphen.
Choose exactly one of `--message`, `--file`, or `--stdin`. Inline arguments
have operating-system size limits and cannot contain NUL; use file/stdin for
large bodies or NUL-containing text. All sources share the same exact-body
validation and immutable submission rules.
Received instructions group the reply command in `<tmt-reply>` tags, with the
request ID and receipt supplied once. These tags do not guarantee hidden UI
rendering and are not terminal-output completion markers. Replace the message
placeholder with your complete response, or use file/stdin with the same
request ID and receipt.
Use exactly one input source and the exact request ID/receipt supplied in the
received `talk` instruction, including detached requests. Never manufacture a
receipt, select the latest request, or infer a current pane. Both `reply` and
`result` are storage-only and work without a live pane on this same local
TMT database; this is not an inbox, listener, remote transport or authentication.
Reply input is one exact valid UTF-8 body up to 1 MiB, preserving empty,
whitespace, BOM, NUL, CR/LF, Unicode, and marker-like text. Stdin is
EOF-driven with a five-second input deadline. Successful submission means the
result was delivered, not that the task succeeded; show a brief truthful
summary only after submission, never as completion evidence.
An identical retry for the same request and attempt keeps the original
`submittedAtMs`; a different body is a conflict and cannot replace the stored
response.
The receipt is local correlation, not remote authentication. New requests freeze
the global retention policy at preparation (90 days by default). Accepted bodies
use that duration from submission; pre-retention-migration requests and bodies
keep seven days. Identical retries are safe only while the body is retained,
with the same receipt and body; retries and reads never renew expiry.
A missing result does not cancel the work. Surface a failed
submission without a success summary; if final summarization fails after
acceptance, do not resubmit.
With `--json`, reply success is `{status:"submitted",requestId,bodyBytes,submittedAtMs}`
and result success is `{status:"completed",requestId,response,bodyBytes,submittedAtMs}`.
Unavailable JSON is
`{status:"unavailable",requestId,error:{code:"RESPONSE_NOT_AVAILABLE",message}}`.
`result` reports `RESPONSE_NOT_AVAILABLE` (exit 3) for pending, unknown, or
expired bodies. Input errors exit 1, input timeout is `RESPONSE_INPUT_TIMEOUT`
(exit 4), and conflicts exit 5. Receipts, endpoints, and raw bodies are not
echoed in acknowledgements.
## Calling an agent
`tmt talk <target> "message" [--timeout <time> | --detach] [--json]` waits for
one durable final by default. The default is 180 seconds unless
`defaults.timeout` is configured. Time accepts positive seconds or `ms`/`s`
suffixes, at most 24 hours. Do not combine explicit timeout with detach.
Pre-send delay accepts zero or a positive finite value, up to 2,147,483,647 ms.
`--wait` is retired and rejected; `--lines` applies to check, not talk.
Stored wait/polling mode settings are inert; `config clear mode` removes
only the explicit local obsolete key, without migrating other settings.
```bash
tmt talk reviewer "Review this patch" --timeout 300 --json
tmt talk reviewer "Run the agreed tests" --detach --json
tmt talk reviewer "Review this patch" --identity coordinator --json
tmt result <request-id> --json
tmt check reviewer 200 # diagnostics only
```
Detached success is `{status:"sent",requestId,target,pane,identity?}`, not task
completion. Completed talk adds the exact `response`, `bodyBytes` and
`submittedAtMs` to request/target/pane correlation. Preserve that request ID.
Talk/send's command-local `--identity <existing-name>` attributes the originator,
not the recipient. An explicit existing identity may be offline and overrides
a different bound caller. It does not create or bind a name or authenticate
authorship. Omission uses a verified caller when present, otherwise remains
anonymous; unlike role access, no caller is required. Unknown explicit names
fail with `NAME_NOT_FOUND` (exit 3); ambiguous or unverifiable context fails
before sending (exit 1). Public `identity` still describes the recipient.
New requests retain exact original messages locally in SQLite, before preamble,
reply instructions and `!` protection, for the frozen duration (90 days by
default). Avoid secrets. The inclusive limit is 1,048,576 UTF-8 bytes of
well-formed Unicode; empty text is valid. Invalid/oversized text returns
`REQUEST_INPUT_INVALID`/`REQUEST_INPUT_TOO_LARGE` (exit 1) before target effects.
Shell/OS argument limits still apply; talk has no file/stdin input option.
Prompt expiry starts at preparation and is not extended by a late final or read.
Historical context is unavailable, never reconstructed from a terminal.
Use identity-scoped `x show` for retained context; there is no offline recipient
inbox. No upload, encryption or secure-erasure guarantee is made.
The observer clock starts immediately before send, after pre-send delay and
preparation. Transport/Enter time counts; synchronous transport cannot be
cancelled mid-operation. A response read at or crossing the deadline is not
accepted by that observer; it may still be retrieved with result afterward.
Do not resend simply because a caller timed out or was interrupted.
Craft clear, specific requests. After receiving a durable response, summarize
the result for the user without treating submission alone as task success.
## Durable identity creation and discovery
Use the same explicit commands inside or outside tmux:
```bash
tmt identity create coordinator --json
tmt identity show coordinator --json
tmt identity list --json
```
These commands use only local storage, without tmux or unrelated configuration.
Create is idempotent for canonical-equivalent names: it preserves the existing
UUID, original display name, profiles and any pane binding. It never logs in,
binds a pane or takes over another caller's identity. Multiple local callers
may explicitly select the same identity; this is not authentication.
Create returns `{identity:{id,name,canonicalName},created}`; show returns
`{identity:{id,name,canonicalName}}`; list returns `{identities:[...]}` in
canonical-name order, including unbound identities. It does not report presence.
Use ordinary `tmt list` for verified active destinations. A new identity alone
cannot receive talk: bind a live pane with `add`, `name` or `this` first.
Names are required for create/show; omission never selects the current pane.
Invalid names return `INVALID_NAME` (exit 1); valid missing show names return
`NAME_NOT_FOUND` (exit 3). Creation does not alter anonymous talk or request-ID
result access. There is no identity rename/delete or listener command.
## Exchange attention
Use X to recover requests originated by your durable identity, including after
timeout, detach, pane loss or process restart. Outside a verified bound pane,
select an existing identity explicitly. This is local attribution, not authentication.
```bash
tmt x --identity coordinator --json
tmt x show <request-id> --identity coordinator --json
tmt x ack <request-id> --revision <revision> --identity coordinator --json
tmt x ackall --identity coordinator --json
```
Bare `x` means `x list`: unacknowledged retained metadata only, without loading
prompt or final bodies. `--limit` defaults to 50 (1-200); `--after` defaults to 0.
Follow non-null `nextAfter` with `--after`; this is a live revision cursor, not
a frozen snapshot. Deduplicate by request ID; restart at 0 to refresh.
List/show never acknowledge. Single `ack` requires the exact current revision
from list/show; a stale revision returns `X_REVISION_CONFLICT` (exit 5).
`ackall` needs no prior list, token or batching: it acknowledges the identity's
current write-transaction snapshot and returns `acknowledgedThrough`, not a count.
It does not claim you read every result. A new request or first final committed
after that snapshot remains unacknowledged. Each repeat takes a new snapshot.
Delivery and final are independent. `not_submitted` does not mean a task is
running; a final may be `retained`, `expired` or `unavailable`. Show exposes exact
retained prompt `message` and final `response`. Acknowledgment neither cancels
work nor deletes content nor asserts success. Settled means a final was submitted
and its current revision acknowledged, even if its body later expires.
Unknown, anonymous, wrong-originator and metadata-expired X records return
`X_NOT_FOUND` (exit 3). Missing caller identity returns `IDENTITY_REQUIRED` (exit 1).
Reads and acknowledgments never renew retention. This is not an offline recipient
queue, memory search or remote access; `talk` still needs a live destination.
## Role profiles
Roles are stored profiles, not automatically injected instructions. Select an
existing durable identity explicitly when working outside tmux:
```bash
tmt role show --identity reviewer --json
tmt role set "Review correctness before style." --identity reviewer --json
tmt role set --file role.md --identity reviewer --json
tmt role clear --identity reviewer --json
```
Choose inline content or `--file`, not both. Omit `--identity` only when the
caller has a verified live tmux identity; otherwise use explicit selection.
Unknown names fail with `NAME_NOT_FOUND`; selecting a name does not create or
bind it. An existing identity without a profile returns `role: null` in JSON.
Clear removes only the profile, not the identity. Explicit access works while
unbound and does not load unrelated configuration. Use `preamble` separately
when text should be injected into messages; role edits never change it.
## Identity preambles
Preambles are separate from role profiles and belong to existing durable global
identities. These commands work without tmux, even when the identity is unbound:
```bash
tmt preamble show # list stored preambles
tmt preamble show reviewer
tmt preamble set reviewer "Review correctness before style."
tmt preamble clear reviewer
```
Names are explicit; omitting the name lists preambles, not the caller's data.
Unknown identities fail with `NAME_NOT_FOUND`; create the intended identity
with `identity create` rather than treating a pane ID or an old registration as its name.
Use `clear`, not blank `set`. Content is limited to 65,536 UTF-8 bytes.
`talk` uses the resolved identity's preamble for both names and bound pane
targets; unnamed panes get none. Role text is never injected automatically.
`--no-preamble`, disabled `preambleMode`, or `preambleEvery 0` skips injection.
Frequency N uses transactional SQLite reservations at effective counts 1, 1+N,
... for each identity. Sent, uncertain, and pending attempts consume a slot;
proven unsent attempts refund only future decisions. Overlapping failures can
therefore differ from exact successful-send spacing; already prepared messages
never change. The SQLite cadence starts fresh; old JSON state is ignored and
left untouched.
Concurrent waits retain separate request records and remain advisory, not a
single-flight lock. Timeout or interruption ends only that waiter; it does not
cancel the recipient or undo sent cadence. `REQUEST_STATE_ERROR` (exit 1) can
occur after possible delivery: follow its inspection guidance, never infer that
retrying is safe. Replies are correlated independently, but same-pane input
serialization and exactly-once agent processing are not guaranteed.
Old JSON/workspace-metadata preambles are ignored, not migrated or deleted.
Reapply intended text explicitly with `preamble set`. Preamble changes persist
across folders, unbind and pane/server restart; clearing one does not clear its
identity or role.
## Committed identity retention
Once identity creation commits, a later binding failure does not delete the
identity. A valid new name tried on an occupied pane can therefore return
`PANE_ALREADY_BOUND` (exit 5) while leaving that name unbound in SQLite.
It is not an active `list`/`talk` destination, but explicit `role --identity`
and `preamble` commands can access it. A later successful bind reuses its UUID
and profiles. Invalid names and missing preflight panes create no identity.
Do not treat a failed bind as permission to delete data or try unrelated names.
## Commands
`name`, `this`, `whoami` and `unbind` require matching live `TMUX` and
`TMUX_PANE` caller context. Missing, malformed or stale context returns
`PANE_NOT_FOUND` (exit 3), not the default pane's identity. Implicit `role`
access returns `IDENTITY_REQUIRED` (exit 1). Do not fabricate caller variables:
outside tmux, use explicit `add <pane-target> <global-name>`, `talk <target>`,
`check <target>`, or `role show|set|clear --identity <name>`. Explicit selection
does not bind or authenticate the caller.
```bash
tmt list
tmt name <global-name> # bind the current pane globally
tmt this <global-name> # exact supported alias for `name`
tmt add <pane-target> <global-name> # bind an explicit pane by stable `%pane_id`
tmt whoami # show the current pane identity
tmt unbind # remove the current pane identity
tmt talk <target> "message" # target a global name or pane
tmt check <target> [lines]
tmt list [target] # list identities or one pane
tmt install [claude|codex|gemini|all]
tmt upgrade
```
`name`, `this`, and `add` manage one global identity per pane. Names can be
undeclared identities; they do not need to match a configured role. `add`
accepts `%pane_id`, `window.pane`, or `session:window.pane` and stores the
resolved stable `%pane_id`. There is no daemon. A pane title update is only a
best-effort side effect and is not a separate command or API.
Global identities are independent of the current working directory. `talk`,
`check`, and `list` accept either a global name or a direct pane target. The
name `all` is an ordinary identity; it is not a special destination. The
current `add` order is `tmt add <pane-target> <global-name>`; the older
name-first order is rejected with a usage error.
Names are unique across servers sharing the same local TMT database, but
`list`, `talk`, and `check` discover and address only the current tmux server.
A `%pane_id` is stable within a server, not unique across servers. Routine
reads preserve bindings on other sockets. Binding a foreign live name fails
with `NAME_ALREADY_ACTIVE` (exit 5); an unverifiable foreign endpoint fails
with `RECONCILIATION_FAILED` (exit 1). Do not delete the binding to bypass an
uncertain check. Rebinding a proven stale endpoint retains its identity and
profile; no cross-server routing or daemon is provided.
Earlier name-only v5 pane markers are not automatically imported into durable
identities. Use `name`, `this`, or `add` explicitly to bind such a pane. Invalid
metadata is not active presence; do not delete durable data or old files to
repair it. Direct pane targeting remains separate from identity discovery.
V5 does not support `update`, `remove`/`rm`, or `migrate`. Use explicit binding
commands above; `unbind` only detaches the current pane and retains its durable
identity/profile. Do not delete old user files as a migration workaround.
`talk` sends text to another pane and can cause external input there. Only use
it when the user has requested that communication or the surrounding task
clearly authorizes it; do not infer permission for unrelated changes. Use
`--timeout <time>` to bound the default wait, `--detach` to return a request ID
after sending, and `--delay <seconds>` to delay sending.
Avoid sending secrets or credentials to another pane. For a requested send
delay, use `--delay` rather than introducing a separate shell sleep.
Install the same native skill with `tmt install` (auto-detects supported agents).
Claude uses `~/.claude/skills/tmux-team`; Codex and Gemini share
`~/.agents/skills/tmux-team`. No plugin or separate command wrapper is needed.
Claude's native skill can be invoked as `/tmux-team`. Inspect conflicts before
using `--force`, which creates recoverable skill backups outside the discovery root.
An old Claude `commands/team.md`
is preserved with a warning by default; explicit forced Claude installation can
back it up after the native skill is installed. Plugin settings are never modified.
Managed links follow package updates. `tmt upgrade` tracks npm `latest`, not
commit-pinned previews; follow the selected release's installation instructions.
## Configuration safety
Use `tmt config show --json` to inspect resolved settings and file paths.
`config set` supports `preambleMode`, `preambleEvery`, and
`pasteEnterDelayMs`; add `--global` for the global file, otherwise it writes
a local override. Numeric writes require decimal digits only: no suffixes,
fractions, signs, or whitespace. Zero disables preamble injection or removes
the paste-to-Enter delay. Preamble frequency is bounded to a safe integer;
paste delay is at most 2147483647 milliseconds.
The default paste-to-Enter delay is 500 milliseconds; `config show` reports
the effective value after global and local overrides.
`tmt config set exchange.retentionDays 90 --global` sets the duration for new
requests only, from 1 through 3650 integer days. It uses `exchange.retentionDays`
in the same global config file. Local overrides and local `config clear` are
not supported for this key. Changing it never extends existing data or changes
the reply acceptance window or observer timeout. Results remain available
without reading current configuration.
Expired content is unavailable at its stored UTC deadline. Request/result
operations perform bounded opportunistic cleanup; without an invocation there
is no punctual physical deletion. A late accepted final has its own duration
from submission, so metadata can outlive the original request horizon. Reads
never acknowledge a result. Cleanup is not file shrinkage or secure erasure;
wall-clock rollback can delay logical expiry while data remains stored.
Invalid known fields in a loaded config return `CONFIG_ERROR` (exit 1) before
talk/check effects, even when another layer would override them. Unknown and
retired fields remain opaque and are not migrated. A rejected settings update
leaves the file unchanged. Correct the reported field; do not delete the whole
configuration as a workaround. Storage-only `reply` and `result` do not load
unrelated settings, so malformed config does not prevent durable submission
or retrieval.
## Command option scope
Options apply only to commands that use them. `--timeout`, `--delay`,
`--detach`, and `--no-preamble` belong to talk/send; `--lines` belongs to
check/read; `--force` belongs to talk/send and install. Unrelated options
and the unsupported `--config` path override fail with `USAGE_ERROR` before
execution. Use `tmt help` for the command-specific option inventory.
Meaningful common options may precede the command, such as
`tmt --timeout 30 talk reviewer "Review this"`. Put command-local options
such as reply `--receipt`, talk/send `--identity`, or install `--dir` after
their command. Use `--`
before a positional message beginning with a hyphen, or equals syntax for
an option value, such as `--message='--json is literal text'`. Literal text
does not enable diagnostic flags. Reply/result accept only their documented
options; `--verbose` and `--debug` are not supported there.
## View and install the bundled skill
`tmt learn --skill` prints the exact bundled universal skill; plain `tmt learn`
shows the guide. Both are text-only. Install default integrations with
`tmt install [claude|codex|gemini|all]`, or choose a skills root explicitly:
```bash
tmt install --dir ./my-skills
```
This links `./my-skills/tmux-team`; do not also specify a provider. Choose a
folder your provider actually discovers and reload its skills if needed.
Managed links follow bundled updates at the same package path. Re-run the same
install command to inspect/repair the target after relocation; existing
unmanaged content is preserved unless `--force` requests a recoverable backup.
Automatic drift reminders inspect known default paths, not custom folders.
They do not reload an active agent, update provider-managed plugins, or track
alpha release channels. Package upgrades and skill installation are separate
from provider discovery.