Oko/Docs

Command reference

oko suggestions tick

Runs one permanent responder tick, including replies and opt-in proactive Slack work.

Invocation#

Command
oko suggestions tick [--channel ID] [--trigger-ts TS]

Inputs and options#

  • --channel selects an exact Slack conversation ID; --trigger-ts requires --channel. Empty, duplicate, malformed and unknown arguments fail before credential reads.
  • The Slack context cache (`oko context refresh`) is refreshed on every tick unless the Oko Desktop setting oko.context.slackRefreshIntervalSeconds states an interval; no interval is built in. oko.context.slackRefreshPageLimit and oko.context.slackRefreshMaxRows bound the refresh only when set. With an interval set, a last-refresh time that cannot be read prints `# slack context cache not refreshed: its last refresh time cannot be read: <cause>` (or `… <value> is not a timestamp: <cause>`) and the cache is not refreshed, rather than taken for one never refreshed; a refresh whose time cannot be recorded prints `# slack context cache refreshed, but its refresh time was not recorded: <cause>`.

Output and state effect#

  • Refreshes supporting context and answers eligible messages. Global approval retries, goal reconciliation, weekly coaching and assignment fanout are omitted from channel-filtered runs.
  • Execution is claimed durably before work; results are retained before Slack delivery. A delivery retry sends the retained result rather than repeating the action. Ambiguous Slack acknowledgements can duplicate a message, not the work.
  • Proactive output requires the existing opt-in. Source and credential failures retain the actual failed operation.
  • The ambient pass (oko.ambient.enabled, every oko.ambient.intervalSeconds) is skipped with `# ambient slack skipped: <cause>` when its last run time cannot be read or is not a timestamp, when a conversation's history cannot be read (`the history of <id> cannot be read: …`), when the company strategy exists but cannot be read (`the company strategy <path> cannot be read: …`; a missing one is sent as no company context), and when the model's answer is not a JSON object with a tool_calls list (the answer is printed). It never decides on a context with those parts silently left out.
  • The weekly velocity review counts each active member's commit days, commits and goals over the last complete ISO week, Monday to Monday in local time, and posts the digest once per week. Whether a member needs a nudge is a typed decision on Brama's `POST /v1/decisions` through Oko's decision alias: a choice between `none`, `low-effort` and `busy-but-unfocused`; only for the last two is a DM written, for the reason chosen. A goal snapshot without a goals list, a done goal whose updatedAt is not an RFC 3339 time, and a repository without an authorDates object or with a commit date that is not a time stop the review with `velocity: <what> …` naming it, instead of counting it as nothing.
  • Who owns an assignment is a typed decision too: a choice among the active members, each described by role and skills; a lone member is the owner without a question, and a decision that cannot be had leaves the assignment unowned with `# no owner judged for <task>: <cause>`.
  • The assignments, member work plans and cost snapshot are published through oko planning publish into oko_assignments, oko_work_plan_snapshot and oko_cost_snapshot of the signed-in member's organization, with their own Wisent session; a failed publish is printed with the table and the database's answer. Member work plans read the team's work telemetry through oko telemetry team.

Refusals and safe exits#

  • Missing Slack/Brama identity reports exact credential failures. Inaccessible channels and auth.test failures refuse. Interrupted execution is not retried blindly; malformed delivery state refuses instead of forgetting history.
  • Every Slack Web API call is made by oko (oko chat api --provider slack) with the oko-slack bot token it reads from Skarbiec; a call Slack rate-limits is refused with HTTP 429 and Slack's body, and the next tick asks again instead of this one waiting.
  • A member's personal message goes by iMessage when the organization has an Ultrareach address and sender and the member a handle: the same send as oko message send --provider ultrareach creates the chat with the oko-ultrareach token it reads from Skarbiec. A refused send is logged with Ultrareach's status and body, and the message goes to the member's Slack DM instead.
  • A member's Slack DM opens only with the one Slack member whose real, user or display name is the member's name, compared whole and without case; a name that is only part of another's, or a first name, is never taken. “no Slack member's real, user or display name is <name>; keep the DM channel as <name>_channel_id in <config>” and “Slack members <ids> are all named <name>; keep the DM channel of the one meant as <name>_channel_id in <config>” name the key of the local Slack config whose channel is used instead.

CLI reference#