{"slug": "cross-agent-cli-for-other-agents-to-use-currently-supports-claude-codex-cursor", "title": "Cross-agent CLI for other agents to use; currently supports claude, codex, cursor agent, copilot, and grok.", "summary": "A developer has created agent_cli, a cross-agent command-line tool that unifies five AI coding agents—Claude, Codex, Cursor, Copilot, and Grok—behind a single interface. The script supports both read-only review and write-capable edit modes, with explicit session management and per-agent model and effort defaults. It aims to simplify cross-agent workflows by centralizing transport quirks and providing a consistent signature for prompts, sessions, and modes.", "body_md": "| #!/usr/bin/env bash | |\n| # | |\n| # agent_cli — one front door for cross-agent work: read-only review/research | |\n| # OR write-capable edit/refactor. | |\n| # | |\n| # Generalizes agent_review (read-only only) by adding an optional trailing | |\n| # `mode` arg. `review` (default) keeps every agent read-only — identical to | |\n| # agent_review. `edit` flips each CLI into its write-capable mode so a worker | |\n| # can apply targeted refactors/edits. Append `edit` to allow writes. | |\n| # | |\n| # Session continuity is explicit: the first arg is either `new` (fresh | |\n| # session) or a session ID from a previous run (resume with full context). | |\n| # There is no implicit \"continue last session\" — you always say which. | |\n| # | |\n| # Wraps the five CLI agents (copilot, codex, claude, cursor, grok) behind a single | |\n| # signature so one doc describes one wrapper instead of five. This script owns the | |\n| # per-CLI transport quirks (read-only vs write mode, stdin redirect, effort | |\n| # flag mapping, default models). When a CLI's API changes, fix it HERE. | |\n| # | |\n| # Usage: | |\n| # Tools/agent_cli <session ID | new> <agent> <model|default> <effort|default> \"<prompt>\" [mode] | |\n| # | |\n| # <session> `new` starts a fresh session; a session ID resumes that session. | |\n| # Every run prints `session: <id>` on stderr for later resumption. | |\n| # IDs are per-agent (claude/copilot/grok UUIDs, codex thread ids, | |\n| # cursor chat ids) — resume with the same agent that minted the id. | |\n| # <agent> copilot | codex | claude | cursor | grok | |\n| # <model> a model id for that agent, or `default` (see DEFAULT_MODEL_* below) | |\n| # <effort> low | medium | high | none | default (mapped per agent) | |\n| # <prompt> the prompt; pass `-` to read it from stdin | |\n| # [mode] review (default, read-only) | edit (write-capable) | |\n| # | |\n| # Examples: | |\n| # Tools/agent_cli new copilot default high \"Review the uncommitted diff.\" | |\n| # Tools/agent_cli new codex gpt-5.6-sol high \"Review Scripts/TreeRegion.gd for perf.\" | |\n| # Tools/agent_cli new claude default default \"Refactor Scripts/Foo.gd: extract helper.\" edit | |\n| # Tools/agent_cli 0198c2… claude default default \"Now run the tests you suggested.\" edit | |\n| # git diff main...HEAD | Tools/agent_cli new claude default high - | |\n| # | |\n| # review mode runs READ-ONLY (no edits); edit mode allows writes within the | |\n| # repo. The repo is the current git toplevel (override with REPO=/path). | |\n| # List models with: Tools/agent_cli <agent> --list-models | |\n| set -euo pipefail | |\n| SCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\" | |\n| # shellcheck source=/dev/null | |\n| source \"$SCRIPT_DIR/colors.sh\" | |\n| REPO=\"${REPO:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}\" | |\n| # Per-agent defaults. Selection rationale lives in AI_MODEL_COMPARISON.md. | |\n| DEFAULT_MODEL_copilot=\"auto\" # Auto grants more token usage than pinning a model. Free tokens. | |\n| DEFAULT_MODEL_codex=\"gpt-5.6-terra\" | |\n| DEFAULT_MODEL_claude=\"claude-opus-4-8\" | |\n| DEFAULT_MODEL_cursor=\"composer-2.5\" | |\n| DEFAULT_MODEL_grok=\"grok-4.5\" | |\n| DEFAULT_EFFORT_copilot=\"low\" # Informational for auto, which rejects explicit effort. | |\n| DEFAULT_EFFORT_codex=\"high\" # Benchmark-backed routine review/final-edit setting. | |\n| DEFAULT_EFFORT_claude=\"medium\" # Normal work; use claude-fable-5 low for very hard tasks. | |\n| DEFAULT_EFFORT_cursor=\"low\" # Informational; Cursor effort is encoded in model ids. | |\n| DEFAULT_EFFORT_grok=\"high\" # Unbenchmarked secondary perspective; use high effort. | |\n| usage() { | |\n| cat <<'EOF' | |\n| Usage: Tools/agent_cli <session ID | new> <agent> <model|default> <effort|default> \"<prompt>\" [mode] | |\n| session `new` for a fresh session, or a session ID to resume (printed as | |\n| `session: <id>` on stderr by every run; IDs are per-agent) | |\n| agent copilot | codex | claude | cursor | grok | |\n| model a model id, or `default` | |\n| effort low | medium | high | none | default | |\n| prompt the prompt; `-` reads from stdin | |\n| mode review (default, read-only) | edit (write-capable) | |\n| review mode runs read-only; edit mode allows writes within the repo. | |\n| Auth/health checks: | |\n| Tools/agent_cli <agent> --check-auth # Test auth for one agent | |\n| Tools/agent_cli --doctor # Test all five agents | |\n| List models: Tools/agent_cli <agent> --list-models | |\n| EOF | |\n| } | |\n| die() { echo -e \"${RED}agent_cli: $*${NC}\" >&2; exit 1; } | |\n| note() { echo -e \"${DKGRAY}» $*${NC}\" >&2; } | |\n| REVIEW_COMPLETION_CONTRACT='Review completion contract: | |\n| - After all tool use, always return a final answer on stdout. Do not stop after a preamble, progress update, or tool result. | |\n| - State the findings with severity and file/line references. If there are no findings, state PASS explicitly. | |\n| - Do not use /tmp or another file as the only report channel; the caller only receives your final stdout. | |\n| - End with exactly one of these lines: | |\n| REVIEW_COMPLETE: PASS | |\n| REVIEW_COMPLETE: FINDINGS' | |\n| finish_result() { | |\n| local result=\"$1\" status=\"$2\" | |\n| printf '%s\\n' \"$result\" | |\n| [ \"$status\" -eq 0 ] || exit \"$status\" | |\n| if [ \"$MODE\" = \"review\" ] && [ \"${AGENT_CLI_SKIP_REVIEW_COMPLETION:-0}\" != \"1\" ]; then | |\n| local last_line | |\n| last_line=\"$(awk 'NF { line = $0 } END { print line }' <<<\"$result\")\" | |\n| case \"$last_line\" in | |\n| \"REVIEW_COMPLETE: PASS\"|\"REVIEW_COMPLETE: FINDINGS\") ;; | |\n| *) | |\n| echo \"agent_cli: reviewer exited 0 without the required final verdict; review is incomplete, not PASS\" >&2 | |\n| exit 2 | |\n| ;; | |\n| esac | |\n| fi | |\n| } | |\n| [ $# -ge 1 ] || { usage >&2; exit 1; } | |\n| # Flag forms keep their original shapes (<agent> --list-models, | |\n| # <agent> --check-auth, --doctor); the run form is session-first. | |\n| if [ \"${2:-}\" = \"--list-models\" ] || [ \"${2:-}\" = \"models\" ] || [ \"${2:-}\" = \"--check-auth\" ] \\ | |\n| || [ \"$1\" = \"--doctor\" ] || [ \"$1\" = \"doctor\" ]; then | |\n| AGENT=\"$1\"; shift | |\n| else | |\n| SESSION=\"$1\"; shift | |\n| case \"$SESSION\" in | |\n| copilot|codex|claude|cursor|grok) | |\n| die \"first arg is now <session ID | new> (got agent '$SESSION'); use \\`new\\` for a fresh session\" ;; | |\n| \"\") die \"empty session arg (expected a session ID or \\`new\\`)\" ;; | |\n| esac | |\n| [ $# -ge 1 ] || { usage >&2; die \"need <agent>\"; } | |\n| AGENT=\"$1\"; shift | |\n| fi | |\n| # --list-models shortcut | |\n| if [ \"${1:-}\" = \"--list-models\" ] || [ \"${1:-}\" = \"models\" ]; then | |\n| case \"$AGENT\" in | |\n| cursor) exec cursor-agent --list-models ;; | |\n| codex) exec codex --help ;; # codex enumerates via -m; no list subcommand | |\n| copilot) die \"copilot has no headless model list; run \\`copilot\\` then /model. Known good: gpt-5.4, claude-sonnet-4-6, auto\" ;; | |\n| claude) die \"claude model ids: claude-fable-5, claude-opus-4-8, claude-sonnet-5, claude-haiku-4-5-20251001\" ;; | |\n| grok) exec grok models ;; | |\n| *) die \"unknown agent '$AGENT'\" ;; | |\n| esac | |\n| fi | |\n| # Auth check functions | |\n| check_agent_auth() { | |\n| local agent=\"$1\" | |\n| local model; v=\"DEFAULT_MODEL_$agent\"; model=\"${!v:-}\" | |\n| [ -z \"$model\" ] && die \"unknown agent '$agent'\" | |\n| note \"checking $agent auth (model: $model)...\" | |\n| local out exit_code=0 | |\n| out=\"$(AGENT_CLI_SKIP_REVIEW_COMPLETION=1 \"$0\" new \"$agent\" \"$model\" none \"Reply with exactly: OK\" review 2>&1)\" || exit_code=$? | |\n| if grep -qi \"OK\" <<<\"$out\"; then | |\n| echo \"${GREEN}✓${NC} $agent: authenticated\" >&2 | |\n| return 0 | |\n| elif grep -qi \"exceeded your monthly quota\\|quota exceeded\\|rate limit\" <<<\"$out\"; then | |\n| echo \"${RED}✗${NC} $agent: authenticated but out of quota / rate limited\" >&2 | |\n| echo \" Wait for the quota window to reset or use another agent\" >&2 | |\n| return 1 | |\n| else | |\n| echo \"${RED}✗${NC} $agent: authentication failed or no response\" >&2 | |\n| echo \" Run the $agent CLI interactively to re-authenticate\" >&2 | |\n| [ \"$exit_code\" -ne 0 ] && echo \" Exit code: $exit_code\" >&2 | |\n| return 1 | |\n| fi | |\n| } | |\n| # --check-auth shortcut | |\n| if [ \"${1:-}\" = \"--check-auth\" ]; then | |\n| check_agent_auth \"$AGENT\" || exit 1 | |\n| exit 0 | |\n| fi | |\n| # --doctor checks all agents | |\n| if [ \"$AGENT\" = \"--doctor\" ] || [ \"$AGENT\" = \"doctor\" ]; then | |\n| failures=0 | |\n| for ag in copilot codex claude cursor grok; do | |\n| check_agent_auth \"$ag\" || failures=$((failures + 1)) | |\n| done | |\n| [ $failures -eq 0 ] && { echo \"${GREEN}All agents authenticated${NC}\" >&2; exit 0; } | |\n| echo \"${RED}$failures agent(s) failed authentication${NC}\" >&2 | |\n| exit 1 | |\n| fi | |\n| [ $# -ge 3 ] || { usage >&2; die \"need <model> <effort> <prompt>\"; } | |\n| MODEL=\"$1\"; EFFORT=\"$2\"; PROMPT=\"$3\"; MODE=\"${4:-review}\" | |\n| [ \"$MODEL\" = \"default\" ] && { v=\"DEFAULT_MODEL_$AGENT\"; MODEL=\"${!v:-}\"; [ -n \"$MODEL\" ] || die \"unknown agent '$AGENT'\"; } | |\n| [ \"$EFFORT\" = \"default\" ] && { v=\"DEFAULT_EFFORT_$AGENT\"; EFFORT=\"${!v:-}\"; [ -n \"$EFFORT\" ] || die \"no default effort for '$AGENT'\"; } | |\n| [ \"$PROMPT\" = \"-\" ] && PROMPT=\"$(cat)\" | |\n| [ -n \"$PROMPT\" ] || die \"empty prompt\" | |\n| case \"$MODE\" in | |\n| review|edit) ;; | |\n| *) die \"unknown mode '$MODE' (expected review | edit)\" ;; | |\n| esac | |\n| if [ \"$MODE\" = \"review\" ] && [ \"${AGENT_CLI_SKIP_REVIEW_COMPLETION:-0}\" != \"1\" ]; then | |\n| PROMPT=\"$(printf '%s\\n\\n%s' \"$PROMPT\" \"$REVIEW_COMPLETION_CONTRACT\")\" | |\n| fi | |\n| case \"$AGENT\" in | |\n| copilot) | |\n| command -v copilot >/dev/null 2>&1 || die \"copilot CLI not found\" | |\n| # review: --plan = read-only/planning (no edits). edit: drop --plan so | |\n| # the agent can write. --allow-all-tools suppresses permission prompts on | |\n| # tools (required non-interactive). Some models (auto, *-4.5) reject | |\n| # --effort, so retry without it on error. | |\n| eff=() | |\n| [ \"$EFFORT\" != \"none\" ] && [ \"$MODEL\" != \"auto\" ] && eff=(--effort \"$EFFORT\") | |\n| plan=(--plan) | |\n| [ \"$MODE\" = \"edit\" ] && plan=() | |\n| # --session-id both names a new session and resumes an existing one. | |\n| sess_id=\"$SESSION\" | |\n| [ \"$sess_id\" = \"new\" ] && sess_id=\"$(uuidgen | tr '[:upper:]' '[:lower:]')\" | |\n| note \"copilot --model $MODEL ${eff[*]:-} ${plan[*]:-} ($MODE)\" | |\n| note \"session: $sess_id\" | |\n| status=0 | |\n| out=\"$(copilot -p \"$PROMPT\" --model \"$MODEL\" --session-id \"$sess_id\" ${eff[@]+\"${eff[@]}\"} ${plan[@]+\"${plan[@]}\"} --allow-all-tools --no-color -C \"$REPO\" </dev/null 2>&1)\" || status=$? | |\n| if grep -q \"does not support reasoning effort\" <<<\"$out\"; then | |\n| note \"model rejects --effort; retrying without it\" | |\n| status=0 | |\n| out=\"$(copilot -p \"$PROMPT\" --model \"$MODEL\" --session-id \"$sess_id\" ${plan[@]+\"${plan[@]}\"} --allow-all-tools --no-color -C \"$REPO\" </dev/null 2>&1)\" || status=$? | |\n| fi | |\n| finish_result \"$out\" \"$status\" | |\n| ;; | |\n| codex) | |\n| command -v codex >/dev/null 2>&1 || die \"codex CLI not found\" | |\n| sandbox=\"read-only\" | |\n| [ \"$MODE\" = \"edit\" ] && sandbox=\"workspace-write\" | |\n| status=0 | |\n| if [ \"$SESSION\" = \"new\" ]; then | |\n| note \"codex exec -m $MODEL model_reasoning_effort=$EFFORT -s $sandbox ($MODE)\" | |\n| raw=\"$(codex exec --strict-config --json -m \"$MODEL\" -c model_reasoning_effort=\"$EFFORT\" \\ | |\n| -s \"$sandbox\" -C \"$REPO\" \"$PROMPT\" </dev/null)\" || status=$? | |\n| else | |\n| # `codex exec resume` has no -s/-C flags; sandbox goes through config | |\n| # and the working directory through a subshell cd. | |\n| note \"codex exec resume $SESSION -m $MODEL model_reasoning_effort=$EFFORT sandbox_mode=$sandbox ($MODE)\" | |\n| raw=\"$( (cd \"$REPO\" && codex exec resume --strict-config --json -m \"$MODEL\" \\ | |\n| -c model_reasoning_effort=\"$EFFORT\" -c sandbox_mode=\"$sandbox\" \\ | |\n| \"$SESSION\" \"$PROMPT\") </dev/null)\" || status=$? | |\n| fi | |\n| result=\"$(printf '%s\\n' \"$raw\" | python3 -c ' | |\n| import sys, json | |\n| message = \"\" | |\n| thread_id = \"\" | |\n| for line in sys.stdin: | |\n| line = line.strip() | |\n| if not line: continue | |\n| try: obj = json.loads(line) | |\n| except Exception: continue | |\n| if obj.get(\"type\") == \"thread.started\" and obj.get(\"thread_id\"): | |\n| thread_id = obj[\"thread_id\"] | |\n| item = obj.get(\"item\", {}) | |\n| if obj.get(\"type\") == \"item.completed\" and item.get(\"type\") == \"agent_message\" and item.get(\"text\"): | |\n| message = item[\"text\"] | |\n| if thread_id: | |\n| print(f\"session: {thread_id}\", file=sys.stderr) | |\n| print(message if message else \"(codex returned no result text)\")')\" | |\n| finish_result \"$result\" \"$status\" | |\n| ;; | |\n| claude) | |\n| command -v claude >/dev/null 2>&1 || die \"claude CLI not found\" | |\n| # Headless Claude can silently stall when permission prompts cannot be | |\n| # displayed. Use full-access mode in this trusted repo; review-only behavior | |\n| # is enforced by the prompt contract, not by Claude's plan-mode permissions. | |\n| # Sessions persist so they can be resumed by ID; the explicit --session-id | |\n| # still prevents the desktop-managed binary from silently resuming an | |\n| # unrelated prior task. | |\n| if [ \"$SESSION\" = \"new\" ]; then | |\n| claude_session_id=\"$(uuidgen | tr '[:upper:]' '[:lower:]')\" | |\n| sess=(--session-id \"$claude_session_id\") | |\n| else | |\n| claude_session_id=\"$SESSION\" | |\n| sess=(--resume \"$SESSION\") | |\n| fi | |\n| cprompt=\"$PROMPT\" | |\n| [ \"$MODE\" = \"review\" ] && cprompt=\"$(printf 'Review-only: do not edit files.\\n\\n%s' \"$PROMPT\")\" | |\n| note \"claude -p --model $MODEL --effort $EFFORT --permission-mode bypassPermissions ($MODE)\" | |\n| note \"session: $claude_session_id\" | |\n| status=0 | |\n| raw=\"$(cd \"$REPO\" && printf '%s' \"$cprompt\" | claude -p \\ | |\n| --model \"$MODEL\" --effort \"$EFFORT\" \\ | |\n| \"${sess[@]}\" \\ | |\n| --permission-mode bypassPermissions --output-format json)\" || status=$? | |\n| result=\"$(printf '%s\\n' \"$raw\" | python3 -c ' | |\n| import json, sys | |\n| raw = sys.stdin.read() | |\n| try: | |\n| obj = json.loads(raw) | |\n| print(obj.get(\"result\") or \"(claude returned no result text)\") | |\n| except Exception: | |\n| print(raw.strip() or \"(claude returned no result text)\")')\" | |\n| finish_result \"$result\" \"$status\" | |\n| ;; | |\n| cursor) | |\n| command -v cursor-agent >/dev/null 2>&1 || die \"cursor-agent CLI not found\" | |\n| # Cursor bakes effort into model ids (e.g. gpt-5.5-high); EFFORT is | |\n| # informational only. review: --mode plan blocks edits. edit: cursor's | |\n| # write/agent mode is the default, so we OMIT --mode (its only --mode | |\n| # choices are plan|ask; there is no `agent` value). Headless -p cannot | |\n| # show tool-permission prompts, so --force --trust are required or it | |\n| # hangs and exits empty. stream-json reliably emits the final result text | |\n| # (text format drops it for agentic runs), so we stream the final result. | |\n| cursor_review_mode=\"${AGENT_CLI_CURSOR_REVIEW_MODE:-plan}\" | |\n| case \"$cursor_review_mode\" in plan|ask) ;; *) die \"AGENT_CLI_CURSOR_REVIEW_MODE must be plan or ask\" ;; esac | |\n| cmode=(--mode \"$cursor_review_mode\"); cprompt=\"Review-only: do not edit any files. $PROMPT\" | |\n| [ \"$MODE\" = \"edit\" ] && { cmode=(); cprompt=\"$PROMPT\"; } | |\n| # A new run pre-mints a chat id via create-chat so the id is known before | |\n| # dispatch; both branches then attach with --resume. Re-prefixing | |\n| # `Review-only:` on a resumed session makes Composer flake (empty result | |\n| # or degenerate repetition), so the prefix is first-message-only; --mode | |\n| # plan remains the hard read-only gate on every review call. | |\n| cursor_chat_id=\"$SESSION\" | |\n| if [ \"$cursor_chat_id\" = \"new\" ]; then | |\n| cursor_chat_id=\"$(cursor-agent create-chat)\" || die \"cursor-agent create-chat failed\" | |\n| [ -n \"$cursor_chat_id\" ] || die \"cursor-agent create-chat returned no chat id\" | |\n| else | |\n| cprompt=\"$PROMPT\" | |\n| fi | |\n| note \"cursor-agent -p --output-format stream-json ${cmode[*]:-} --force --trust --model $MODEL ($MODE; effort '$EFFORT' n/a)\" | |\n| note \"session: $cursor_chat_id\" | |\n| status=0 | |\n| raw=\"$(cursor-agent -p --output-format stream-json ${cmode[@]+\"${cmode[@]}\"} --force --trust \\ | |\n| --workspace \"$REPO\" --model \"$MODEL\" --resume \"$cursor_chat_id\" \\ | |\n| \"$cprompt\")\" || status=$? | |\n| result=\"$(printf '%s\\n' \"$raw\" | python3 -c ' | |\n| import sys, json | |\n| assistant = \"\" | |\n| result = \"\" | |\n| for line in sys.stdin: | |\n| line = line.strip() | |\n| if not line: continue | |\n| try: obj = json.loads(line) | |\n| except Exception: continue | |\n| if obj.get(\"type\") == \"assistant\": | |\n| content = obj.get(\"message\", {}).get(\"content\", []) | |\n| text = \"\".join(item.get(\"text\", \"\") for item in content if item.get(\"type\") == \"text\") | |\n| if text.strip(): assistant = text | |\n| elif obj.get(\"type\") == \"result\" and obj.get(\"result\"): | |\n| result = obj[\"result\"] | |\n| print(assistant if assistant else result if result else \"(cursor returned no result text)\")')\" | |\n| finish_result \"$result\" \"$status\" | |\n| ;; | |\n| grok) | |\n| command -v grok >/dev/null 2>&1 || die \"grok CLI not found\" | |\n| # Both modes run --permission-mode bypassPermissions: headless grok | |\n| # cancels the session (stopReason \"Cancelled\", answer lost) when plan or | |\n| # dontAsk mode hits a tool approval, and --sandbox read-only does not | |\n| # actually block writes on this host. Review read-only is therefore | |\n| # prompt-level (Review-only prefix) like claude, plus --disallowed-tools | |\n| # to strip the direct edit tools; Bash remains available for searching. | |\n| # Effort maps to --reasoning-effort (high|medium|low); omit for `none`. | |\n| eff=() | |\n| [ \"$EFFORT\" != \"none\" ] && eff=(--reasoning-effort \"$EFFORT\") | |\n| gate=(); gprompt=\"$PROMPT\" | |\n| if [ \"$MODE\" = \"review\" ]; then | |\n| gate=(--disallowed-tools \"Write,Edit,MultiEdit,NotebookEdit\") | |\n| gprompt=\"Review-only: do not edit any files. $PROMPT\" | |\n| fi | |\n| if [ \"$SESSION\" = \"new\" ]; then | |\n| grok_session_id=\"$(uuidgen | tr '[:upper:]' '[:lower:]')\" | |\n| sess=(--session-id \"$grok_session_id\") | |\n| else | |\n| grok_session_id=\"$SESSION\" | |\n| sess=(--resume \"$SESSION\") | |\n| fi | |\n| note \"grok -p -m $MODEL ${eff[*]:-} --permission-mode bypassPermissions ${gate[*]:-} ($MODE)\" | |\n| note \"session: $grok_session_id\" | |\n| status=0 | |\n| raw=\"$(grok -p \"$gprompt\" -m \"$MODEL\" ${eff[@]+\"${eff[@]}\"} \\ | |\n| --permission-mode bypassPermissions ${gate[@]+\"${gate[@]}\"} \\ | |\n| \"${sess[@]}\" --cwd \"$REPO\" --output-format json </dev/null)\" || status=$? | |\n| result=\"$(printf '%s\\n' \"$raw\" | python3 -c ' | |\n| import json, sys | |\n| raw = sys.stdin.read() | |\n| try: | |\n| obj = json.loads(raw) | |\n| print(obj.get(\"text\") or \"(grok returned no result text)\") | |\n| except Exception: | |\n| print(raw.strip() or \"(grok returned no result text)\")')\" | |\n| finish_result \"$result\" \"$status\" | |\n| ;; | |\n| *) | |\n| die \"unknown agent '$AGENT' (expected copilot | codex | claude | cursor | grok)\" | |\n| ;; | |\n| esac |", "url": "https://wpnews.pro/news/cross-agent-cli-for-other-agents-to-use-currently-supports-claude-codex-cursor", "canonical_source": "https://gist.github.com/jamonholmgren/92ae359ec929fcac3e1b7f691c1bf463", "published_at": "2026-07-22 19:43:48+00:00", "updated_at": "2026-08-10 03:35:38.273297+00:00", "lang": "en", "topics": ["developer-tools", "ai-agents", "ai-tools"], "entities": ["Claude", "Codex", "Cursor", "Copilot", "Grok"], "alternates": {"html": "https://wpnews.pro/news/cross-agent-cli-for-other-agents-to-use-currently-supports-claude-codex-cursor", "markdown": "https://wpnews.pro/news/cross-agent-cli-for-other-agents-to-use-currently-supports-claude-codex-cursor.md", "text": "https://wpnews.pro/news/cross-agent-cli-for-other-agents-to-use-currently-supports-claude-codex-cursor.txt", "jsonld": "https://wpnews.pro/news/cross-agent-cli-for-other-agents-to-use-currently-supports-claude-codex-cursor.jsonld"}}