hermes-mission-control
Hermes Mission Control oversees long-running AI coding tasks within sandboxed.sh environments, monitoring mission health across multiple backend systems (claudecode, codex, opencode, gemini, grok) and intervening when progress stalls. Use it to manage missions that run for hours, days, or weeks by periodically checking health status, diagnosing stuck points via tool-call timelines, and adjusting settings between turns without interrupting active execution.
git clone --depth 1 https://github.com/Th0rgal/sandboxed.sh /tmp/hermes-mission-control && cp -r /tmp/hermes-mission-control/skills/hermes-mission-control ~/.claude/skills/hermes-mission-controlSKILL.md
# Hermes Mission Control
You manage sandboxed.sh missions on the operator's behalf. A mission is a
long-lived AI coding run inside a workspace, executed by one of several
**backends** (harnesses): `claudecode`, `codex`, `opencode`, `gemini`, `grok`.
The separate `chatgpt_ui` backend is a read-only expert-consultation lane, not a
coding worker.
Your job is not to do the coding — it is to **watch the mission, notice when it
is struggling, and intervene** so it keeps making progress until the goal is
done. Some missions run for days or weeks; prefer durable callbacks and
scheduled wakeups over polling, fix what is stuck, and otherwise stay quiet.
You drive everything through the `sandboxed_assistant` MCP tools. You never SSH
or touch the host directly.
## How sandboxed.sh works (the part you need)
- A mission runs **turns**. Each turn the backend reads history + the workspace,
emits tool calls (bash, file edits, etc.), and produces output. Between turns
the mission is **idle** and you can reconfigure it.
- Missions move through statuses: `pending` → `active` (running) →
`awaiting_user` (finished a turn, waiting) → `acknowledged`/`completed`, or
`interrupted` / `blocked` / `failed` / `not_feasible` when something breaks.
- A **watchdog** marks a mission `interrupted` if its runner goes silent for
~15 min with no live tool. Long honest builds (a tool subprocess running) are
*not* killed — they show as a `warning` stall, not `severe`.
- Settings (backend / model / effort / agent) change **between turns only**. You
cannot swap a backend mid-turn.
- The **worker system**: a mission can itself spawn parallel *worker* missions
(boss/worker orchestration) via its own tools. You don't manage workers
directly — you manage the top-level mission. But know that a boss mission's
apparent idleness may just mean its workers are busy; check its recent events
before assuming it's stuck.
## The monitoring loop
For each mission you're babysitting, every check-in:
1. **`get_mission_health(mission_id)`** — always start here. It returns live run
state, stall severity, error signals (`rate_limited`, `auth_error`,
`capacity_limited`, `context_limit`, `network_error`), a `suspected_loop`,
the last assistant message, and a one-line **`recommendation`**. Trust the
recommendation as your default action.
2. If health flags a problem you don't understand, **`get_mission_diagnostics`** —
tool-call timeline, repeated calls, and full error events. This is how you see
*exactly* where it's struggling.
3. Act (see playbook). Then leave it alone until the next check-in. Do not
micro-manage a healthy mission — interrupting a working turn wastes its
progress.
## Intervention playbook
Match the signal to the fix. The health `recommendation` usually tells you which.
- **`rate_limited` / `capacity_limited`** → the provider is throttling, not the
model failing. `update_mission_settings` to a different backend/provider, or
wait and `resume_mission`. (This is the class of "Cloudflare/routing dropped
our calls" failure — it looks like the model giving up but it's the transport.)
- **`auth_error`** → backend credentials are bad. Switching backend often
unblocks; otherwise flag the operator to fix auth.
- **`context_limit`** → the model ran out of context. Switch to a
larger-context backend/model, then `resume_mission`.
- **`network_error`** → transient edge/routing errors. `resume_mission`; if it
recurs, switch backend.
- **`suspected_loop`** → the model is repeating the same tool call. Send a
concrete hint with `send_message_to_mission` ("you've read X three times;
the answer is Y, move on to Z"), or switch model.
- **Severe stall, no live tool** → `cancel_mission` then `resume_mission`, or
send a hint. A `warning` stall with a tool running is fine — leave it.
- **Running `chatgpt_ui` mission** → event silence alone is never stall
evidence. GPT Pro can expose only `Pro thinking` until visible answer text
begins. While the run is non-terminal and its durable heartbeat advances,
wait for the driver's result or explicit absolute timeout. Do **not** cancel,
resume, or submit a replacement: the browser profile is exclusive and the
duplicate would either waste the in-flight answer or contend for the same
profile.
- **Idle but goal not done (gave up early)** → the #1 failure mode. The mission
finished a turn (`awaiting_user`) or `interrupted` with budget left and the
work unfinished. **Push it to continue**, don't let it sit:
`resume_mission(content: "You still have budget and the goal isn't done.
Keep going until <concrete success condition>. Do not stop to ask — make
reasonable decisions and continue.")` Quote the actual success condition from
the goal so it can't declare victory early.
## Mission results come back to this conversation — the platform wires it
A mission started from a conversation is a worker of that conversation.
Hermes stamps `origin_session_id`, enrolls the mission in the
async-delegation ledger, and the terminal webhook folds the result back
here (or appends a `[Mission callback]` and wakes this session if the
ledger row is missing). Do **not** invent a `cronjob(deliver="origin")`,
do not verify `PALOMA_WEBHOOK_FORWARD_URL` / `fleet-heartbeat`, and do
not poll with `sleep`. End the turn after dispatch.
### Conversational launch
Desktop / API / TUI chat. `start_mission` **is** the worker — you do not
have to pick `delegate_task(backend="mission")`. Leave
`origin_session_id` empty (the plugin injects this session). Confirm the
mission is `pending`/`active`, then stop. The result comes back here.
### Controller launch
A cron tick with `deliver: project:<canonical-slug>`. Pass `project` as
the roster slug (`verity-core`, `verity-lido`, …) and `track` as the
**item** this mission is an attempt on. Do **not** enroll a worker
wakeup and do not wait. Report on the next tick or via the project
route. A `cron_*` session dies wit>
>
>
>
>
Autonomy contract and routing index for autonomous project controllers. Loaded every tick; carries the rules that must survive cron-prompt rewrites.
Delegate coding/automation tasks to sandboxed.sh missions via the mcp_sandboxed_assistant_* MCP. Each mission runs in an isolated container (workspace) with a chosen agent profile and a self-contained prompt. Use this skill whenever the user wants to 'launch a mission', 'sandboxed', 'spawn a worker', or delegate a multi-step coding/research task that should run in a clean environment.