Files
multi-agent-mux/.agents/skills/multi-agent-mux-create/SKILL.md
T

14 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. 2.1.0 godopu MIT
linux
macos
terminal
herdr
hermes
tags related_skills prereq_skills
agent
herdr
claude
antigravity
agy
multi-agent
context
session
multi-agent-mux-resume
multi-agent-mux-stop
multi-agent-mux-monitor
claude-code
claude-code

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 + claudelanding-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
# Use lib.sh's has_real_herdr, NOT `command -v herdr` / `type -P herdr`: once
# lib.sh is sourced the former matches its herdr() function and the latter
# matches the .mam/shim wrapper, so both pass on a host with no herdr (B-3).
has_real_herdr || { echo "ERROR: herdr not installed"; exit 1; }
echo "Herdr session name: ${HERDR_SESSION_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 → abort with a non-zero exit and report the reason (automated 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 claude inside, auto-handles trust/bypass dialogs
    • see <workdir>/agent_sessions.md for the canonical wrapper template

Herdr Session Isolation (격리 세션)

When running multiple agent sessions alongside other workflows (e.g., cmux, background 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 session using the HERDR_SESSION_NAME environment variable or the --herdr-session <name> flag (opt-in; alias: --herdr-server; legacy env alias: HERDR_SERVER_NAME). Additionally, you can specify --herdr-workspace <name> (default: workspace slug without mam- prefix) to name and group the agent panes inside a dedicated Herdr workspace tab in the Herdr runtime (herdr workspace create --label / rename) as well as recording it in .mam/agent-sessions.yaml. Note that --herdr-workspace configures the workspace tab label within the session, whereas --herdr-session selects the daemon socket itself.

Under the hood this 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

  1. Via Environment Variable:
    export HERDR_SESSION_NAME=multi-agent-canary
    # All subsequent commands (create, status, stop, etc.) will run in the isolated 'multi-agent-canary' herdr session.
    
  2. Via Option Flag:
    bash scripts/create_session.sh --workspace /path/to/project --agent claude --role developer --herdr-session multi-agent-canary --herdr-workspace my-project
    
  3. 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"
    
  4. 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
    

Why use --herdr-session?

  • By default, all skills target default herdr session socket — fine for single-workspace use.
  • By using an isolated session via HERDR_SESSION_NAME (or --herdr-session), your agent sessions are completely separated from your default user workspace, ensuring 0% interference — this is backed by a genuinely separate herdr session/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_SESSION_NAME> followed by herdr session delete <HERDR_SESSION_NAME> — this only affects that named session, never the default one.

Output format

When invoked, the script creates or updates ./.mam/agent-sessions.yaml with:

herdr_sessions:
- name: <workspace>-creator-<agent>           # E.g. landing-page-creator-claude
  status: running                             # Initial status for a freshly created agent
  role: Developer
  herdr_session_created_at: '2026-08-04T12:00:00Z'
  herdr_session_epoch: 1785844800
  herdr_session: <HERDR_SESSION_NAME>         # Isolated session name (default: 'mam-<ws-slug>')
  delegate_job_id: null
  pane:
    index: 0
    pid: 12345
    cmd: claude
    cmd_full: claude --dangerously-skip-permissions
    cwd: /path/to/project
  start_command: "HERDR_SESSION_NAME=<herdr_session> herdr new-session -d -s <SESSION_NAME> -x 140 -y 40 -c <WORKSPACE> <CMD_FULL>"
  attach_command: "HERDR_SESSION_NAME=<herdr_session> herdr agent attach <SESSION_NAME>"
  kill_command: "HERDR_SESSION_NAME=<herdr_session> herdr kill-session -t <SESSION_NAME>"

Workflow

WORKSPACE=/path/to/project
AGENT=claude  # claude | agy | hermes | cline — always pass it explicitly
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, agy, hermes or cline, 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_session: <HERDR_SESSION_NAME>         # Isolated session name (default: 'mam-<ws-slug>')
  herdr_server: <HERDR_SESSION_NAME>          # Alias for herdr_session
  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_SESSION_NAME=<herdr_session> herdr new-session -d -s <SESSION_NAME> -x 140 -y 40 -c <WORKSPACE> <CMD_FULL>"
  attach_command: "HERDR_SESSION_NAME=<herdr_session> herdr agent attach <SESSION_NAME>"
  kill_command: "HERDR_SESSION_NAME=<herdr_session> 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_SESSION_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_session: 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/setsid for the agent itself — those background the agent outside herdr. The whole point of this skill is the herdr session is the supervisor. nohup is OK only for launching the wrapper (which itself creates the herdr session via herdr new-session -d).
  • Claude Session ID Auto-Assignment: Fresh claude sessions automatically generate a new UUID (mam_gen_uuid) passed via claude --session-id <uuid>. claude_session_id_own is stored in .mam/agent-sessions.yaml with session_id_source: assigned and session_id_verified: false.
  • First Message Materialization: The transcript file .jsonl is created on disk when the first user prompt is sent. The monitor loop (reconcile.sh) verifies the transcript and promotes session_id_verified: true and last_visible_status: pinned.
  • Wrapper script MUST NOT be created via hermes profile alias — that command writes a hermes -p <profile> wrapper that destroys the herdr behavior. Create wrappers manually (see lab-landing-page-creator-claude template).
  • Always use the workspace-relative path in herdr cwd — relative paths break when herdr respawns in a different shell context.

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-pane above are tmux-compat pseudo-commands only understood after source .agents/skills/lib.sh (see Workflow) — the real herdr binary has no such subcommands. The block above uses the real herdr agent get/herdr agent read equivalents so it also works standalone.

When NOT to use this skill

  • Resuming an old conversationmulti-agent-mux-resume
  • Killing an existing sessionmulti-agent-mux-stop
  • Just attaching to an existing sessionherdr agent attach <name> (no skill needed)
  • One-shot print mode (claude -p "...") → no herdr needed; use claude-code skill's print mode