ao-desktop-dev
Launch, restart, or troubleshoot the real AO Electron desktop app from this repository; run a checkout against isolated or real…
Talk to a project's AO orchestrator: pass the user's request to it, wait for its reply and relay it. The default route for starting or changing work, "catch me up", "why", "what next" and plans. Use for "in <project>: <ask>", "tell the orchestrator ...", "catch me up on
$ npx -y skills add orchestratorinc/agent-orchestrator --skill ao-orchestrator --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/ao-orchestratorContext preview
The summary Claude sees to decide when to auto-load this skill.
Talk to a project's AO orchestrator: pass the user's request to it, wait for its reply and relay it. The default route for starting or changing work, "catch me up", "why", "what next" and plans. Use for "in <project>: <ask>", "tell the orchestrator ...", "catch me up on
name: ao-orchestrator description: >- Talk to a project's AO orchestrator: pass the user's request to it, wait for its reply and relay it. The default route for starting or changing work, "catch me up", "why", "what next" and plans. Use for "in <project>: <ask>", "tell the orchestrator ...", "catch me up on <project>", "start work on ...".
Follow the ao-rules skill ("Who does what: orchestrator first"). Sending a message is a write: do it only for what the user asked in this turn.
Match the user's words against project ids on every host (`aoapi GET projects`). One match: use it. The same project id on two hosts (two separate projects that share a folder name): ask which host, unless the user named one or memory has a default for that project. No match: list the projects and ask.
f(){ <aoapi helper>; aoapi GET "sessions?orchestratorOnly=true&active=true&project=<project>" | python3 -c '
import json,sys
for s in json.load(sys.stdin)["sessions"]: print(s["id"], (s.get("activity") or {}).get("state",""), s.get("provisionState",""))'; }; ff(){ <aoapi helper>; P='<project>'; TAG="[via Grok Bot #$(date +%H%M%S)]"; F=~/.ao-grok/out/$(date +%F)-<short name>.md
mkdir -p ~/.ao-grok/out; { printf '%s ' "$TAG"; cat <<'EOF'
<message>
EOF
} > "$F"
H=$(aoapi GET "projects/$P" | python3 -c 'import json,sys; d=json.load(sys.stdin); c=(d.get("project",d).get("config") or {}); print((c.get("orchestrator") or {}).get("agent") or (c.get("worker") or {}).get("agent") or "")')
aoapi POST sessions "$(python3 -c 'import json,sys; b={"projectId":sys.argv[1],"kind":"orchestrator","mode":"chat","displayName":"Orchestrator","prompt":open(sys.argv[2]).read()}; b.update({"harness":sys.argv[3]} if sys.argv[3] else {}); print(json.dumps(b))' "$P" "$F" "$H")" | python3 -c 'import json,sys; d=json.load(sys.stdin); d=d.get("session",d); print("started", d["id"])' && echo "TAG=$TAG"; }; fAfter about 10 seconds, check `provisionState` with `aoapi GET "sessions/<new id>"`. If it is `failed`, handle it as above.
Write the message to a file on `via`, then send it. The message is the user's request in their words, plus only the context from this chat the orchestrator needs. Don't add your own design choices. Start it with a tag so you can find the reply:
f(){ <aoapi helper>; O='<orchestrator id>'; TAG="[via Grok Bot #$(date +%H%M%S)]"; F=~/.ao-grok/out/$(date +%F)-<short name>.md
mkdir -p ~/.ao-grok/out; { printf '%s ' "$TAG"; cat <<'EOF'
<message>
EOF
} > "$F"
B=$(python3 -c 'import json,sys; print(json.dumps({"message":open(sys.argv[1]).read(),"userAuthored":True}))' "$F")
if aoapi POST "sessions/$O/send" "$B" >/dev/null; then echo "sent TAG=$TAG F=$F"; return 0; fi
echo "SEND_FAILED: resuming the agent and trying once more"
aoapi POST "sessions/$O/resume-agent" '{}' >/dev/null; sleep 5
aoapi POST "sessions/$O/send" "$B" >/dev/null && echo "sent TAG=$TAG F=$F"; }; fA failed send prints AO's error. If it still fails after the retry, tell the user the orchestrator isn't accepting messages and to open it in AO.
If the orchestrator was `active` in step 2, the message waits and runs as its own turn after the current one. Tell the user right away, in one line: "The orchestrator is busy with <what its last turn is about>. Your question is queued and runs next." Then go on to step 4.
If the user wants to change what it is doing right now ("stop that", "use X instead"), steer instead. Write the file and tag as above, then:
f(){ <aoapi helper>; O='<orchestrator id>'; F='<message file>'
aoapi POST "sessions/$O/conversation/steer-or-send" "$(python3 -c 'import json,sys,uuid; print(json.dumps({"text":open(sys.argv[1]).read(),"clientMessageId":str(uuid.uuid4())}))' "$F")"; }; f`"outcome":"sent"` means it arrived (in the running turn, or as a new turn if the orchestrator was idle). Then go to step 4.
Check every 10 seconds for up to 5 minutes. Done when the orchestrator is no longer `active` and a turn that starts with your tag has a reply:
f(){ <aoapi helper>; O='<orchestrator id>'; TAG='<tag>'
for i in $(seq 30); do sleep 10
st=$(aoapi GET "sessions/$O" | python3 -c 'import json,sys; d=json.load(sys.stdin); d=d.get("session",d); print((d.get("activity") or {}).get("state",""))')
[ "$st" = active ] && continue
aoapi GET "sessions/$O/history?offset=0&limit=5" | python3 -c '
import json,sys
for t in json.load(sys.stdin).get("turns") or []:
if (t.get("userRequest") or "").startswith(sys.argv[1]) and t.get("agentResponse"):
print(t["agentResponse"]); raise SystemExit(0)
raise SystemExit(1)' "$TAG" && return 0
done; echo STILL_WORKING; }; fIf the orchestrator started workers, list them in one line (ao-status
Plan, run and supervise fleets of agents from task to merged PR. Desktop (macOS, Windows, Linux) + iPhone & Android apps. Supports Claude Code, Codex & 35+ coding agents.
Launch, restart, or troubleshoot the real AO Electron desktop app from this repository; run a checkout against isolated or real…
Help clarify human bug reports, search for duplicates, and gather diagnostic evidence separately from a concise issue draft.
Direct actions on one AO session or PR: stop or interrupt, resume, merge a PR, start a review, screenshot a session's browser,…
Find AO sessions that wait on the user, show each question or approval as tap-to-answer options, and send the answer back to that…
Shared rules and the connection helper for every ao-* skill (run Orchestrator from chat). Read before running any ao-* skill.
First run of Orchestrator Bot: find every computer that runs AO, save them as AO hosts, add a remote AO host that has no Grok Bot…