Configuration¶
Developer reads its config from a developer.yaml file. Copy example.developer.yaml to developer.yaml and customize it — developer.yaml is gitignored. This file defines which repos it manages, how to set them up locally, and what quality tools to run.
Where Developer looks¶
The config file is the first of these:
--config PATH, given before the command (developer --config ~/developer/developer.yaml review myrepo 5);- the
DEVELOPER_CONFIGenvironment variable; developer.yamlin the current directory;developer.yamlat the root of the Developer checkout.
Developer keeps its clones (repos/) and a record of every run (runs/), and reads its GitHub App credentials (.env), in its home directory. That is the directory holding developer.yaml, unless DEVELOPER_HOME names another one. Running from a checkout, all three live at the project root, as before. An installed developer works from any directory that holds a developer.yaml.
Format¶
repos:
assistant:
github:
owner: gregology
repo: assistant
testing_philosophy: >-
Test rigor is proportional to irreversibility.
Dispatch, provenance, and non-undoable actions need thorough tests.
setup:
- uv sync --all-extras
quality_tools:
- name: mypy
cmd: [uv, run, mypy, app/, --ignore-missing-imports]
- name: pytest
cmd: [uv, run, pytest]
timeout: 600
Fields¶
claude (optional)¶
How Developer runs Claude Code. Every setting is optional. Anything left out uses Claude Code's own default, except max_turns, which is 50.
claude:
cli_path: null # a claude binary; null uses the one bundled with the SDK
model: sonnet # an alias such as opus, sonnet or haiku, or a full model ID
effort: high # low, medium, high, xhigh or max
max_budget_usd: 5 # per agent run; the run stops if it costs more
max_turns: 50 # per agent run; the run stops if the agent needs more
stages: # overrides for particular stages
craft_pr: {effort: low, max_turns: 15}
implement_step: {model: opus, max_budget_usd: 20}
stages takes the stage names from the pipeline docs, plus implement_step (every implementation step in resolve), audit (every audit) and investigate (the add command's agent). A stage name both resolve and address use, such as quality_fix, applies to both. An unknown stage name is an error.
A stage that uses all its turns before it finishes stops the run, with an error that names the setting to raise. The run's transcript in runs/ still shows what the stage cost.
DEVELOPER_CLAUDE_CLI in the environment overrides cli_path.
repos (required)¶
Top-level key. Each entry underneath is a repo, keyed by whatever name you want to use on the command line.
github (required)¶
GitHub coordinates:
Both owner and repo are required. Developer uses these to construct API URLs, clone URLs, and the bot's commit identity.
env (optional)¶
Environment variables for the repo's setup and teardown commands, its quality tools, and the agent that works on it. They're added to Developer's own environment.
$VAR and ${VAR} take a variable's value from Developer's environment when a run starts, and $$ stands for a $. A run stops if a variable it names isn't set.
This is the place for facts about the machine, such as where a version manager keeps the repo's tools. A version manager's shell hook, like mise activate or direnv, doesn't run for the commands Developer starts, so they only find those tools if env puts them on PATH.
Developer keeps GitHub credentials away from the agent, so GITHUB_APP_ID, GITHUB_PRIVATE_KEY, GITHUB_TOKEN and GH_TOKEN can't be set here.
setup (optional)¶
List of shell commands that prepare a fresh checkout. They run inside each run's own worktree, before the agent starts.
Commands run with shell=True, so pipes and redirects work. They run in order, and each can rely on the ones before it. If one fails, the rest are skipped and the run stops before the agent starts. validate reports each command's result, including the ones a failure skipped.
teardown (optional)¶
List of shell commands that stop whatever setup started outside the worktree, such as containers or background services. They run in the worktree when the run ends, however it ends, including when setup failed partway.
Every command runs, even after one fails, and a failure is logged as a warning. validate counts a failed teardown command as a failure.
Each run's worktree is a new directory with a name of its own. Tools that name what they create after the directory, as Docker Compose does with its projects, keep each run's services apart. Fixed host ports are still shared, so two runs of a repo that publishes a fixed port can't set up at the same time.
quality_tools (optional)¶
List of tools that check code quality. Each needs a name and a cmd (as a list of strings). timeout is optional: the number of seconds a tool may run before it counts as failed, 120 by default.
quality_tools:
- name: ruff
cmd: [uv, run, ruff, check, src/, tests/]
- name: mypy
cmd: [uv, run, mypy, --ignore-missing-imports]
Quality tools run during the resolve and address pipelines (after implementation, before opening a PR). They also run during audit refactor as signal for the agent. If a tool fails, the agent gets up to three attempts to fix the issues.
Removed: provider and providers¶
Developer only runs Claude, so these keys were removed. provider: claude is still accepted with a warning. Any other provider value, or a providers block, is an error.
sandbox (optional)¶
What the agent's Bash commands may reach beyond the worktree. Commands always run in Claude Code's sandbox: by default they can write only inside the worktree and the temp directory, can't use the network, and can't read credential files such as ~/.ssh, ~/.config/gh or Developer's .env.
allowed_domains-- hosts commands may connect to, for example package registries the test suite needs.allow_write-- extra paths commands may write to, for example a package manager's cache.
On Linux the sandbox needs bubblewrap and socat. Ubuntu 24.04 and later also need an AppArmor profile for bwrap; see Claude Code's sandbox docs.
testing_philosophy (optional)¶
Free-text description of the repo's testing approach. This gets injected into audit prompts so the agent understands what kind of test coverage the project expects.
Validation¶
Developer validates config on every run. Unknown keys are errors, so a typo can't be silently ignored. If something is wrong, you get an error naming each setting at fault:
Error: /home/you/developer/developer.yaml is invalid:
repos.assistant.github.owner: Field required
repos.assistant.quality_tool: Extra inputs are not permitted
You can also validate that a repo's full config works from scratch:
This clones into a temp directory, sets up a fresh worktree exactly as a run does, runs every quality tool in it, and reports pass/fail for each step. It proves the config actually works, not just that it parses.
Adding a repo¶
The quickest way is to let Developer discover the config automatically:
This clones the repo, runs an investigation agent to discover setup and teardown commands, testing philosophy, and quality tools, then writes the result to developer.yaml. Use --dry-run to preview without saving. The same operation is available via the API (POST /repos).
To add a repo manually, add a block under repos in your developer.yaml:
repos:
my-new-repo:
github:
owner: myorg
repo: my-new-repo
setup:
- npm install
quality_tools:
- name: eslint
cmd: [npx, eslint, src/]
Developer clones it on first run. No other setup needed.