From milknado
Configure milknado's per-flavor worker execution by interviewing the user and writing milknado.toml — agent_family, [milknado.worker.tools] allowlists, and [milknado.flavor.*] tables for each TaskFlavor (implement, spec, spike, prototype, research). Use when the user wants to set up or tune how milknado runs workers — phrases like "configure milknado flavors", "set up milknado.toml", "tune the research/spec/spike agent", "which model should milknado use for prototypes", "skip quality gates for spikes", "milknado worker tools", "per-flavor agent config". Interviews for agent family, then per-flavor model/agent, tools, quality gates, and brief prepend; writes the tables and validates them with `milknado agents check` plus a flavor resolution probe. Do NOT use for running graphs (milknado run) or planning (milknado plan).
How this skill is triggered — by the user, by Claude, or both
Slash command
/milknado:milknado-configThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Set up `milknado.toml` so each **task flavor** runs with the right agent, tools,
Set up milknado.toml so each task flavor runs with the right agent, tools,
quality gates, and briefing. Interview the user, write the tables, validate.
milknado.toml and wants more than the bare default.Not for: running the graph (milknado run), planning (milknado plan), or
graph/node edits. This skill only writes config.
A milknado task node carries a TaskFlavor: implement (the default),
spec, spike, prototype, research. At dispatch time milknado resolves a
flavor profile — execution_agent, quality_gates, brief_prepend — and
runs the worker with it. The profile comes from [milknado.flavor.<flavor>] in
milknado.toml, falling back to the global worker config when a flavor sets
nothing.
Resolution precedence (per field — see flavor_profile.py):
execution_agent (explicit full CLI) → else flavor
tools derived against the family built-in default → else the config-level
execution_agent.[] means skip gates) → else config
default.prompts.worker_brief_prepend.agent_family is one of claude | cursor | gemini | codex; it picks the default
planning + execution commands and (for claude/gemini) the tool allowlist.
milknado.toml at the project root (milknado init creates a
default if missing).$XDG_CONFIG_HOME/milknado/milknado.toml (else
~/.config/milknado/milknado.toml), merged under the project file
(project wins). Global brief_prepend_path is resolved against the global
config dir; project_root, db_path, plugins are ignored if set globally.Decide with the user whether a flavor preset is project-specific (most cases — gates are project commands) or a personal default for the global file.
Work top-down. Prefer a structured prompt (e.g. AskUserQuestion) so the user
picks from options; accept free-form too. Don't ask about flavors the user
doesn't want to touch — implement usually needs no override at all.
milknado.toml is absent, run
milknado init (or hand-write a minimal [milknado] table). Read the current
file first — you will edit it in place, preserving comments and existing keys.agent_family (claude default). This sets the
default models and which families can restrict tools (only claude and
gemini enforce a CLI tool allowlist; cursor and codex have no
per-tool restriction — their tools list won't gate anything, so steer those
users to execution_agent/quality_gates instead).[milknado.worker.tools.<family>] is a
single list. Bare list replaces the built-in allowlist; include the "..."
sentinel once to mean "the built-in default, plus these". Use this for tools
every flavor should have (e.g. add "Bash(just:*)" so workers can run the
project's recipes).spec, spike, prototype, research, and implement only
if they want to change the default): for each one the user wants to tune, ask:
spec) needs a full execution_agent string, which opts
out of the tool allowlist. To keep the allowlist, change tools instead
(model stays the family default).research → read-only +
WebSearch, dropping edit tools; spike → add WebSearch via "...").[] to skip (typical for
spec/research/spike where there's no code to test).brief_prepend_path (a file, or a list of
files concatenated) that tells the worker how to behave for this flavor.[milknado.worker.tools] and [milknado.flavor.*] tables into
milknado.toml (see "Writing" below).See references/flavor-presets.md for recommended presets per flavor and a full
worked milknado.toml. Offer those as the starting point, then tailor.
[milknado]
agent_family = "claude"
# Family-wide worker allowlist. Bare list REPLACES the built-in default;
# "..." expands in place to the built-in default (at most one sentinel).
[milknado.worker.tools]
claude = ["...", "Bash(just:*)"]
# Per-flavor override. Every field optional; absent = inherit.
[milknado.flavor.research]
quality_gates = [] # [] = skip; omit = inherit
tools = ["mcp__tilth__*", "Read", "Grep", "Glob", "WebSearch"] # replaces default
brief_prepend = "Research only. Investigate and report; do not modify code."
# brief_prepend_path = "agents/research.md" # mutually exclusive with brief_prepend
[milknado.flavor.spec]
execution_agent = "claude --model opus -p" # explicit full CLI; opts out of allowlist
quality_gates = []
milknado.toml in place — add/replace the [milknado.worker.tools]
and [milknado.flavor.*] tables; keep the user's other keys and comments. Do
not regenerate the whole file (that would strip comments).[milknado.flavor.<flavor>] table per flavor you're configuring. Only emit
fields that differ from the inherited default — an empty table is a no-op.brief_prepend and brief_prepend_path are mutually exclusive in the same
table. brief_prepend_path may be a string or a list of strings (files joined
with a blank line).After writing, confirm the file parses and the profiles resolve as intended:
# Base resolution + that the file loads (family / planning / execution command):
milknado agents check
# Per-flavor resolution probe — prints the resolved profile for every flavor:
uv run python - <<'PY'
from pathlib import Path
from milknado.domains.common.config import load_config
from milknado.domains.common.flavor_profile import resolve_flavor_profile
from milknado.domains.common.types import TaskFlavor
cfg = load_config(Path("milknado.toml"))
for f in TaskFlavor:
p = resolve_flavor_profile(cfg, f)
print(f"{f.value:10} agent={p.execution_agent!r}")
print(f"{'':10} gates={list(p.quality_gates)} brief={'set' if p.brief_prepend else 'none'}")
PY
load_config raises on malformed tables (unknown flavor key, disallowed
executable, bad sentinel count, missing brief_prepend_path, non-list gates) —
a clean run means the config is well-formed. If it raises, read the message, fix
the offending table, re-run.
execution_agent opts out of the allowlist. A full CLI string is run
verbatim; the tools allowlist no longer applies. Must start with one of
claude, codex, cursor-agent, gemini (basename checked).tools-derived model is the family default, not opus — derivation uses the
built-in family command (sonnet for claude, flash for gemini). Want a bigger
model and a tool list? You must spell the whole command in execution_agent.tools only restricts claude and gemini. cursor-agent headless and
codex have no CLI tool-allowlist flag, so a tools list is inert for them.quality_gates = [] skips gates; omitting the key inherits. They're
different — be explicit about which the user wants.brief_prepend replaces, it does not append to the config-level
worker_brief_prepend."..." sentinel per tool list."..." expands the BUILT-IN family allowlist, not your
[milknado.worker.tools] override. So if you added "Bash(just:*)"
family-wide and a flavor re-specifies tools = ["...", "WebSearch"], that
flavor does not inherit Bash(just:*) — re-add it in the flavor's list if
it's needed there.quality_gates shown in docs (uv run pytest / ruff check /
ty check) are milknado's own; a consuming project sets its own gate commands.npx claudepluginhub paulnsorensen/milknado --plugin milknadoCreates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.