一键导入
doey-add-team
Spawn a team from a .team.md definition file. Usage: /doey-add-team <name>
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Spawn a team from a .team.md definition file. Usage: /doey-add-team <name>
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Plan-first task creation — research, breakdown, risk analysis, then create tasks from approved plan. Usage: /doey-planned-task <goal>
Request a respawn of the current worker pane. Use when you need to "respawn me", "restart myself", "fresh context", or "reset my pane". Writes an atomic respawn request that kills the current Claude process and relaunches with a fresh context.
Discover scaffolding patterns in this project — structural fingerprints, accretion files, and refactoring patterns from git history. Returns candidates worth turning into templates.
Spawn the doey-scaffy MCP server so workers can drive the Scaffy template engine via tool calls. Loaded automatically when a task needs scaffy_run / scaffy_validate / scaffy_list / scaffy_audit / scaffy_discover / scaffy_new / scaffy_fmt or any scaffy:// resource.
Create a new scaffy template from existing files (--from-files) or interactively. Outputs to .doey/scaffy/templates/<name>.scaffy.
Manage persistent project tasks — list, add, transition, show, subtasks, decisions, notes. Tasks stored in .doey/tasks/ (survives reboot). Use when you need to "show tasks", "add a task", "mark a task done", "what are we working on", or "create a task".
| name | doey-add-team |
| description | Spawn a team from a .team.md definition file. Usage: /doey-add-team <name> |
cat /tmp/doey/*/session.env 2>/dev/null | head -20 || truetmux list-windows -F '#{window_index} #{window_name}' 2>/dev/null || truels -1 .team.md *.team.md .doey/*.team.md ~/.config/doey/teams/*.team.md 2>/dev/null || echo "(none found in common locations)"Spawn a team from a .team.md file. No confirmation. Taskmaster/Subtaskmaster only.
---
name: team-name
description: What this team does
---
## Panes
| Pane | Role | Agent | Name | Model |
|------|------|-------|------|-------|
| 0 | manager | doey-manager | Team Lead | opus |
| 1 | reviewer | - | Reviewer | opus |
## Workflows
| Trigger | From | To | Subject |
|---------|------|----|---------|
| stop | reviewer | manager | review_complete |
RUNTIME_DIR=$(tmux show-environment DOEY_RUNTIME 2>/dev/null | cut -d= -f2-)
source "${RUNTIME_DIR}/session.env"
TEAM_NAME="${1:?Usage: /doey-add-team <name>}"
if command -v doey >/dev/null 2>&1 && doey add-team "$TEAM_NAME" 2>/dev/null; then
echo "Team spawned via doey CLI"; exit 0
fi
TEAM_DEF=""
for _search_dir in "$PROJECT_DIR" "$PROJECT_DIR/.doey" "${HOME}/.config/doey/teams" "$(dirname "$(command -v doey 2>/dev/null || echo /dev/null)")/../../share/doey/teams"; do
for _candidate in "${_search_dir}/${TEAM_NAME}.team.md" "${_search_dir}/${TEAM_NAME}"; do
[ -f "$_candidate" ] && { TEAM_DEF="$_candidate"; break 2; }
done
done
[ -z "$TEAM_DEF" ] && { echo "ERROR: '${TEAM_NAME}' not found"; exit 1; }
TEAMDEF_FILE="${RUNTIME_DIR}/teamdef_${TEAM_NAME}.env"
TEAM_DESC=$(sed -n '/^---$/,/^---$/{ /^description:/{ s/^description:[[:space:]]*//; p; }; }' "$TEAM_DEF")
PANE_COUNT=0
PANE_DEFS=""
_in_panes=false
while IFS= read -r line; do
case "$line" in
"## Panes"*) _in_panes=true; continue ;;
"## "*) _in_panes=false; continue ;;
esac
[ "$_in_panes" = "false" ] && continue
echo "$line" | grep -q '^|[[:space:]]*Pane' && continue
echo "$line" | grep -q '^|[[:space:]]*-' && continue
echo "$line" | grep -q '^|' || continue
_pane=$(echo "$line" | cut -d'|' -f2 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
_role=$(echo "$line" | cut -d'|' -f3 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
_agent=$(echo "$line" | cut -d'|' -f4 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
_name=$(echo "$line" | cut -d'|' -f5 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
_model=$(echo "$line" | cut -d'|' -f6 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
[ -z "$_pane" ] && continue
[ "$_agent" = "-" ] && _agent=""
PANE_DEFS="${PANE_DEFS}${_pane}|${_role}|${_agent}|${_name}|${_model}
"
PANE_COUNT=$(( PANE_COUNT + 1 ))
done < "$TEAM_DEF"
[ "$PANE_COUNT" -eq 0 ] && { echo "ERROR: No pane definitions found in $TEAM_DEF"; exit 1; }
echo "Parsed ${PANE_COUNT} panes from team definition"
# Parse workflows
WORKFLOWS=""
_in_workflows=false
while IFS= read -r line; do
case "$line" in
"## Workflows"*) _in_workflows=true; continue ;;
"## "*) _in_workflows=false; continue ;;
esac
[ "$_in_workflows" = "false" ] && continue
echo "$line" | grep -q '^|[[:space:]]*Trigger' && continue
echo "$line" | grep -q '^|[[:space:]]*-' && continue
echo "$line" | grep -q '^|' || continue
_trigger=$(echo "$line" | cut -d'|' -f2 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
_from=$(echo "$line" | cut -d'|' -f3 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
_to=$(echo "$line" | cut -d'|' -f4 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
_subject=$(echo "$line" | cut -d'|' -f5 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
[ -z "$_trigger" ] && continue
WORKFLOWS="${WORKFLOWS}${_trigger}|${_from}|${_to}|${_subject}
"
done < "$TEAM_DEF"
# Write teamdef env
cat > "${TEAMDEF_FILE}.tmp" << TDEF_EOF
TEAM_DEF_NAME=${TEAM_NAME}
TEAM_DEF_DESC=${TEAM_DESC}
TEAM_DEF_FILE=${TEAM_DEF}
TEAM_DEF_PANE_COUNT=${PANE_COUNT}
TEAM_DEF_PANES=$(echo "$PANE_DEFS" | head -c -1 | tr '\n' ';')
TEAM_DEF_WORKFLOWS=$(echo "$WORKFLOWS" | head -c -1 | tr '\n' ';')
TDEF_EOF
mv "${TEAMDEF_FILE}.tmp" "$TEAMDEF_FILE"
echo "Teamdef written to $TEAMDEF_FILE"
tmux new-window -t "$SESSION_NAME" -n "$TEAM_NAME" -c "$PROJECT_DIR"
sleep 0.5
NEW_WIN=$(tmux display-message -t "$SESSION_NAME" -p '#{window_index}')
for _s in $(seq 1 $((PANE_COUNT - 1))); do
tmux split-window -t "${SESSION_NAME}:${NEW_WIN}" -c "$PROJECT_DIR"
done
tmux select-layout -t "${SESSION_NAME}:${NEW_WIN}" tiled
sleep 0.5
MANAGER_PANE_IDX=""
WORKER_PANES_LIST=""
while IFS='|' read -r _pane _role _agent _name _model; do
[ -z "$_pane" ] && continue
tmux select-pane -t "${SESSION_NAME}:${NEW_WIN}.${_pane}" -T "T${NEW_WIN} ${_name}"
case "$_role" in
manager) MANAGER_PANE_IDX="$_pane" ;;
*) [ -n "$WORKER_PANES_LIST" ] && WORKER_PANES_LIST="${WORKER_PANES_LIST},${_pane}" || WORKER_PANES_LIST="${_pane}" ;;
esac
done << PANE_INPUT
$(echo "$PANE_DEFS")
PANE_INPUT
WORKER_COUNT=$(echo "$WORKER_PANES_LIST" | tr ',' '\n' | grep -c .)
TEAM_FILE="${RUNTIME_DIR}/team_${NEW_WIN}.env"
cat > "${TEAM_FILE}.tmp" << TEAM_EOF
SESSION_NAME=${SESSION_NAME}
PROJECT_DIR=${PROJECT_DIR}
PROJECT_NAME=${PROJECT_NAME}
WINDOW_INDEX=${NEW_WIN}
GRID=custom
TOTAL_PANES=${PANE_COUNT}
MANAGER_PANE=${MANAGER_PANE_IDX}
WORKER_PANES=${WORKER_PANES_LIST}
WORKER_COUNT=${WORKER_COUNT}
TEAM_DEF=${TEAM_NAME}
TEAM_NAME=${TEAM_NAME}
TEAM_DESC=${TEAM_DESC}
TEAM_EOF
mv "${TEAM_FILE}.tmp" "$TEAM_FILE"
CURRENT_WINDOWS=$(grep '^TEAM_WINDOWS=' "${RUNTIME_DIR}/session.env" 2>/dev/null | cut -d= -f2 | tr -d '"')
[ -n "$CURRENT_WINDOWS" ] && NEW_WINDOWS="${CURRENT_WINDOWS},${NEW_WIN}" || NEW_WINDOWS="${NEW_WIN}"
TMPENV=$(mktemp "${RUNTIME_DIR}/session.env.tmp_XXXXXX")
if grep -q '^TEAM_WINDOWS=' "${RUNTIME_DIR}/session.env"; then
sed "s/^TEAM_WINDOWS=.*/TEAM_WINDOWS=${NEW_WINDOWS}/" "${RUNTIME_DIR}/session.env" > "$TMPENV"
else
cat "${RUNTIME_DIR}/session.env" > "$TMPENV"
echo "TEAM_WINDOWS=${NEW_WINDOWS}" >> "$TMPENV"
fi
mv "$TMPENV" "${RUNTIME_DIR}/session.env"
while IFS='|' read -r _pane _role _agent _name _model; do
[ -z "$_pane" ] && continue
_model_flag=""
[ -n "$_model" ] && _model_flag="--model $_model"
_agent_flag=""
[ -n "$_agent" ] && _agent_flag="--agent \"$_agent\""
_cmd="claude --dangerously-skip-permissions ${_model_flag} --name \"T${NEW_WIN} ${_name}\" ${_agent_flag}"
source "$HOME/.local/bin/doey-send.sh" 2>/dev/null || true
doey_send_launch "${SESSION_NAME}:${NEW_WIN}.${_pane}" "$_cmd"
sleep 3
done << LAUNCH_INPUT
$(echo "$PANE_DEFS")
LAUNCH_INPUT
echo "All ${PANE_COUNT} Claude instances launched"
bash -c "
eval \"\$(sed -n '/^_env_val()/,/^}/p' '${PROJECT_DIR}/shell/doey.sh')\"
eval \"\$(sed -n '/^_layout_checksum()/,/^}/p' '${PROJECT_DIR}/shell/doey.sh')\"
eval \"\$(sed -n '/^rebalance_grid_layout()/,/^}/p' '${PROJECT_DIR}/shell/doey.sh')\"
rebalance_grid_layout '${SESSION_NAME}' '${NEW_WIN}' '${RUNTIME_DIR}'
"
if [ -n "$MANAGER_PANE_IDX" ]; then
sleep 8
MGR_PANE="${SESSION_NAME}:${NEW_WIN}.${MANAGER_PANE_IDX}"
BRIEFING=$(mktemp "${RUNTIME_DIR}/task_XXXXXX.txt")
cat > "$BRIEFING" << BRIEF_EOF
You are leading team "${TEAM_NAME}": ${TEAM_DESC}
Your panes (from ${TEAM_DEF}):
$(echo "$PANE_DEFS" | while IFS='|' read -r _p _r _a _n _m; do [ -n "$_p" ] && echo "- Pane $_p: $_n (role: $_r, agent: ${_a:-none}, model: $_m)"; done)
Workflows:
$(echo "$WORKFLOWS" | while IFS='|' read -r _t _f _to _s; do [ -n "$_t" ] && echo "- On $_t from $_f -> notify $_to (subject: $_s)"; done)
Coordinate your team. Dispatch initial tasks to workers based on the team definition.
BRIEF_EOF
source "$HOME/.local/bin/doey-send.sh" 2>/dev/null || true
BRIEFING_CONTENT=$(cat "$BRIEFING")
doey_send_verified "$MGR_PANE" "$BRIEFING_CONTENT" && echo "Subtaskmaster briefed" || echo "Subtaskmaster briefing delivery failed"
rm -f "$BRIEFING"
fi
sleep 5
NOT_READY=0; DOWN_PANES=""
while IFS='|' read -r _pane _role _agent _name _model; do
[ -z "$_pane" ] && continue
CHILD_PID=$(pgrep -P "$(tmux display-message -t "${SESSION_NAME}:${NEW_WIN}.${_pane}" -p '#{pane_pid}')" 2>/dev/null)
OUTPUT=$(tmux capture-pane -t "${SESSION_NAME}:${NEW_WIN}.${_pane}" -p 2>/dev/null)
if [ -z "$CHILD_PID" ] || ! echo "$OUTPUT" | grep -q "bypass permissions"; then
NOT_READY=$((NOT_READY + 1)); DOWN_PANES="$DOWN_PANES ${NEW_WIN}.$_pane"
fi
done << VERIFY_INPUT
$(echo "$PANE_DEFS")
VERIFY_INPUT
if [ "$NOT_READY" -eq 0 ]; then echo "All panes booted"; else echo "WARNING: ${NOT_READY} not ready:${DOWN_PANES}"; fi
Output: team name, window, layout, boot status. Teardown: /doey-kill-window ${NEW_WIN}. Bash 3.2. 3s stagger. Search: root → .doey/ → ~/.config/doey/teams/ → share. Missing ## Workflows = skip. Agent - = no flag.