13 KiB
name, description, version, author, license, platforms, environments, metadata
| name | description | version | author | license | platforms | environments | metadata | |||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| multi-agent-mux-create | Create a new agent session (claude, antigravity/agy) in a dedicated herdr session for context-preserving long-running work. Always creates a herdr session — never backgrounds with nohup/disown. Writes the new session to .mam/agent-sessions.yaml. Use when you want to start a fresh agent (no prior UUID) for a new project workspace. | 1.0.0 | godopu | MIT |
|
|
|
Multi-Agent Create — Start a Fresh Agent in a herdr Session
Companion skills:
multi-agent-mux-resume(resume an existing UUID),multi-agent-mux-stop(terminate),multi-agent-mux-monitor(live status). Single source of truth:./.mam/agent-sessions.yaml(this skill writes to it; never read it ad-hoc — go through this skill).
What this skill does
Spawn a new agent (claude or agy/antigravity-cli) in a dedicated herdr session for context-preserving long-running work. The herdr session is the container; the agent's session ID is data inside the container. This skill creates the container + starts the agent — but does not resume an old conversation (use multi-agent-mux-resume for that).
For all agents: the herdr session name is produced by lib.sh::derive_session_name — the single source of truth shared by create/resume/stop/status/monitor (P0-A). The rule (verbatim from the function):
slug = the two trailing path components of the absolute workspace,
_→-, lowercased, joined with-; name =<slug>-creator-<agent>.
So $WORKSPACE_ROOT/landing_page/refer_landing_page + claude → landing-page-refer-landing-page-creator-claude. The workspace basename (refer_landing_page) is included; the hand-written historical entry that dropped it (lab-landing-page-creator-claude) was the bug, not the convention.
Pre-flight checks
Before doing anything, verify the environment:
# 1) herdr available and isolated server status
command -v herdr || { echo "ERROR: herdr not installed"; exit 1; }
echo "Herdr server name: ${HERDR_SERVER_NAME:-default}"
# 2) claude / agy available
command -v claude # required for --agent claude
command -v agy # required for --agent agy
# 3) claude auth (if --agent claude)
claude auth status 2>&1 | python3 -c "import json,sys; d=json.load(sys.stdin); assert d.get('loggedIn'), 'claude not logged in'"
# 4) target workspace exists
test -d "$WORKSPACE" || { echo "ERROR: workspace $WORKSPACE not a directory"; exit 1; }
If any check fails → kanban_block(reason="...") (worker path) or report to user (interactive path). Do not proceed with a half-broken setup.
Standard names
- herdr session name:
derive_session_name <workspace> <agent>(lib.sh)<workspace-slug>=basename $(dirname $WORKSPACE)-basename $WORKSPACE(lowercase,_→-)- examples:
landing-page-refer-landing-page-creator-claude,paper-pdf2md-creator-agy - never re-derive this by hand — source lib.sh and call the function
- wrapper script (claude only):
~/.local/bin/<workspace-slug>-creator-claude- contents: herdr new-session with
claudeinside, auto-handles trust/bypass dialogs - see
<workdir>/agent_sessions.mdfor the canonical wrapper template
- contents: herdr new-session with
Herdr Server Isolation (격리 서버)
When running multiple agent sessions alongside other workflows (e.g., cmux, Kanban workers, manual herdr sessions), sharing the default herdr server can lead to session name conflicts, monitoring clutter, and accidental destruction of user sessions via global commands.
To prevent this, you can run this skill inside an isolated herdr server using the HERDR_SERVER_NAME environment variable or the --herdr-server <name> flag (opt-in).
Under the hood this now maps to a real, separate herdr session (herdr --session <name> — its own socket, its own agent list/workspace list, completely invisible to the default session and vice versa), not just a workspace label inside the same server. lib.sh's shim bootstraps the named session's server headlessly (herdr --session <name> server, backgrounded) the first time it's needed, and scopes every subsequent herdr call to it automatically — this headless bootstrap is what lets it work even when the skill itself is running from inside another herdr-managed pane (a plain interactive herdr --session <name> launch is blocked there by herdr's "nested herdr is disabled" guard; headless server mode isn't).
How to use
- Via Environment Variable:
export HERDR_SERVER_NAME=multi-agent-canary # All subsequent commands (create, status, stop, etc.) will run in the isolated 'multi-agent-canary' herdr server. - Via Option Flag:
bash scripts/create_session.sh --workspace /path/to/project --agent claude --role developer --herdr-server multi-agent-canary - Submit Job Integration:
You can automatically register a delegated job with a prompt when creating a session:
bash scripts/create_session.sh --workspace /path/to/project --agent claude --role developer --submit-job "Task prompt here" - Onboard Integration:
You can automatically submit a project alignment/orientation job to the new agent when creating a session:
bash scripts/create_session.sh --workspace /path/to/project --agent claude --role developer --onboard
Recommended Alias
You can set an alias in your shell to easily query sessions on the isolated server:
alias tmc='herdr -L multi-agent-canary'
tmc ls # Lists only your multi-agent sessions
Safety Rules (Pitfall 29 Summary)
- Never use global server termination commands like
herdr server stopas they will destroy every workspace/agent on that server (including your own workspace sessions if they share the server). (kill-server/kill-session -aare tmux-era names that don't exist in herdr's real CLI — see Pitfalls below.) - By using an isolated server via
HERDR_SERVER_NAME, your agent sessions are completely separated from your default user workspace, ensuring 0% interference — this is now backed by a genuinely separateherdrsession/socket, not merely a workspace label. - To deliberately tear down an entire isolated group at once (all its workspaces and agents), use
herdr session stop <HERDR_SERVER_NAME>followed byherdr session delete <HERDR_SERVER_NAME>— this only affects that named session, never the default one.
Workflow
WORKSPACE=/path/to/project
AGENT=claude # or agy
source .agents/skills/lib.sh
SESSION_NAME="$(derive_session_name "$WORKSPACE" "$AGENT")"
# 1. If session already alive, fail fast
herdr has-session -t "$SESSION_NAME" 2>/dev/null && {
echo "ERROR: herdr session '$SESSION_NAME' already exists. Use multi-agent-mux-resume to attach or multi-agent-mux-stop first."
exit 1
}
# 2. Spawn the herdr session with the agent inside
case "$AGENT" in
claude)
# Use the wrapper if it exists, else inline herdr new-session
# Use the wrapper if it exists (LOCAL_BIN env var overrides default $HOME/.local/bin)
local_bin="${LOCAL_BIN:-$HOME/.local/bin}"
if [ -x "$local_bin/$SESSION_NAME" ]; then
nohup "$local_bin/$SESSION_NAME" >/dev/null 2>&1 &
else
herdr new-session -d -s "$SESSION_NAME" -x 140 -y 40 -c "$WORKSPACE" "claude"
fi
;;
agy)
herdr new-session -d -s "$SESSION_NAME" -x 140 -y 40 -c "$WORKSPACE" "agy --dangerously-skip-permissions"
;;
*) echo "ERROR: --agent must be claude or agy, got: $AGENT"; exit 2 ;;
esac
# 3. Wait for agent TUI to be ready (varies: claude ~5s, agy ~3s)
sleep 6
# 4. Capture pane metadata
PANE_PID=$(herdr list-panes -t "$SESSION_NAME" -F '#{pane_pid}')
PANE_CWD=$(herdr list-panes -t "$SESSION_NAME" -F '#{pane_current_path}')
PANE_CMD=$(herdr list-panes -t "$SESSION_NAME" -F '#{pane_current_command}')
# `herdr list-sessions` doesn't exist (real or shimmed) — we just spawned this
# session ourselves, so stamp the epoch locally instead of round-tripping herdr.
HERDR_EPOCH=$(date +%s)
Registering the session in agent-sessions.yaml
After spawn, append a new herdr_sessions[] entry to .mam/agent-sessions.yaml:
- name: <SESSION_NAME>
status: running
herdr_session_created_at: 2026-06-17T...Z # ISO 8601 UTC
herdr_session_epoch: <HERDR_EPOCH>
herdr_server: <HERDR_SERVER_NAME> # Isolated server name (default: 'default')
pane:
index: 0
pid: <PANE_PID>
cmd: <AGENT> # 'claude' or 'agy'
cmd_full: <full command line, see table below>
cwd: <PANE_CWD>
tui: # only for claude
model: <from TUI status>
provider: <from TUI status>
plan: <from TUI status>
account: <from TUI status>
version: <from TUI status>
start_command: "HERDR_SERVER_NAME=<herdr_server> herdr new-session -d -s <SESSION_NAME> -x 140 -y 40 -c <WORKSPACE> <CMD_FULL>"
attach_command: "HERDR_SERVER_NAME=<herdr_server> herdr agent attach <SESSION_NAME>"
kill_command: "HERDR_SERVER_NAME=<herdr_server> herdr kill-session -t <SESSION_NAME>"
# All three require `source .agents/skills/lib.sh` first — `new-session`/`kill-session`
# are tmux-compat pseudo-commands the shim translates, and `HERDR_SERVER_NAME` is what
# the shim reads to route to the right isolated herdr *session* (real `herdr` has no
# env-var-based scoping of its own; `herdr_server: default` needs no prefix at all).
cmd_full per agent (this is the actual command line in the pane, not the resume command):
| agent | cmd_full |
|---|---|
| claude (interactive) | claude |
| agy (interactive) | agy --dangerously-skip-permissions |
Use the agent-sessions-yaml-edit script in scripts/ to safely append (preserves comments + format):
bash .agents/skills/multi-agent-mux-create/scripts/create_session.sh \
--workspace "$WORKSPACE" --agent "$AGENT" --role "$ROLE" --session "$SESSION_NAME"
The script handles the YAML append, pane capture, and the last_visible_status placeholder.
Pitfalls
- Don't use
nohup/disown/setsidfor the agent itself — those background the agent outside herdr. The whole point of this skill is the herdr session is the supervisor.nohupis OK only for launching the wrapper (which itself creates the herdr session viaherdr new-session -d). - Don't trust
--session-id <uuid>flags blindly — claude/agy may not accept a fixed session id on first spawn. The session id is assigned on first user message; you can read it back from~/.claude/projects/.../session.jsonlheaders or~/.gemini/.../cache/last_conversations.jsonAFTER the first message. - Wrapper script MUST NOT be created via
hermes profile alias— that command writes ahermes -p <profile>wrapper that destroys the herdr behavior. Create wrappers manually (seelab-landing-page-creator-claudetemplate). - Always use the workspace-relative path in herdr
cwd— relative paths break when herdr respawns in a different shell context. - The first
claudemessage generates the session id —multi-agent-mux-createonly sets up the container. If you need a known session id for later resume, send a placeholder message (e.g. "init") and read it back, then callmulti-agent-mux-resumelater.
Verification
After spawn + YAML append:
# 1. herdr session is alive (real native command — no lib.sh needed)
herdr agent get "$SESSION_NAME" >/dev/null 2>&1 && echo OK || echo MISSING
# 2. pane has the expected cmd + cwd
herdr agent get "$SESSION_NAME" | python3 -c "
import sys, json
a = json.load(sys.stdin)['result']['agent']
print(f\"cmd={a['agent']} cwd={a['cwd']}\")
"
# 3. agent-sessions.yaml has the new entry
python3 -c "
import yaml
d = yaml.safe_load(open('.mam/agent-sessions.yaml'))
names = [s['name'] for s in d['herdr_sessions']]
assert '$SESSION_NAME' in names, 'session not registered'
print('OK:', names)
"
# 4. Optional: check the TUI status (real native command)
herdr agent read "$SESSION_NAME" --source visible --lines 20 # TUI ready = agent banner visible, no dialog text
herdr has-session/herdr list-panes/herdr capture-paneabove are tmux-compat pseudo-commands only understood aftersource .agents/skills/lib.sh(seeWorkflow) — the realherdrbinary has no such subcommands. The block above uses the realherdr agent get/herdr agent readequivalents so it also works standalone.
When NOT to use this skill
- Resuming an old conversation →
multi-agent-mux-resume - Killing an existing session →
multi-agent-mux-stop - Just attaching to an existing session →
herdr agent attach <name>(no skill needed) - One-shot print mode (claude -p "...") → no herdr needed; use
claude-codeskill's print mode