mirror of
https://github.com/mattpocock/skills.git
synced 2026-07-29 02:52:42 +07:00
feat(spawn): default to the running agent; herdr-first management, no nohup
Six agents (claude, codex, pi, cursor, opencode, copilot). claude keeps its native --bg/agents management. Everything else spawns interactively inside herdr when its server is up (list/read/send/attach); otherwise a transient systemd --user unit gives status/logs/stop. Research confirmed none of the five non-claude CLIs has a native background job manager. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
fc73c04a34
commit
085d886fca
@@ -1,19 +1,19 @@
|
|||||||
---
|
---
|
||||||
name: spawn
|
name: spawn
|
||||||
description: Hand the current conversation off to a fresh background agent — claude or codex — that picks up the work immediately.
|
description: Hand the current conversation off to a fresh background agent that picks up the work immediately.
|
||||||
argument-hint: "[claude|codex] What will the next session be used for?"
|
argument-hint: "[agent] What will the next session be used for?"
|
||||||
disable-model-invocation: true
|
disable-model-invocation: true
|
||||||
---
|
---
|
||||||
|
|
||||||
Write a handoff summary of the current conversation so a fresh agent can continue the work, then spawn the agent with it via the bundled [spawn.sh](spawn.sh) — run it, never read it:
|
Write a handoff summary of the current conversation so a fresh agent can continue the work, then spawn the agent with it via the bundled [spawn.sh](spawn.sh) — run it, never read it:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bash <this skill's base directory>/spawn.sh <claude|codex> "<descriptive session name>" - <<'PROMPT'
|
bash <this skill's base directory>/spawn.sh <agent> "<descriptive session name>" - <<'PROMPT'
|
||||||
<handoff summary>
|
<handoff summary>
|
||||||
PROMPT
|
PROMPT
|
||||||
```
|
```
|
||||||
|
|
||||||
Spawn `claude` unless the user named `codex`. The agent starts in the current working directory; the script prints how the user monitors the session — relay that.
|
`<agent>` is one of `claude | codex | pi | cursor | opencode | copilot`. Spawn the agent you are running as, unless the user named another. The agent starts in the current working directory; the script prints how the user monitors and manages the session — relay that.
|
||||||
|
|
||||||
The handoff summary:
|
The handoff summary:
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,17 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# spawn.sh <claude|codex> <name> [prompt|-]
|
# spawn.sh <agent> <name> [prompt|-]
|
||||||
# Launches a background agent session seeded with the prompt.
|
# Launches a background agent session seeded with the prompt.
|
||||||
# Prompt is read from stdin when the third argument is omitted or '-'.
|
# Prompt is read from stdin when the third argument is omitted or '-'.
|
||||||
|
#
|
||||||
|
# claude has native managed background jobs (claude --bg / claude agents).
|
||||||
|
# Every other agent is spawned interactively inside herdr when its server is
|
||||||
|
# running (list/read/send/attach management); otherwise as a supervised
|
||||||
|
# one-shot under the user's systemd session (status/logs/stop management).
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
echo "usage: spawn.sh <claude|codex> <name> [prompt|-] (prompt read from stdin when omitted or '-')" >&2
|
echo "usage: spawn.sh <claude|codex|pi|cursor|opencode|copilot> <name> [prompt|-]" >&2
|
||||||
|
echo " prompt is read from stdin when omitted or '-'" >&2
|
||||||
exit 2
|
exit 2
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,24 +25,67 @@ if [ "$prompt" = "-" ]; then
|
|||||||
fi
|
fi
|
||||||
[ -n "$prompt" ] || { echo "spawn.sh: empty prompt" >&2; exit 2; }
|
[ -n "$prompt" ] || { echo "spawn.sh: empty prompt" >&2; exit 2; }
|
||||||
|
|
||||||
case "$agent" in
|
if [ "$agent" = "claude" ]; then
|
||||||
claude)
|
|
||||||
claude --bg --name "$name" "$prompt"
|
claude --bg --name "$name" "$prompt"
|
||||||
echo "Spawned claude session '$name'. Manage it with: claude agents"
|
echo "Spawned claude session '$name'. Manage it with: claude agents"
|
||||||
;;
|
exit 0
|
||||||
codex)
|
fi
|
||||||
|
|
||||||
|
# Interactive invocation, seeded with the prompt — used inside herdr panes.
|
||||||
|
case "$agent" in
|
||||||
|
codex) interactive=(codex "$prompt") ;;
|
||||||
|
pi) interactive=(pi "$prompt") ;;
|
||||||
|
cursor) interactive=(cursor-agent "$prompt") ;;
|
||||||
|
opencode) interactive=(opencode --prompt "$prompt") ;;
|
||||||
|
copilot) interactive=(copilot -i "$prompt") ;;
|
||||||
|
*) usage ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if herdr agent list >/dev/null 2>&1; then
|
||||||
|
herdr agent start "$name" --cwd "$PWD" --no-focus -- "${interactive[@]}"
|
||||||
|
echo "Spawned $agent session '$name' in herdr."
|
||||||
|
echo " list: herdr agent list"
|
||||||
|
echo " read: herdr agent read '$name'"
|
||||||
|
echo " steer: herdr agent send '$name' '<text>'"
|
||||||
|
echo " attach: herdr agent attach '$name'"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
command -v systemd-run >/dev/null 2>&1 || {
|
||||||
|
echo "spawn.sh: no herdr server running and systemd-run unavailable — launch herdr and retry" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Non-interactive one-shot — flags keep the run from blocking on approvals.
|
||||||
|
case "$agent" in
|
||||||
|
codex) oneshot=(codex exec --sandbox workspace-write --skip-git-repo-check "$prompt") ;;
|
||||||
|
pi) oneshot=(pi -p "$prompt") ;;
|
||||||
|
cursor) oneshot=(cursor-agent -p --force --output-format text "$prompt") ;;
|
||||||
|
opencode) oneshot=(opencode run --title "$name" "$prompt") ;;
|
||||||
|
copilot) oneshot=(copilot -p "$prompt" --allow-all-tools) ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# The systemd user manager doesn't inherit this shell's PATH; resolve the
|
||||||
|
# binary now and pass PATH through for any children it spawns.
|
||||||
|
bin="$(command -v "${oneshot[0]}")" || {
|
||||||
|
echo "spawn.sh: ${oneshot[0]} is not installed" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
oneshot[0]="$bin"
|
||||||
|
|
||||||
slug="$(printf '%s' "$name" | tr '[:upper:] ' '[:lower:]-' | tr -cd 'a-z0-9-')"
|
slug="$(printf '%s' "$name" | tr '[:upper:] ' '[:lower:]-' | tr -cd 'a-z0-9-')"
|
||||||
dir="${TMPDIR:-/tmp}/codex-spawns"
|
unit="spawn-${slug:-session}-$(date +%H%M%S)"
|
||||||
mkdir -p "$dir"
|
systemd-run --user --unit "$unit" --working-directory="$PWD" \
|
||||||
base="$dir/${slug:-session}-$(date +%Y%m%d-%H%M%S)"
|
--setenv=PATH="$PATH" --setenv=HOME="$HOME" "${oneshot[@]}" >/dev/null 2>&1
|
||||||
nohup codex exec --sandbox workspace-write --cd "$PWD" \
|
|
||||||
-o "$base.last.md" - <<<"$prompt" >"$base.log" 2>&1 &
|
echo "Spawned $agent session '$name' as user unit $unit (no herdr server running)."
|
||||||
echo "Spawned codex session '$name' (pid $!)."
|
echo " status: systemctl --user status $unit"
|
||||||
echo " log: $base.log"
|
echo " logs: journalctl --user -u $unit -f"
|
||||||
echo " final answer: $base.last.md"
|
echo " stop: systemctl --user stop $unit"
|
||||||
echo " follow with: tail -f $base.log"
|
case "$agent" in
|
||||||
;;
|
codex) echo " resume: codex exec resume <session id from logs>" ;;
|
||||||
*)
|
pi) echo " resume: pi -c (from this directory)" ;;
|
||||||
usage
|
cursor) echo " resume: cursor-agent resume" ;;
|
||||||
;;
|
opencode) echo " resume: opencode run -c (or: opencode session list)" ;;
|
||||||
|
copilot) echo " resume: copilot --resume" ;;
|
||||||
esac
|
esac
|
||||||
|
|||||||
Reference in New Issue
Block a user