shelbi message

View as markdown
shelbi message [OPTIONS] [ID] [KIND] [BODY]
shelbi message status <MSG_ID>

ID, KIND, and BODY are optional at the parser (so the status subcommand parses) but required for the base shelbi message form — omitting any of them there is a runtime error.

shelbi message pushes a message to a task's assigned workspace through a file-based message log at <worktree>/.shelbi/messages/<task-id>.log. Each call appends one durable JSON line (msg_id, ts, kind, an optional in_response_to, and body) and prints queued <msg-id> → <task> (<kind>) followed by a note that delivery is not yet confirmed. The worker reads the log from where it left off at the end of each turn and folds any new messages into what it's doing. The msg-id (shaped m-<millis>-<pid>) is what shelbi message status takes.

shelbi message does not type text or Enter into the session, so the session's verified-submit mechanism intentionally does not apply. Runner hooks consume the file record. Keeping this path file-based avoids duplicate delivery and lets the message survive a session restart.

Queued is not delivered

The push being durable is not the same as the worker having read it. A worker only drains and acknowledges its messages at the end of a turn, which for a busy worker can be well after you send. So a plain shelbi message reports the message as queued, not delivered, and does not print a success check.

To learn the real outcome, either block on it or query it:

  • --wait[=SECS] blocks until the worker confirms delivery (default 120s), and exits non-zero if the window elapses with no confirmation.
  • shelbi message status <msg-id> reports the current state (delivered, queued, unconfirmed, undeliverable, or an unknown id) from the durable events stream, exiting 0 only when the worker has acked.

A message queued while the worker is running is delivered at the worker's next turn end, however many messages came before it. If the session dies first, it is delivered at the next turn end after that task's session resumes.

Undeliverable messages

A message to a task that is already done, or with no worker session running, is refused. It exits non-zero and is recorded as ack=undeliverable with a reason (done or no_session), so shelbi message status reports it later. It is not written to the log, so it will not be delivered if a worker starts later: send it again if it still applies. A refused --in-response-to reply leaves the question open in shelbi question list.

A task that is unassigned, whose workspace or machine is no longer declared, or whose worktree doesn't exist yet is an error, and nothing is written or recorded.

<KIND> classifies the message so the workspace knows how to treat it:

KindMeaning
replyResponse to a workspace's request-clarification. Pair with --in-response-to <question-id>.
directiveCourse correction — "stop what you're doing, the spec changed."
contextAdditional background info the workspace should fold in.

send vs message

send and message are easy to confuse. They both get words to a running workspace, but through different channels:

shelbi sendshelbi message
ChannelKeystrokes into the live sessionJSON record in the message log file
DurabilityMessage text is ephemeral; delivery verdict is recorded in events.logDurable record in <worktree>/.shelbi/messages/<task-id>.log
Delivery proofSession submission is verified; no worker semantic ackWorker acks the msg_id at its next turn; query with status or block with --wait
Typed / classifiedFree textreply / directive / context
Reach for it whenA quick, live nudge to a paneA message that must survive, be logged, and be confirmed

Rule of thumb: use shelbi send for an off-the-cuff nudge, and shelbi message when the workspace genuinely needs to receive, record, and act on the message.

Arguments

ArgumentTypeDefaultDescription
[ID]string—Task id whose assigned workspace receives the message. Required for the base message form.
[KIND]reply | directive | context—Message kind. Required for the base message form.
[BODY]string—Message body. Required for the base message form.

Flags

FlagTypeDefaultDescription
--in-response-to <QUESTION-ID>string—Question id this message replies to (sets in_response_to). Typically paired with kind = reply.
--wait [<SECS>]int120 when bareBlock until the worker confirms delivery, polling the events stream. Exits non-zero if the window elapses without an ack=worker.
-p, --project <PROJECT>stringenv / cwd lookupProject to operate on. Defaults to $SHELBI_PROJECT, or the registered project whose work_dir contains the current directory.

A push first checks that the hub daemon runs the same version as this CLI. On a mismatch it offers to restart the daemon; with the global -y it restarts without asking; non-interactively (or while workspaces are busy) it stops and tells you to run shelbi daemon restart. message status skips this check.

Subcommands

shelbi message status <MSG_ID>

Report a pushed message's delivery state from events.log, keyed on the msg_id that shelbi message printed. Prints delivered and exits 0 when the worker has acked, so a script can gate on it. Otherwise it exits non-zero with queued (no ack yet), unconfirmed (the daemon's ack window passed with no ack; a late ack can still land), undeliverable (refused when it was sent, with the reason), or unknown message id (never pushed, or too old to still be in recent events.log history).

Examples

Send a course correction to the workspace working add-auth:

shelbi message add-auth directive "hold off — the auth spec changed, wait for the updated task"

Reply to a workspace's clarification question:

shelbi message add-auth reply "yes, use the existing session table" --in-response-to q-004

Once the reply is queued, --in-response-to also marks the stored question answered, so it drops off shelbi question list. Read a question in full with shelbi question show <id> before you answer it.

Fold in extra background without redirecting the work:

shelbi message add-auth context "the staging DB is seeded with the fixtures you'll need"

Send a directive and block until the worker confirms it read it (fail the script if it does not within 90 seconds):

shelbi message add-auth directive "the auth spec changed, wait for the update" --wait 90

Check delivery of an earlier push without blocking:

shelbi message status m-1785764991921-86377

See also

  • shelbi question lists and shows the clarification questions a reply answers.
  • shelbi send — the ephemeral counterpart: types a message straight into the workspace's pane instead of the durable message log.
  • Workspaces — what a workspace is and how a task gets assigned to one.