Write your own chain
You will have a chain of your own: a copy of the shipped default chain with a
lint node after verification. The node runs your linter. When the linter
fails, an agent fixes what it reported and the linter runs again, with a time
cap, and nobody can skip it.
test_scopes in repos.yaml. The shipped
verification node runs every scope whose paths the change touches, and its
fix loop repairs the failures:test_scopes:
- paths: ["src/**"]
command: npm test
- paths: ["src/**/*.ts"]
command: sh -c 'npm run lint && npx tsc --noEmit'
command runs with no shell too. See
test_scopes.Before you start
- A running Kraft server and a connected repo.
- A lint command that exits 0 when the code is clean. This guide uses
npm run lint && npx tsc --noEmit. Use your own. - Your config directory:
~/.kraft/config/, or$KRAFT_HOME/config/if you setKRAFT_HOME. You editlibrary.yamlin it and add a file underchains/.
1. Add the tasks to the library
Add two tasks to library.yaml, under tasks:. One runs the linter. The other
is the agent that repairs what the linter reports.
tasks:
lint:
kind: subprocess
command: sh -c 'npm run lint && npx tsc --noEmit'
repair_lint:
kind: agent
harness: claude
profile: strong
prompt: Fix the lint and type errors the lint step reported. Change no behavior.
Kraft does not run command through a shell, so && and pipes need the
sh -c '...' wrapper. A failing lint becomes a critical finding that holds the
end of the command's output, and the repair agent reads it.
Inside a fix loop, Kraft replaces the repair task's prompt with its own
instruction. See Subprocess tasks for
how the command runs and how its exit code becomes a status, and
Fix loop and judge
for what the repair agent is told.
2. Add the node to the library
Add a lint node to library.yaml, under nodes::
nodes:
lint:
kind: exec
skippable: false
policy:
time_cap_minutes: 30
tasks:
- id: lint
extends: lint
fix_loop:
tasks:
- id: repair
extends: repair_lint
judge:
id: judge
extends: strict_judge
max_attempts: 3
What each key does:
skippable: false: refuseskraft item skipon this node, a chain revision that proposes skipping it, andkraft item create --skip-nodes lint.policy.time_cap_minutes: 30: caps the node's running time, fix loop included. Hitting it stops the item and waits for you. Kraft does not count it as a lint failure, so no repair attempt is spent. See Time caps.fix_loop.tasks: runs after a failing lint, then the lint runs again. The loop repeats until lint passes ormax_attemptsruns out. Then the node is stuck: an escalation turn tries first, then the item stops and waits for you. The loop's wall clock comes frompolicy.yaml(default, orloops.lint.fix_loop). See Fix loop and judge and policy.yaml.judge: optional.strict_judgeis the judge task the shipped library provides, the oneverificationuses. See The judge.
3. Make the chain
Copy the default chain and give the copy its own id. cp -n never overwrites a file, so run it once: if chains/with-lint.yaml exists, skip the copy and keep editing it.
cd "${KRAFT_HOME:-$HOME/.kraft}/config"
cp -n chains/default.yaml chains/with-lint.yaml
In chains/with-lint.yaml, change id: default to id: with-lint. Then add the
lint node right after verification. The finished file, with the unchanged
nodes left out:
id: with-lint
nodes:
# ... spec through implementation, unchanged
- id: verification
extends: verification
- id: lint
extends: lint
- id: work_brief
kind: exec
tasks:
- id: author
extends: write_work_brief
# ... the rest, unchanged
A chain file cannot extend another chain, so the copy is a full copy. It does not
follow changes to the shipped default chain. See
Upgrade your configuration.
4. Check it and load it
kraft admin templates lint
kraft admin reload
kraft admin templates show with-lint --resolved
A pass prints these two lines (the counts are your own):
$ kraft admin templates lint
3 chain(s), no errors
$ kraft admin reload
reloaded 3 template(s) and policy.yaml and intake.yaml
lintreads the files from disk. It printsN chain(s), no errorsbefore you reload. On an error it prints onefile:line:column: messageline for each issue and exits 1.reloadmakes the running server read the files again, with no restart. It printsinvalid:lines and exits 1 for a file that does not load.show --resolvedprints the chain with every library component expanded. Look for yourlintnode with itsfix_loop, itspolicyandskippable: false.showasks the running server, so before the reload it answersunknown chain.
5. Use it
Name the chain when you file work:
kraft item create "Add the export button" --chain with-lint
kraft item set-chain ID --chain with-lint switches an item that has not
started yet.
To make it the repo's default instead, set default_chain: with-lint on the
repo's entry in repos.yaml. Every item filed on that repo without a chain then
gets with-lint, however it is filed: kraft item create, the MCP tool, the
board's New work item composer, POST /api/work-items, POST /api/triggers, and
auto-intake. Naming a chain still wins.
Check it worked
Steps 3 and 4 already show the chain loads. These checks prove it on a real item and cost a full run, so they are optional:
kraft item skip IDon the lint node answerspath: 'lint' does not allow skipping.- File a small item on the new chain. Once it passes
verification, list the lint node's findings:kraft view events ID --type findings_measured
The output is a table with the columnsSEQ,WHEN,TYPEandDETAIL. A failing lint shows afindings_measuredrow for nodelintwith onecriticalfinding. A clean lint shows afindings_measuredrow with no findings. Without--type,kraft view events IDalso shows what followed: afix_cycle_startedrow after a failing lint, ornode_completedforlintafter a clean one.
Next steps
- Chain file keys: every key a node, step and task takes.
- Library and chains: the library sections and how a chain extends them.
- Add a security review or a gate reviewer: put the shipped review skills in a chain of your own.
- Share chains with add-ons: publish chains of your own as a Kraft add-on that other instances install. An add-on cannot carry this guide's
subprocesslint task or extend your local library. - Upgrade your configuration: take what a new release ships without losing this chain.
Get notified when an item needs you
Set up a webhook or alerts in your browser, so Kraft tells you when a work item waits at a gate or stops, and check that a test reaches you.
Add a security review or a gate reviewer
Add the shipped security-review and gate-review skills to a chain of your own, since no shipped chain uses them.