Replace a built-in step
Point a pipeline entry at your `command:` instead of `builtin:`. Keep the same step id so gates, loops, and feedback keep working. The built-in steps stay available as defaults; replacing one is a config change, not a new pipeline.
Point a pipeline entry at your command: instead of builtin:. Keep the same step id so gates, loops, and feedback keep working. The built-in steps stay available as defaults; replacing one is a config change, not a new pipeline.
Keep the same id
The default pipeline runs review-standards and review-spec. Those ids are what the loop and any later gate refer to. If you change only the program behind review-standards, the loop still collects that step's feedback and a gate that waits on it still waits.
Switch back by restoring builtin: review on that id.
Worked example: a team checklist
examples/custom-steps/review-checklist/ replaces the default review step with a small custom review that runs the team's own checklist script. The pipeline id stays review-standards.
review-standards: { command: ["python3", "./step.py"], timeout: 5m, config: { fail_on: major } }
review-spec: { builtin: review, args: ["--focus", "spec"], timeout: 5m, config: { fail_on: major } }The parallel review group is unchanged:
- parallel:
name: review
fail_fast: false
steps:
- review-standards
- review-specstep.py speaks the protocol. checklist.sh is the team's script: it fails added FIXME lines that have no owner, for example FIXME(sam). Findings become fail with feedback, the same way the default review step reports findings, so the loop still iterates.
To switch review-standards back to the default review step:
review-standards: { builtin: review, args: ["--focus", "standards"], timeout: 5m, config: { fail_on: major } }Wrap a built-in
When you only want to wrap the default, start it from your step and then add your own checks. Forward the request on stdin to kusaw step review with the same --focus that id used:
import subprocess, sys
req = sys.stdin.read()
proc = subprocess.run(
["kusaw", "step", "review", "--focus", "standards"],
input=req, text=True, capture_output=True,
)
sys.stdout.write(proc.stdout)
sys.stderr.write(proc.stderr)Your program still has to handshake, and its last stdout line still has to be a result. You can emit extra progress first, or replace an ok from the default with fail if your extra check fires.
How to switch back
- On that step id, replace
command: [...]withbuiltin: <name>. - Restore any
args:the default used (--focus standardsfor the default review step). - Run
kusaw validate.
The pipeline list does not change.
Write your first step
This page is a Python 3 worked example that uses only the standard library. Copy `examples/custom-steps/todo-check/` or type the excerpts as you go. The code on this page is that example. A [Go example](examples.md) that speaks the same protocol is linked from More examples.
Use an agent inside your step
A custom step can start the agent CLI you already configured. That is Claude Code, or the Cursor CLI with the model setting it accepts. Kusaw does not choose one for you. Pass a runner [preset](../glossary.md#preset) (`read_only`, `edit`, or `interview`) rather than assembling vendor flags by hand.