Poke AI

Poke your connected AI terminal from Uclusion, and how the local queue delivers those prompts.

What a poke is

Every job has a Poke AI button in its right side panel, and every unresolved bug, task, grouped task, question, and suggestion shows a compact Poke AI control in its expanded header. Pressing one sends the message Start <short code>, for example Start J-6, to the AI terminals connected through the Uclusion MCP proxy. On a connected terminal your agent receives the message through uclusion codex, uclusion listen, or uclusion wait, loads the item with get_job, and begins the workflow without you typing anything in its chat. See Cursor IDE chat for Cursor.

Start is reserved for this explicit human action in the UI. Automatic collaborator events use the event-style Added, Updated, and Responded messages described below instead.

Any message about a nested item includes its parent as well: a comment on a job carries the job (Start T-all-180 of J-all-123), a reply on a view-level thread carries its root, and anything inside a question’s options — whose short codes are local to the question’s inline decision market — carries the enclosing question, for example Start C-1 of Q-all-556. The parent is always a globally resolvable code, so the agent can classify the message and load the enclosing work without any lookup on the nested code itself.

Cursor IDE chat

Cursor IDE chat does not consume Poke AI deliveries or the automatic Added, Updated, and Responded messages on this page. Cursor does not offer a way to start a turn in an idle IDE chat after a Uclusion change. That is a Cursor limitation. Start the next turn yourself by typing Responded or another message. Name the relevant short code when starting different work. Use find_work when no concrete work was named.

Automatic responds

You do not need to poke after responding to the AI. Every semantic human reply, option vote, or Resolve on AI-authored assistance sends Responded <short code> naming what you responded on (releases before mid-2026 sent a bare Responded.). This includes input from someone who is not a current job assignee: that response is advisory and does not make the question answerable, but it still wakes the AI so the advice is not missed. Any human Resolve delegates the choice to the AI and unblocks the question; it does not silently select an option. A human reply in a task or information thread the AI participates in also sends Responded with the reply’s short code and the job as parent, such as Responded C-all-90 of J-all-123. Every response carries its own short code this way, including the one that answers the job’s last open assistance; the job’s changed stage shows in the reload rather than in the message identity. A response inside an option uses the same compound identity with the question as parent, such as Responded C-2 of Q-all-500, and a reply on a standalone view-level bug, question, or suggestion carries its root the same way, such as Responded C-all-91 of B-all-52. Only a change to the root itself, a reopen or a resolution, names the thread root alone, such as Responded B-all-52, because the root is the changed item. The waiting agent reloads that item and continues on its own.

Automatic events for collaborators

After the AI has participated in a job by commenting, replying, voting, or approving, Uclusion also wakes it for response-worthy human changes:

  • Creating a task, grouped task, question, suggestion, or blocker sends Added <item short code> of <job short code>.
  • Editing, moving, or deleting one of those items sends Updated <item short code> of <job short code>. Assignment changes, job-description changes, and explicit stage changes send Updated <job short code>.
  • Editing the current intent/design capsule body sends Updated <capsule short code> of <job short code>.
  • Proposing a new option on a question sends Added <option code> of <question short code>; editing or promoting one sends Updated <option code> of <question short code>.

Added and Updated are additive events, not instructions to replace the work already in progress. The agent reloads the enclosing job, incorporates the change into its current work, and keeps the active job as its scope. If nothing is active, the loaded target becomes active work. A reloaded stage may lock further execution; the agent respects that live stage without treating the event as a new instruction to start the job. For a deleted job item, get_job explicitly says that the requested item was deleted and returns the current enclosing job with that item absent.

A capsule body update is the exception to additive context. It replaces the selected target’s implementation contract. The agent reloads that capsule and Reports, resolves its obsolete review naming the same capsule, and reconciles active work before continuing. If no lane is active, it performs that cleanup without treating the event as permission to start implementation.

Adding an item can itself change the job’s stage or readiness—for example, adding a blocker can move a Doable job to Blocked. In that case Uclusion holds the item’s Added event until the derived workflow write commits, then sends that same item event. The agent’s resulting get_job reload contains both the newly added item and the current stage, without a second stage event or a window where the agent is told about the blocker but still reads Doable. Other derived stage changes do not emit an additional stage Added/Updated event; votes may still produce their normal Responded hand-back. Cosmetic metadata remains silent.

Codex must be started through uclusion for pokes to work

uclusion codex

Arguments for Codex go after --; for example, this starts the session with an initial task:

uclusion codex -- "Run find_work"

Do not pass --remote: the launcher owns Codex’s connection so it can deliver Pokes to the right chat. Configuration and feature flags such as -c, --config, --enable, --disable, and --strict-config may be passed normally after --. The launcher applies them to the visible Codex session and the private Codex runtime where needed.

A Poke has the same input behavior as typing its message into that chat:

  • If Codex is idle, the Poke starts a turn.
  • If a regular turn is active, the Poke is steered into it like pressing Enter and is handled at Codex’s next safe model or tool boundary. Stacked Pokes retain their arrival order.
  • An inline Codex review in the primary chat, or a manual compaction, cannot accept steered input. The Poke remains queued until that operation changes or ends.

The bridge does not mark a Poke delivered merely because Codex accepted an API request. It waits until Codex commits that exact user message. It can retry input proven unable to commit without duplicating a user message that already committed.

Known issues

Codex can remain silent after accepting a Poke. This behavior matches open Codex bug #23807, a five-minute stall between a tool result and the next model request. Uclusion has observed the same failure shape after uclusion codex delivered and Codex committed a Poke: the chat showed that it was working without producing output.

Codex may retry automatically after about five minutes. To recover sooner, interrupt the turn, then type continue in the same Codex chat. Do not press Poke AI again for the same item because the original message may already be in the chat and a second Poke can duplicate the instruction.

Choosing whether Codex processes the retained backlog

By default, after the bridge acquires ownership, it establishes a startup cutoff and skips every Poke already waiting at that cutoff. For example, switching from Claude to Codex does not make the new Codex session process the last week of retained Claude Pokes. To process that retained backlog deliberately, put --deliver-existing-pokes before the passthrough separator:

uclusion codex --deliver-existing-pokes -- "Run find_work"

With the option, the bridge processes its retained backlog in arrival order and then continues with later Pokes. Without it, Pokes arriving after the launch cutoff are still delivered. The default cutoff does not delete queue records, skip update notices, or advance the cursor used by listen, wait, or another named consumer. It also cannot cancel a Poke that Codex had already committed before the bridge restarted.

Which Codex chat receives the Poke

The primary, input-owning Codex chat receives Pokes. Starting a new primary chat, resuming one, or forking one changes that target in order with Poke admission, so the Poke is sent to the primary that was current when Codex accepted it. A later intentional switch is allowed and can therefore hide a still-running Poke in the old chat. Temporarily viewing /side or an /agent transcript does not retarget Pokes, so work can appear in the primary chat while one of those views is on screen. Update notices wait for the primary chat to become idle.

uclusion codex must launch the session; it cannot attach autonomous delivery to a Codex process that is already running. It requires Codex CLI 0.145.0 or newer. Only one bridge may own a workspace and environment at a time. The launcher currently supports Linux and macOS, where it can verify that the visible Codex terminal is still alive.

How uclusion listen and uclusion wait work

The MCP proxy keeps a websocket subscription open for your account and writes every inbound prompt into a local, user-private queue on your machine (~/.uclusion/poke_inbox.sqlite3), de-duplicated by message id so broadcast and retry copies deliver once. Two commands read that queue, both polling it every quarter second and taking the same environment flag as every other CLI command:

  • uclusion listen never exits. It prints each prompt as one line the moment it arrives, so an AI harness that can raise a running command’s output lines as events (such as Claude Code’s persistent Monitor) is woken per prompt with no restart between deliveries. Prefer this form wherever the harness supports it.
  • uclusion wait --timeout <seconds> is for harnesses that only receive a command’s output when it exits (for example uclusion -e stage wait --timeout 3600). When at least one prompt is pending it prints the whole pending backlog, one prompt per line, and exits, so a burst of pokes costs a single wait; exiting silently means the timeout expired with nothing new.

While idle both commands also check about every fifteen minutes whether a newer Uclusion release is available and print a one-time update notice when they first see one — wait exits after printing it, while listen keeps running.

Prompts are not removed when they are read. They stay in the queue until they age out after seven days, and delivery tracks each session’s own cursor: uclusion listen automatically generates a private per-session identity (the UCLUSION_CONSUMER environment variable or --consumer overrides it), while a bare uclusion wait shares the default cursor so turn-start drains keep treating the pending backlog as live work. Every session therefore receives every prompt that arrives while it is armed, and a freshly started session begins clean: its cursor starts at arm time, so the retained backlog is never redelivered — anything still needing attention already shows on the agent’s find work list. Session cursors idle past the retention window are garbage collected automatically.

Starting without an old backlog

Fresh sessions do this automatically: a new listener’s cursor starts at arm time, so the prompts that piled up while you were away — for instance a week of Claude Pokes after time spent in Codex — are simply never delivered, and old activity, including an old Start click, never hijacks a new session. Whatever still needs attention is on the agent’s find work list. The --ignore-existing-pokes flag remains for the shared default cursor used by a bare uclusion wait, whose pending backlog is otherwise live work at turn start. (A session on an older CLI may still deliver the backlog with a (replayed) suffix on each line; agents drop those lines.)

Skipping advances only that consumer’s own cursor. Prompts arriving afterward are still delivered, nothing is deleted from the queue, update notices still appear, and other consumers — including the Codex bridge — are unaffected.

The backlog stays available on request: ask your agent at the start of a session and it arms its listener with --deliver-existing-pokes, which keeps the fresh cursor at zero so the whole retained backlog is delivered as that session’s private copy — nothing else is affected. That also supports schemes built on the queue itself, like sessions that scan the backlog for the first Start no other session has already taken.

The form of the messages

The message text is the contract, and the first word tells you which kind arrived:

Kind Form Sent when
Poke Start <short code> A person explicitly presses Poke AI in the Uclusion UI
Added Added <short code> A person creates a response-worthy task, grouped task, question, suggestion, or blocker on a job where AI collaborates
Updated Updated <short code> A person makes a response-worthy edit, including a current capsule body replacement, move, deletion, assignment change, description change, or explicit stage change on a job where AI collaborates
Respond Responded <short code> A semantic human reply, vote, or Resolve hands activity back to the AI; advisory responses are included even when they do not unblock work

The first word is the contract: an explicit UI poke begins Start, creation begins Added, a response-worthy mutation begins Updated, and a human hand-back begins Responded. Agents and any scheme you build on top of the queue can rely on that prefix. Any nested item appends of <parent short code> to the applicable form — the enclosing job for a comment on a job, the thread root for a view-level reply, and the enclosing question for anything inside its option market. The parent is always globally resolvable, which is what lets an agent set aside messages about work it does not own without looking anything up. An older release may append (replayed) to a line delivered from a new session’s backlog replay — schemes parsing the queue should accept that suffix on any form, and agents treat any such line as history to drop rather than an instruction to act. (Very old releases may still deliver a bare Responded. with no short code, and releases before mid-2026 sent nested comment messages without the of <parent> suffix.)

Multi-agent by default

Every agent session automatically gets its own delivery cursor: each uclusion listen generates a private per-session identity, and the Codex bridge keeps its dedicated cursor. Every session therefore receives every prompt — nothing is stolen by whichever process happened to poll first — so running a second session, deliberately or by accident, never makes a Poke disappear. Only a bare uclusion wait with no session identity still shares the default cursor, which is what surfaces that drain at turn start rely on.

The installed workflow files tell each agent to process its stream single-threaded: prompts about the job or bug it is currently working are handled immediately, anything else is briefly mentioned and set aside, and when the current work finishes the agent runs its find work list, which already reflects whatever arrived meanwhile — a set-aside Start never auto-starts; if you still want it worked, you pick it from that list. Dividing the labor between concurrent sessions stays your responsibility: tell each session what it owns, and the set-aside behavior keeps them out of each other’s lanes.

For schemes that need explicit, durable identities — a leader agent distributing work, or a named lane that survives restarts — set the UCLUSION_CONSUMER environment variable for a session or launch with --consumer <name>: every distinct name receives every prompt exactly once, in order. Beyond delivery, the opt-in work claim lock below keeps idle agents from starting the same work; anything finer stays yours to manage through the instructions you give them.

The opt-in work claim lock

Delivery alone cannot stop two idle agents, possibly on different machines, from both running their find work list and starting the same job or bug. The work claim lock closes that gap. It is off by default; enable it with:

uclusion update --work-claims

and disable it with uclusion update --no-work-claims. For a non-production environment, put its option before the subcommand, for example uclusion -e stage update --work-claims. Restart the affected AI client sessions (or reconnect their Uclusion MCP servers) after the command completes so the new setting loads.

With the lock enabled, each agent’s Uclusion connection exposes a claim_work tool and the installed workflow tells the agent to use it: right before starting work, the agent claims its candidates in preference order in a single call and is granted the first one that is free, so an agent behind several busy peers lands directly on unclaimed work instead of collecting one denial per taken item. The agent starts the item it was granted and releases the claim when the work hands off. A claim denied outright means everything listed is already being worked. Merely reading an item never claims it, so agents can triage freely without blocking each other.

The lock is held server side against the agent’s live connection and its expiry is refreshed by the connection’s normal heartbeat, so it needs no attention:

  • An agent that hands work off releases its claim immediately.
  • An agent that exits cleanly releases all of its claims on shutdown.
  • An agent that crashes or loses its network simply stops refreshing; the claim expires on its own within a few minutes and the work becomes claimable again.
  • A brief network drop does not lose the lock. The reconnecting agent re-asserts the short codes it holds and recovers each one whose old connection is gone, while a code another agent legitimately claimed in the meantime stays with its new owner.

The lock is a coordination aid, not a permission system: agents on the same account cooperate through it, and if the lock service is ever unreachable the agent proceeds without it rather than stopping work.