Skip to content

Settings

Arnel Robles edited this page Oct 20, 2026 · 4 revisions

Settings

Every setting is an environment variable. Set it in the env block of your Claude Code settings. An off switch can also go inline in front of one Bash command: LEAN_ALLOW_SLOP=1 git commit ....

Working mode

hooks/mode.py reads these at session start and adds a note for the agent. The defaults print nothing.

Setting Values Default What it does
LEAN_AGENTS many, one many one runs everything in the one session: no subagents or workflows, one ticket at a time, and the critic's hunt and refute as two passes in the same context. The review report then says the finder and the judge shared a context.
LEAN_MODELS mixed, one mixed one keeps every step on the session's model: no cheap drafter and no escalation. A finding not fixed in one round gets one more round, then goes to you.
LEAN_MODEL_CHEAP sonnet, opus, haiku, fable sonnet The model that drafts, runs the spec review, and runs the critic's hunt and refute.
LEAN_MODEL_STRONG sonnet, opus, haiku, fable opus The model that takes a finding not fixed in one round, or an unsure tier 2 answer.
LEAN_MODEL_FAST sonnet, opus, haiku, fable haiku The model for agents that read and report: code search, running the gates, the retro's fact collection. It never judges code.

Rules that follow from the code:

  • Values are trimmed and lowercased, so One is one.
  • An unknown value prints a warning and falls back to the default.
  • The model settings take Claude Code model aliases, not full model ids. claude-opus-5-5 is rejected with a warning.
  • The model settings are ignored with LEAN_MODELS=one.
  • Setting LEAN_MODEL_CHEAP and LEAN_MODEL_STRONG to the same model leaves no escalation step. The note says so.
  • Setting LEAN_MODEL_FAST to the strong model, while the cheap one differs, prints a warning that the read-and-report agents now cost the most.
  • LEAN_AGENTS=one with LEAN_MODELS=mixed: a session cannot change its own model, so the cheap draft and the escalation happen only when you switch with /model. The agent says when a step wants the other model and carries on if you do not switch.

Models and the Cascade lists which step uses which model.

Hook off switches

Setting Turns off
LEAN_ALLOW_ATTRIBUTION=1 The attribution block in public-text.py
LEAN_ALLOW_SLOP=1 The slop block in public-text.py
LEAN_ALLOW_COMMIT_AUTHOR=1 commit-author.py
LEAN_ALLOW_SCRATCHPAD_ROOT=1 scratchpad-root.py
LEAN_SKIP_STYLE_NOTE=1 style-note.py
LEAN_SKIP_TEST_BEFORE_PUSH=1 record-test-run.py and test-before-push.py
LEAN_SKIP_VERIFY_CLAIM=1 verify-claim.py
LEAN_SKIP_DOCS_CONTAINERS=1 docs-containers.py
LEAN_SKIP_LESSON_LOG=1 lesson-log.py
LEAN_SKIP_PR_MERGE_BLOCKED=1 pr-merge-blocked.py
LEAN_BRAIN_RESUME=off brain-resume.py, the open items digest at session start
LEAN_SESSION_ENV=off session-env.py, the session id for brain items and answers

Hooks says what each one checks.

Script settings

Setting Script Default What it does
LEAN_BASE needs-review.sh, check-top-level-md.sh, check-workflow-keys.py origin/HEAD, then origin/main, then origin/master The base branch to diff against.
LEAN_ALLOW_WIDE_CHARS=1 style-scan off Skips the check for characters at or above U+2000, for text in other scripts.
LEAN_NO_PYYAML=1 check-workflow-keys.py off Uses the built-in indentation detector even when PyYAML is installed.
LEAN_SYNC_DRY_RESTORE=1 sync-default.sh off Prints the restore commands and does not run them.
HEAVY_WAIT heavy.sh 300 Seconds to wait for a lane before exit 75. test-phase sets 3600 unless you set it.
HEAVY_STALL heavy.sh off Seconds without new test progress before the command is stopped (exit 76). test-phase sets it from --stall.
HEAVY_PROGRESS heavy.sh dotnet's [+N/xM/?K] counter and lines starting passed or failed A Python regex for what counts as progress.
HEAVY_TIMING_FILE heavy.sh unset A file that gets the seconds the command waited for the lane.
HEAVY_BACKEND=python heavy.sh flock on Linux with util-linux, else python Forces the Python lock helper on Linux. Used by the self-test.
HEAVY_LOCK_DIR heavy.sh /tmp/heavy-locks Where the lane lock files live. Every agent has to agree on it.
HOLDOUT_BUILD_CMD holdout.sh dotnet build --configuration Release --no-restore The build command.
HOLDOUT_TEST_CMD holdout.sh dotnet test --no-build --configuration Release --filter FullyQualifiedName~ Runs one test class. The test id from the spec is appended.
HOLDOUT_BASE holdout.sh origin/master The base branch for the merge base.
REVIEW_LOG log-review.sh, retro-signals.sh review-log.tsv Path of the review log.
LEAN_DB lean-stats, every hook, log-review.sh ~/.lean/lean.db Path of the lean-stats database.
LEAN_STATS=off lean-stats, every hook, log-review.sh on Stops every write to the database.
ATTEMPTS, SLEEP check-deployed-sha.sh 20, 6 Retry count and seconds between tries.

Brain and test queue settings

Setting Used by Default What it does
LEAN_BRAIN_DB brain, brain-mcp, test-phase, the brain hooks, the VS Code extension ~/.local/share/lean/brain.db Path of the brain database. See Brain.
LEAN_SESSION_ID, LEAN_SESSION_CWD brain add, brain-mcp set by session-env.py The session and folder stored on an item, so an answer can find its session. Not meant to be set by hand.
LEAN_TEST_PHASE_DIR test-phase ~/.local/share/lean/test-phase Where each drain writes its run folder and logs.
TEST_PHASE_RUNNER test-phase detected mtp or vstest. Overrides detection of the test runner.
TEST_PHASE_DOTNET_ARGS test-phase empty Extra dotnet arguments for every job, split like a shell line.
TEST_PHASE_STALL test-phase 600 Default for --stall, in seconds. 0 is off.
TEST_PHASE_REMOTES=off test-phase, lean_remote.py on Turns every remote lane off.
TEST_PHASE_REMOTES_FILE test-phase, lean_remote.py, the VS Code extension ~/.config/lean/remotes.ini The remote lanes config. See Remote Lanes.
TEST_PHASE_REST test-phase 600 Seconds a remote lane rests after a host, connection or copy failure.
BRAIN_MCP_ARGV_LOG brain-mcp unset Appends the arguments of every brain call to this file. The self-test uses it. See Brain MCP.

CLAUDE_SCRATCHPAD is read, not set, by scratchpad-root.py: a directory it treats like a scratchpad root.

Clone this wiki locally