Delegate computer use from Amp to Codex via Herdr
I love @AmpCode and have been using it for 90% of my coding tasks in the last few weeks.
But I really wanted to use my Mac Mini for computer use because it's already logged in to Chrome and has all my apps.
Turns out you can just ask Amp to build that for you!
Amp does have it's own computer use but for my use at least it was a bit slow, I couldn't paste passwords properly, and it wasn't easy to get it logged in to all my Chrome tabs.
So I chatted with Puck, their assistant who is becoming more useful to me than Instinct and Grok Bot, and figured out a way to do it:
1. Set up an always-on Amp runner on the Mac Mini so an Amp thread can run there
2. A @herdrdev session with an open pane that lets Amp prompt it and reply
3. A personal Amp skill that tells agents in an Orb to farm out GUI and browser tasks to the Codex CLI on the Mini, via Herdr
Amp can now run `codex --yolo` on my Mini with GPT-6 Luna High and chat back/forth to do whatever I need. I just used it to set up a new Google Oauth and Github Oauth app, as well as change some DNS records on Cloudflare.
I have the ChatGPT Chrome extension installed on the Mini, Codex is the best by far at computer use and Luna is incredibly capable and cheap.
Every task gets a fresh Codex instance so nothing carries over once Amp is done with it.
I also have Jump Desktop so if there is a need to enter a password or 2FA code or a captcha I can use it on desktop or phone and then Amp tells Codex to continue.
Here's the prompt and skill to give it your Amp agent:
Set up this Mac so my Amp agents in orbs can hand it browser and desktop tasks.
I've added the delegating-computer-use skill (SKILL.md and config.json). Read it first.
Steps
1. Check Amp is installed and signed in, in the macOS account I use for the desktop.
2. Keep an Amp runner running with a user LaunchAgent that starts at login and restarts it if it stops. I use `amp --no-tui --runner-id <id> --remote-control-terminal --log-file <path>`. Check `amp --help` for the flags on this version.
3. Install Herdr (herdr.dev) and save its agent skill (`herdr --skill`) to a file. Create a dedicated Herdr session and workspace for the GUI worker with one shell pane. Don't touch my normal terminal panes.
4. Check Codex is installed, signed in and can use computer use.
5. Fill in config.json with the runner ID, working directory, Herdr session, workspace label, worker name, lock directory and Herdr skill path. Keep the model, reasoning effort and launch args unless I say otherwise.
6. Stop and tell me if something needs a password, a macOS permission prompt or a setting only I can change.
7. Give me a harmless read-only test I can send from an Amp orb thread, like opening example.com in Chrome and reporting the page title.```
SKILL.md
````markdown
---
name: delegating-computer-use
description: "Runs signed-in browser and native desktop tasks through a temporary high-mode Amp runner thread and a fresh Herdr Codex worker. Use when an Orb needs the user's local sessions or native GUI tools."
---
# Delegate computer use
Read bundled [config.json](config.json).
Use the configured runner for local sessions and native GUI tasks. If unavailable,
report the blocker. Never silently fall back to Orb Desktop or another runner/session.
## From an Orb
1. Call `list_runners` once; confirm `runner_id` is online and serves `working_directory`.
2. Create one temporary thread with `executor: "runner"`, configured `runner_id`
and `working_directory`, `agent_mode: "high"`, and `intent: "environment-access"`.
Omit `archive_when_done`. Tell it to load this skill, do the work itself,
and create no further threads.
3. Include a stable request ID, this thread's reply URL, the task, authorization
limits, and safe evidence needed. Require replies via `send_thread_message`;
do not also use `wait_for_threads`. Save the returned runner thread URL.
4. Send all follow-ups, including completed human handoffs, to that same thread.
Do not replace a blocked worker or replay an uncertain action.
Already on the configured runner for this request? Execute the steps below directly.
Only a temporary task thread may archive itself, never the originating project thread.
## On the runner
Read `herdr_skill_path` and its worker reference. Use only the configured dedicated
Herdr session/workspace (never an empty/default session) and live pane IDs.
Only one GUI worker may run at a time.
1. Create the lock's parent if needed, then atomically claim `owner_lock_directory`
with `mkdir`. On failure, report the conflict without touching the worker or lock.
Never steal a live lock. Empty or old locks are not proof of abandonment;
dead-owner recovery needs explicit approval and confirmation the owner cannot resume.
2. Write `owner.md` inside the claimed lock: unique ownership token, request ID,
owner/reply thread URLs, scope, and action state. Add pane/process identity after launch.
3. Discover and reuse the persistent workspace and shell pane. Create missing resources
with `--no-focus` only if authorized. Require the shell in the foreground and no
existing worker; otherwise retain the lock and report the conflict.
4. Start a fresh interactive Codex process/conversation for each new request.
Use configured model, reasoning effort, and launch arguments; defaults are
GPT-6 Luna high with mandatory `--yolo --no-alt-screen`. Verify actual launch state.
Never substitute safer approval flags, use `exec`/`resume`/`--last`, or start a
second worker after a timeout. `--yolo` does not expand task authorization.
Use these commands with values from config and the discovered pane ID:
```sh
herdr --session <herdr_session> workspace list
herdr --session <herdr_session> pane list --workspace <workspace-id>
herdr --session <herdr_session> pane process-info --pane <pane-id>
herdr --session <herdr_session> agent list
herdr --session <herdr_session> agent start <worker_name> --kind codex --pane <pane-id> -- --model gpt-6-luna -c model_reasoning_effort=high --yolo --no-alt-screen
herdr --session <herdr_session> agent prompt <worker_name> "<task>" --wait --timeout 120000
herdr --session <herdr_session> agent get <worker_name>
herdr --session <herdr_session> agent read <worker_name> --source recent-unwrapped --lines 120
# If still working, wait for the same turn; do not resend it.
herdr --session <herdr_session> agent wait <worker_name> --timeout 120000
Inspect the reply and task evidence: `idle`, `done`, or a timeout is not proof of success.
## Prompts and human handoff
Write delegated task prompts directly in first person, preserving scope and limits.
Keep routing metadata outside the worker prompt; omit “Ian wants” and delegation framing.
When authentication may arise, include:
> If you need me to enter a password, approve MFA, solve a CAPTCHA, or complete another human-only authentication step, stop and tell me what is needed. I can take over through Jump Desktop. Never request, read, type, copy, expose, or store my credentials.
Stop at native app/site permission prompts too; never approve or bypass them.
Report blockers to the origin. While blocked or an action is uncertain, retain the
same runner thread, Codex process/conversation, and lock. Resume only after user
steering and checking actual state; do not repeat completed actions.
## Complete and clean up
When the task is verified complete and nothing is pending:
1. Reply to the origin with results, safe evidence, and any unverified claims;
say cleanup is pending. Record completed actions and delivery in `owner.md`.
2. Exit only this task's idle Codex, then verify the original shell is foreground,
the task process is gone, and the dedicated agent list is empty:
herdr --session <herdr_session> agent send-keys <worker_name> ctrl+d
herdr --session <herdr_session> pane process-info --pane <pane-id>
herdr --session <herdr_session> agent list
3. Re-read `owner.md`; require the token, request ID, and owner URL to match.
Remove only that file, then `rmdir` the lock directory. Ownership drift or
unexpected files stop cleanup. Preserve Herdr's session/workspace/pane and logs.
4. Report cleanup, then `update_thread(thread=<own URL>, archived=true)` only for
this temporary runner thread, without worktree-removal flags. If reply delivery
fails, leave the thread unarchived; do not replay the task.
On failure or cancellation, establish the actual action outcome and confirm work
has stopped before the same checked cleanup. If uncertain or cleanup fails, retain
the lock and thread and report the blocker. A lock loser owns no resources and may
archive its temporary thread after reporting the conflict.
````
config.json
{
"runner_id": "ian-mac",
"working_directory": "/Users/mac",
"herdr_session": "amp-workers",
"herdr_workspace_label": "amp-workers",
"worker_name": "amp-gui",
"owner_lock_directory": "/Users/mac/.local/state/amp-workers/owner.lock",
"herdr_skill_path": "/Users/mac/.agents/skills/herdr/SKILL.md",
"codex_launch_args": ["--yolo", "--no-alt-screen"],
"model": "gpt-6-luna",
"reasoning_effort": "high"
}
Amp thread in an orb
Temporary runner thread
on the Mac Mini
HERDR pane (always there)
Fresh Codex, GPT-6 Luna high
Chrome or a Mac app
password, MFA or CAPTCHA?
I take over in Jump Desktop
Result goes back to the orb
Codex exits, runner archives
HERDR pane stays ready