Command reference
oko asks ask
Compares the complete proposed question and choices with the operator's standing decisions through Brama before it writes or redelivers an ask. An unrelated question is delivered on every channel the signed-in person chose (`oko contact`) and Oko Desktop or a watched Oko terminal on this machine. Each delivery records what its channel answered. An identical waiting ask is found rather than duplicated; a question no channel takes remains undelivered with each cause.
Invocation#
oko asks ask --from PRODUCT --subject ID --question TEXT [--detail TEXT] [--choice ANSWER]... [--expires-at TIME] [--session ID] [--answered ID|TIME]... [--grant CAPABILITY --lifetime TEXT --admits COMMAND... --effect TEXT --unblocks OBJECT... --tried ROUTE... --risk TEXT --undo TEXT] [--socket PATH]Inputs and options#
- --from names the product that asks (weles, jeden, brama, stado); --subject names what it is about, a run or task id the product understands; --question is the question in one sentence; --detail adds what the person needs to answer it.
- --expires-at, an RFC 3339 time, is when an answer stops counting, for a question whose moment passes (a phone prompt Google withdraws). Without it the ask waits until answered or withdrawn.
- --choice, repeatable, offers one answer the asking product acts on, in the order given; Oko Desktop and Oko iOS show each as a button, and any other answer is refused. Without it the ask takes a free-text answer.
- --socket names the Oko service to hand the ask to Oko Desktop through; without it, the installed one (`OKO_BROKER_SOCKET`, else this user's declared socket).
- --session names the agent session the ask comes from, so the person's replies to what that session already asked him in chat (`oko asks pleas --session`) are read before anything is sent: his reply to the session's newest chat request, and to an earlier chat request for a command this ask admits (`--admits`) or for the grant it names (`--grant`), refuse the ask until each is named with --answered. A session with no live transcript on this machine is refused as `oko asks pleas` refuses it.
- --answered, repeatable, names each answer of his the asker read and shaped this ask by: the id of the earlier ask the same product sent about the same subject, and the `answered_at` of each chat exchange named in a refusal; without it such a repeat is refused with his words.
- A question already settled by a standing operator decision is refused even when --answered names an earlier reply; the model cites the actual ledger message. A failed decision read or Brama judgment refuses before any channel is tried, so an outage question also waits for a working decision route rather than bypassing the operator's settled restrictions.
- --grant names the exact consent or capability an ask requests (`{"tool": "build", "actions": ["stado"]}`). Such an ask carries its whole case, because the person refuses a request he cannot judge: --lifetime (how long the grant lasts), --admits, repeatable (each exact command it lets run), --effect (what the person will observe when they run), --unblocks, repeatable (each Oko task, defect or blocker it unblocks), --tried, repeatable (each cheaper route already tried, with how it was refused), --risk (what can go wrong) and --undo (how the effect is undone). The case is written after --detail into the ask's detail, one labelled part per line in that order (`Grant: …`, `Lifetime: …`, `Admits:` with one `- <command>` line each, …, `Undo: …`), so Oko Desktop, Oko iOS and `oko asks show` show it.
- Example: `oko asks ask --from weles --subject run-36231f17 --question 'Approve the Google sign-in on your phone now?' --choice approved --choice not_received --expires-at 2026-10-07T05:30:00Z`.
Output and state effect#
- Writes the ask, then delivers it on every channel that has not taken it yet, each delivery one row with the channel's own words: `oko-desktop` delivered as `shown by Oko Desktop (pid N)`, or failed; `terminal` delivered as `written to <session> (<executable>, N viewer(s)), …`, or failed; the Stado channels from Stado's `channel<TAB>verdict<TAB>detail` lines, with the ask's id and the command that answers it in the page; `oko-ios` as the database's delivery function records it (`device <token>: …`, or why no iPhone was reached). Prints `{ask, standing, deliveries, new, id}`: the ask with its `standing`, its `deliveries`, `new` (false when an identical waiting ask was found) and `id`, the ask's id at the top level for the caller that withdraws or waits on it (Tama's grant window).
- Every wait says so on standard error in the `czekam` lines: `Oko Desktop showing ask <id>` and `the watched terminals taking ask <id>` at the service's socket, `stado alerts send …`, and `the database's delivery of ask <id> on oko-ios, database, preferences` on the shared database's Realtime stream; a session view names the channel a run stands on and since when.
- A Stado page does not stand behind a service that stopped answering: when `stado alerts send` announces a wait on an address this machine's Stado resolver already holds unanswered past the refresh interval it declares (a vault the alerts item is read from, say), Oko ends that Stado call at once and records the Stado channels as failed with `stado alerts send --subject … was ended where it started to wait: <address>: this machine's Stado resolver holds <n> connection(s) on <bind> unanswered longer than the <s>s refresh interval it declares: …`. The same holds for every Stado call Oko makes.
- An ask whose --from names an announcer (`oko asks announcers`) is written, or found waiting, and handed to its own `oko asks deliver <id> --socket <socket>`, and this command ends at once: it prints the same document with the deliveries made so far and `delivering`, the file the separate delivery writes its output and refusal to (`OKO_ASK_DELIVERY_LOGS`, else `ask-deliveries/<id>.log` in Oko's folder). `oko asks show <id>` reads the deliveries as they are recorded. Tama's grant window is such an asker: its ask only says where the grant is answered, so the grant is never held on a channel.
Refusals and safe exits#
- `oko asks ask would revisit the operator's standing decision in <session> #<ordinal> (<time>): <verbatim words>; <cause>; nothing was asked` when Brama finds a conflicting request; the ledger citation is verified before refusal. An unreadable standing ledger, unavailable Brama, uncertain judgment or invalid citation refuses with the actual failed operation and cause; no ask or delivery row is written. `--answered` never overrides this check. The real disposable-account journey under tests/decisions checks the persisted absence.
- `ask <id> reached nobody: <channel> failed (<detail>); …; oko-desktop failed (<detail>); terminal failed (<detail>); the ask is undelivered in the shared database (`oko asks list` shows it so), `oko asks deliver <id>` and the same `oko asks ask` deliver it again on the channels that did not take it, Oko's service delivers it again as a channel recovers, and `oko contact set` chooses more channels` — exit 1; the ask and its failed deliveries are written, so `oko asks show <id>` reads them with standing `undelivered`. The `oko-desktop` details: `no Oko Desktop is attached to Oko's service at <socket>; open Oko Desktop on this machine`; `Oko's PTY broker at <socket> is not answering: <error>; it runs inside the Oko service (`oko serve`); Oko Desktop shows asks only while Oko's service runs on this machine`; `Oko's service at <socket> runs a build that cannot show asks (unknown command: show-ask); install the current Oko and start it`; `Oko Desktop hung up before it showed the ask (watchers <ids>)`. The `terminal` details: `no terminal of Oko's service at <socket> is being watched; `oko sessions attach <id>` in the person's own terminal puts one on their screen`; `Oko's service at <socket> runs a build that cannot write asks to terminals (unknown command: announce-ask); install the current Oko and start it`; the broker's own refusal followed by `terminals take asks only while Oko's service runs on this machine`.
- `oko asks ask requires --from <text>`, the same for --subject and --question, `oko asks ask requires a non-empty --from` (and --subject, --question), `oko asks ask offers an empty --choice ""; each choice is an answer the asker acts on`, `oko asks ask offers --choice <answer> twice; each choice is offered once`, `--expires-at <text> is not an RFC 3339 time such as 2026-10-07T05:30:00Z: <error>`, `--expires-at <time> is already past, so nobody could answer in time; nothing was asked` (exit 2).
- `<product> asked about <subject> before (ask <id>) and the person answered "<answer>" on <surface> at <time>; read that answer and shape this ask by it, then name the answer you read with --answered <id> to ask again` (exit 1, nothing asked): the person's newest answer to the same product's ask about the same subject, word for word, as `oko asks history` reads it. Real test: `tests/asks/history.rs`.
- `session <id> already asked him for this in chat (the newest request this session wrote in chat, put on his clipboard: <command>; asked him to confirm the grant <grant> and the window answered <answer>) and he replied at <time>: "<his last paragraph>"; read that reply and shape this ask by it, then name the reply you read with --answered <answered_at> to ask again` (exit 1, before the shared database is read), and the same sentence with `an earlier request for the same command or grant` for an older exchange whose clipboard command carries one of this ask's --admits commands verbatim or whose grant equals this ask's --grant. Nothing he said is interpreted: his newest reply refuses until it is named, whatever it says, so the next ask is shaped by it. Real test: `tests/asks/pleas.rs` (`cargo test --manifest-path rust/Cargo.toml --test asks-pleas`).
- `oko asks ask: an ask for a grant carries its whole case, and this one lacks --tried (each cheaper route already tried, with how it was refused), …; the operator refuses a request he cannot judge`, naming every missing part; `oko asks ask: --risk, --undo make the case for a grant, and no --grant names the grant it is for`; `oko asks ask: one ask asks for one grant; --grant was given N times`; `oko asks ask: --lifetime is said once` for a part said once that was given twice (exit 2, before the shared database is read). Real test: `tests/asks/case.rs` (`cargo test --test asks-case`; its written-case journey runs in a disposable signed-in account).
- A delivery that fails on one channel is not a refusal while another took the ask: it is recorded on the ask as `failed` with its reason — the database's `public.app_config holds no push_function_url or push_secret, so no channel was tried`, `this person chose no channel to be asked on`, `no iPhone of this person is registered for Oko notifications; open Oko on the iPhone signed in as this person and allow notifications`, `device <token>: APNs HTTP <status>: <body>`; a Stado channel's own `refused: <provider's answer>`, or, under every chosen Stado channel when nothing could be paged, Stado's refusal as `stado alerts send --subject "<product> asks: <subject>" exited <status>: <Stado's stderr>` — the call named by its subject, never by the ask's text, so the cause comes first and is not cut off (`tests/asks/journey.rs` checks it) — and `oko asks show` prints it.
- `ask <id> was delivered, but what each channel answered could not be recorded: <database answer>` when the deliveries cannot be written; `the shared database's Realtime socket could not be opened to wait on ask <id>: <error>` and the other stream refusals of `oko asks wait` while waiting for the database's verdict on Oko iOS.
- The shared database refusals of `oko database check` (no signed-in session, no organization).