Install
$ agentstack add skill-jesamkim-oh-my-skills-orca-cli ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Orca CLI Orchestration
Run multi-agent coding work from Claude Code with a clear division of labor:
| Role | Who | How | |------|-----|-----| | Orchestrator — decompose, route, judge, integrate | Claude Code (you) | this skill | | Code implementation | Codex | orca dispatch (lane) or Stably worktree/orchestration | | Spec writing / second-opinion review | Kiro CLI | direct headless call (kiro-cli chat --no-interactive) — orca has no Kiro adapter |
You are the orchestrator. Do not write the implementation code yourself when a task has been routed to a worker; your job is decomposition, dispatch, judging results, and integration. You still read diffs and run tests — verification is orchestrator work.
Supported platforms: macOS and Linux only (Windows is explicitly out of scope — orcastrator's kill/process-group semantics are POSIX-only, and the wrapper scripts assume a POSIX shell).
Step 0: Detect which "orca" this machine has
Two unrelated tools ship a binary named orca. Their command sets are incompatible, so detect first, then read the matching reference:
bash /scripts/detect_orca.sh
# prints: VARIANTBIN e.g. "orcastrator /home/u/.npm-global/bin/orca"
| VARIANT | Tool | Command style | Read next | |---------|------|---------------|-----------| | orcastrator | happycatlabs/orca (npm orcastrator) | dispatch / inspect / answer / resume / lanes / kill | references/orcastrator.md | | stably | Stably Orca ADE (onorca.dev) | worktree / terminal / orchestration task-create → dispatch → check --wait | references/stably.md, then $ORCA skills get orca-cli for the version-matched guide | | unknown | an explicit ORCA_CLI_COMMAND/ORCA_BIN override matched neither contract (exit 2) | — | report the override and its error; do not fall through to another binary | | none | neither installed | — | offer npm i -g orcastrator (lightweight) or Stably desktop/orca serve install; orcastrator can also run via npx -y -p orcastrator orca ... without install |
Use the printed BIN path for every later call ($ORCA below). Do not trust bare orca on PATH — a Stably relay shim commonly shadows the npm bin, and on Linux outside Orca terminals bare orca can even be the GNOME screen reader (the script refuses to execute that one; it would start speech aloud).
Overrides are strict: when ORCA_CLI_COMMAND (exported by Stably for managed sessions) or ORCA_BIN is set, only that executable is considered — a mismatch prints unknown and exits 2. Report that error instead of falling back to another binary, which could silently target a different Orca build.
The detection result holds for the whole session; do not re-run it per command.
Model policy (applies to every dispatch)
- Default: omit the model flag. Each agent then runs on its own configured
default (Codex config, Kiro auto routing). This is the right call for most tasks and the cheapest.
- Explicit override: when the user names a model ("codex는 gpt-5.5로",
"kiro는 opus로 리뷰"), pass it through — never silently drop it:
- orcastrator:
--modelondispatchonly —resumeaccepts just
--timeout and keeps the lane's original model; to change models, dispatch a new lane. (Valid names come from $ORCA agents manifests; e.g. the claude adapter lists fable|opus|sonnet|haiku.)
- Codex model names are provider-qualified and pass through unvalidated.
The codex adapter advertises no model list — --model goes verbatim to the app-server, which resolves it against the model_provider in ~/.codex/config.toml. On Bedrock Mantle that means the full provider ID (openai.gpt-5.6-sol), not the short name: --model gpt-5.6-sol fails the lane ~14 s in with agent_failed / 404 The model 'gpt-5.6-sol' does not exist (measured 2026-08-03). Before overriding, check grep ^model ~/.codex/config.toml and match its naming scheme — and if the user's requested model IS that default, just omit the flag.
- Stably: model flags go on the agent command itself, e.g.
--command 'codex --model gpt-5.5 -c model_reasoning_effort="xhigh"' (worktree create --agent does not accept model flags — see reference)
- Kiro:
--model(e.g.claude-opus-4.82.2x credits,
claude-sonnet-4.6 1.3x, claude-haiku-4.5 0.4x). Don't hardcode opus for routine work.
- If an override fails with an unknown-model error, report the error and the
agent's advertised model list; do not quietly fall back to the default.
Orchestration loop (orcastrator variant)
The lane contract in one pass — full details, envelope schema, exit codes, and pitfalls in references/orcastrator.md:
# 1. dispatch one focused task per lane (prints a handle line, then blocks
# until the lane settles; run in background for parallel lanes)
$ORCA dispatch --agent codex --cwd . "Fix the flaky token-refresh test. Repro: npm test -- --grep refresh"
# 2. wait / check state (terminal states also satisfy --wait-for blocked;
# ALWAYS branch on the returned status field, never on "the wait returned")
$ORCA inspect lane_a3f81c02 --wait-for blocked --timeout 900000
# 3a. if status=blocked: read blocked.questions, then answer — and resume too
# when the question is parked (see the live/parked split below; the
# envelope's next[] already lists the right commands)
$ORCA answer lane_a3f81c02 "Use the staging database"
# 3b. if status=completed: JUDGE the result yourself (read the diff, run tests)
# ok:true means delivery, NOT correctness — semanticOutcome stays "unknown"
# 4. follow-up on a completed lane (the only terminal state that can resume)
$ORCA resume lane_a3f81c02 "Now add tests for the edge cases"
# housekeeping
$ORCA lanes # list all lanes
$ORCA kill lane_... # stop a queued/running/blocked lane
Reacting to signals
There is no push notification or callback — you learn a lane's state only by asking. dispatch returns one envelope when the lane settles (blocked or terminal), and inspect is how you ask afterwards. Everything below is verified against orcastrator 0.2.25; references/orcastrator.md has the event-level detail.
| Signal | What you see | What to do | |--------|--------------|------------| | Waiting on a question | status: blocked, ok: true, exit 0, blocked.questions[] (options[] only when the agent offered choices), next[] prefilled | Answer it — see the live/parked split below | | Still working | status: running, no terminal envelope yet | Keep waiting with a fresh --wait-for; don't kill | | Wait window expired | ok: false, code: timeout, exit 5, with status = the lane's real last-known state, the lane block, and error.message/error.remediation — but no blocked, next[], or warnings[] | The wait command failed; the lane did not. Branch on status: only roll the wait forward while queued/running, since re-waiting a blocked lane loops forever. Run a plain inspect to get the omitted parts (the question itself, stale-running warnings) | | Success | status: completed, nativeStatus: completed | Judge it yourself: read the diff, run the tests | | Failure | status: failed — branch on code, not exit alone (agent_failed/adapter_error/agent_unavailable exit 3; a dispatch/resume that ran out of time with no pending question settles failed with code: timeout, exit 5) | Read error.message; a failed lane cannot resume — re-dispatch | | Dispatch timed out with a pending question | status: blocked, exit 0 — the turn parks the question as live: false instead of failing | Treat it as blocked, not failed: answer, then resume. Re-dispatching here throws away the agent's work | | Killed / lost | status: killed \| lost, terminal | Re-dispatch. (lost is a reserved state with no v0 code path) | | Possibly-orphaned run | status: running + a stale running warning in warnings[] | The warning tests the pid currently in lane.process, which a resumed adapter overwrites once it emits agent_started — so a healthy resume can still trip it in the window before that. Check the latest resume_started: resumer pid alive → a resume is driving the lane, keep waiting and don't kill; pid dead → resume reclaims it (preferred, keeps the work); no resume_started at all → the original dispatch died, resume fails invalid_state, so kill then re-dispatch |
Rules that follow from the contract:
--wait-for blockedis satisfied by terminal states too (so the wait
can't hang), and --wait-for done means terminal only (completed|failed|killed|lost). Always branch on the returned status; never infer it from the fact that the wait returned.
--wait-foralone prints no events — it is a synchronization
primitive. Add --follow (or read afterwards with --since ) when you want the event stream. Note --follow polls (fs.watch + timer fallback, ~150 ms); there is no daemon, and --detach is rejected with usage_error.
- Read
warnings[]. Stale-running detection lives only in per-lane
inspect — lanes returns a snapshot with no warnings, so a dead dispatcher is invisible there.
- Don't kill a quiet lane. A cursor lane's cold start takes 30–100 s, but
it emits a single heartbeat about a second in (from its early stderr) precisely so you can tell a live cold start from a pre-output hang — so the signal to watch is that heartbeat's absence, not the long startup itself. codex/claude emit no heartbeat at all; their liveness signal is progress events.
- blocked:
answervsresumedepends on whether the question is live.
A live question (the original dispatch is still polling for the answer) takes answer and then --wait-for done; resume on it is rejected with invalid_state (exit 4) to prevent double-driving. A parked question (the dispatch already exited) needs answer and then resume — answering alone returns "Answer recorded (generation N)" and leaves the lane blocked. next[] encodes this split and is the right default, with one exception it can't see: a stale live: true whose poller has died still advertises answer-and-wait, but nothing will consume the answer — resume is allowed and necessary there.
- Confirm the answer was consumed by generation, not by presence. The
submission answered event (no consumed field) stays in the append-only log forever; consumption appears as a later answered event with consumed: true and the same generation. So "still unread" means no later matching consumption event exists — not merely that you can see an unconsumed one.
Rules that prevent the common failure modes:
- One write-capable lane per working directory. Parallel lanes writing the
same cwd will conflict — give each parallel lane its own git worktree cwd. Prompt-level file assignment ("you only touch README.md") is not isolation: workers still see each other's uncommitted changes in git status, and one git stash or commit -a eats the other's work.
- Deliver briefs from a file, not inline. Write the lane brief to a file
and dispatch with "$(cat brief.md)" — inline backticks/quotes in a prompt break shell argument splitting and fail the dispatch with usage_error.
- Match the brief to the task's shape — use Codex goals for long work.
Codex exposes create_goal/update_goal tools inside lanes (verified on codex-cli 0.146.x, feature goals stable). For a multi-step or likely-to-resume task, add to the brief: "Start by calling creategoal with this objective and the acceptance criteria; when finished call updategoal to mark it complete, or blocked if you must stop on a question." The goal record survives the thread, so an orca resume continues against the same tracked objective instead of a cold prompt. Contract limits: one unfinished goal per thread (complete it before creating another), and the agent may only set complete/blocked — pause/resume/budget states belong to the user/system. Skip goal instructions for short single-pass fixes; they add turn overhead without tracking value.
blockedis success, not failure (exit 0). Answer the question instead
of killing the lane.
- Never infer correctness from
ok:true. The envelope separates
delivery / nativeStatus / semanticOutcome; no envelope ever claims the work is right. Verify: run the tests, read the diff. Distrust the agent's self-reported numbers too — Codex's sandbox quotes node --test file-level counts (# tests 3) as if they were per-test counts; run the suite yourself and cite your own output.
- Parse only the final stdout line (one JSON envelope per command); stderr
is diagnostics, not contract.
- Agent choice within orca:
codexfor real engineering (responds well to
detailed briefs), cursor for narrow scoped edits (30–100 s cold start), claude lanes are analysis-only (headless claude -p denies writes by default).
Orchestration loop (stably variant)
Same roles, different verbs — supervised coordination uses orca orchestration task-create → dispatch --inject → check --wait, fire-and- forget handoffs use orca worktree create --agent codex --prompt. Read references/stably.md before issuing commands; the lifecycle rules (worker_done authority, full-handoff vs supervised, worktree ids) are easy to get wrong.
Kiro: spec writing and independent review
Kiro is not an orca agent (orca agent-context lists codex/claude/cursor/ opencode, no kiro), so orca cannot dispatch it as a worker. If the kiro skill is installed, prefer it: scripts/kiro_lane.sh runs Kiro in an orca terminal and returns a handle at once, which keeps the spec/review step from blocking this orchestration loop —
K=/scripts/kiro_lane.sh
h="$(bash $K start --tier deep --title "spec: " "Write an implementation spec for : requirements, design, tasks. Context: ")"
bash $K wait --handle "$h" --timeout 900 && bash $K read --handle "$h"
Bare fallback when that skill is absent:
# spec writing (read-only file access is enough)
kiro-cli chat --no-interactive --trust-tools=fs_read \
"Write an implementation spec for : requirements, design, tasks. Context: "
# explicit model override, per the model policy above
kiro-cli chat --no-interactive --model claude-opus-4.8 --trust-tools=fs_read "..."
The spec-first flow that makes this trio work:
- Ambiguous or multi-day feature → Kiro writes the spec (requirements /
design / task list).
- You split the spec's task list into lane-sized briefs — each brief carries
the relevant spec excerpt, file paths, and acceptance criteria. Codex responds to detail; "fix the bug" briefs waste a dispatch.
- Dispatch to Codex, run the loop above.
- After integration, an independent review pass before commit — the
orchestrator judging its own dispatches is the same trap as reviewing your own code. Review-gate fallback chain (each step's failure is why the next exists): (a) Kiro review mode, preferably as a lane (run_kiro_review.sh --lane) since a real review takes minutes and blocking this loop on it buys nothing; if Kiro's non-interactive policy blocks execute_bash (it is rejected outright — there is no user to approve it), (b) re-run Kiro read-only (--trust-tools=fs_read — static analysis still yields a verdict), then (c) a codex review lane. A run with no review verdict is not "reviewed" — say so in the report instead of letting the gate silently pass.
- Honor the verdict. A no-ship is overridden only with concrete evidence the
reviewer could not obtain (e.g. you executed the behavior-preservation check its static analysis couldn't run) — never with constraints you authored yourself ("my brief forbade test edits" is circular, since you can change the brief). If the
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: jesamkim
- Source: jesamkim/oh-my-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.