Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 59 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,17 +86,74 @@ scripts/squad-tmux-launch.sh /path/to/project --dry-run
It can:
- read project-local launcher config from `.squad/launcher.yaml`
- read a task brief from `.squad/run-task.md`
- or auto-discover the latest implementation plan + matching spec from `docs/superpowers/...`
- or use custom discovery globs from `.squad/launcher.yaml -> task_discovery`
- generate manager / inspector prompt files under `.squad/quickstart/`
- start a tiled `tmux` session and inject `/squad` commands into Claude panes
- start a tiled `tmux` session and inject `/squad` commands into the configured AI CLI panes
- optionally create an isolated git worktree before launching agents

Requirements:
- `tmux`
- `ruby` (used to parse `launcher.yaml`)
- `claude`
- the configured AI CLI commands (for example `claude`, `codex`, `gemini`, or `opencode`)

This launcher is intentionally separate from the core Rust CLI. Treat it as optional automation for people who want a repeatable multi-terminal workflow.

### Launcher client configuration

The launcher now supports a generic default client plus per-role overrides:

```yaml
runtime:
command: codex
args:
- --dangerously-bypass-approvals-and-sandbox

worker_command: claude
worker_args:
- --dangerously-skip-permissions
```

With that config:
- manager panes use `codex --dangerously-bypass-approvals-and-sandbox`
- worker panes use `claude --dangerously-skip-permissions`
- inspector panes fall back to the default `codex` command unless you override them separately

Supported runtime keys:
- `runtime.command` / `runtime.args`: default client command for all panes
- `runtime.manager_command` / `runtime.manager_args`
- `runtime.worker_command` / `runtime.worker_args`
- `runtime.inspector_command` / `runtime.inspector_args`

For backwards compatibility, `runtime.claude_command` and `runtime.claude_args` are still accepted as legacy aliases for the default client configuration.

### Launcher task discovery

Task sources are resolved in this order:

1. `--task-file <path>`
2. `<project>/.squad/run-task.md`
3. auto-discovery

Default auto-discovery looks for files named with a `YYYY-MM-DD-` date prefix:

- the newest `docs/superpowers/plans/YYYY-MM-DD-*-implementation.md`
- plus the newest matching `docs/superpowers/specs/YYYY-MM-DD-*-design.md`

If your repo uses a different layout or naming convention, configure it in `.squad/launcher.yaml`:

```yaml
task_discovery:
plan_globs:
- workitems/plans/*-plan.md
spec_globs:
- workitems/specifications/*-spec.md
plan_suffix: -plan.md
spec_suffix: -spec.md
```

`plan_globs` and `spec_globs` are resolved relative to the `project-dir` you pass to the launcher. With that config, the launcher will pick the newest matching plan, derive its topic from the filename, and attach the newest matching spec with the same topic slug.

## Usage Flow

```
Expand Down
61 changes: 59 additions & 2 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,17 +88,74 @@ scripts/squad-tmux-launch.sh /path/to/project --dry-run
它可以:
- 从 `.squad/launcher.yaml` 读取项目级启动配置
- 从 `.squad/run-task.md` 读取本次任务说明
- 或自动发现 `docs/superpowers/...` 下最新的 implementation plan 和匹配 spec
- 或通过 `.squad/launcher.yaml -> task_discovery` 使用自定义发现规则
- 在 `.squad/quickstart/` 下生成 manager / inspector prompt
- 启动平铺布局的 `tmux` 会话,并自动向 Claude pane 注入 `/squad` 命令
- 启动平铺布局的 `tmux` 会话,并自动向配置好的 AI CLI pane 注入 `/squad` 命令
- 在启动 agent 前可选地创建独立 git worktree

依赖:
- `tmux`
- `ruby`(用于解析 `launcher.yaml`)
- `claude`
- 你在配置里指定的 AI CLI 命令(例如 `claude`、`codex`、`gemini`、`opencode`)

这个启动器刻意保持在核心 Rust CLI 之外。它是给需要固定化多终端协作流程的用户准备的可选自动化能力。

### Launcher 客户端配置

Launcher 现在支持“通用默认客户端 + 角色级覆盖”:

```yaml
runtime:
command: codex
args:
- --dangerously-bypass-approvals-and-sandbox

worker_command: claude
worker_args:
- --dangerously-skip-permissions
```

上面的配置表示:
- manager pane 默认使用 `codex --dangerously-bypass-approvals-and-sandbox`
- worker pane 使用 `claude --dangerously-skip-permissions`
- inspector pane 如果没有单独覆盖,则继续继承默认的 `codex`

支持的运行时字段:
- `runtime.command` / `runtime.args`:所有 pane 的默认客户端命令
- `runtime.manager_command` / `runtime.manager_args`
- `runtime.worker_command` / `runtime.worker_args`
- `runtime.inspector_command` / `runtime.inspector_args`

为了向后兼容,`runtime.claude_command` 和 `runtime.claude_args` 仍然可用,并会被当作默认客户端配置的旧别名。

### Launcher 任务发现规则

任务输入按下面的优先级解析:

1. `--task-file <path>`
2. `<project>/.squad/run-task.md`
3. 自动发现

默认的自动发现规则会寻找:

- 最新的 `docs/superpowers/plans/????-??-??-*-implementation.md`(文件名需以 `YYYY-MM-DD-` 日期前缀开头)
- 以及同主题、最新匹配的 `docs/superpowers/specs/????-??-??-*-design.md`(同样要求 `YYYY-MM-DD-` 前缀)

如果你的仓库目录或命名规则不同,可以在 `.squad/launcher.yaml` 里配置:

```yaml
task_discovery:
plan_globs:
- workitems/plans/*-plan.md
spec_globs:
- workitems/specifications/*-spec.md
plan_suffix: -plan.md
spec_suffix: -spec.md
```

`plan_globs` 和 `spec_globs` 都是相对于你传入的 `project-dir` 解析的。配置后,launcher 会选出最新的 plan,从文件名里提取 topic,再自动附带同一 topic 的最新 spec。

## 使用流程

```
Expand Down
39 changes: 39 additions & 0 deletions scripts/lib/squad-tmux-launcher-helpers.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ shell_join() {
printf '%s' "$joined"
}

expand_home_path() {
local path="$1"
if [[ "$path" == "~" ]]; then
path="$HOME"
elif [[ "${path:0:2}" == "~/" ]]; then
path="$HOME/${path:2}"
fi
printf '%s' "$path"
}

pane_command_candidates() {
local command_name="$1"
local resolved=""
Expand Down Expand Up @@ -170,6 +180,35 @@ path_is_within() {
[[ "$path" == "$base" || "$path" == "$base"/* ]]
}

pane_capture_has_workspace_trust_prompt() {
local capture="$1"
[[ "$capture" == *"Yes, I trust this folder"* ]] && [[ "$capture" == *"Enter to confirm"* ]]
}

pane_capture_has_interactive_prompt() {
local capture="$1"
[[ "$capture" == *"❯"* || "$capture" == *"›"* ]]
}

pane_capture_has_pending_command_input() {
local capture="$1"
local command_text="$2"
[[ -n "$command_text" ]] || return 1
[[ "$capture" == *"❯"*"$command_text"* ]]
}

pane_capture_has_squad_command_activity() {
local capture="$1"
case "$capture" in
*"Skill(/squad)"*|*"Bash(squad "*|*"Joined as "*|*"joining the squad"*|*"I'm joining the squad"*|*"I'll join the squad"*|*"No agents online."*|*"Initialized squad workspace."*)
return 0
;;
*)
return 1
;;
esac
}

ensure_repo_local_worktree_ignored() {
local repo_root="$1"
local path="$2"
Expand Down
Loading
Loading