View and change the dev-lead leg roster — which model and effort each adapter runs, per role and per round. Use when the user wants to see or edit that roster.
Installs into .claude/skills of the current project.
Are you the author of Config?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/aarontzeng-config)
---
name: config
description: View and change the dev-lead leg roster — which model and effort each adapter runs, per role and per round. Use when the user wants to see or edit that roster.
---
# Config: the dev-lead leg roster
The roster says which model and effort each CLI adapter runs, per role
(implement / review) and per round (`r1`, `fix`). It is a declaration the
lead reads. [`scripts/leg-cmd.sh`](../../scripts/leg-cmd.sh) still requires
an explicit `--model` — there is no safe default, because the model is the
cross-family accounting decision. Nothing in the roster is a launcher default.
## Where it lives
The first source that is SET wins — an explicit path that does not exist is
reported, never swapped for another file:
1. `DEV_LEAD_ROSTER`
2. `$CLAUDE_PLUGIN_DATA/roster.json` — Claude Code's per-plugin directory, used
only when it is dev-lead's own (`dev-lead-<marketplace>`): a lead's shell
can inherit ANOTHER plugin's value (measured: codex's). A codex or agy lead
will not have the variable at all.
3. `~/.claude/plugins/data/dev-lead-dev-lead/roster.json`
A missing file is normal on a new machine: `roster.py init` (run as in the
Procedure below) copies
[`templates/roster.example.json`](../../templates/roster.example.json) there,
never over an existing file or symlink without `--force`. Its model ids are
examples; take each slot through steps 2-3 below before relying on it.
Keys that start with `_` are comments and are kept across writes.
## Procedure
Resolve the suite root the same way the other skills do. The helper has to
come from that tree: cwd is the target repo, and a bare scripts path would
miss.
```bash
DEV_LEAD=${DEV_LEAD_ROOT:-$(ls -d "$HOME"/.claude/plugins/cache/dev-lead/dev-lead/* 2>/dev/null | sort -V | tail -1)}
[ -x "$DEV_LEAD/scripts/roster.py" ] || { echo "dev-lead root unresolved — set DEV_LEAD_ROOT to your checkout"; exit 1; }
"$DEV_LEAD/scripts/roster.py" show
```
1. **Show.** Run `"$DEV_LEAD/scripts/roster.py" show`. A fix round that
inherits prints each of r1's legs marked inherited. If the file is
missing, the command names the path and how to start one with `init`
(or write one leg with `set`); that is not an error.
2. **Write one leg per call.** If the user named assignments, apply each
with `set` and a `--why` that quotes the user. Do not invent a reason
they did not give.
`"$DEV_LEAD/scripts/roster.py" set <round> <role> <adapter> --model M [--effort E] [--family F] [--lens L] --why "<the user's words>"`
An opencode review leg routed by lens is the `by_lens` entry: pass
`--lens`. `set fix --inherit r1 --why "<the user's words>"` makes the
fix round match r1.
If the user did not name assignments, ask per slot. Use the host's
multiple-choice question tool when it has one. Offer the current value,
that adapter's `effort.examples` spellings from
[`data/launch.json`](../../data/launch.json), and free text -- except
where the effort block says `closed: true` (claude, both roles, since
0.6.56): there the examples are the whole vocabulary and `set` refuses any
other word, because that CLI ignores an unknown effort and runs at its
default. Ask whether the fix round inherits r1 or differs.
**No config file to align (since 0.6.28).** codex review runs `codex
exec -c model_reasoning_effort=<e>`, so the roster's effort is the effort
that runs; no shipped leg reads its effort from a file on the machine.
`roster.py config-effort` still exists for a `config_only` adapter should
one return, and answers "nothing to write" for codex. Do not offer to edit
`~/.codex/config.toml`: it only decides the companion fallback's depth,
and changing it is the user's own act.
3. **Probe a new model once, with a real call.** A model that has never
been dispatched on this machine gets one cheap real call before it is
written. A row in a CLI's model listing is not evidence the model can
be called.
4. **The merge gate.** `roster.py show` prints it first. If the user named
it, apply `"$DEV_LEAD/scripts/roster.py" gate <user|lead> --why "<the
user's words>"`. Otherwise ask once, in their words: does dev-lead land a
fully green verdict itself (`lead`), or does the person approve the
verdict and diff first (`user`, the default)? Say what it does NOT change:
anything not fully green — an unanswered review round, a failing test, an
open blocker, an unverified finding — still goes to the person either way, and a stricter repo
contract still wins.
5. **Check.** `"$DEV_LEAD/scripts/roster.py" check`. A family that cannot
be the accounting leg is a warning: it prints and does not fail. Any
error does. `set` refuses to write a roster that fails, so a failure
here means the file was changed outside this skill.
6. **Report.** For each slot this session changed, say old → new: model,
effort, family, whether the fix round inherits, or the merge gate.
`unset <round> <role> <adapter>` stores `null` for that leg. An unset leg
is not a default model. The next dispatch has to name one.