src/autoskillit/skills_extended/write-recipe/SKILL.md
Generate YAML recipes for .autoskillit/recipes/. Use when user says "make script skill", "generate script", "script a workflow", "write a script", "create a script", "new recipe", "write a pipeline", or when loaded by other skills for script formatting.
npx skillsauth add talont-org/autoskillit write-recipeInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Format a workflow into a YAML recipe following the workflow schema.
/autoskillit:write-recipe
No positional arguments. The skill prompts interactively for workflow details.
NEVER:
.claude/commands/, .claude/skills/, or anywhere else).autoskillit/recipes/ directory/autoskillit:<name> syntaxALWAYS:
.autoskillit/recipes/{name}.yaml as the ONLY outputvalidate_recipe after saving and fix any errorsEvery recipe that produces output files MUST scope its write destinations through a
per-run context variable captured in the init step:
init to create a unique timestamped directory and capture its path as
${{ context.work_dir }}, ${{ context.planner_dir }}, or similar.${{ context.<var> }}/subdir/ — never via bare {{AUTOSKILLIT_TEMP}}/name/....non-unique-output-path lint rule (severity: ERROR) rejects any recipe step
that uses a bare {{AUTOSKILLIT_TEMP}}/ path without a context-variable prefix.Valid patterns:
${{ context.planner_dir }}/phases/ (run-scoped via captured unique dir)${{ context.work_dir }}/output/ (clone-scoped)Invalid pattern (rejected by lint):
{{AUTOSKILLIT_TEMP}}/myrecipe/data/ (bare — shared across runs, causes stale artifacts)Recipes have their own discovery and invocation mechanism — completely separate from the skill system. You do not need to create anything else for the script to be usable. The lifecycle is:
.autoskillit/recipes/{name}.yamllist_recipes MCP tool (lists all scripts in that directory)load_recipe("{name}") MCP tool (returns raw YAML)No SKILL.md, no slash command registration, no Markdown companion file — the YAML file
in .autoskillit/recipes/ is the only artifact needed. The MCP tools handle everything else.
Every generated script MUST follow the workflow YAML schema:
name: {script-name}
autoskillit_version: "{version}" # from kitchen_status.package_version
description: {One line description.}
summary: {Concise pipeline chain, e.g. "plan > verify > implement > test > merge"}
ingredients:
var_name:
description: {What this input is for}
required: true # or false
default: {value} # optional
steps:
step_name:
tool: {mcp_tool_name}
with:
arg1: "${{ inputs.var_name }}"
arg2: "literal value"
capture: # optional — extract values for later steps
var_name: "${{ result.field_name }}"
on_success: next_step
on_failure: escalate
retry: # optional
max_attempts: 3
on: needs_retry
on_exhausted: escalate
done:
action: stop
message: "Pipeline complete."
escalate:
action: stop
message: "Failed — human intervention needed."
name, autoskillit_version (stamped), description, summary (required), inputs, stepsdescription, optional required (default false) and defaulttool (MCP tool call) or action (terminal: stop)with: for arguments, on_success/on_failure for routingaction: stop and a message:${{ inputs.var_name }} for declared inputs and ${{ context.var_name }} for values captured by preceding stepsmax_attempts, on (condition field), on_exhausted (step name)> to chain steps (e.g., "plan > verify > implement > test > merge")| Field | Required | Type | Notes |
|-------|----------|------|-------|
| name | Yes | string | Unique identifier; validation fails if empty |
| autoskillit_version | No | string | Package version that generated this script. Set from kitchen_status.package_version. Used by migration system to detect outdated scripts. |
| description | Yes | string | Human-readable, shown in listings |
| summary | Yes | string | Pipeline chain shown in list_recipes output |
| inputs | No | mapping | Omit if the script has no configurable values |
| kitchen_rules | Yes | list[str] | Orchestrator discipline rules. Must enumerate forbidden native tools (Read, Grep, Glob, Edit, Write, Bash, Task, Explore, WebFetch, WebSearch, NotebookEdit). |
| steps | Yes | mapping | At least one step required |
| Field | Required | Default | Notes |
|-------|----------|---------|-------|
| description | No | "" | What this input is for |
| required | No | false | Whether the agent must prompt for it |
| default | No | null | Value used when not provided |
| Field | Required | Notes |
|-------|----------|-------|
| tool | Yes (xor action) | MCP tool name (see Tool Reference below) |
| with | No | Arguments passed to the tool; values support ${{ inputs.X }} and ${{ context.X }} |
| on_success | No | Step name to route to on success, or "done" |
| on_failure | No | Step name to route to on failure |
| capture | No | Map of context_var → ${{ result.field }} expressions. Captured values available to later steps via ${{ context.var }} |
| retry | No | Retry block (see below) |
| note | No | Human-readable annotation for the agent; not executed |
| Field | Required | Notes |
|-------|----------|-------|
| action | Yes (xor tool) | Must be "stop" |
| message | Yes | Displayed to the agent when this step is reached |
| Field | Default | Notes |
|-------|---------|-------|
| max_attempts | 3 | How many times to retry before giving up |
| on | null | Response field to check. Valid values: exit_code, is_error, needs_retry, result, retry_reason, session_id, subtype |
| on_exhausted | "escalate" | Step name to jump to when retries run out |
Extracts values from tool results into a pipeline-scoped context dict. Subsequent steps reference captured values via ${{ context.var_name }}.
| Field | Type | Notes |
|-------|------|-------|
| capture | mapping | Keys are context variable names; values must be ${{ result.field }} expressions |
Rules:
${{ result.* }} expressions (literals and other namespaces are rejected)${{ result.data.path }})Example:
steps:
implement:
tool: run_skill
with:
skill_command: "/autoskillit:implement-worktree-no-merge ${{ context.plan_path }}"
cwd: "."
capture:
worktree_path: "${{ result.worktree_path }}"
on_success: test
test:
tool: test_check
with:
worktree_path: "${{ context.worktree_path }}"
The system validates scripts against these rules:
name must be non-emptysteps must contain at least one steptool or action (not both, not neither)action: stop) must have a messageon_success and on_failure targets must reference a step name defined in the file, or the literal "done"retry.on_exhausted must reference a defined step nameretry.on must be one of the valid response fields listed above${{ inputs.X }} references must match a declared input namecapture values must contain ${{ result.* }} expressionscapture values must only use the result.* namespace${{ context.X }} references must point to a variable captured by a preceding steprun_skill steps should have a capture: block to explicitly wire outputs (warning: IMPLICIT_HANDOFF)${{ context.X }} (warning: DEAD_OUTPUT)Available tools for use in tool: fields:
| Tool | Arguments (with:) | Purpose |
|------|---------------------|---------|
| run_skill | skill_command, cwd, model (optional), step_name (optional) | Run a Claude Code headless session with a skill |
| test_check | worktree_path | Run test suite, returns PASS/FAIL |
| merge_worktree | worktree_path, base_branch | Merge after test gate |
| reset_test_dir | test_dir, force (optional, default false) | Clear test directory (requires reset guard marker) |
| classify_fix | worktree_path, base_branch | Analyze diff for restart scope (full vs partial) |
| reset_workspace | test_dir | Reset workspace, preserving configured directories |
| run_cmd | cmd, cwd, timeout (optional) | Execute arbitrary shell command |
| validate_recipe | script_path | Validate a script file against the workflow schema |
These skills ship with the autoskillit plugin and are invoked as /autoskillit:<name>:
analyze-prs, arch-lens-c4-container, arch-lens-concurrency, arch-lens-data-lineage, arch-lens-deployment, arch-lens-development, arch-lens-error-resilience, arch-lens-module-dependency, arch-lens-operational, arch-lens-process-flow, arch-lens-repository-access, arch-lens-scenarios, arch-lens-security, arch-lens-state-lifecycle, audit-arch, audit-bugs, audit-claims, audit-cohesion, audit-defense-standards, audit-docs, audit-feature-gates, audit-friction, audit-impl, audit-review-decisions, audit-tests, build-execution-map, bundle-local-report, close-kitchen, collapse-issues, compose-pr, compose-research-pr, design-guards, diagnose-ci, dry-walkthrough, elaborate-phase, enrich-issues, exp-lens-benchmark-representativeness, exp-lens-causal-assumptions, exp-lens-comparator-construction, exp-lens-error-budget, exp-lens-estimand-clarity, exp-lens-exploratory-confirmatory, exp-lens-fair-comparison, exp-lens-governance-risk, exp-lens-iterative-learning, exp-lens-measurement-validity, exp-lens-pipeline-integrity, exp-lens-randomization-blocking, exp-lens-reproducibility-artifacts, exp-lens-sensitivity-robustness, exp-lens-severity-testing, exp-lens-unit-interference, exp-lens-validity-threats, exp-lens-variance-stability, implement-experiment, implement-worktree, implement-worktree-no-merge, investigate, issue-splitter, make-arch-diag, make-campaign, make-experiment-diag, make-groups, make-plan, make-req, merge-pr, mermaid, migrate-recipes, open-integration-pr, open-kitchen, pipeline-summary, plan-experiment, plan-visualization, planner-analyze, planner-assess-review-approach, planner-consolidate-wps, planner-elaborate-assignments, planner-elaborate-phase, planner-elaborate-wps, planner-extract-domain, planner-generate-phases, planner-reconcile-deps, planner-refine, planner-refine-assignments, planner-refine-phases, planner-refine-wps, planner-validate-task-alignment, prepare-issue, prepare-pr, prepare-research-pr, process-issues, promote-to-main, rectify, reload-session, report-bug, resolve-claims-review, resolve-design-review, resolve-failures, resolve-merge-conflicts, resolve-research-review, resolve-review, retry-worktree, review-approach, review-design, review-pr, review-research-pr, run-experiment, scope, setup-environment, setup-project, smoke-task, stage-data, triage-issues, troubleshoot-experiment, validate-audit, validate-review-decisions, validate-test-audit, verify-diag, vis-lens-always-on, vis-lens-antipattern, vis-lens-caption-annot, vis-lens-chart-select, vis-lens-color-access, vis-lens-methodology-norms, vis-lens-figure-table, vis-lens-multi-compare, vis-lens-reproducibility, vis-lens-story-arc, vis-lens-temporal, vis-lens-uncertainty, generate-report, write-recipe
When the user describes a workflow using bare skill names (e.g., "use make-plan", "then run investigate"), you MUST resolve each name before writing it into the YAML.
For each bare skill name the user mentions:
.claude/skills/<name>/SKILL.md exist in the project directory?<name> in the Bundled AutoSkillit Skills list above?/<name> (bare slash command)/autoskillit:<name>"I see
<name>exists as both a local project skill (/<name>) and a bundled AutoSkillit skill (/autoskillit:<name>). Which should this script use? The local version is recommended since it's tailored to your project."
This is the reference format. All generated scripts should match this style:
name: implementation
description: Plan, verify, implement, test, and merge a task.
summary: make-plan > dry-walk > implement > test > merge
kitchen_rules:
- "NEVER use native Claude Code tools (Read, Grep, Glob, Edit, Write,
Bash, Task, Explore, WebFetch, WebSearch, NotebookEdit) from the
orchestrator. All work is delegated through run_skill."
- "Route to on_failure when a step fails — do not investigate directly."
ingredients:
task:
description: What to implement
required: true
project_dir:
description: Path to the project
required: true
work_dir:
description: Working directory (can be same as project_dir)
default: "."
base_branch:
description: Branch to merge into
default: develop
steps:
plan:
tool: run_skill
with:
skill_command: "/autoskillit:make-plan ${{ inputs.task }}"
cwd: "${{ inputs.work_dir }}"
capture:
plan_path: "${{ result.plan_path }}"
on_success: verify
on_failure: escalate
verify:
tool: run_skill
with:
skill_command: "/autoskillit:dry-walkthrough ${{ context.plan_path }}"
cwd: "${{ inputs.work_dir }}"
on_success: implement
on_failure: escalate
implement:
tool: run_skill
with:
skill_command: "/autoskillit:implement-worktree-no-merge ${{ context.plan_path }}"
cwd: "${{ inputs.work_dir }}"
capture:
worktree_path: "${{ result.worktree_path }}"
retries: 0
on_context_limit: retry_worktree
on_success: test
on_failure: escalate
retry_worktree:
tool: run_skill
with:
skill_command: "/autoskillit:retry-worktree ${{ context.plan_path }} ${{ context.worktree_path }}"
cwd: "${{ context.worktree_path }}"
on_success: test
on_failure: escalate
test:
tool: test_check
with:
worktree_path: "${{ context.worktree_path }}"
on_success: merge
on_failure: fix
merge:
tool: merge_worktree
with:
worktree_path: "${{ context.worktree_path }}"
base_branch: "${{ inputs.base_branch }}"
on_success: done
on_failure: escalate
fix:
tool: run_skill
with:
skill_command: "/autoskillit:resolve-failures ${{ context.worktree_path }} ${{ context.plan_path }} ${{ inputs.base_branch }}"
cwd: "${{ inputs.work_dir }}"
on_success: done
on_failure: escalate
done:
action: stop
message: "Implementation complete."
escalate:
action: stop
message: "Failed — human intervention needed."
A condensed bugfix loop showing retry, classify, and routing patterns:
name: example-loop
description: Test, fix, and merge with automatic retry.
summary: test > investigate > plan > implement > verify > merge
kitchen_rules:
- "NEVER use native Claude Code tools (Read, Grep, Glob, Edit, Write,
Bash, Task, Explore, WebFetch, WebSearch, NotebookEdit) from the
orchestrator. All work is delegated through run_skill."
- "Route to on_failure when a step fails — do not investigate directly."
ingredients:
test_dir:
description: Directory containing the project to test
required: true
base_branch:
description: Branch to merge fixes into
default: develop
helper_dir:
description: Directory for helper agent sessions
required: true
steps:
test:
tool: test_check
with:
worktree_path: "${{ inputs.test_dir }}"
on_success: done
on_failure: investigate
investigate:
tool: run_skill
with:
skill_command: "/autoskillit:investigate the test failures"
cwd: "${{ inputs.helper_dir }}"
on_success: plan
on_failure: escalate
plan:
tool: run_skill
with:
skill_command: "/autoskillit:rectify the investigation findings"
cwd: "${{ inputs.helper_dir }}"
capture:
plan_path: "${{ result.plan_path }}"
on_success: implement
on_failure: escalate
implement:
tool: run_skill
with:
skill_command: "/autoskillit:implement-worktree-no-merge ${{ context.plan_path }}"
cwd: "${{ inputs.helper_dir }}"
retries: 0
on_context_limit: escalate
on_success: verify
on_failure: escalate
verify:
tool: test_check
with:
worktree_path: "${{ inputs.test_dir }}"
on_success: merge
on_failure: classify
note: Re-test after implementation. If still failing, classify the fix scope.
classify:
tool: classify_fix
with:
worktree_path: "${{ inputs.test_dir }}"
base_branch: "${{ inputs.base_branch }}"
note: If full_restart, go back to investigate. If partial_restart, go back to implement.
on_success: merge
on_failure: escalate
merge:
tool: merge_worktree
with:
worktree_path: "${{ inputs.test_dir }}"
base_branch: "${{ inputs.base_branch }}"
on_success: done
on_failure: escalate
done:
action: stop
message: "All tests passing. Fix merged successfully."
escalate:
action: stop
message: "Human intervention needed. Review the latest output for details."
When converting old .claude/commands/ or .claude/skills/ Markdown recipes to YAML:
| Markdown Pattern | YAML Equivalent |
|------------------|-----------------|
| SETUP: block with var = value | inputs: block with description, required, default |
| Hardcoded paths in SETUP | required: true inputs (never hardcode paths) |
| PIPELINE: numbered steps | steps: keyed by descriptive name |
| run_skill("/skill-name ...", cwd=...) | tool: run_skill with with: {skill_command: "...", cwd: "..."} |
| run_skill(...) with retry | tool: run_skill with retries: field |
| → ESCALATE / prose failure routing | on_failure: escalate |
| PASS → next step | on_success: next_step |
| FAIL → fix attempt | on_failure: fix |
| Repeat up to 3x, then ESCALATE | retry: {max_attempts: 3, on: needs_retry, on_exhausted: escalate} |
| IF condition: branching | Multiple steps with on_success/on_failure routing |
| FOR each part: loops | Not representable in YAML schema — add a note: explaining the loop for the agent |
| Prose Notes: section | note: field on individual steps, or comments in YAML |
| AskUserQuestion prompts | Not in schema — the agent handles prompting before executing the script |
| review_approach = false (optional) | Input with required: false and default: "false" |
| Local skill refs (bare skill-name) | Follow the Skill Reference Disambiguation procedure above to resolve |
Some Markdown patterns require agent interpretation rather than YAML structure:
FOR each plan_part): Add a note: to the implement step explaining that the agent should glob for plan parts and iterateIF review_approach == true): Use an input with a default and add a note: explaining the conditionalSETUP: block — remove hardcoded paths, make them required: trueon_success / on_failure routing for every tool stepretry: blocks where the Markdown says "repeat" or "retry"done and escalate stepssummary: line capturing the pipeline chainnote: fields for agent-interpreted logic (loops, conditionals)When called directly as /autoskillit:write-recipe:
kitchen_status to get package_version and stamp autoskillit_version: "{package_version}" as the second top-level field (after name). This is required for the migration system to track script age..autoskillit/recipes/{name}.yaml (create the directory if needed)validate_recipe with the saved file path. If errors are returned, fix them and re-validate until clean. Review the quality.warnings in the response:
DEAD_OUTPUT: A capture: key is never referenced by any reachable downstream step via ${{ context.X }}. Either add a ${{ context.X }} reference in the downstream step's with: block, or remove the unused capture.IMPLICIT_HANDOFF: A run_skill step has no capture: block. Add a capture: block to explicitly wire outputs to downstream steps via ${{ context.X }}, or confirm the skill's output is intentionally unused.generate_recipe_card on the saved script. This creates .autoskillit/recipes/contracts/{name}.yaml alongside the recipe. Use run_python with autoskillit.recipe.contracts.generate_recipe_card passing the script path and scripts directory, or rely on load_recipe which auto-generates contracts on first load..autoskillit/recipes/{name}.yaml. Load it with load_recipe("{name}") via the MCP tool."After telling the user, emit the structured output token as the very last line of your text output:
IMPORTANT: Emit the structured output tokens as literal plain text with no markdown formatting on the token names. Do not wrap token names in
**bold**,*italic*, or any other markdown. The adjudicator performs a regex match on the exact token name — decorators cause match failure.
recipe_path = {absolute_path_to_saved_recipe_file}
Recipes are YAML workflow files in .autoskillit/recipes/. They are:
load_recipe MCP toolThey are NOT:
/autoskillit:<name>).autoskillit/skills/ or any other directory.yaml files)Never tell the user to run a script with /autoskillit:<name>. The correct
invocation is always via load_recipe("<name>").
When loaded via the Skill tool by another skill (e.g., setup-project), the calling agent already has all the workflow context in its conversation. Use that context directly:
Apply the format rules above to produce the YAML script. Do not re-ask for information the calling agent has already gathered.
When the agent is given an existing script's YAML content and a requested change:
validate_recipe on the saved pathrun_python with autoskillit.recipe.contracts.generate_recipe_card or rely on load_recipe auto-generation on next load.This edit mode is invoked when load_recipe routes the user's modification request through this skill. The skill receives the existing YAML as context.
data-ai
Create Uncertainty Representation visualization planning spec showing error bar definitions, distribution-aware alternatives, and multi-seed variance protocols. Statistical lens answering "How is uncertainty honestly represented?"
data-ai
Create Temporal Dynamics visualization planning spec showing axis scaling (linear vs log), smoothing disclosure, epoch/step alignment, run aggregation (mean + variance bands), early-stopping markers, and wall-clock vs step-count x-axis. Temporal lens answering "Are training dynamics shown clearly and honestly?"
data-ai
Create Narrative Story Arc visualization planning spec showing visual consistency across the report (same color = same model everywhere), logical figure progression, redundant figure detection, and narrative dependency between figures. Narrative lens answering "Do the figures tell a coherent story across the report?"
development
Create Replicative Reproducibility visualization planning spec showing data availability, preprocessing parameter disclosure (bin widths, smoothing windows), plotting library/version, random seeds, and code reference per figure. Replicative lens answering "Can the figures be reproduced from the data and code?"