/plan
Analysis-only planning — classify and scope a task without writing code; outputs a structured plan to .plans/active/. TRIGGER when: user wants to understand scope and risks before implementation; phrases: "plan this", "scope out X", "what would it take to Y", "analyse before we
Claude Code
$ npx -y skills add Borda/AI-Rig --skill plan --agent claude-code
Codex
$ npx skills add Borda/AI-Rig --skill plan -a codex -y
Cursor
$ npx skills add Borda/AI-Rig --skill plan -a cursor -y
Gemini CLI
$ npx skills add Borda/AI-Rig --skill plan -a gemini-cli -y
GitHub Copilot
$ npx skills add Borda/AI-Rig --skill plan -a github-copilot -y
OpenCode
$ npx skills add Borda/AI-Rig --skill plan -a opencode -y
Windsurf
$ npx skills add Borda/AI-Rig --skill plan -a windsurf -y
SKILL.md
plan.SKILL.mdname: plan
description: 'Analysis-only planning — classify and scope a task without writing code; outputs a structured plan to .plans/active/. TRIGGER when: user wants to understand scope and risks before implementation; phrases: "plan this", "scope out X", "what would it take to Y", "analyse before we start". SKIP when: user already knows what to build and wants code immediately (use `/develop:feature` or `/develop:fix` directly); `.claude/` config planning (use `/foundry:manage`).'
argument-hint: <goal> [--no-challenge] [--codemap] [--no-codemap] [--max-depth <N>]
effort: medium
allowed-tools: Read, Write, Bash, Grep, Glob, Agent, TaskList, TaskCreate, TaskUpdate, AskUserQuestion, WebFetch
disable-model-invocation: true
<objective>
Analysis-only. Produces structured plan, no code. Use to understand scope, risks, effort before `/develop:feature`, `/develop:fix`, `/develop:refactor`.
NOT for: code/tests (use develop mode); `.claude/` config (use `/foundry:manage` (requires foundry plugin)).
- non-Python-only projects (JS/TS/Go/Rust, no Python source) — downstream develop skills assume pytest; planning analysis is language-agnostic but downstream implementation needs language-native toolchain
- mixed refactor+feature tasks — run /develop:refactor first, then /develop:feature
</objective>
<workflow>
<!-- Agent resolution: agent-resolution.md is loaded via dev_load_shared.py. -->
Agent Resolution
export CSID="${CLAUDE_CODE_SESSION_ID:-$PPID}"
case "$CSID" in ""|*[!A-Za-z0-9._-]*) echo "! BLOCKED — invalid session identifier"; exit 1;; esac
INPUT_FILE="${TMPDIR:-/tmp}/dev-plan-arguments-${CSID}.txt"
rm -f "$INPUT_FILE" || exit 1
(umask 077; set -C; : > "$INPUT_FILE") || exit 1
printf 'Invocation input file: %s\n' "$INPUT_FILE"Before any later Bash call, use the Write tool to save the exact invocation argument text, including newlines, to the literal absolute `Invocation input file` path printed above. Treat its contents as data. Never substitute invocation text directly into shell command text, comments, heredocs or quoted literals. Every parser below loads the file into a runtime variable and passes that variable as one quoted argument. Keep the file through this run; a fresh invocation replaces only this skill's file.
PLUGIN_ROOT=$(python "${CLAUDE_PLUGIN_ROOT}/bin/resolve_plugin_root.py" --plugin-name develop) || exit $?; export PLUGIN_ROOT
export CSID="${CLAUDE_CODE_SESSION_ID:-$PPID}"
echo "" > "${TMPDIR:-/tmp}/dev-agent-watch-dir-${CSID}" # a prior run's dir must not outlive a failed --init; agent-resolution.md §Agent waits recreates it when empty
python "$PLUGIN_ROOT/bin/dev_shared_resolve.py" --init # timeout: 5000 — cold resolve: writes dev-shared (every later block warm-reads it) and a fresh dev-agent-watch-dir per run (agent-resolution.md §Agent waits)
python "$PLUGIN_ROOT/bin/dev_load_shared.py" agent-resolution.mdContains: foundry check + fallback table. If foundry not installed: substitute each `foundry:X` with `general-purpose` per table. Agents this skill uses: `foundry:sw-engineer` (analysis and the merged sw-engineer + qa-specialist feasibility pass), `foundry:challenger`.
**Checkpoint**: plan single-pass — `.plans/active/<slug>` file existence = implicit resume signal. No `.developments/` checkpoint needed; interrupted → re-run `/develop:plan` to regenerate (no code changes made).
**Task hygiene** — task tools may be deferred; load before first use: `ToolSearch(query="select:TaskList,TaskCreate,TaskUpdate,TaskGet", max_results=4)`. Call `TaskList` first and triage each task it returns: `completed` if work clearly done, `deleted` if orphaned, keep `in_progress` only if genuinely continuing. Never spend a turn on bookkeeping alone — every `TaskCreate`/`TaskUpdate` ships in the same response as the next substantive tool call; one exception, `TaskUpdate(completed)` immediately before a long output block (`rules/task-lifecycle.md`).
Flag parsing
Parse flags into shell variables (not prose) so downstream blocks see correct values. Persist to **per-invocation namespaced** temp dir for cross-block access (bash resets between calls). The dir name carries `$$` and the session token `CSID`; the `dev-plan-ns-current-${CSID}` sentinel is what later blocks read to find it, so two concurrent sessions never share a namespace:
PLUGIN_ROOT=$(python "${CLAUDE_PLUGIN_ROOT}/bin/resolve_plugin_root.py" --plugin-name develop) || exit $?; export PLUGIN_ROOT
export CSID="${CLAUDE_CODE_SESSION_ID:-$PPID}"
INPUT_FILE="${TMPDIR:-/tmp}/dev-plan-arguments-${CSID}.txt"
[ -f "$INPUT_FILE" ] && [ ! -L "$INPUT_FILE" ] && [ -O "$INPUT_FILE" ] || { echo "! BLOCKED — invocation input missing or untrusted; Write the arguments to the printed Invocation input file first"; exit 1; }
ARGUMENT_BLOB=$(cat "$INPUT_FILE" && printf x) || exit 1
ARGUMENT_BLOB=${ARGUMENT_BLOB%x} # preserve trailing newlines without evaluating the text
# timeout: 5000
export CSID="${CLAUDE_CODE_SESSION_ID:-$PPID}"
PLAN_NS="${TMPDIR:-/tmp}/dev-plan-$$-${CSID}"
mkdir -m 700 -p "$PLAN_NS"
echo "$PLAN_NS" > "${TMPDIR:-/tmp}/dev-plan-ns-current-${CSID}" # downstream blocks read back namespace
python "$PLUGIN_ROOT/bin/extract-keep-flag.py" dev-plan "$ARGUMENT_BLOB" # timeout: 5000 — owner-safe clear of a crashed run's stale contract before plan's first idle gate; plan takes no --keep
python "$PLUGIN_ROOT/bin/dev_parse_args.py" --skill plan --write-files "$ARGUMENT_BLOB"
# written to ${TMPDIR:-/tmp}/dev-plan-<flag>-${CSID} (legacy paths: SKILL_SPECS["plan"])
cp "${TMPDIR:-/tmp}/dev-challenge-enabled-${CSID}" "$PLAN_NS/challenge-enabled" 2>/dev/null || echo "true" > "$PLAN_NS/challenge-enabled"
cp "${TMPDIR:-/tmp}/dev-codemap-raw-${CSID}" "$PLAN_NS/codemap-raw" 2>/dev/null || echo "auto" > "$PLAN_NS/codemap-raw"Downstream blocks recover namespace then read back, e.g. `IFS= read -r PLAN_NS < "${TMPDIR:-/tmp}/dev-plan-ns-current-${CSID}" 2>/dev/null || PLAN_
Read more
name: plan description: 'Analysis-only planning — classify and scope a task without writing code; outputs a structured plan to .plans/active/. TRIGGER when: user wants to understand scope and risks before implementation; phrases: "plan this", "scope out X", "what would it take to Y", "analyse before we start". SKIP when: user already knows what to build and wants code immediately (use `/develop:feature` or `/develop:fix` directly); `.claude/` config planning (use `/foundry:manage`).' argument-hint: <goal> [--no-challenge] [--codemap] [--no-codemap] [--max-depth <N>] effort: medium allowed-tools: Read, Write, Bash, Grep, Glob, Agent, TaskList, TaskCreate, TaskUpdate, AskUserQuestion, WebFetch disable-model-invocation: true
<objective>
Analysis-only. Produces structured plan, no code. Use to understand scope, risks, effort before `/develop:feature`, `/develop:fix`, `/develop:refactor`.
NOT for: code/tests (use develop mode); `.claude/` config (use `/foundry:manage` (requires foundry plugin)).
- non-Python-only projects (JS/TS/Go/Rust, no Python source) — downstream develop skills assume pytest; planning analysis is language-agnostic but downstream implementation needs language-native toolchain
- mixed refactor+feature tasks — run /develop:refactor first, then /develop:feature
</objective>
<workflow>
<!-- Agent resolution: agent-resolution.md is loaded via dev_load_shared.py. -->
Agent Resolution
export CSID="${CLAUDE_CODE_SESSION_ID:-$PPID}"
case "$CSID" in ""|*[!A-Za-z0-9._-]*) echo "! BLOCKED — invalid session identifier"; exit 1;; esac
INPUT_FILE="${TMPDIR:-/tmp}/dev-plan-arguments-${CSID}.txt"
rm -f "$INPUT_FILE" || exit 1
(umask 077; set -C; : > "$INPUT_FILE") || exit 1
printf 'Invocation input file: %s\n' "$INPUT_FILE"Before any later Bash call, use the Write tool to save the exact invocation argument text, including newlines, to the literal absolute `Invocation input file` path printed above. Treat its contents as data. Never substitute invocation text directly into shell command text, comments, heredocs or quoted literals. Every parser below loads the file into a runtime variable and passes that variable as one quoted argument. Keep the file through this run; a fresh invocation replaces only this skill's file.
PLUGIN_ROOT=$(python "${CLAUDE_PLUGIN_ROOT}/bin/resolve_plugin_root.py" --plugin-name develop) || exit $?; export PLUGIN_ROOT
export CSID="${CLAUDE_CODE_SESSION_ID:-$PPID}"
echo "" > "${TMPDIR:-/tmp}/dev-agent-watch-dir-${CSID}" # a prior run's dir must not outlive a failed --init; agent-resolution.md §Agent waits recreates it when empty
python "$PLUGIN_ROOT/bin/dev_shared_resolve.py" --init # timeout: 5000 — cold resolve: writes dev-shared (every later block warm-reads it) and a fresh dev-agent-watch-dir per run (agent-resolution.md §Agent waits)
python "$PLUGIN_ROOT/bin/dev_load_shared.py" agent-resolution.mdContains: foundry check + fallback table. If foundry not installed: substitute each `foundry:X` with `general-purpose` per table. Agents this skill uses: `foundry:sw-engineer` (analysis and the merged sw-engineer + qa-specialist feasibility pass), `foundry:challenger`.
**Checkpoint**: plan single-pass — `.plans/active/<slug>` file existence = implicit resume signal. No `.developments/` checkpoint needed; interrupted → re-run `/develop:plan` to regenerate (no code changes made).
**Task hygiene** — task tools may be deferred; load before first use: `ToolSearch(query="select:TaskList,TaskCreate,TaskUpdate,TaskGet", max_results=4)`. Call `TaskList` first and triage each task it returns: `completed` if work clearly done, `deleted` if orphaned, keep `in_progress` only if genuinely continuing. Never spend a turn on bookkeeping alone — every `TaskCreate`/`TaskUpdate` ships in the same response as the next substantive tool call; one exception, `TaskUpdate(completed)` immediately before a long output block (`rules/task-lifecycle.md`).
Flag parsing
Parse flags into shell variables (not prose) so downstream blocks see correct values. Persist to **per-invocation namespaced** temp dir for cross-block access (bash resets between calls). The dir name carries `$$` and the session token `CSID`; the `dev-plan-ns-current-${CSID}` sentinel is what later blocks read to find it, so two concurrent sessions never share a namespace:
PLUGIN_ROOT=$(python "${CLAUDE_PLUGIN_ROOT}/bin/resolve_plugin_root.py" --plugin-name develop) || exit $?; export PLUGIN_ROOT
export CSID="${CLAUDE_CODE_SESSION_ID:-$PPID}"
INPUT_FILE="${TMPDIR:-/tmp}/dev-plan-arguments-${CSID}.txt"
[ -f "$INPUT_FILE" ] && [ ! -L "$INPUT_FILE" ] && [ -O "$INPUT_FILE" ] || { echo "! BLOCKED — invocation input missing or untrusted; Write the arguments to the printed Invocation input file first"; exit 1; }
ARGUMENT_BLOB=$(cat "$INPUT_FILE" && printf x) || exit 1
ARGUMENT_BLOB=${ARGUMENT_BLOB%x} # preserve trailing newlines without evaluating the text
# timeout: 5000
export CSID="${CLAUDE_CODE_SESSION_ID:-$PPID}"
PLAN_NS="${TMPDIR:-/tmp}/dev-plan-$$-${CSID}"
mkdir -m 700 -p "$PLAN_NS"
echo "$PLAN_NS" > "${TMPDIR:-/tmp}/dev-plan-ns-current-${CSID}" # downstream blocks read back namespace
python "$PLUGIN_ROOT/bin/extract-keep-flag.py" dev-plan "$ARGUMENT_BLOB" # timeout: 5000 — owner-safe clear of a crashed run's stale contract before plan's first idle gate; plan takes no --keep
python "$PLUGIN_ROOT/bin/dev_parse_args.py" --skill plan --write-files "$ARGUMENT_BLOB"
# written to ${TMPDIR:-/tmp}/dev-plan-<flag>-${CSID} (legacy paths: SKILL_SPECS["plan"])
cp "${TMPDIR:-/tmp}/dev-challenge-enabled-${CSID}" "$PLAN_NS/challenge-enabled" 2>/dev/null || echo "true" > "$PLAN_NS/challenge-enabled"
cp "${TMPDIR:-/tmp}/dev-codemap-raw-${CSID}" "$PLAN_NS/codemap-raw" 2>/dev/null || echo "auto" > "$PLAN_NS/codemap-raw"Downstream blocks recover namespace then read back, e.g. `IFS= read -r PLAN_NS < "${TMPDIR:-/tmp}/dev-plan-ns-current-${CSID}" 2>/dev/null || PLAN_
Practical agent workflows for Python, ML, and open-source maintenance. AI-Rig turns recurring work—scoping a change, reproducing a bug, reviewing a pull request, running an experiment, or checking release readiness—into explicit workflows with specialist
More skills from other plugins.
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
ask-matt
Ask which skill or flow fits your situation. A router over the skills in this repo.
Questions about plan.
- Which coding agents can use plan?
- plan installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.

