mirror of
https://github.com/ksyasuda/dotfiles.git
synced 2026-08-20 06:15:24 -07:00
update
This commit is contained in:
@@ -1,93 +1,184 @@
|
|||||||
---
|
---
|
||||||
name: claude-code-computer-delegate
|
name: claude-code-computer-delegate
|
||||||
description: "Route Claude Code computer-use, browser-use, GUI automation, and workstation interaction tasks to Codex subagents only. Use when Claude Code needs another agent to inspect or operate a desktop app, browser, local UI, terminal-driven workflow, or repo task involving computer control. Always use GPT-5.6 Codex models only: gpt-5.6-terra for narrow/simple work and gpt-5.6-sol for complex/high-risk work. Never use gpt-5.6-luna, Luna aliases, Claude models, or non-GPT-5.6 Codex models."
|
description: "Delegate desktop GUI and workstation control to a Codex subagent that acts as remote hands while Claude Code reads the screenshots. Use when a task needs to see or operate the local desktop: take a screenshot, check what is currently on screen, inspect or drive a native or Electron app window, read window/workspace/monitor state, launch a desktop program, or run a live-session workflow that a sandboxed shell cannot reach. Not for web pages (use the Chrome DevTools or Playwright MCP tools) and not for ordinary repo edits (use the delegate skill). Codex only: gpt-5.6-terra for narrow work, gpt-5.6-sol for complex or risky work; never gpt-5.6-luna, Luna aliases, or Claude models."
|
||||||
---
|
---
|
||||||
|
|
||||||
# Claude Code Computer Delegate
|
# Claude Code Computer Delegate
|
||||||
|
|
||||||
## Overview
|
## The one thing to understand first
|
||||||
|
|
||||||
Delegate computer-use work from Claude Code to Codex subagents. Route every task to `gpt-5.6-terra` or `gpt-5.6-sol`; reject Luna and every other model.
|
**Codex is the hands. Claude Code is the eyes.**
|
||||||
|
|
||||||
## Hard Rules
|
Verified on this machine: a `codex exec` subagent *cannot view image files*. Asked to
|
||||||
|
screenshot the desktop and describe it, it replies `CANNOT VIEW IMAGES`. So never ask
|
||||||
|
Codex "what does the screen look like" or "check whether the dialog appeared". It is
|
||||||
|
blind.
|
||||||
|
|
||||||
- Use provider `codex` only.
|
The working division of labor:
|
||||||
- Use only `gpt-5.6-terra` or `gpt-5.6-sol`.
|
|
||||||
- Never use `gpt-5.6-luna`, `luna`, aliases, "latest", fallback models, Claude models, or pre-5.6 Codex models.
|
|
||||||
- If a requested model violates these rules, stop and report the conflict. Do not silently substitute.
|
|
||||||
- Do not delegate recursively. The Codex subagent must complete the task itself and report back.
|
|
||||||
- Prefer read-only delegation for inspection, diagnosis, screenshots, or review. Use write mode only for explicit implementation or file edits.
|
|
||||||
|
|
||||||
## Route Selection
|
| Step | Who | How |
|
||||||
|
|---|---|---|
|
||||||
|
| Capture screen, drive windows, launch apps, run live-session commands | Codex subagent | `grim`, `hyprctl`, `wtype` |
|
||||||
|
| Interpret pixels: layout, colors, error text, "did it work" | Claude Code (you) | `Read` the PNG path Codex reports |
|
||||||
|
| Decide the next action | Claude Code (you) | Send a follow-up brief |
|
||||||
|
|
||||||
Choose the smallest adequate route:
|
Codex reasons only over **text**: `hyprctl -j clients` JSON, command output, exit codes,
|
||||||
|
log files. Have it report those. Have it report *screenshot paths*, never screenshot
|
||||||
|
*descriptions*.
|
||||||
|
|
||||||
| Complexity | Use | Model | Effort |
|
## Use this skill when
|
||||||
|---|---|---|---|
|
|
||||||
| Narrow | Single screen, one command, simple browser/GUI check, small file inspection, bounded terminal task | `gpt-5.6-terra` | medium |
|
|
||||||
| Narrow but context-heavy | Same scope, but with long logs, many screenshots, or nuanced UI state | `gpt-5.6-terra` | high |
|
|
||||||
| Standard | Multi-step computer workflow, multi-file repo task, ordinary debugging, meaningful trade-offs | `gpt-5.6-sol` | medium |
|
|
||||||
| Deep | Architecture, security, concurrency, risky edits, broad ambiguity, high-impact user/system state | `gpt-5.6-sol` | high |
|
|
||||||
|
|
||||||
Default to `gpt-5.6-sol` when failure could change user data, spend money, publish, delete, overwrite, or affect credentials. Default to `gpt-5.6-terra` when the task is reversible, local, and easy to verify.
|
- "What's on my screen right now", "take a screenshot", "look at my desktop"
|
||||||
|
- Inspecting or operating a native/Electron/GTK/Qt app window
|
||||||
|
- Reading window, workspace, or monitor layout state
|
||||||
|
- Launching or focusing a desktop program
|
||||||
|
- A command that must touch the live graphical session
|
||||||
|
|
||||||
## Preferred Invocation
|
## Do NOT use this skill when
|
||||||
|
|
||||||
When the local `delegate` broker is available, use it because it enforces the approved Codex model set and safe execution modes:
|
- **Web page or web app work.** You have `chrome-devtools` and `playwright` MCP tools
|
||||||
|
in-process. They give you the DOM, console, network, and snapshots you can actually
|
||||||
|
see. Delegating browser work to a blind subagent is strictly worse. Use the MCP tools.
|
||||||
|
- **Plain repo work** (reading code, edits, reviews) with no GUI involved. Use the
|
||||||
|
`delegate` skill instead.
|
||||||
|
- The task is a single command you can just run in Bash yourself. Do that.
|
||||||
|
|
||||||
|
## Hard model policy
|
||||||
|
|
||||||
|
- Provider `codex` only. Model must be `gpt-5.6-terra` or `gpt-5.6-sol`.
|
||||||
|
- Never `gpt-5.6-luna`, `luna`, aliases, `latest`, fallbacks, Claude models, or pre-5.6
|
||||||
|
Codex models.
|
||||||
|
- If the user names a model outside this set, stop and report the conflict. Do not
|
||||||
|
silently substitute.
|
||||||
|
- The subagent must not delegate further.
|
||||||
|
|
||||||
|
| Complexity | Model | Effort |
|
||||||
|
|---|---|---|
|
||||||
|
| Single screenshot, one command, bounded lookup | `gpt-5.6-terra` | medium |
|
||||||
|
| Same scope, long logs or fiddly state | `gpt-5.6-terra` | high |
|
||||||
|
| Multi-step GUI workflow, ordinary debugging | `gpt-5.6-sol` | medium |
|
||||||
|
| Risky, ambiguous, or touching credentials/money/user data | `gpt-5.6-sol` | high |
|
||||||
|
|
||||||
|
Default to `sol` when a mistake could change user data, spend money, publish, delete, or
|
||||||
|
overwrite. Default to `terra` when the action is reversible and easy to verify.
|
||||||
|
|
||||||
|
## Sandbox: the part that used to silently fail
|
||||||
|
|
||||||
|
GUI access requires `--sandbox danger-full-access`. This is not optional and there is no
|
||||||
|
narrower mode that works.
|
||||||
|
|
||||||
|
Measured on this box (Wayland, Hyprland 0.56.2):
|
||||||
|
|
||||||
|
| Sandbox | `grim` screenshot | `hyprctl` |
|
||||||
|
|---|---|---|
|
||||||
|
| `read-only` | fails, `failed to create display` | fails, `Couldn't set socket timeout` |
|
||||||
|
| `workspace-write` | fails, `failed to create display` | fails |
|
||||||
|
| `workspace-write --add-dir /run/user/1000` | still fails | still fails |
|
||||||
|
| `danger-full-access` | works | works |
|
||||||
|
|
||||||
|
The sandbox passes `WAYLAND_DISPLAY` and `XDG_RUNTIME_DIR` through as environment
|
||||||
|
variables but blocks the compositor sockets themselves, so the failure looks like a
|
||||||
|
missing display rather than a permission error. `--add-dir` does not fix it.
|
||||||
|
|
||||||
|
Because `danger-full-access` removes the sandbox entirely, keep the blast radius in the
|
||||||
|
brief instead: name the exact commands allowed, and forbid everything else.
|
||||||
|
|
||||||
|
## Run it
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python3 /Users/sudacode/.agents/skills/delegate/scripts/delegate.py \
|
cd "$PWD" && timeout 900 codex exec \
|
||||||
--provider codex \
|
|
||||||
--tier quick \
|
|
||||||
--mode read \
|
|
||||||
--repo "$PWD" <<'TASK'
|
|
||||||
<self-contained computer-use task>
|
|
||||||
TASK
|
|
||||||
```
|
|
||||||
|
|
||||||
Map tiers as follows:
|
|
||||||
|
|
||||||
- `quick` -> `gpt-5.6-terra`, medium
|
|
||||||
- `quick-context` -> `gpt-5.6-terra`, high
|
|
||||||
- `standard` -> `gpt-5.6-sol`, medium
|
|
||||||
- `deep` -> `gpt-5.6-sol`, high
|
|
||||||
|
|
||||||
Use `--mode write` only when the user explicitly wants implementation or edits.
|
|
||||||
|
|
||||||
## Direct Codex Fallback
|
|
||||||
|
|
||||||
If the broker is unavailable, call Codex directly with an approved model:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
codex exec \
|
|
||||||
--ignore-user-config \
|
--ignore-user-config \
|
||||||
--model gpt-5.6-terra \
|
--model gpt-5.6-terra \
|
||||||
--config 'model_reasoning_effort="medium"' \
|
--config model_reasoning_effort="medium" \
|
||||||
--config 'approval_policy="never"' \
|
--config approval_policy="never" \
|
||||||
--sandbox read-only \
|
--sandbox danger-full-access \
|
||||||
--ephemeral \
|
--ephemeral \
|
||||||
--skip-git-repo-check \
|
--skip-git-repo-check \
|
||||||
--cd "$PWD" \
|
--output-last-message /tmp/codex-gui-1.md \
|
||||||
-
|
--cd "$PWD" - <<'TASK'
|
||||||
|
<brief from the template below>
|
||||||
|
TASK
|
||||||
|
cat /tmp/codex-gui-1.md
|
||||||
```
|
```
|
||||||
|
|
||||||
For write tasks, use `--sandbox workspace-write`; never grant broader access unless the user explicitly approves that exact operation.
|
Notes that matter:
|
||||||
|
|
||||||
## Task Brief
|
- Always feed the brief on stdin via a **quoted** heredoc (`<<'TASK'`) so the shell does
|
||||||
|
not expand anything in it. The trailing `-` is what tells Codex to read stdin.
|
||||||
|
- `--output-last-message` gives you the clean report; stdout also carries the reasoning
|
||||||
|
stream, which is what you want when a run fails.
|
||||||
|
- Give screenshots a path you can reach afterward. Prefer your scratchpad directory.
|
||||||
|
- A nonzero exit or empty report file is a failure even if stdout printed something.
|
||||||
|
Check both.
|
||||||
|
|
||||||
Write a complete brief; the Codex subagent starts with no conversation context. Include:
|
## Brief template
|
||||||
|
|
||||||
- Goal and definition of done.
|
Codex starts with zero context.
|
||||||
- Exact app, browser tab, local URL, file path, command, or screen state involved.
|
|
||||||
- Constraints: forbidden actions, allowed edits, credentials/payment/publishing restrictions.
|
|
||||||
- Verification expected: screenshot, command output, tests, or concise report.
|
|
||||||
- Reporting format: summary, actions taken, evidence, files changed, verification, open questions.
|
|
||||||
|
|
||||||
Pass raw evidence such as errors, logs, screenshots paths, or diffs. Do not tell Codex the answer to find.
|
```
|
||||||
|
You are a subagent with direct access to the live graphical session.
|
||||||
|
|
||||||
## Safety Checks
|
Environment: Wayland + Hyprland. Available: grim (screenshot), slurp (region),
|
||||||
|
wtype (typing), hyprctl (window control and JSON introspection), xdotool
|
||||||
|
(XWayland windows only), playwright, google-chrome-stable, firefox.
|
||||||
|
|
||||||
- Before launching: state selected model, tier, mode, and why.
|
You CANNOT view images. Never describe the contents of a screenshot. Capture it,
|
||||||
- After completion: inspect the report and verify load-bearing claims before acting on them.
|
report the absolute path, and let the caller look at it.
|
||||||
- For write mode: review `git diff` and run targeted tests/checks before reporting success.
|
|
||||||
- On failure: report selected model, exact command path used, and the error. Retry once only for transient failures, with the same allowed model family.
|
Hard constraints:
|
||||||
|
- Run only these commands: <explicit list>
|
||||||
|
- Do not close, move, or resize the user's existing windows unless told to.
|
||||||
|
- Do not type into or click on windows the task does not name.
|
||||||
|
- Do not delegate further or invoke Codex/Claude recursively.
|
||||||
|
|
||||||
|
Report, in these sections:
|
||||||
|
- Summary: what you did.
|
||||||
|
- Screenshots: absolute path of each, and what each was meant to capture.
|
||||||
|
- Structural state: relevant `hyprctl -j clients` output or command stdout, verbatim.
|
||||||
|
- Commands run: each with its exit code.
|
||||||
|
- Open questions: anything you could not determine without vision.
|
||||||
|
|
||||||
|
Task:
|
||||||
|
<self-contained task>
|
||||||
|
```
|
||||||
|
|
||||||
|
Pass raw evidence. Do not tell Codex the answer you expect it to find.
|
||||||
|
|
||||||
|
## Desktop cookbook (verified available here)
|
||||||
|
|
||||||
|
Prefer structured text over pixels wherever possible, since that is the part Codex can
|
||||||
|
reason about.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
grim /path/shot.png # whole screen
|
||||||
|
grim -g "$(slurp)" /path/region.png # region (interactive, needs a human)
|
||||||
|
hyprctl -j clients # every window: class, title, at[x,y], size[w,h], workspace
|
||||||
|
hyprctl -j activewindow # focused window
|
||||||
|
hyprctl -j monitors # geometry and scale
|
||||||
|
hyprctl notify -1 3000 "rgb(44ccff)" "message"
|
||||||
|
wtype 'text to type' # types into the focused window
|
||||||
|
```
|
||||||
|
|
||||||
|
`hyprctl -j clients` is the highest-value call: it returns exact window rectangles, so
|
||||||
|
Codex can position and identify windows without seeing anything.
|
||||||
|
|
||||||
|
## Known limits, state honestly
|
||||||
|
|
||||||
|
- **No synthetic mouse clicks.** `ydotool` is not installed and the user is not in the
|
||||||
|
`input` group, so `/dev/uinput` is not writable. There is no working click injection.
|
||||||
|
If a task needs a click, say so and ask the user, rather than having Codex flail.
|
||||||
|
- **Hyprland 0.56 changed the dispatch API** to a Lua form (`hl.dsp.window.close()`).
|
||||||
|
Old `hyprctl dispatch <name>` strings error out. Verify a dispatcher before relying on
|
||||||
|
it.
|
||||||
|
- `xdotool` only reaches XWayland clients, not native Wayland ones.
|
||||||
|
- **Screenshots are downscaled when you Read them.** A 3440x1440 capture is shown to you
|
||||||
|
at 2000x837. If you derive coordinates from the image, multiply by the stated factor
|
||||||
|
before handing them to anything.
|
||||||
|
|
||||||
|
## After the run
|
||||||
|
|
||||||
|
- Read the screenshot yourself before believing any claim about UI state.
|
||||||
|
- Treat the report as a claim. Spot-check load-bearing parts against the raw output.
|
||||||
|
- On failure, report the model, the exact command, and the error. Retry once only for
|
||||||
|
transient faults, on the same model family. If the error is `failed to create display`,
|
||||||
|
the sandbox flag was wrong, not the task.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
interface:
|
interface:
|
||||||
display_name: "Claude Code Computer Delegate"
|
display_name: "Claude Code Computer Delegate"
|
||||||
short_description: "Route Claude Code computer-use tasks to Codex"
|
short_description: "Codex acts on the desktop; Claude Code reads the screenshots"
|
||||||
default_prompt: "Use $claude-code-computer-delegate to route computer-use work from Claude Code to the right Codex model."
|
default_prompt: "Use $claude-code-computer-delegate to drive the local desktop through a Codex subagent (gpt-5.6-terra or gpt-5.6-sol) and interpret the captured screenshots here."
|
||||||
|
|||||||
@@ -5,9 +5,13 @@ description: Delegate self-contained tasks to Claude or Codex subagents run as f
|
|||||||
|
|
||||||
# Delegate
|
# Delegate
|
||||||
|
|
||||||
Hand a self-contained task to a fresh Claude or Codex subagent and get back a
|
Hand a self-contained task to a fresh `claude` or `codex` CLI process and get
|
||||||
structured report. Each invocation is one subagent; run several in parallel for
|
back a structured report. Each invocation is one subagent; run several in
|
||||||
independent tasks.
|
parallel for independent tasks.
|
||||||
|
|
||||||
|
You call the CLIs directly. The command shapes below are the default recipe,
|
||||||
|
not a fixed harness — adjust flags when the task needs it (extra directories,
|
||||||
|
different tools, a longer timeout), and say what you changed in your report.
|
||||||
|
|
||||||
## When to delegate
|
## When to delegate
|
||||||
|
|
||||||
@@ -61,45 +65,123 @@ The subagent starts with zero context. Write a self-contained task containing:
|
|||||||
|
|
||||||
Pass raw evidence; do not tell the subagent the answer you expect.
|
Pass raw evidence; do not tell the subagent the answer you expect.
|
||||||
|
|
||||||
|
Wrap the brief in this scaffold. Keep the constraint block matching the mode
|
||||||
|
and keep the report sections verbatim — the result-handling steps below assume
|
||||||
|
them.
|
||||||
|
|
||||||
|
```
|
||||||
|
You are a subagent completing a delegated task inside the current repository.
|
||||||
|
Work independently; the caller cannot answer questions mid-task. If the task is
|
||||||
|
ambiguous, choose the safest reasonable interpretation and note the choice in
|
||||||
|
your report.
|
||||||
|
|
||||||
|
<constraints for the chosen mode — see below>
|
||||||
|
- Do not delegate further or invoke Claude or Codex recursively.
|
||||||
|
|
||||||
|
End your reply with a report containing these sections:
|
||||||
|
- Summary: what you did or found, in a few sentences.
|
||||||
|
- Details: key evidence, decisions, or findings, with file:line references.
|
||||||
|
- Files changed: list each changed file, or "none".
|
||||||
|
- Verification: what you ran and the outcome, or "not verified" and why.
|
||||||
|
- Open questions: anything unresolved the caller must decide, or "none".
|
||||||
|
|
||||||
|
Task:
|
||||||
|
<self-contained task brief>
|
||||||
|
```
|
||||||
|
|
||||||
|
`read` constraints:
|
||||||
|
|
||||||
|
```
|
||||||
|
Hard constraints:
|
||||||
|
- You are in read-only mode. Do not modify, create, rename, or delete files.
|
||||||
|
- Do not commit, branch, push, or contact external systems that change state.
|
||||||
|
- Base claims on repository evidence. Cite file paths and line numbers.
|
||||||
|
```
|
||||||
|
|
||||||
|
`write` constraints:
|
||||||
|
|
||||||
|
```
|
||||||
|
Hard constraints:
|
||||||
|
- Work only inside the given repository directory.
|
||||||
|
- Do not commit, branch, push, or open pull requests unless the task says to.
|
||||||
|
- Do not delete or rename files the task does not cover; if something looks
|
||||||
|
wrong or unexpected, stop and report instead of guessing.
|
||||||
|
- Verify your work (build, tests, or a targeted check) when feasible.
|
||||||
|
```
|
||||||
|
|
||||||
## Run it
|
## Run it
|
||||||
|
|
||||||
Resolve `<skill-dir>` to the directory containing this `SKILL.md`. Send the
|
Always send the prompt on stdin via a quoted heredoc (`<<'TASK'`) so nothing in
|
||||||
task on stdin; do not interpolate it into the shell command.
|
the brief is expanded or re-parsed by the shell. Run the CLI from the target
|
||||||
|
repo with `cd <repo> && ...`.
|
||||||
|
|
||||||
|
Codex, read-only:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python3 <skill-dir>/scripts/delegate.py \
|
cd /path/to/repo && codex exec \
|
||||||
--provider codex \
|
--ignore-user-config \
|
||||||
--tier standard \
|
--model gpt-5.6-sol \
|
||||||
--mode read \
|
--config model_reasoning_effort="medium" \
|
||||||
--repo "$PWD" <<'TASK'
|
--config approval_policy="never" \
|
||||||
<self-contained task brief>
|
--sandbox read-only \
|
||||||
|
--ephemeral \
|
||||||
|
--skip-git-repo-check \
|
||||||
|
--output-last-message /tmp/delegate-codex-1.md \
|
||||||
|
--cd /path/to/repo - <<'TASK'
|
||||||
|
<scaffold + brief>
|
||||||
|
TASK
|
||||||
|
cat /tmp/delegate-codex-1.md
|
||||||
|
```
|
||||||
|
|
||||||
|
Codex, write mode: swap `--sandbox read-only` for `--sandbox workspace-write`.
|
||||||
|
|
||||||
|
`--output-last-message` writes just the final report; Codex's stdout also
|
||||||
|
carries its reasoning stream, which is useful when a run fails or you want to
|
||||||
|
see what it actually did. Add `--add-dir <dir>` for extra writable roots.
|
||||||
|
|
||||||
|
Claude, read-only:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /path/to/repo && claude --print \
|
||||||
|
--model claude-opus-4-8 \
|
||||||
|
--effort medium \
|
||||||
|
--disable-slash-commands \
|
||||||
|
--no-session-persistence \
|
||||||
|
--permission-mode plan \
|
||||||
|
--tools Read,Glob,Grep <<'TASK'
|
||||||
|
<scaffold + brief>
|
||||||
TASK
|
TASK
|
||||||
```
|
```
|
||||||
|
|
||||||
Flags:
|
Claude, write mode: replace the last two lines with
|
||||||
|
|
||||||
- `--provider claude|codex` (required)
|
```bash
|
||||||
- `--tier quick|quick-context|standard|deep` (default `standard`)
|
--permission-mode acceptEdits \
|
||||||
- `--mode read|write` (default `read`)
|
--tools Read,Glob,Grep,Edit,Write,Bash \
|
||||||
- `--model <approved-model>` for an explicit allowed override
|
--allowedTools Edit,Write,Bash
|
||||||
- `--repo <dir>` (default cwd)
|
```
|
||||||
- `--timeout <seconds>` (default 1800)
|
|
||||||
- `--dry-run` to inspect routing and command construction without running
|
Claude prints the final message on stdout. Widen `--tools` when a task
|
||||||
|
genuinely needs more (for example `WebSearch` for external research, or
|
||||||
|
`Bash` in read mode for a `git diff` the subagent must see) — that is a
|
||||||
|
deliberate choice, so note it when you report back.
|
||||||
|
|
||||||
|
Give long runs a timeout that fits the task (the Bash tool's `timeout` is in
|
||||||
|
milliseconds; 1800000 is a reasonable ceiling for a `deep` tier run).
|
||||||
|
|
||||||
Parallel delegation: launch each invocation as a separate background shell
|
Parallel delegation: launch each invocation as a separate background shell
|
||||||
command, then collect the outputs. Never point two `write`-mode subagents at
|
command, write each Codex report to its own `--output-last-message` path, then
|
||||||
overlapping files; split by file/directory or run them sequentially.
|
collect the outputs. Never point two `write`-mode subagents at overlapping
|
||||||
|
files; split by file/directory or run them sequentially.
|
||||||
|
|
||||||
## Handle the result
|
## Handle the result
|
||||||
|
|
||||||
The report ends with Summary / Details / Files changed / Verification / Open
|
- Treat the report as a subagent's claim, not ground truth: spot-check
|
||||||
questions sections. Then:
|
load-bearing findings, and for `write` mode review the diff (`git diff`) and
|
||||||
|
re-run verification before building on it.
|
||||||
- Treat it as a subagent's claim, not ground truth: spot-check load-bearing
|
|
||||||
findings, and for `write` mode review the diff (`git diff`) and re-run
|
|
||||||
verification before building on it.
|
|
||||||
- Relay the outcome to the user in your own words; credit which provider/model
|
- Relay the outcome to the user in your own words; credit which provider/model
|
||||||
produced it when it matters.
|
produced it when it matters.
|
||||||
- On failure, report the provider, model, and exact error. Retry once with the
|
- On failure, report the provider, model, and exact error. A nonzero exit or
|
||||||
same route if transient; escalate tier or switch provider only deliberately,
|
empty output is a failure even if the CLI printed something — check both.
|
||||||
and say you did.
|
Retry once with the same route if transient; escalate tier or switch provider
|
||||||
|
only deliberately, and say you did.
|
||||||
|
|||||||
Binary file not shown.
@@ -1,270 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
"""Delegate a self-contained task to a Claude or Codex subagent."""
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
import os
|
|
||||||
import shutil
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
import tempfile
|
|
||||||
from dataclasses import dataclass
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
|
|
||||||
ALLOWED_MODELS = {
|
|
||||||
"codex": frozenset({"gpt-5.6-terra", "gpt-5.6-sol"}),
|
|
||||||
"claude": frozenset(
|
|
||||||
{"claude-sonnet-4-6", "claude-sonnet-5", "claude-opus-4-8"}
|
|
||||||
),
|
|
||||||
}
|
|
||||||
|
|
||||||
# tier -> provider -> (model, effort)
|
|
||||||
ROUTES = {
|
|
||||||
"quick": {
|
|
||||||
"codex": ("gpt-5.6-terra", "medium"),
|
|
||||||
"claude": ("claude-sonnet-4-6", "medium"),
|
|
||||||
},
|
|
||||||
"quick-context": {
|
|
||||||
"codex": ("gpt-5.6-terra", "high"),
|
|
||||||
"claude": ("claude-sonnet-5", "high"),
|
|
||||||
},
|
|
||||||
"standard": {
|
|
||||||
"codex": ("gpt-5.6-sol", "medium"),
|
|
||||||
"claude": ("claude-opus-4-8", "medium"),
|
|
||||||
},
|
|
||||||
"deep": {
|
|
||||||
"codex": ("gpt-5.6-sol", "high"),
|
|
||||||
"claude": ("claude-opus-4-8", "high"),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
READ_ONLY_RULES = """\
|
|
||||||
Hard constraints:
|
|
||||||
- You are in read-only mode. Do not modify, create, rename, or delete files.
|
|
||||||
- Do not commit, branch, push, or contact external systems that change state.
|
|
||||||
- Base claims on repository evidence. Cite file paths and line numbers."""
|
|
||||||
|
|
||||||
WRITE_RULES = """\
|
|
||||||
Hard constraints:
|
|
||||||
- Work only inside the given repository directory.
|
|
||||||
- Do not commit, branch, push, or open pull requests unless the task says to.
|
|
||||||
- Do not delete or rename files the task does not cover; if something looks
|
|
||||||
wrong or unexpected, stop and report instead of guessing.
|
|
||||||
- Verify your work (build, tests, or a targeted check) when feasible."""
|
|
||||||
|
|
||||||
REPORT_FORMAT = """\
|
|
||||||
End your reply with a report containing these sections:
|
|
||||||
- Summary: what you did or found, in a few sentences.
|
|
||||||
- Details: key evidence, decisions, or findings, with file:line references.
|
|
||||||
- Files changed: list each changed file, or "none".
|
|
||||||
- Verification: what you ran and the outcome, or "not verified" and why.
|
|
||||||
- Open questions: anything unresolved the caller must decide, or "none"."""
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
|
||||||
class Route:
|
|
||||||
provider: str
|
|
||||||
model: str
|
|
||||||
effort: str
|
|
||||||
|
|
||||||
|
|
||||||
def select_route(provider: str, tier: str) -> Route:
|
|
||||||
if tier not in ROUTES:
|
|
||||||
raise ValueError(f"Unknown tier: {tier}")
|
|
||||||
if provider not in ("claude", "codex"):
|
|
||||||
raise ValueError(f"Unknown provider: {provider}")
|
|
||||||
model, effort = ROUTES[tier][provider]
|
|
||||||
return Route(provider, model, effort)
|
|
||||||
|
|
||||||
|
|
||||||
def apply_model_override(route: Route, model: str) -> Route:
|
|
||||||
if model not in ALLOWED_MODELS[route.provider]:
|
|
||||||
raise ValueError(f"Model {model!r} is not allowed for {route.provider}")
|
|
||||||
return Route(route.provider, model, route.effort)
|
|
||||||
|
|
||||||
|
|
||||||
def build_command(
|
|
||||||
route: Route,
|
|
||||||
repo: Path,
|
|
||||||
mode: str,
|
|
||||||
output_path: Path | None = None,
|
|
||||||
) -> list[str]:
|
|
||||||
if route.provider == "codex":
|
|
||||||
if output_path is None:
|
|
||||||
raise ValueError("Codex requires an output path")
|
|
||||||
sandbox = "read-only" if mode == "read" else "workspace-write"
|
|
||||||
return [
|
|
||||||
"codex",
|
|
||||||
"exec",
|
|
||||||
"--ignore-user-config",
|
|
||||||
"--model",
|
|
||||||
route.model,
|
|
||||||
"--config",
|
|
||||||
f'model_reasoning_effort="{route.effort}"',
|
|
||||||
"--config",
|
|
||||||
'approval_policy="never"',
|
|
||||||
"--sandbox",
|
|
||||||
sandbox,
|
|
||||||
"--ephemeral",
|
|
||||||
"--skip-git-repo-check",
|
|
||||||
"--output-last-message",
|
|
||||||
str(output_path),
|
|
||||||
"--cd",
|
|
||||||
str(repo),
|
|
||||||
"-",
|
|
||||||
]
|
|
||||||
|
|
||||||
command = [
|
|
||||||
"claude",
|
|
||||||
"--print",
|
|
||||||
"--model",
|
|
||||||
route.model,
|
|
||||||
"--effort",
|
|
||||||
route.effort,
|
|
||||||
"--disable-slash-commands",
|
|
||||||
"--no-session-persistence",
|
|
||||||
]
|
|
||||||
if mode == "read":
|
|
||||||
command += [
|
|
||||||
"--permission-mode",
|
|
||||||
"plan",
|
|
||||||
"--tools",
|
|
||||||
"Read,Glob,Grep",
|
|
||||||
]
|
|
||||||
else:
|
|
||||||
command += [
|
|
||||||
"--permission-mode",
|
|
||||||
"acceptEdits",
|
|
||||||
"--tools",
|
|
||||||
"Read,Glob,Grep,Edit,Write,Bash",
|
|
||||||
"--allowedTools",
|
|
||||||
"Edit,Write,Bash",
|
|
||||||
]
|
|
||||||
return command
|
|
||||||
|
|
||||||
|
|
||||||
def build_prompt(task: str, route: Route, mode: str) -> str:
|
|
||||||
rules = READ_ONLY_RULES if mode == "read" else WRITE_RULES
|
|
||||||
return f"""You are a {route.provider} subagent completing a delegated task \
|
|
||||||
inside the current repository. Work independently; the caller cannot answer \
|
|
||||||
questions mid-task. If the task is ambiguous, choose the safest reasonable \
|
|
||||||
interpretation and note the choice in your report.
|
|
||||||
|
|
||||||
{rules}
|
|
||||||
- Do not delegate further or invoke Claude or Codex recursively.
|
|
||||||
|
|
||||||
{REPORT_FORMAT}
|
|
||||||
|
|
||||||
Task:
|
|
||||||
{task.strip()}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def run_delegation(
|
|
||||||
route: Route,
|
|
||||||
repo: Path,
|
|
||||||
prompt: str,
|
|
||||||
mode: str,
|
|
||||||
*,
|
|
||||||
timeout: int = 1800,
|
|
||||||
) -> str:
|
|
||||||
if shutil.which(route.provider) is None:
|
|
||||||
raise RuntimeError(f"Required CLI is not installed: {route.provider}")
|
|
||||||
|
|
||||||
with tempfile.TemporaryDirectory(prefix="delegate-") as temp_dir:
|
|
||||||
output_path = (
|
|
||||||
Path(temp_dir) / "report.md" if route.provider == "codex" else None
|
|
||||||
)
|
|
||||||
command = build_command(route, repo, mode, output_path)
|
|
||||||
try:
|
|
||||||
result = subprocess.run(
|
|
||||||
command,
|
|
||||||
cwd=repo,
|
|
||||||
input=prompt,
|
|
||||||
text=True,
|
|
||||||
capture_output=True,
|
|
||||||
timeout=timeout,
|
|
||||||
check=False,
|
|
||||||
)
|
|
||||||
except subprocess.TimeoutExpired as error:
|
|
||||||
raise RuntimeError(
|
|
||||||
f"{route.provider} delegation timed out after {timeout}s"
|
|
||||||
) from error
|
|
||||||
if result.returncode != 0:
|
|
||||||
detail = (result.stderr or result.stdout).strip() or "no error output"
|
|
||||||
raise RuntimeError(
|
|
||||||
f"{route.provider} delegation failed ({result.returncode}): {detail}"
|
|
||||||
)
|
|
||||||
if route.provider == "codex":
|
|
||||||
if output_path is None or not output_path.is_file():
|
|
||||||
raise RuntimeError("Codex did not produce a report")
|
|
||||||
report = output_path.read_text().strip()
|
|
||||||
else:
|
|
||||||
report = result.stdout.strip()
|
|
||||||
if not report:
|
|
||||||
raise RuntimeError(f"{route.provider} returned an empty report")
|
|
||||||
return report
|
|
||||||
|
|
||||||
|
|
||||||
def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
|
|
||||||
parser = argparse.ArgumentParser(
|
|
||||||
description="Delegate a self-contained task to a Claude or Codex subagent."
|
|
||||||
)
|
|
||||||
parser.add_argument("--provider", choices=("claude", "codex"), required=True)
|
|
||||||
parser.add_argument(
|
|
||||||
"--tier",
|
|
||||||
choices=("quick", "quick-context", "standard", "deep"),
|
|
||||||
default="standard",
|
|
||||||
)
|
|
||||||
parser.add_argument("--mode", choices=("read", "write"), default="read")
|
|
||||||
parser.add_argument("--model", help="Approved model override")
|
|
||||||
parser.add_argument("--repo", type=Path, default=Path.cwd())
|
|
||||||
parser.add_argument("--timeout", type=int, default=1800)
|
|
||||||
parser.add_argument("--dry-run", action="store_true")
|
|
||||||
return parser.parse_args(argv)
|
|
||||||
|
|
||||||
|
|
||||||
def main(argv: list[str] | None = None) -> int:
|
|
||||||
args = parse_args(argv)
|
|
||||||
try:
|
|
||||||
task = sys.stdin.read().strip()
|
|
||||||
if not task:
|
|
||||||
raise ValueError("Task must be provided on stdin")
|
|
||||||
repo = args.repo.expanduser().resolve()
|
|
||||||
if not repo.is_dir():
|
|
||||||
raise ValueError(f"Repository directory does not exist: {repo}")
|
|
||||||
route = select_route(args.provider, args.tier)
|
|
||||||
if args.model:
|
|
||||||
route = apply_model_override(route, args.model)
|
|
||||||
prompt = build_prompt(task, route, args.mode)
|
|
||||||
if args.dry_run:
|
|
||||||
output_path = (
|
|
||||||
Path(tempfile.gettempdir()) / "delegate-dry-run-report.md"
|
|
||||||
if route.provider == "codex"
|
|
||||||
else None
|
|
||||||
)
|
|
||||||
command = build_command(route, repo, args.mode, output_path)
|
|
||||||
print(f"provider: {route.provider}")
|
|
||||||
print(f"model: {route.model}")
|
|
||||||
print(f"effort: {route.effort}")
|
|
||||||
print(f"mode: {args.mode}")
|
|
||||||
print(f"command: {' '.join(command)}")
|
|
||||||
print(f"prompt:\n{prompt}")
|
|
||||||
return 0
|
|
||||||
report = run_delegation(
|
|
||||||
route,
|
|
||||||
repo,
|
|
||||||
prompt,
|
|
||||||
args.mode,
|
|
||||||
timeout=args.timeout,
|
|
||||||
)
|
|
||||||
print(f"[{route.provider} · {route.model} · {route.effort} · {args.mode}]")
|
|
||||||
print(report)
|
|
||||||
return 0
|
|
||||||
except (OSError, RuntimeError, ValueError) as error:
|
|
||||||
print(f"delegate: error: {error}", file=sys.stderr)
|
|
||||||
return 2
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
raise SystemExit(main())
|
|
||||||
@@ -228,6 +228,12 @@ trust_level = "trusted"
|
|||||||
[projects."/home/sudacode/games/ModEngine2"]
|
[projects."/home/sudacode/games/ModEngine2"]
|
||||||
trust_level = "trusted"
|
trust_level = "trusted"
|
||||||
|
|
||||||
|
[projects."/truenas/jellyfin/anime/BanG Dream! It's MyGO!!!!!/Season-1"]
|
||||||
|
trust_level = "trusted"
|
||||||
|
|
||||||
|
[projects."/tmp/claude-1000/-home-sudacode--agents-skills-claude-code-computer-delegate/df15b0bc-3ae1-4e90-a006-21c31ddc8634/scratchpad"]
|
||||||
|
trust_level = "trusted"
|
||||||
|
|
||||||
[notice.model_migrations]
|
[notice.model_migrations]
|
||||||
"gpt-5.3-codex" = "gpt-5.4"
|
"gpt-5.3-codex" = "gpt-5.4"
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ update_ms = 2000
|
|||||||
|
|
||||||
#* Processes sorting, "pid" "program" "arguments" "threads" "user" "memory" "cpu lazy" "cpu direct",
|
#* Processes sorting, "pid" "program" "arguments" "threads" "user" "memory" "cpu lazy" "cpu direct",
|
||||||
#* "cpu lazy" sorts top process over time (easier to follow), "cpu direct" updates top process directly.
|
#* "cpu lazy" sorts top process over time (easier to follow), "cpu direct" updates top process directly.
|
||||||
proc_sorting = "memory"
|
proc_sorting = "cpu lazy"
|
||||||
|
|
||||||
#* Reverse sorting order, True or False.
|
#* Reverse sorting order, True or False.
|
||||||
proc_reversed = false
|
proc_reversed = false
|
||||||
|
|||||||
Reference in New Issue
Block a user