| name | migrate-agents |
| description | Convert .agents/agents.json entries into the script-first shape — one <id>.sh + <id>.json per agent. Non-destructive (agents.json untouched). Use on /migrate-agents or to convert prompt-style agents into bash scripts. |
/migrate-agents — bulk-convert agents.json → scripts
Companion to the in-app "Convert to script" button, but at directory level. For
each agent entry in .agents/agents.json that does not already have a matching
.agents/<id>.sh, materialize:
.agents/<id>.sh — executable bash body that execs the prior
claude -p $prompt / codex exec $prompt command. Default body is the
single-LLM-call template — replace it with prechecks + escalation when you
want to save tokens (see .agents/scripts.md and .agents/health.sh).
.agents/<id>.json — sidecar metadata (title, description, icon,
opensPr, engine, model, inPlace) — exactly what was previously the
agents.json entry, minus prompt.
Hard rules
- Non-destructive. Do NOT delete entries from
.agents/agents.json. The
runner branches to .sh when present and falls back to the prompt entry
otherwise — keeping both makes the migration safe to revert.
- Skip on conflict. If
.agents/<id>.sh already exists, leave it alone
and skip that agent (do not overwrite hand-edited scripts).
- chmod 755 every script written.
- Sidecar JSON, 2-space indent, trailing newline.
Process
set -euo pipefail
json=".agents/agents.json"
[ -f "$json" ] || { echo "no .agents/agents.json — nothing to migrate"; exit 0; }
ids=$(jq -r '.[] | .id' "$json")
for id in $ids; do
script=".agents/$id.sh"
if [ -f "$script" ]; then
echo "skip $id — script already exists"
continue
fi
prompt=$(jq -r --arg id "$id" '.[] | select(.id == $id) | .prompt' "$json")
engine=$(jq -r --arg id "$id" '.[] | select(.id == $id) | (.engine // "claude")' "$json")
model=$(jq -r --arg id "$id" '.[] | select(.id == $id) | (.model // "")' "$json")
if [ "$engine" = "claude" ]; then
cmd="claude -p $(printf %q "$prompt") --permission-mode auto \${TERMINAL_MODEL:+--model \"\$TERMINAL_MODEL\"}"
else
cmd="codex exec -s danger-full-access -C \"\$TERMINAL_WORKTREE\" \${TERMINAL_MODEL:+--model \"\$TERMINAL_MODEL\"} $(printf %q "$prompt")"
fi
cat > "$script" <<EOF
#!/usr/bin/env bash
# Auto-generated by /migrate-agents from .agents/agents.json.
# Edit freely. Runtime env: TERMINAL_REPO, TERMINAL_RUN_ID, TERMINAL_BRANCH,
# TERMINAL_WORKTREE, TERMINAL_ENGINE, TERMINAL_MODEL. Helpers on PATH:
# terminal-cli ticket / hitl / activity / notify.
set -uo pipefail
exec $cmd
EOF
chmod 755 "$script"
jq --arg id "$id" '.[] | select(.id == $id) | del(.prompt)' "$json" > ".agents/$id.json"
echo "migrated $id"
done
After running, restart TerMinal (or just open the Agents tab) and each row
will render the script body in its expander with an "edit" button — replace
the auto-generated single-LLM-call with a precheck-then-escalate pattern
when it'd save tokens.
What this is NOT
- Not the agent designer. The designer creates new agents from a
natural-language description; this skill converts existing ones in place.
- Not a sidecar editor. Once the
.sh + .json exist, edit them with your
configured editor (the Agents tab's "edit" button opens the .sh in
Cursor/VS Code; the sidecar is plain JSON).