Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Create or maintain `STRATEGY.md` — the product's target problem, our approach, who it's for, key metrics, and tracks of work. Use when starting a new product, updating direction, or when prompts like 'write our strategy', 'update the roadmap', 'what are we working on', or 'set up the strategy doc' come up. Also fires when `/flow-next:prospect`, `/flow-next:plan`, `/flow-next:interview`, or `/flow-next:capture` need upstream grounding and no strategy doc exists yet.
.claude/skills/gmickel-flow-next-strategy/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-09 | ✗→✓ | ▲ Improved | 162% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 96% | 0% |
| case-13 | ✗→✓ | ▲ Improved | 169% | 0% |
| case-14 | ✗→✓ | ▲ Improved | 101% | 0% |
| case-18 | ✗→✓ | ▲ Improved | 237% | 0% |
flow-next-strategy produces and maintains STRATEGY.md — a short, durable anchor at the repo root (peer of README.md / GLOSSARY.md) that captures what the product is, who it serves, how it succeeds, and where the team is investing. Downstream skills (/flow-next:prospect, /flow-next:plan, /flow-next:interview, /flow-next:capture, /flow-next:sync) read it as grounding when sections_filled >= 1.
The document is short and structured on purpose. Good answers to a handful of sharp questions produce a better strategy than any amount of prose. This skill asks those questions, pushes back on weak answers, and writes the doc.
Note: The current year is 2026. Use this when dating the strategy document.
flowctl is bundled — NOT installed globally. which flowctl will fail (expected). Define once; subsequent blocks use $FLOWCTL:
bashFLOWCTL="${CODEX_HOME:-$HOME/.codex}/scripts/flowctl" [ -x "$FLOWCTL" ] || FLOWCTL="<plugin-root>/scripts/flowctl" # <plugin-root> = the directory two levels above this skill's SKILL.md file (the harness gave you that file's absolute path when the skill loaded); substitute it literally [ -x "$FLOWCTL" ] || FLOWCTL=".flow/bin/flowctl"
Ask the user via plain text. Render the options below as a numbered list 1. … N., followed by a final option N+1. Other — type your own answer. Print the question, then the numbered list, then stop and wait for the user's next message before continuing. Parse the reply as: a bare number 1–N+1 → that option; the literal text of an option label → that option; free text after Other → custom answer.
Default to plain-text numbered prompt. Never silently skip the question.
Ask one question at a time. Free-form responses for the substantive sections (Target problem / Our approach / Who it's for / Key metrics / Tracks). Single-select with lead-with-recommendation only for routing decisions (which section to revisit, include this optional section, foreign-file resolution).
<focus_hint> #$ARGUMENTS </focus_hint>
Interpret any argument as an optional focus: a section name to revisit (metrics, approach, tracks, problem, persona, milestones, not-working-on) or a scope hint. With no argument, proceed open-ended and let the file state decide the path.
/flow-next:prospect; tasks belong in specs and /flow-next:plan. Do not let either creep into the doc.references/interview.md)..flow/ wipe. STRATEGY.md lives at repo root, never under .flow/. The project's strategy belongs to the project, not flow-next (R18 invariant from the 0.39.0 glossary epic).0.1 — Ralph block (R17)
/flow-next:strategy is exploratory and human-in-the-loop. Autonomous loops have no business deciding repo strategy. Hard-error with exit 2 when running under Ralph.
bashif [[ -n "${REVIEW_RECEIPT_PATH:-}" || "${FLOW_RALPH:-}" == "1" ]]; then echo "[STRATEGY: user-triggered only — Ralph cannot run /flow-next:strategy]" >&2 exit 2 fi
No env-var opt-in. Ralph never decides direction.
0.2 — Read file state
bashSTATUS_JSON=$("$FLOWCTL" strategy status --json 2>/dev/null) || STATUS_JSON= if ! printf '%s' "$STATUS_JSON" | jq -e ' type == "object" and (.exists | type == "boolean") and (.husk | type == "boolean") and (.sections_filled as $n | ($n | type) == "number" and ($n | floor) == $n and $n >= 0 and $n <= 7) and (.total_sections as $n | ($n | type) == "number" and ($n | floor) == $n and $n >= 5 and $n <= 7) and (.sections_filled <= .total_sections) and (.last_updated == null or (.last_updated | type == "string")) and (.file_path == null or (.file_path | type == "string")) and (.generator == null or (.generator | type == "string")) and (.generator_match | type == "boolean") and (.husk == ((.exists == true) and (.sections_filled == 0))) and (.generator_match == (.generator == "flow-next-strategy")) ' >/dev/null 2>&1; then echo "[STRATEGY: unable to classify STRATEGY.md safely — leaving it unchanged]" >&2 exit 0 fi EXISTS=$(printf '%s' "$STATUS_JSON" | jq -r '.exists') HUSK=$(printf '%s' "$STATUS_JSON" | jq -r '.husk') SECTIONS_FILLED=$(printf '%s' "$STATUS_JSON" | jq -r '.sections_filled') GENERATOR_MATCH=$(printf '%s' "$STATUS_JSON" | jq -r '.generator_match') FILE_PATH=$(printf '%s' "$STATUS_JSON" | jq -r '.file_path // empty')
JSON fields (frozen by Task 1):
exists (bool) — file presenthusk (bool) — exists: true AND sections_filled == 0sections_filled (int) — populated required + included optional-section count (0-7)total_sections (int) — 5 required + populated optional sections (5-7)last_updated (str|null) — ISO date from frontmatterfile_path (str|null) — absolute path of resolved STRATEGY.mdgenerator (str|null) — frontmatter generator valuegenerator_match (bool) — generator == "flow-next-strategy"0.3 — Subdirectory walk-up surfacing (R16)
If file_path is set and differs from ${PWD}/STRATEGY.md, surface one line in chat before any question fires:
Using repo-root STRATEGY.md at <file_path>.This is the only line printed before routing — keep the noise floor low.
0.4 — Foreign-file resolution (R15)
If exists: true AND generator_match: false, do not write. Fire plain-text numbered prompt:
body: "Found a STRATEGY.md at <file_path> not generated by flow-next-strategy (generator: <generator or "missing">). Recommended: keep — do not overwrite a hand-written or external-tool strategy doc. Confidence: your-call] — your project, your call."options:keep → exit 0 with one-line stdout: Keeping existing STRATEGY.md unchanged.migrate → exit 0 with stderr: Multi-format migration deferred to v2. Either delete or rename the file, then re-run /flow-next:strategy to bootstrap from scratch.rewrite → second confirmation plain-text numbered prompt:body: "Confirm destructive overwrite? The existing file at <file_path> will be replaced. Recommended: cancel. Confidence: your-call]."options: confirm-overwrite → proceed to Phase 1 first-run interview; cancel → exit 0.Single-select plain-text numbered prompt, lead-with-recommendation, neutral option labels.
0.5 — Routing
After Ralph block, walk-up surfacing, and foreign-file resolution:
| State | Route | |-------|-------| | exists: false | Phase 1 (first-run interview) | | exists: true AND husk: true AND generator_match: true | Phase 1 (first-run; husk was probably an aborted run) | | exists: true AND husk: false AND generator_match: true | Phase 2 (section-revisit update) |
Announce the selected path, then load exactly one direct workflow reference:
Strategy doc not found — let's write it., then read and follow references/first-run.md.Found existing strategy — let's review and update., then read and follow references/update.md.Do not read the unselected workflow. A foreign file stays entirely in Phase 0.4 unless the user confirms rewrite; confirmed rewrite selects the first-run workflow. Any state not matched by the table is unsafe to classify: leave the file unchanged and exit 0 with the same safe-classification stderr line from Phase 0.2.
Done when: the Ralph guard has passed, STATUS_JSON has validated, the selected path was announced, and exactly one of references/first-run.md / references/update.md has been read — or the run exited 0 leaving STRATEGY.md untouched.
After writing (first-run or update), surface the file's role to the user in one paragraph:
.flow/specs/ is empty (and any legacy .flow/epics/ is also empty) AND .flow/prospects/ is empty: Strategy doc written. Next, /flow-next:prospect [optional focus] generates ranked candidate ideas grounded in the strategy you just captured..flow/ is populated: Strategy doc written. Downstream skills (/flow-next:prospect, /flow-next:plan, /flow-next:interview, /flow-next:capture, /flow-next:sync) will read STRATEGY.md as grounding on next invocation.One paragraph max. No follow-up questions.
Done when: STRATEGY.md is on disk at the repo root with the sections the interview filled, and exactly one handoff paragraph has been surfaced — nothing else printed at exit.
/flow-next:plan./flow-next:capture and /flow-next:plan.# <name> Strategy H1 + frontmatter) on disk — file never deleted (R23 invariant, mirrors render_glossary_file).context: fork — plain-text numbered prompt must stay reachable across phases.vanity / fluff / feature-list / goal-stated-as-problem are internal labels for formulating sharper follow-ups.references/strategy-template.md catches this.Marketing section is dropped on purpose; do not re-introduce it. Section order is locked."$FLOWCTL" strategy {status,read} only. The skill writes the file directly via Write; no strategy add/list command exists.The deliverable is the written STRATEGY.md itself. Surface to chat:
No internal summary printed at exit beyond the Phase 3 handoff line. The file IS the report.
Other measured skills in the registry, with their headline benchmark lift.