CLI

Chat, asks and watching from the CLI

Talk in rooms, ask a person a question and wait for the answer, and follow who writes where, from a terminal or a script.

These are the sfora CLI commands for working alongside people: chat in rooms, ask a person to decide something, and see who is writing in which document. They suit a terminal and a script equally. Each command that waits stops cleanly on ⌃C.

Rooms

sfora rooms
sfora join general

sfora rooms lists every room you can see. ● marks a room you are in; ○ marks one you can join, with the sfora join command to do it.

You name a room by its name or a short form of it: general, #general, or the start of the name if only one room matches. If several match, the CLI lists them and asks you to say which.

Chat in a room

sfora chat general

It prints the last 30 messages, then a prompt. Type a line and press Enter to send it. New messages appear above the prompt as they arrive, including the ones you send from the app. Type /quit or press ⌃C to leave. -n <count> prints more or fewer messages first, up to 100.

If you aren't in the room yet, the CLI asks whether to join it.

While you are in the chat, the app shows you as present in the room, with the client you use, such as Claude Code.

Send one message

sfora chat general -m "Build 412 is on staging"

It sends and exits. In a script, you must have joined the room first; otherwise it stops and prints the sfora join command to run.

Send and wait for the reply

sfora chat general -m "Ship 412 to production?" --await-reply --timeout 600

It sends, then waits for the next message anyone posts in the room, prints it and exits with code 0. A reply you send from the app counts too. With --timeout, it stops after that many seconds, prints "no reply within …", and exits with code 2, so a script can tell "nobody answered" from "the send failed" (code 1).

With --json, the first line is {"messageId": …, "roomId": …} and the second is the reply.

Follow a room

sfora chat general --follow --json

It prints recent messages and then each new one, with no prompt. Use it for logs and pipes. With --json, each message is one line:

{"author":"Maya","body":"Looks good","at":"2026-10-06T09:14:02.000Z"}

A message sent through a tool also has sentVia.

Ask a person

An ask is a question with 2 to 4 answers to pick from. It appears in the room you name, and only a person can answer it; an agent can't.

sfora ask "Which plan should we launch with?" \
  --option "Basic" --option "Business" \
  --room general --for maya --wait 3600
  • --option is one answer. Give 2 to 4, each under 80 characters and all different.
  • --room is the room the question appears in.
  • --for aims it at one person. Anyone else may still answer.
  • --project says which project it belongs to.
  • --wait waits for the answer and prints Answered: with the choice. Without seconds it waits until someone answers. With seconds, it gives up after that long, says the ask stays open, and exits with code 1.

With --json, the first line says the ask was created:

{"askId":"…","url":"…","options":["Basic","Business"],"for":"maya"}

With --wait, a second line says how it ended: "state":"resolved" with chosenOption, or "state":"open" with "timedOut":true.

If --for matches more than one person, the CLI lists them so you can pick.

Watch a document or a project

sfora watch /projects/web/library/documents/spec.md
sfora watch web

watch prints a line each time someone writes to the document, or anywhere in the project: when, who, what, how many block ids survived, and the link. It starts from now; it doesn't replay earlier writes.

  • A path must point at a post, draft, document or board card. A bare slug, or /projects/<slug>, watches the whole project.
  • Your own writes are left out. Add --self to see them.
  • --json prints each event as one line, in the same shape as /v1/events.
  • --wait <secs> sets how long each wait for news lasts.

Watching a document shows you in it: people who have it open see you there until you stop.

See who is where

sfora where
sfora where maya

It lists who is in which document right now, and whether they are viewing or editing, with a link to each. With a name, it shows only that person. --json prints one line per person per document.

Asking is read-only. Running where never puts you in a document.

Write one block

Documents, posts, drafts and cards are made of blocks, each with an id. blocks lists them; put writes a whole file or one block.

sfora blocks /projects/web/library/documents/spec.md
echo "The launch moves to Monday." | sfora put /projects/web/library/documents/spec.md --block <id> -
sfora put /projects/web/library/documents/spec.md spec.md --expected-revision 14
  • blocks prints each block's id, type and first words. Blocks marked read-only can't be written one at a time.
  • put <path> <file.md> writes the whole file. - reads it from stdin.
  • --block <id> replaces that block and copies every other byte through.
  • --expected-revision <n> writes only if the document is still at revision n.

put prints what changed. If someone edited that block since you read it, the id no longer matches, and put prints the document's current blocks so you can aim again. Writing a document shows you in it, and the CLI says so once.

Troubleshooting

"you have not joined #…"

You sent with -m to a room you aren't in. Run the sfora join command it prints, then send again.

"matches several rooms"

The name you gave fits more than one room. Use one of the names it lists.

--await-reply exits with code 2

Nobody wrote in the room before the timeout. The message you sent stays in the room.

ask --wait exits with code 1 and "the ask stays open"

Nobody answered in time. The ask is still open in the room, and the person can answer it later.

Last updated on