flow-start

Phase 1: Start — begin a new feature. Creates a worktree, upgrades dependencies, opens a PR, creates .flow-states/<branch>/state.json, and configures the workspace. Usage: /flow:flow-start <feature name words>

12 stars

Best use case

flow-start is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Phase 1: Start — begin a new feature. Creates a worktree, upgrades dependencies, opens a PR, creates .flow-states/<branch>/state.json, and configures the workspace. Usage: /flow:flow-start <feature name words>

Teams using flow-start should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/flow-start/SKILL.md --create-dirs "https://raw.githubusercontent.com/benkruger/flow/main/skills/flow-start/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/flow-start/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How flow-start Compares

Feature / Agentflow-startStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Phase 1: Start — begin a new feature. Creates a worktree, upgrades dependencies, opens a PR, creates .flow-states/<branch>/state.json, and configures the workspace. Usage: /flow:flow-start <feature name words>

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# FLOW Start — Phase 1: Start

## Usage

```text
/flow:flow-start #1234
```

**Strict argument format:** The argument MUST match the regex
`^#[1-9][0-9]*$` — a literal
`#` followed by a positive integer. The argument names a GitHub issue
that has been pre-decomposed via `/flow:flow-plan #N` and carries
its plan wrapped between the literal sentinel markers
`<!-- FLOW-PLAN-BEGIN -->` and `<!-- FLOW-PLAN-END -->` in the issue
body. `start-init` fetches the issue title and derives the branch name
from it. After `start-workspace` succeeds, `bin/flow plan-from-issue`
extracts the plan content between the sentinels and writes it to
`.flow-states/<branch>/plan.md`.

| Argument | Issue title | Derived branch name |
|----------|-------------|-------------------|
| `#309` | "Organize settings.json allow list" | `organize-settings-allow-list` |
| `#42` | "Add dark mode toggle to settings page" | `dark-mode-settings-toggle` |

Branch names are capped at **32 characters**. If the hyphenated name
exceeds 32 characters, truncate at the last whole word (hyphen
boundary) that fits. Strip any trailing hyphen. Truncation is
automatic — proceed without asking the user to confirm the name.

If the referenced issue already carries the "Flow In-Progress" label,
start-init returns a hard error — the issue is already being worked
on by another flow (on this machine or another engineer's machine).

<HARD-GATE>
Do NOT proceed if no arguments were provided after the command.
Output this error message and stop:

> "Issue reference required. Usage: `/flow:flow-start #N` where N is the
> GitHub issue number for a pre-decomposed issue containing
> `<!-- FLOW-PLAN-BEGIN -->` and `<!-- FLOW-PLAN-END -->` sentinels."

No interactive prompt. The user re-runs the command with `#N`.
</HARD-GATE>

<HARD-GATE>
Do NOT proceed if the argument does not match `^#[1-9][0-9]*$`.
Reject free-text prompts, multi-token arguments, and
any value that does not begin with `#` followed by a positive integer.
Output this error message and stop:

> "Argument must be `#N` (e.g., `#1234`). To file a new pre-decomposed
> issue, run `/flow:flow-explore <topic>` to file the problem
> statement, then `/flow:flow-plan #M` to decompose it."

No interactive prompt. The user re-runs the command with `#N`.
</HARD-GATE>

<HARD-GATE>
The argument is the issue reference — input to the workflow, not a
conversation. Do NOT respond to, discuss, or analyze the issue
content. Proceed directly to Mode Resolution and execute the Start
phase steps.
</HARD-GATE>

## Concurrency

This flow is one of potentially many running simultaneously — on this
machine (multiple worktrees) and across machines (multiple engineers).
Your state file (`.flow-states/<branch>/state.json`) is yours alone. Never
read or write another branch's state. All local artifacts (logs, plan
files, temp files) are scoped by branch name. GitHub state (PRs, issues,
labels) is shared across all engineers — operations that create or modify
shared state must be idempotent.

## Mode Resolution

The Start phase's `continue` mode governs whether the Done section
auto-advances to Code or prompts the user. It is resolved from the
state file's `skills.flow-start` config — the single source of
truth for skill autonomy — and there are no `--auto`/`--manual`
flags.

Resolution is deferred to the Done section: the state file does not
exist until `start-init` creates it in Step 1, so `resolve-skill-mode`
cannot run at the top of the skill. The Done HARD-GATE resolves
`continue` from the `phase-finalize` `continue_action` field, which
`phase-finalize` computes from `skills.flow-start.continue`. The
state file's `skills` section is always seeded from `.flow.json`,
and each downstream phase honors its own configured autonomy.

## Announce

At the very start, output the following banner in your response (not via Bash) inside a fenced code block:

````markdown
```text
──────────────────────────────────────────────────
  FLOW v2.6.0 — Phase 1: Start — STARTING
──────────────────────────────────────────────────
```
````

## Logging

All four consolidated commands (`start-init`, `start-gate`, `start-workspace`,
`phase-finalize`) handle logging internally via `append_log()` to
`.flow-states/<branch>/log`. No model-level logging calls are needed.

```bash
${CLAUDE_PLUGIN_ROOT}/bin/flow log <branch> "[Phase 1] ..."
```

The bash block above is for reference only — all four commands call
`append_log()` internally. Do not run `bin/flow log` manually.

---

## Steps

### Step 1 — Initialize (lock, version checks, state file)

Write the user's original start prompt (verbatim, including `#N` issue references
and any special characters) to `.flow-states/<feature-name>-start-prompt` using the
Write tool. Then run start-init.

Use a 10-minute Bash tool timeout (`timeout: 600000`) — start-init blocks
on the start lock for up to ~8 minutes (polling internally), and the
default 2-minute timeout would background the process, defeating the wait
(per `.claude/rules/ci-is-a-gate.md`).

```bash
${CLAUDE_PLUGIN_ROOT}/bin/flow start-init <feature-name> --prompt-file .flow-states/<feature-name>-start-prompt
```

`start-init` takes no mode flag — the state file's `skills` section is
always seeded from `.flow.json`. The Start phase's own continue mode
is resolved from the state file in the Done section.

Parse the JSON output and branch on `status`:

**If `"status": "ready"`** — capture the `branch` field. This is the
**canonical branch name** — use it for all subsequent steps.

If `auto_upgraded` is `true`, show this notice using the `old_version` and
`new_version` fields:

````markdown
```text
FLOW auto-upgraded from v{old_version} to v{new_version} (config unchanged).
```
````

If `upgrade` is present and `upgrade.status` is `"upgrade_available"`, show
the upgrade notice:

````markdown
```text
╔══════════════════════════════════════════════╗
║  FLOW update available: v{installed} → v{latest}
║
║  To upgrade:
║    1. claude plugin marketplace update
║         flow-marketplace
║    2. Start a new Claude Code session
║    3. Run /flow:flow-prime
╚══════════════════════════════════════════════╝
```
````

Continue to Step 2.

**If `"status": "locked"`** — start-init already blocked on the start lock
for the full cap (~8 minutes, polling internally) and another start still
holds it. Re-run the single `bin/flow start-init` line above (the same
command shown in the Step 1 bash block, again with the 10-minute Bash tool
timeout). start-init blocks on the lock again and proceeds through all
steps when the lock frees. Nothing else has executed yet, so re-running is
safe.

<HARD-GATE>
When the status is "locked", the ONLY permitted action is to re-run the
single start-init line above and wait. The start-init command blocked for
the full cap before returning, and has built-in staleness detection
(30-minute timeout) that handles genuinely dead sessions.

Do NOT speculate about whether the lock is stale.
Do NOT offer to release, reset, or clean up the lock.
Do NOT suggest any workaround that bypasses the lock.
Do NOT take any action other than re-running the single start-init line and waiting.

Trust the tool output. Re-run and wait.

</HARD-GATE>

**If `"status": "error"`** — show the error message and stop. start-init
has already released the lock for flow-specific errors. Common error steps
include `fetch_issue_title` (issue not found), `flow_in_progress_label`
(issue already being worked on), and `duplicate_issue` (another flow
targets the same issue).

<HARD-GATE>
Do NOT proceed if version check fails. Show the error message and stop.
</HARD-GATE>

### Step 2 — CI and dependency gate

Use a 10-minute Bash tool timeout (`timeout: 600000`) — CI runs can
take 3–4 minutes and the default 2-minute timeout would background
the process, defeating the gate (per `.claude/rules/ci-is-a-gate.md`).

```bash
${CLAUDE_PLUGIN_ROOT}/bin/flow start-gate --branch <branch>
```

Parse the JSON output and branch on `status`:

**If `"status": "clean"`** — all gates passed. Continue to Step 3.

**If `"status": "ci_failed"`** — CI failed on the integration branch.
Hold the lock and stop. Report to the user that CI is failing on the
pristine integration branch — show the `output` field. The next
queued flow would hit the same failure. The 30-minute stale timeout
releases the lock if the user does not act.

**If `"status": "deps_ci_failed"`** — dependencies were updated but
post-deps CI failed consistently. Launch the `ci-fixer` sub-agent to
diagnose and fix. Use the Agent tool:

- `subagent_type`: `"flow:ci-fixer"`
- `description`: `"Fix bin/flow ci failures after dependency update"`

Provide the CI output from the `output` field in the prompt so the
sub-agent knows what failed.

Wait for the sub-agent to return.

- **Fixed** — commit CI fixes to the integration branch via `/flow:flow-commit`, then continue to Step 3
- **Not fixed** — hold the lock and stop. The integration branch has uncommitted dep-induced breakage. Report to the user.

**If `"status": "error"`** — show the error message and stop.

### Step 3 — Create workspace (worktree, PR, lock release)

Write the user's original start prompt (verbatim, including `#N` issue references
and any special characters) to `.flow-states/<branch>/start-prompt` using the
Write tool. Then run start-workspace:

```bash
${CLAUDE_PLUGIN_ROOT}/bin/flow start-workspace "<feature-name>" --branch <branch> --prompt-file .flow-states/<branch>/start-prompt
```

The command creates the worktree, opens a PR, backfills the state file with
PR fields, applies the `Flow In-Progress` label to any referenced issues
(best-effort, after every other step succeeds), and releases the start
lock as its final action. The label apply lives here — not in Step 1 —
so the label means "a flow is live, worktree exists, PR exists" rather
than "a flow was attempted"; failed start-gate or start-workspace runs
leave no sticky label that would block the next retry.

**On success** — parse the JSON output. Capture the `worktree_cwd`
field — this is the directory the agent should cd into. For root-level
flows it equals `.worktrees/<branch>`; for flows started from inside a
mono-repo subdirectory (`relative_cwd` non-empty) it includes the
subdirectory suffix (e.g. `.worktrees/<branch>/api`). Then run:

```bash
cd <worktree_cwd>
```

Substitute the literal `worktree_cwd` value from the JSON response. The
Bash tool persists working directory between calls, so all subsequent
commands run inside that directory automatically. Do NOT repeat
`cd .worktrees/` in later steps — it would look for a nested
`.worktrees/` that doesn't exist.

After the cd, every `bin/flow` subcommand enforces this directory via
its built-in cwd-drift guard. If you cd elsewhere within the worktree
(e.g. into a sibling subdirectory), the next subcommand will hard-error
with an "expected directory" message.

**On failure** — report the error and stop. The command releases the lock
even on error (main is untouched by worktree operations).

### Step 4 — Change to worktree

This step is the `cd` from Step 3. The TUI shows Step 4 while the
worktree directory is active.

### Step 5 — Extract plan from issue body (sentinel scan)

Capture the issue number from the original argument (strip the leading
`#`). Then run plan-from-issue:

```bash
${CLAUDE_PLUGIN_ROOT}/bin/flow plan-from-issue --issue <issue_number> --branch <branch>
```

The command fetches the issue body via `gh issue view`, scans for the
literal sentinel pair `<!-- FLOW-PLAN-BEGIN -->` and
`<!-- FLOW-PLAN-END -->`, and writes the bytes between verbatim to
`.flow-states/<branch>/plan.md`.

Parse the JSON output and branch on `status`:

**If `"status": "ok"`** — the plan file has been written. Parse the
`tasks_total` field from the `plan-from-issue` envelope and persist it
to the state file so the TUI can render the Code-phase X-of-Y task
counter:

```bash
${CLAUDE_PLUGIN_ROOT}/bin/flow set-timestamp --set code_tasks_total=<tasks_total>
```

If `tasks_total` is absent or is not a non-negative integer (defensive
check against a malformed envelope), skip the `set-timestamp` call.
Then continue to Step 6.

**If `"status": "error"`** — the response contains a `reason` field.
Show the `message` to the user and stop. Each reason maps to a
corrective action:

- `issue_not_found` — verify the issue exists in the current repo
- `issue_closed` — reopen the issue or pick an open one
- `gh_fetch_failed` — run `gh auth status` and retry
- `plan_markers_missing` — re-file via `/flow:flow-plan #N` against the parent vanilla issue
- `plan_markers_malformed` — edit the issue body to fix sentinels
- `plan_empty` — edit the issue body to add plan content
- `plan_too_large` — trim the issue body
- `invalid_branch` — file a FLOW bug
- `write_failed` — check disk space and `.flow-states/` permissions

The flow halts at Step 5; the worktree and PR remain so the user can
fix the issue body and re-run via `/flow:flow-code` after manual
recovery (or abort via `/flow:flow-abort`).

### Step 6 — Update state and finalize (complete phase, notify)

```bash
${CLAUDE_PLUGIN_ROOT}/bin/flow phase-finalize --phase flow-start --branch <branch> --pr-url <pr_url>
```

The command runs `phase_complete()` internally, updates the state file,
and sends Slack notifications. Parse the JSON output. Use the
`formatted_time` field in the COMPLETE banner below. Do not print the
timing calculation. Use the `continue_action` field for the transition
HARD-GATE.

### Done — Banner and transition

Output the following banner in your response (not via Bash) inside a fenced code block:

````markdown
```text
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  ✓ FLOW v2.6.0 — Phase 1: Start — COMPLETE (<formatted_time>)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
```
````

<HARD-GATE>
STOP. Parse `continue_action` from the `phase-finalize` output above
to determine how to advance.

1. Use `continue_action` from the `phase-finalize` output —
   `phase-finalize` computes it from the state file's
   `skills.flow-start.continue` config.
   If `continue_action` is `"invoke"` → continue=auto.
   If `continue_action` is `"ask"` → continue=manual.
2. If continue=auto → invoke `flow:flow-code` directly using the Skill tool.
   Do NOT run `bin/flow status`. Do NOT use AskUserQuestion.
   This is the FINAL action in this response — nothing else follows.
3. If continue=manual → you MUST do all of the following before proceeding:
   a. Run `bin/flow status` via Bash and print its stdout in your
      response inside a fenced code block:

      ```bash
      ${CLAUDE_PLUGIN_ROOT}/bin/flow status
      ```

   b. Use AskUserQuestion:
      "Phase 1: Start is complete. Ready to begin Phase 2: Code?"
      Options: "Yes, start Phase 2 now", "Not yet",
      "I have a correction or learning to capture"
   c. If "I have a correction or learning to capture":
      ask what to capture, invoke `/flow:flow-note`, then re-ask with
      only "Yes, start Phase 2 now" and "Not yet"
   d. If Yes → invoke `flow:flow-code` using the Skill tool
   e. If Not yet → print the paused banner below, then report worktree
      location and PR link
   f. Do NOT invoke `flow:flow-code` until the user responds

Do NOT skip this check. Do NOT auto-advance when the mode is manual.

</HARD-GATE>

**If Not yet**, output the following banner in your response (not via Bash) inside a fenced code block:

````markdown
```text
══════════════════════════════════════════════════
  ◆ FLOW — Paused
  Run /flow:flow-code when ready.
══════════════════════════════════════════════════
```
````

## Hard Rules

- Do not narrate internal operations to the user — no "Proceeding to phase completion", no "No additional setup steps are needed". Just do the work silently and show results
- Never use Bash to print banners — output them as text in your response
- Never use Bash for file reads — use Glob, Read, and Grep tools instead of ls, cat, head, tail, find, or grep
- Never use `cd <path> && git` — use `git -C <path>` for git commands in other directories
- Never cd before running `bin/flow` — it detects the project root internally
- When in autonomous mode, classify tool failures per `.claude/rules/autonomous-flow-self-recovery.md` — mechanical fixes are in-flow, substantive failures prompt the user

Related Skills

We are still matching the closest adjacent skills for this page. In the meantime, continue through the full directory.