refactor(skills): rename multi-agent-* + agent-sessions-monitor + delegate-job to tmux-agent-orchestrate-*
Renamed 6 skills directories to tmux-agent-orchestrate-* prefix: - multi-agent-create → tmux-agent-orchestrate-create - multi-agent-resume → tmux-agent-orchestrate-resume - multi-agent-delete → tmux-agent-orchestrate-delete - multi-agent-status → tmux-agent-orchestrate-status - agent-sessions-monitor → tmux-agent-orchestrate-monitor - delegate-job → tmux-agent-orchestrate-delegate-job Updated: - skills/lib.sh internal paths (delegate_submit_job etc.) - skills/tmux-agent-orchestrate-status/scripts/status.sh (monitor path) - skills/tmux-agent-orchestrate-monitor/scripts/reconcile.sh - .gitignore (HTML ignore patterns) - 6 SKILL.md frontmatter (name, related_skills, prereq_skills) and body - All script headers and Korean comments Notes: - tmux session naming convention unchanged (<slug>-creator-<agent>) — workspace identifier based, kept for backward compatibility - Existing 2 sessions in -L multi-agent-canary untouched - YAML delegate_job_id / agent-session (tmux:canary-...) preserved for log history compatibility Verified on isolated server -L agy-rename-test (kill-server after).
This commit is contained in:
@@ -0,0 +1,218 @@
|
||||
---
|
||||
name: tmux-agent-orchestrate-create
|
||||
description: "Create a new agent session (claude, antigravity/agy) in a dedicated tmux session for context-preserving long-running work. Always creates a tmux session — never backgrounds with nohup/disown. Writes the new session to ~/PuKi/lab/agent_sessions/agent-sessions.yaml. Use when you want to start a fresh agent (no prior UUID) for a new project workspace."
|
||||
version: 1.0.0
|
||||
author: godopu
|
||||
license: MIT
|
||||
platforms: [linux, macos]
|
||||
environments: [terminal, tmux]
|
||||
metadata:
|
||||
hermes:
|
||||
tags: [agent, tmux, claude, antigravity, agy, multi-agent, context, session]
|
||||
related_skills: [tmux-agent-orchestrate-resume, tmux-agent-orchestrate-delete, tmux-agent-orchestrate-monitor, claude-code]
|
||||
prereq_skills: [claude-code]
|
||||
---
|
||||
|
||||
# Multi-Agent Create — Start a Fresh Agent in a tmux Session
|
||||
|
||||
> **Companion skills**: `tmux-agent-orchestrate-resume` (resume an existing UUID), `tmux-agent-orchestrate-delete` (terminate), `tmux-agent-orchestrate-monitor` (live status).
|
||||
> **Single source of truth**: `~/PuKi/lab/agent_sessions/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 tmux session** for context-preserving long-running work. The tmux 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 `tmux-agent-orchestrate-resume` for that).
|
||||
|
||||
For all agents: the tmux session name is produced by **`lib.sh::derive_session_name`** — the single source of truth shared by create/resume/delete/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 `/home/godopu16/PuKi/lab/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:
|
||||
|
||||
```bash
|
||||
# 1) tmux available and isolated server status
|
||||
command -v tmux || { echo "ERROR: tmux not installed"; exit 1; }
|
||||
echo "Tmux server name: ${TMUX_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
|
||||
|
||||
- **tmux 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: tmux new-session with `claude` inside, auto-handles trust/bypass dialogs
|
||||
- see `~/PuKi/lab/landing_page/refer_landing_page/agent_sessions.md` for the canonical wrapper template
|
||||
|
||||
## Tmux Server Isolation (격리 서버)
|
||||
|
||||
When running multiple agent sessions alongside other workflows (e.g., cmux, Kanban workers, manual tmux sessions), sharing the default tmux 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 tmux server** using the `TMUX_SERVER_NAME` environment variable or the `--tmux-server <name>` flag (opt-in).
|
||||
|
||||
### How to use
|
||||
1. **Via Environment Variable**:
|
||||
```bash
|
||||
export TMUX_SERVER_NAME=multi-agent-canary
|
||||
# All subsequent commands (create, status, delete, etc.) will run in the isolated 'multi-agent-canary' tmux server.
|
||||
```
|
||||
2. **Via Option Flag**:
|
||||
```bash
|
||||
bash scripts/create_session.sh --workspace /path/to/project --agent claude --tmux-server multi-agent-canary
|
||||
```
|
||||
3. **Submit Job Integration**:
|
||||
You can automatically register a delegated job with a prompt when creating a session:
|
||||
```bash
|
||||
bash scripts/create_session.sh --workspace /path/to/project --agent claude --submit-job "Task prompt here"
|
||||
```
|
||||
|
||||
### Recommended Alias
|
||||
You can set an alias in your shell to easily query sessions on the isolated server:
|
||||
```bash
|
||||
alias tmc='tmux -L multi-agent-canary'
|
||||
tmc ls # Lists only your multi-agent sessions
|
||||
```
|
||||
|
||||
### Safety Rules (Pitfall 29 Summary)
|
||||
- Never use global server termination commands like `tmux kill-server` or `tmux kill-session -a` as they will destroy all sessions on that server (including your own workspace sessions if they share the server).
|
||||
- By using an isolated server via `TMUX_SERVER_NAME`, your agent sessions are completely separated from your default user workspace, ensuring 0% interference.
|
||||
|
||||
## Workflow
|
||||
|
||||
```bash
|
||||
WORKSPACE=/path/to/project
|
||||
AGENT=claude # or agy
|
||||
source ~/PuKi/lab/agent_sessions/skills/lib.sh
|
||||
SESSION_NAME="$(derive_session_name "$WORKSPACE" "$AGENT")"
|
||||
|
||||
# 1. If session already alive, fail fast
|
||||
tmux has-session -t "$SESSION_NAME" 2>/dev/null && {
|
||||
echo "ERROR: tmux session '$SESSION_NAME' already exists. Use tmux-agent-orchestrate-resume to attach or tmux-agent-orchestrate-delete first."
|
||||
exit 1
|
||||
}
|
||||
|
||||
# 2. Spawn the tmux session with the agent inside
|
||||
case "$AGENT" in
|
||||
claude)
|
||||
# Use the wrapper if it exists, else inline tmux new-session
|
||||
if [ -x "$HOME/.local/bin/$SESSION_NAME" ]; then
|
||||
nohup "$HOME/.local/bin/$SESSION_NAME" >/dev/null 2>&1 &
|
||||
else
|
||||
tmux new-session -d -s "$SESSION_NAME" -x 140 -y 40 -c "$WORKSPACE" "claude"
|
||||
fi
|
||||
;;
|
||||
agy)
|
||||
tmux 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=$(tmux list-panes -t "$SESSION_NAME" -F '#{pane_pid}')
|
||||
PANE_CWD=$(tmux list-panes -t "$SESSION_NAME" -F '#{pane_current_path}')
|
||||
PANE_CMD=$(tmux list-panes -t "$SESSION_NAME" -F '#{pane_current_command}')
|
||||
TMUX_EPOCH=$(tmux list-sessions -F '#{session_created}' -t "$SESSION_NAME" 2>/dev/null | head -1)
|
||||
```
|
||||
|
||||
## Registering the session in agent-sessions.yaml
|
||||
|
||||
After spawn, append a new `tmux_sessions[]` entry to `~/PuKi/lab/agent_sessions/agent-sessions.yaml`:
|
||||
|
||||
```yaml
|
||||
- name: <SESSION_NAME>
|
||||
status: running
|
||||
tmux_session_created_at: 2026-06-17T...Z # ISO 8601 UTC
|
||||
tmux_session_epoch: <TMUX_EPOCH>
|
||||
tmux_server: <TMUX_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: <the exact tmux new-session command used>
|
||||
attach_command: "tmux attach -t <SESSION_NAME>"
|
||||
kill_command: "tmux kill-session -t <SESSION_NAME>"
|
||||
```
|
||||
|
||||
`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
|
||||
bash ~/PuKi/lab/agent_sessions/skills/tmux-agent-orchestrate-create/scripts/create_session.sh \
|
||||
--workspace "$WORKSPACE" --agent "$AGENT" --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 tmux. The whole point of this skill is *the tmux session is the supervisor*. `nohup` is OK only for *launching the wrapper* (which itself creates the tmux session via `tmux 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.jsonl` headers or `~/.gemini/.../cache/last_conversations.json` AFTER the first message.
|
||||
- **Wrapper script MUST NOT be created via `hermes profile alias`** — that command writes a `hermes -p <profile>` wrapper that destroys the tmux behavior. Create wrappers manually (see `lab-landing-page-creator-claude` template).
|
||||
- **Always use the workspace-relative path** in tmux `cwd` — relative paths break when tmux respawns in a different shell context.
|
||||
- **The first `claude` message generates the session id** — `tmux-agent-orchestrate-create` only 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 call `tmux-agent-orchestrate-resume` later.
|
||||
|
||||
## Verification
|
||||
|
||||
After spawn + YAML append:
|
||||
|
||||
```bash
|
||||
# 1. tmux session is alive
|
||||
tmux has-session -t "$SESSION_NAME" && echo OK || echo MISSING
|
||||
|
||||
# 2. pane has the expected cmd + cwd
|
||||
tmux list-panes -t "$SESSION_NAME" -F 'cmd=#{pane_current_command} cwd=#{pane_current_path}'
|
||||
|
||||
# 3. agent-sessions.yaml has the new entry
|
||||
python3 -c "
|
||||
import yaml
|
||||
d = yaml.safe_load(open('$HOME/PuKi/lab/agent_sessions/agent-sessions.yaml'))
|
||||
names = [s['name'] for s in d['tmux_sessions']]
|
||||
assert '$SESSION_NAME' in names, 'session not registered'
|
||||
print('OK:', names)
|
||||
"
|
||||
|
||||
# 4. Optional: send a probe via tmux send-keys and capture-pane
|
||||
tmux send-keys -t "$SESSION_NAME" "" Enter
|
||||
sleep 2
|
||||
tmux capture-pane -t "$SESSION_NAME" -p -S -20
|
||||
```
|
||||
|
||||
## When NOT to use this skill
|
||||
|
||||
- **Resuming an old conversation** → `tmux-agent-orchestrate-resume`
|
||||
- **Killing an existing session** → `tmux-agent-orchestrate-delete`
|
||||
- **Just attaching to an existing session** → `tmux attach -t <name>` (no skill needed)
|
||||
- **One-shot print mode (claude -p "...")** → no tmux needed; use `claude-code` skill's print mode
|
||||
Reference in New Issue
Block a user