From task
Structured task execution: plan, external analysis, approval, implement, quality control, present. Use /do <task description> for any feature, bug fix, or task. Also manages provider/model config via /do config.
npx claudepluginhub manaporkun/claude-plugins --plugin taskThis skill uses the workspace's default tool permissions.
Execute the following phases strictly in order. Do not skip phases.
Provides Ktor server patterns for routing DSL, plugins (auth, CORS, serialization), Koin DI, WebSockets, services, and testApplication testing.
Conducts multi-source web research with firecrawl and exa MCPs: searches, scrapes pages, synthesizes cited reports. For deep dives, competitive analysis, tech evaluations, or due diligence.
Provides demand forecasting, safety stock optimization, replenishment planning, and promotional lift estimation for multi-location retailers managing 300-800 SKUs.
Execute the following phases strictly in order. Do not skip phases. Present output to the user at each checkpoint marked with STOP.
If $ARGUMENTS starts with config: strip config from the start of $ARGUMENTS (trim remaining whitespace) and jump to the Config Management section. Do not run any phases.
If $ARGUMENTS contains --continue: strip --continue from arguments, then:
ls .claude/plans/*.md 2>/dev/null.claude/plans/." and STOP.<filename>"If $ARGUMENTS contains --refresh-env: run rm ~/.claude/do-env.json 2>/dev/null, then strip --refresh-env from the task description before proceeding.
If $ARGUMENTS is empty or contains only whitespace (after stripping flags):
Usage: /do <task description> — plan and implement a task
/do config — view and change provider/model settings
Before starting Phase 1, detect available agents and project context.
Agent availability is cached at ~/.claude/do-env.json to avoid redundant which checks on every invocation.
If $ARGUMENTS contains --refresh-env: run rm ~/.claude/do-env.json 2>/dev/null, then strip --refresh-env from the task description before proceeding.
cat ~/.claude/do-env.json 2>/dev/null || trueagents array and ollamaModels array from the cacheagents is non-empty): for CLI-based agents (gemini, codex, ollama, claude, aider, copilot), run which <agent> 2>/dev/null to confirm it's still installed. For openrouter, check [ -n "${OPENROUTER_API_KEY:-}" ]. For openai, check [ -n "${OPENAI_API_KEY:-}${OPENAI_COMPATIBLE_API_KEY:-}" ]. If validation fails for the first agent in the list or agents is empty, discard cache and proceed to step 3.for cmd in gemini codex ollama claude aider copilot; do which $cmd 2>/dev/null && echo "$cmd: found" || echo "$cmd: not found"; done[ -n "${OPENROUTER_API_KEY:-}" ] && echo "openrouter: found" || echo "openrouter: not found"[ -n "${OPENAI_API_KEY:-}${OPENAI_COMPATIBLE_API_KEY:-}" ] && echo "openai: found" || echo "openai: not found"ollama list 2>/dev/null~/.claude/do-env.json with this structure:
{ "agents": ["gemini", "codex", "claude", "aider", "openrouter", "openai", "copilot"], "ollamaModels": ["qwen2.5-coder"], "detectedAt": "2026-03-22T14:25:00Z" }
Use only the agent names that were found. Use the Bash tool to write the file, e.g.:
sh -c 'echo "{\"agents\":[\"gemini\",\"codex\",\"claude\",\"aider\",\"openrouter\",\"openai\"],\"ollamaModels\":[],\"detectedAt\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"}" > ~/.claude/do-env.json'Run uname -s to record the platform (e.g. Darwin or Linux). This informs command compatibility (e.g. mktemp behavior, available utilities).
These are project-specific and must be checked every time:
cat .claude/do-config.json 2>/dev/null || truesh -c 'ls -1 package.json Podfile *.xcodeproj pyproject.toml requirements.txt go.mod Cargo.toml Makefile 2>/dev/null || echo "no project files"'Record which agents are available and proceed. If no external agents are found, skip external review phases.
If .claude/do-config.json exists, validate and use its values:
configVersion must be 1 if present (reserved for future schema changes). If missing, default to 1.agents must be an object with array values (e.g. {"planReview": [...], "codeReview": [...]}), not a bare string or array"gemini", "codex", "ollama:<model>", "openrouter", "openrouter:<model>", "claude", "aider", "openai", "openai:<model>", "copilot", or "copilot:<model>"maxIterations and maxCodeReviewIterations must be positive integers if presentskipReviewThreshold must be an object with maxFiles and maxSteps as positive integers if presentSchema:
{
"configVersion": 1,
"agents": {
"planReview": ["ollama:qwen2.5-coder", "gemini"],
"codeReview": ["gemini", "codex"]
},
"agentCommands": {
"gemini": "cat {file} | gemini -p \"Review the content provided via stdin. Respond in plain text.\" -o text",
"codex": "cat {file} | codex exec --json -",
"ollama": "cat {file} | ollama run {model}",
"openrouter": "${CLAUDE_SKILL_DIR}/scripts/openrouter.sh {file} {model}",
"claude": "cat {file} | claude -p --bare --output-format text --allowedTools \"Read\"",
"aider": "aider --no-auto-commits --no-git --dry-run --yes --message-file {file}",
"openai": "${CLAUDE_SKILL_DIR}/scripts/openai-compatible.sh {file} {model}",
"copilot": "copilot -p \"$(cat {file})\" -s --allow-all-tools"
},
"qc": {
"test": "npm test",
"build": "npm run build",
"lint": "eslint ."
},
"maxIterations": 3,
"maxCodeReviewIterations": 2,
"skipReviewThreshold": { "maxFiles": 1, "maxSteps": 2 }
}
The agents field controls which agent is used per phase. Each entry is an ordered list — the skill tries the first available agent and falls back to the next.
Agent format:
"gemini" — Gemini CLI"codex" — Codex CLI"ollama:<model>" — Ollama with a specific model (e.g. "ollama:qwen2.5-coder")"openrouter" — OpenRouter API (default model: google/gemini-3.1-pro-preview)"openrouter:<model>" — OpenRouter with a specific model (e.g. "openrouter:anthropic/claude-sonnet-4")"claude" — Claude Code headless mode (claude -p)"aider" — Aider in dry-run review mode"openai" — OpenAI-compatible API (default model: gpt-5.4)"openai:<model>" — OpenAI-compatible API with a specific model (e.g. "openai:gpt-4.1-mini")"copilot" — GitHub Copilot CLI (copilot -p)"copilot:<model>" — GitHub Copilot CLI with a specific model (e.g. "copilot:gpt-4.1")The model separator may be : or / interchangeably (e.g. copilot/gpt-4.1 === copilot:gpt-4.1). Normalise to : in the config file.
If agents is omitted, all phases use the first available agent detected in the environment.
The agentCommands field is optional — if omitted, use the default commands listed in the Analyze phase.
Security note: Custom
agentCommandsexecute directly in your shell. Only use this field in projects you trust — a malicious.claude/do-config.jsonin a cloned repo could run arbitrary commands when/dois invoked.
If no config file exists, auto-detect everything from the environment output above.
.claude/plans/<descriptive-slug>.mdIf no external agent is available, skip to Phase 3.
Small-plan threshold: Before proceeding, check if the plan modifies only N files and has M or fewer implementation steps, where N and M come from skipReviewThreshold in config (default: maxFiles: 1, maxSteps: 2). If so, skip external review with a note: "Plan is small — skipping external review." and proceed directly to Phase 3.
${CLAUDE_SKILL_DIR}/prompts/plan-review.md ($CLAUDE_SKILL_DIR is set by Claude Code to the skill's directory at runtime){TASK} → the task description ($ARGUMENTS){PLAN} → the full plan content{CONTEXT} → brief codebase context (key file paths, interfaces involved)PLAN_REVIEW_FILE=$(mktemp /tmp/do-plan-review-XXXXXX) && cat > "$PLAN_REVIEW_FILE" << 'PLAN_EOF'
<prompt content here>
PLAN_EOF
agents.planReview in config, or fall back to the first detected agent.timeout: 60000 (60 seconds) for the first attempt. If it times out or fails, try the next agent with timeout: 90000 (90 seconds). Agents that require authentication or network setup may need longer on first run.
cat $PLAN_REVIEW_FILE | gemini -p "Review the implementation plan provided via stdin. Respond in plain text." -o textcat $PLAN_REVIEW_FILE | codex exec --json -cat $PLAN_REVIEW_FILE | ollama run <model> — replace <model> with the model from the agent string (e.g. ollama:qwen2.5-coder → qwen2.5-coder)${CLAUDE_SKILL_DIR}/scripts/openrouter.sh $PLAN_REVIEW_FILE <model> — replace <model> with the model from the agent string (e.g. openrouter:anthropic/claude-sonnet-4 → anthropic/claude-sonnet-4). If no model is specified, omit the second argument to use the default (google/gemini-3.1-pro-preview). Requires OPENROUTER_API_KEY env var.cat $PLAN_REVIEW_FILE | claude -p --bare --output-format text --allowedTools "Read" — runs Claude Code in headless mode. Uses --bare to skip loading hooks/plugins/MCP for fast, deterministic execution.aider --no-auto-commits --no-git --dry-run --yes --message-file $PLAN_REVIEW_FILE — runs Aider in read-only dry-run mode so it reviews without modifying files.${CLAUDE_SKILL_DIR}/scripts/openai-compatible.sh $PLAN_REVIEW_FILE <model> — works with any OpenAI-compatible API (OpenAI, Azure, LM Studio, etc.). Replace <model> with the model from the agent string (e.g. openai:gpt-4.1-mini → gpt-4.1-mini). If no model is specified, omit the second argument to use the default (gpt-5.4). Requires OPENAI_API_KEY or OPENAI_COMPATIBLE_API_KEY env var. Set OPENAI_BASE_URL or OPENAI_COMPATIBLE_BASE_URL for non-OpenAI providers.copilot -p "$(cat $PLAN_REVIEW_FILE)" -s --allow-all-tools [--model <model>] — runs the GitHub Copilot CLI in non-interactive mode. Replace <model> with the model from the agent string (e.g. copilot:gpt-4.1 → gpt-4.1). Omit --model entirely if no model is specified to use Copilot's default. Requires copilot CLI installed and authenticated.agentCommands defines a command for this agent, use it with {file} replaced by $PLAN_REVIEW_FILE and {model} replaced by the model nametimeout parameter instead of the timeout shell command (which is unavailable on macOS)rm -f $PLAN_REVIEW_FILE — this MUST be the very next Bash command after the agent call, regardless of whether it succeeded, failed, or timed out. Do not process the agent output or perform any other action before running cleanup. This prevents prompt content from remaining on disk if subsequent steps fail.Present to the user:
STOP. Ask the user to approve, reject, or request changes to the plan.
Branch creation: Before implementing, check if the working directory is a git repository:
Run git rev-parse --git-dir 2>/dev/null — if this fails, skip branch creation silently (not a git repo).
Run git rev-parse --abbrev-ref HEAD 2>/dev/null — if the current branch already starts with do/, skip branch creation silently.
Otherwise, generate a branch name:
do/ and truncate the slug to 50 characters total (e.g. do/add-dark-mode-toggle)Run git checkout -b <branch-name> and record the branch name for Phase 6.
Review the approved plan
For each implementation unit:
For large tasks with independent units, spawn multiple agents in parallel using worktree isolation
After all agents complete, verify the full set of changes is coherent
Run QC commands based on project type (or config overrides). Before running any auto-detected command, verify it exists:
node -e "process.exit(require('./package.json').scripts?.test ? 0 : 1)" before attempting npm test. Only run npm run build if a build script exists. Only run npx playwright test if playwright is in dependencies.which pytest, which go, etc.) before running.| Type | Commands |
|---|---|
| Node.js | npm test (if test script exists), npx playwright test (if installed), npm run build (if build script exists) |
| iOS/macOS | xcodebuild -scheme <scheme> -destination 'platform=iOS Simulator,name=iPhone 16' build |
| Python | pytest |
| Go | go test ./... |
| Rust | cargo test |
| Other | Check Makefile, CI config, or .claude/do-config.json for commands |
If qc.lint is set in .claude/do-config.json, run that command (or each command if it's an array) and skip auto-detection. qc.lint accepts a string or an array of strings:
"lint": "eslint . --fix" — single command"lint": ["eslint . --fix", "prettier --write ."] — multiple commands, run in orderOtherwise, detect linters by checking for config files in the project root. Run all checks in a single Bash command:
sh -c 'ls -1 .eslintrc* eslint.config.* biome.json biome.jsonc .prettierrc* prettier.config.* .oxlintrc.json ruff.toml .flake8 .pylintrc pylintrc mypy.ini .mypy.ini .golangci.yml .golangci.yaml .golangci.toml .golangci.json rustfmt.toml .rustfmt.toml 2>/dev/null; grep -l "\[tool\.ruff\]\|\[tool\.pylint\]\|\[tool\.mypy\]" pyproject.toml 2>/dev/null; grep -l "\[flake8\]" setup.cfg 2>/dev/null; true'
For each detected config file, map it to a linter using this registry. Then verify the binary is available before running.
Linter registry:
| Ecosystem | Config indicator | Binary check | Fix command | Check-only command |
|---|---|---|---|---|
| Node.js | .eslintrc*, eslint.config.* | npx --no-install eslint --version 2>/dev/null | npx eslint . --fix | npx eslint . |
| Node.js | biome.json, biome.jsonc | npx --no-install biome --version 2>/dev/null | npx biome check . --fix | npx biome check . |
| Node.js | .prettierrc*, prettier.config.* | npx --no-install prettier --version 2>/dev/null | npx prettier --write . | npx prettier --check . |
| Node.js | .oxlintrc.json | npx --no-install oxlint --version 2>/dev/null | npx oxlint . --fix | npx oxlint . |
| Python | ruff.toml, or [tool.ruff] in pyproject.toml | which ruff 2>/dev/null | ruff check . --fix | ruff check . |
| Python | .flake8, or [flake8] in setup.cfg | which flake8 2>/dev/null | (no auto-fix) | flake8 . |
| Python | .pylintrc, pylintrc, or [tool.pylint] in pyproject.toml | which pylint 2>/dev/null | (no auto-fix) | pylint <changed_files> |
| Python | mypy.ini, .mypy.ini, or [tool.mypy] in pyproject.toml | which mypy 2>/dev/null | (no auto-fix) | mypy . |
| Go | .golangci.yml / .yaml / .toml / .json | which golangci-lint 2>/dev/null | golangci-lint run --fix | golangci-lint run |
| Go | (always if go.mod exists) | which go 2>/dev/null | (no auto-fix) | go vet ./... |
| Rust | (always if Cargo.toml exists) | which cargo 2>/dev/null | cargo clippy --fix --allow-dirty -- -D warnings | cargo clippy -- -D warnings |
| Rust | rustfmt.toml, .rustfmt.toml | which cargo 2>/dev/null | cargo fmt | cargo fmt --check |
If a config file is found but the binary is not available, skip with a note: "Detected <config> but <tool> is not installed — skipping."
If no linters are detected and qc.lint is not set: "No linter config files detected — skipping lint step." Proceed to 5b.
Run detected linters in this order:
cargo fmt) — run with auto-fix flags first so style issues are resolved before linters check logicgo vet, Clippy) — run with --fix where supportedGet the list of changed files: git diff --name-only HEAD
When ≤ 20 files changed, pass only the changed files (filtered by relevant extension) to linters that support file targeting: ESLint, Prettier, oxlint, Ruff, Flake8, Pylint, mypy.
Always run project-wide for: Biome, golangci-lint, Cargo clippy, cargo fmt, go vet.
On failure: analyze the error, fix the issue, re-run the failing linter.
Maximum N iterations per failing command, where N comes from maxIterations in config (default: 3). If still failing after max attempts, report the failure and continue to 5b.
If no external agent is available, skip to Phase 6.
git ls-files --others --exclude-standard and filter to files relevant to the plan)git add -N <file1> <file2> ... only for those plan-relevant new files (do NOT use git add -N . — it would expose unrelated files like .env or credentials to the external agent)git diff HEAD (captures both staged, unstaged, and intent-to-add files)${CLAUDE_SKILL_DIR}/prompts/code-review.md{TASK} → the task description ($ARGUMENTS){PLAN} → the approved plan content{DIFF} → the full diff outputCODE_REVIEW_FILE=$(mktemp /tmp/do-code-review-XXXXXX) && cat > "$CODE_REVIEW_FILE" << 'REVIEW_EOF'
<review prompt content here>
REVIEW_EOF
agents.codeReview in config, or fall back to the first detected agent.$CODE_REVIEW_FILE as the temp file). For Codex specifically, you may also try codex review as an alternative.
Clean up: rm -f $CODE_REVIEW_FILE — this MUST be the very next Bash command after the agent call, regardless of outcome. Do not process output before cleanup.maxCodeReviewIterations in config (default: 2)Present to the user:
Ask the user for final approval.
Reached when $ARGUMENTS started with config. The remaining text after stripping
config is the subcommand. Parse it and dispatch below.
The config file is .claude/do-config.json in the current project directory.
| Value | Description |
|---|---|
gemini | Gemini CLI |
codex | Codex CLI |
ollama:<model> | Ollama with a specific model (e.g. ollama:qwen2.5-coder) |
openrouter | OpenRouter API (default model: google/gemini-3.1-pro-preview) |
openrouter:<model> | OpenRouter with a specific model |
claude | Claude Code headless mode |
aider | Aider in dry-run review mode |
openai | OpenAI-compatible API (default model: gpt-5.4) |
openai:<model> | OpenAI-compatible API with a specific model |
copilot | GitHub Copilot CLI (copilot -p) |
copilot:<model> | GitHub Copilot CLI with a specific model (e.g. copilot:gpt-4.1) |
Use comma separation for fallback order: copilot,gemini means try copilot first, then gemini.
The model separator can be either : or / — copilot:gpt-4o and copilot/gpt-4o are equivalent. Always normalise to : when writing to the config file.
CLI-only agents (gemini, codex, claude, aider) do not accept a model suffix. copilot accepts an optional model suffix — omit it to use Copilot's default model.
showPrint the current configuration.
cat .claude/do-config.json 2>/dev/null || true.claude/do-config.json found — /do is using auto-detected defaults." and STOP.Provider config (.claude/do-config.json)
─────────────────────────────────────────
Plan review agents : copilot, gemini
Code review agents : copilot:gpt-4o
Max iterations : 3
Max code review : 2
Skip threshold : 1 file / 2 steps
QC commands
─────────────────────────────────────────
test : npm test
build : npm run build
lint : eslint .
Omit sections that are not set.
set provider <value>Set both planReview and codeReview to the same provider(s).
<value>: split on commas, trim each entry, validate against the provider list above. Error and STOP if invalid..claude/do-config.json or start from {"configVersion":1}.agents.planReview and agents.codeReview to the parsed array.<value>"set plan <value>Set only agents.planReview. Same steps as set provider but only that field.
Respond: "Set plan review agents to: <value>"
set code <value>Set only agents.codeReview. Same steps as set provider but only that field.
Respond: "Set code review agents to: <value>"
set model <model>Update the model suffix on all currently configured API providers, in both
planReview and codeReview. Skip CLI-only agents (gemini, codex, claude, aider).
/do config set provider <provider> first." and STOP.agents.planReview and agents.codeReview: strip any existing :<model> suffix and append :<model>.set iterations <n>Set maxIterations (max QC fix retries). Validate <n> is a positive integer.
Respond: "Set max iterations to <n>."
set code-iterations <n>Set maxCodeReviewIterations. Validate <n> is a positive integer.
Respond: "Set max code review iterations to <n>."
set skip-threshold <maxFiles> <maxSteps>Set skipReviewThreshold. Validate both are positive integers.
Respond: "Set skip threshold to <maxFiles> file(s) / <maxSteps> step(s)."
set qc <type> <command>Add or replace a QC command. <type> is the key (e.g. test, lint).
Everything after <type> is the command string.
Respond: "Set QC command <type> to: <command>"
unset providerRemove the agents key from config entirely (revert to auto-detection).
Respond: "Removed agent config — /do will auto-detect available agents."
unset qc <type>Remove qc.<type> from config.
Respond: "Removed QC command <type>."
resetDelete .claude/do-config.json.
.claude/do-config.json and revert all settings to defaults. Proceed? (yes/no)"rm -f .claude/do-config.json → respond "Config deleted."refreshClear the agent detection cache.
rm -f ~/.claude/do-env.json/do will re-detect on next run."Respond:
Usage: /do config [subcommand]
show Print current config
set provider <value> Set provider for both phases
set plan <value> Set provider for plan review only
set code <value> Set provider for code review only
set model <model> Update model on all API providers
set iterations <n> Set max QC fix iterations
set code-iterations <n> Set max code review iterations
set skip-threshold <files> <steps> Set small-plan skip threshold
set qc <type> <command> Add or replace a QC command
unset provider Remove agent config (revert to auto-detect)
unset qc <type> Remove a QC command
reset Delete the config file
refresh Clear agent detection cache
Provider formats:
gemini | codex | claude | aider
ollama:<model>
openrouter | openrouter:<model>
openai | openai:<model>
copilot | copilot:<model>
Use commas for fallback order: copilot,gemini
When writing .claude/do-config.json:
python3 to produce pretty-printed JSON (2-space indent).configVersion: 1.python3 - <<'PYEOF' > .claude/do-config.json
import json, sys
with open(".claude/do-config.json") as f:
data = json.load(f)
# ... mutate data ...
print(json.dumps(data, indent=2))
PYEOF
For a fresh file, start with {"configVersion": 1} and mutate from there.