Cross-session messaging lets two Qoder CLI CN sessions running on the same machine, under the same user account, see each other and exchange messages. A session can ask a peer to pick up a task, hand it a file, or answer a question, without you copying text between terminals.
Use it when work naturally spans more than one session — one terminal on the backend and one on the frontend, or a long-running session you want to hand something to from a second window.
When the feature is on, each session listens on a private socket and records it in a per-user registry. Other sessions read that registry to discover peers, and connect directly to deliver a message.
Both the socket and its directory are readable only by your own user account. Sessions belonging to other users on the same machine cannot see or reach yours.
Ask the Agent to list what it can reach, or let it call
A session's name is its current title, so it changes when you run
Type
Accepting the row inserts the label that addresses that session. A label containing spaces is inserted with the spaces escaped, the same way a file path is.
Mentioning a session tells the Agent which one you mean; it does not send anything. Ask for what you want in the same message — "ask @reviewer to rerun CI" — and the Agent messages it. A message that only mentions a session does not message it.
If the name matches more than one live session, the Agent is given the labels that each address exactly one, and asks which you meant rather than guessing. Names are self-chosen and unverified, so nothing addresses a session on a name alone when it is ambiguous.
Typing
The Agent uses the same
Each session decides for itself what to do with incoming peer messages, through the
When a message is held because the trust question cannot be settled automatically, the session asks you directly:
The prompt is the last thing this session will put on screen, so it never interrupts a permission confirmation or a dialog you are part-way through. It only appears when nothing else is asking you for something. Approving delivers the message on the next turn; declining drops it and tells the sender it was refused. The excerpt is shortened for display — approving delivers the whole message — and any attached files are named by count, because they are copied on arrival and removed again if you decline.
Only one approval is asked at a time, and only while the screen is otherwise free. A message that arrives while a prompt or a dialog is open is still held and is reviewed with
Run
The first line always states the inbound policy in effect and where it came from — your own settings, a repository setting, or the permission-mode fallback, in which case it states the rule rather than a single example of it. This is worth reading when messages are not arriving at all, since a repository setting of
Approving queues the message for the next turn. Declining drops it and tells the sender it was refused.
A message from a peer is treated as a request from a colleague, not as an instruction from you:
Isolation rests on file permissions: the socket and its directory are restricted to your own user account. Within that boundary the sender's self-reported name is not cryptographically verified, so any process already running as you could present itself as any peer. Treat cross-session messages as trusted only to the extent that everything running under your user account is trusted, and prefer
Beta Cross-session messaging is a beta feature and is not enabled by default. Set the feature flag before starting Qoder CLI CN:QODERCN_FEATURE_CROSS_SESSION=1 qodercn. The flag can also be stored asQODERCN_FEATURE_CROSS_SESSION=1in the user-level configuration.envfile so later sessions enable it automatically. Default user-level configuration path:$HOME/.qoder-cn/.env. Restart Qoder CLI CN after changing.env. The feature requires Unix domain sockets and is available on macOS and Linux only.
How it works
When the feature is on, each session listens on a private socket and records it in a per-user registry. Other sessions read that registry to discover peers, and connect directly to deliver a message.
Discovering peers
Ask the Agent to list what it can reach, or let it call ListAgents on its own. The listing has two groups: agents running inside the current session, and peer sessions elsewhere on the machine.
/rename and when the Agent retitles the conversation. The status column tracks the session in the same way: busy while its Agent is working, waiting while it is asking for a confirmation, shell while its user is at a shell prompt, and idle otherwise.
A session that has no title is named after its working directory, plus its handle — the -7c above. Without it, every session working in the same directory would present the same name and none of them could be addressed. Two sessions in /home/dev/api therefore appear as api-7c and api-3f, not twice as api.
A peer is addressed by the label in its row, or by its handle alone. A handle is derived from the socket the session listens on, so it is the same in every session's listing, and it does not change when the session is retitled — -7c reaches that session whatever it is called by then. A titled session's name has no handle in it, so its row states one: handle -3f.
Run /peers to see the same list along with the handle this session is reachable at.
Mentioning a peer in the prompt
Type @ followed by at least one character to complete on peer sessions along with files and agents. Peer rows lead with the @ and are described as session, with the session's status and how long it has been running, so they are distinguishable from a file of the same name.
@ on its own does not list peer sessions, and a mention that matches nothing is left in the text as written.
Sending a message
The Agent uses the same SendMessage tool it uses for teammates, with a peer name as the recipient. Files can be attached by absolute path and are copied to the recipient so it can read them.
A send reports honestly. If the peer exited between the listing and the send, the result says so and suggests listing again rather than silently succeeding.
Controlling what arrives
Each session decides for itself what to do with incoming peer messages, through the security.crossSessionInbound setting:
accept— deliver the message into the session's next turn.hold— park the message for your review; the Agent never sees it until you approve it.refuse— decline everything; nothing is delivered and no attachment is written to disk.
security.crossSessionInbound to accept explicitly; a value you configure yourself is always honoured, even there.
Project-level settings may only make this stricter. A value in a repository's checked-in settings can tighten accept to hold, but never loosen hold to accept. Because that means a repository can override your own choice, /peers always names the setting in effect and the file it came from.
Approving a held message
When a message is held because the trust question cannot be settled automatically, the session asks you directly:
/peers instead, as is one whose prompt was already open when something else needed the screen — that message goes back to the queue rather than waiting out its deadline behind whatever replaced it.
How long the prompt waits is set by general.dialogExpiry, which defaults to five minutes. When it lapses the message is dropped and the sender is told it expired rather than that you refused it — a distinction the sending Agent can act on. never removes the deadline for other dialogs but not for this one, so a single unanswered prompt cannot stop every later message from asking.
A message held because you configured hold yourself is parked without a prompt, since your own standing instruction is not a question. Those are reviewed with /peers.
A hold that came from a settings file in the repository does prompt. It is the same value, but it is the repository's decision rather than yours, so it is put to you instead of quietly removing a prompt you would otherwise have seen.
Reviewing held messages
Run /peers to see the policy in effect, reachable peers, and anything waiting for review:
refuse produces no held messages to explain itself.
Each held message shows an id, its sender, why it was held, and a preview. The sender is identified by the handle derived from the address it asked replies at, and /peers says whether a session is still reachable there. Neither that address nor the name beside it is verified — no session can prove who sent it a message — but a handle can be checked against the peer list above it, where a name can only be read.
Approve or decline by id:
What a peer message can and cannot do
A message from a peer is treated as a request from a colleague, not as an instruction from you:
- It never counts as your approval for a pending permission prompt.
- A leading
/in a peer message is plain text, never a slash command. - Permission boundaries are per-session. If a peer was denied an action and asks another session to perform it instead, the receiving Agent is instructed to refuse and surface it to you.
Security notes
Isolation rests on file permissions: the socket and its directory are restricted to your own user account. Within that boundary the sender's self-reported name is not cryptographically verified, so any process already running as you could present itself as any peer. Treat cross-session messages as trusted only to the extent that everything running under your user account is trusted, and prefer hold on sessions that run with elevated permissions.
Settings reference
security.crossSessionInbound—accept,hold, orrefuse. Controls inbound peer messages for this session.general.dialogExpiry—60s,5m,10m, ornever. How long an approval prompt waits before the message is dropped as expired. Defaults to5m. Read from your own settings only, never from a repository.