Skip to content

Configuration: `homeostat.yaml`

One file at the KB root. homeostat validate checks it, and the dashboard’s Settings pages edit every key. Only version and team are required; everything else has a default. A KB for one code repo lists its areas; a KB for several lists each repo under repos, with its own areas.

A key Homeostat does not know is an error for homeostat validate, the KB’s own check, so a typo is caught in CI. Everywhere else (session hooks, sync, the MCP server, the dashboard) it is a warning and the key is ignored: a laptop still on an older version keeps reading the rest of a config that a newer version added an option to, and its sessions say once that it needs updating. From 0.5.11 the plugin runs the version the KB’s CI pins, so that happens only on a laptop whose clone has not synced yet.

version, team, teams, areas, repos, topics

Section titled “version, team, teams, areas, repos, topics”
Key Default Meaning
version (required) Always 1
team.members (required) Each member has an id (lowercase), role (junior, member, senior or lead; seniors and leads own the config), and areas they review. Optional: handle (@user, @org/team or an email, used for CODEOWNERS and to recognise reviewers on the git host), emails (the emails they commit with: how a laptop is matched to its member, before the git name), slack (their Slack member ID; the morning review notice mentions named reviewers), optOut: true (the daily run never reads their PRs or review comments), and usage: true (their sync shares per-day usage counts, sessions, injections, rules served, MCP calls and document reads for the last seven days, in their heartbeat for the Performance page; off by default, and HOMEOSTAT_SHARE_USAGE=1 on their machine does the same)
team.reviewers (unset) Member ids who decide the lessons the daily run is unsure about. When set, only they are asked to review its PRs and listed in CODEOWNERS; other members’ roles only weigh their lessons. Unset, area owners decide, then seniors and leads. Give them a slack member ID to be mentioned in the morning notice
teams {} Team name → handle (@org/team), members, areas it owns, and repos it works in. The owning team approves its areas’ rules and documents. Every session still reads every team’s rules for the files it touches
areas {} Area name → path globs in your code repo, for a KB without repo folders. core is implicit and applies everywhere. With repos, leave it out: each repo has its own. A rule drafted from review copies its area’s globs into its scope; it is read with the area’s globs of today, so a folder added here reaches every such rule at once, with no rule rewritten. A rule whose scope names a path the area does not list (or, written by hand, one of several area globs) keeps its own scope
repos (unset) A multi-repo KB: each code repo by short name (its folder under knowledge/), with source (owner/name on the git host) and its own areas. Shared rules live in knowledge/core/, each repo’s in knowledge/<repo>/<area>/, and a session gets only its own repo’s rules. Then leave top-level areas and sources.repos out, and name areas elsewhere as <repo>/<area>. Unset, every rule applies to every repo
topics (unset) Topic name → one-line description. With topics, rules are grouped into one file per topic, knowledge/<area>/<topic>.md, each rule a ## section; without them, each rule is its own file. In a multi-repo KB these are the shared rules’ topics, and each repo lists its own as repos.<name>.topics. general is always allowed
migrated.on (unset) Written by homeostat migrate: the day it ran. A developer’s sync moves their pending lessons created by then to the new layout; leave it as written
migrated.areas (unset) Written by homeostat migrate: each old area and the repo it moved to (shared for knowledge/core/)
Key Default Meaning
scoring.weights.prFeedbackChangedCode 3 Review feedback followed by a code change
scoring.weights.prFeedback 0 Review feedback with no code change after it
scoring.weights.manual 2 Written by a member by hand
scoring.weights.agentHandoff 0 Written by an agent at the end of a session
scoring.weights.deepDive 0 Produced by the deep dive (merges)
scoring.weights.seniorAuthor 1 Bonus when a senior wrote it
scoring.weights.conflict -2 Per conflict with another rule
scoring.weights.flag -2 Per open flag
scoring.autoMergeThreshold 3 Legacy: used only by homeostat curate run on its own. The daily run decides by scoring.confidence
scoring.autoMerge.enabled true Turn auto-merge off entirely
scoring.autoMerge.areas [] Areas that may auto-merge; empty means all
scoring.autoMerge.excludeAreas [] Areas that always need a reviewer, e.g. core
scoring.autoMerge.maxPerRun 5 Legacy: the most entries homeostat curate, run on its own, may auto-merge
scoring.confidence.accept 70 The daily run merges a lesson at or above this confidence (0–100) with no reviewer
scoring.confidence.coreAccept 80 The same, for core and global rules, which reach every session
scoring.confidence.decline 35 Lessons below this are declined; between decline and accept they go to a reviewer
scoring.confidence.base.prFeedbackChangedCode 50 Starting points: a review comment followed by a code change
scoring.confidence.base.prFeedback 20 a review comment with no code change after it
scoring.confidence.base.manual 45 written by a team member (learn, /homeostat:learn)
scoring.confidence.base.agentHandoff 25 written by an agent (handoff notes, MCP)
scoring.confidence.base.deepDive 40 produced by the deep dive
scoring.confidence.roles.junior 0 Added for the role of the person the lesson came from: its writer, or the reviewer it was drawn from
scoring.confidence.roles.member 6
scoring.confidence.roles.senior 14
scoring.confidence.roles.lead 20
scoring.confidence.bonus.areaOwner 6 That person works in the lesson’s area
scoring.confidence.bonus.specific 8 The rule names a concrete function, path or package
scoring.confidence.bonus.goodTitle 4 A clear title of three words or more
scoring.confidence.bonus.repeat 10 Per extra independent occurrence in the same run (up to two)
scoring.confidence.bonus.modelRating 10 The most the model’s own rating of a drafted lesson adds or removes
scoring.confidence.penalty.vagueTitle 15 Subtracted for a title like “lesson1”
scoring.confidence.penalty.conflict 25 Subtracted when it contradicts an accepted rule (which also sends it to a person)
scoring.confidence.penalty.flag 20 Subtracted per open flag
scoring.confidence.penalty.judge 30 Subtracted when the judge finds a drafted rule claims what its review thread does not (which also sends it to a person; details)
scoring.reviewCadence weekly Reserved for review reminders; not used yet
scoring.reviewPrs developer How the daily run groups lessons for a person: one review PR per developer a day (developer), or one PR per lesson (lesson), each merged or closed on its own. The Slack notice then lists each PR with its lesson’s title
Key Default Meaning
agents.runtime api How the daily run, the deep dive, bootstrap and migrate --topics reach Claude: api (a Console key), bedrock, vertex, or claude-code. See runtimes
agents.bedrock.region AWS_REGION AWS region for runtime: bedrock
agents.vertex.projectId ANTHROPIC_VERTEX_PROJECT_ID Google Cloud project for runtime: vertex
agents.vertex.region global global, us, eu or a region
agents.maxCostUsd (none: no cap) Most US dollars one daily run, deep dive or bootstrap spends on model calls. No call starts once the run has spent it; what is left waits for the next run (details). homeostat daily --max-cost <usd> overrides it for one run. Runtimes that report no cost (api, bedrock, vertex) are priced from their tokens, an estimate
agents.curator.enabled true Run the daily run under homeostat up. The curator settings (model, effort) also apply to bootstrap, seed and migrate --topics
agents.curator.schedule 0 6 * * * Cron (UTC) for homeostat up; CI uses its own schedule
agents.curator.model claude-opus-5-5 Any model id the runtime accepts
agents.curator.effort medium low, medium, high, xhigh or max
agents.curator.lookbackHours 26 How far back each run reads merged PRs
agents.curator.consolidateCalls 30 Most model calls per daily run that decide whether a new lesson updates, repeats or adds to the rules most like it (details). Lessons past the cap, and every lesson with --no-reviews or 0, fall back to the word-overlap duplicate check
agents.curator.docPatchCalls 20 Most calls per daily run that check whether a lesson makes a team document out of date. Each sends only the three sections the thread matches best (about 3,000 tokens at most), not every document covering its file; no matching section, no call
agents.curator.judgeCalls 100 Most model calls per daily run that judge a drafted rule about to merge with no person against its review thread (details). A pass takes one call, a failure three. Set it above the number of lessons a busy day merges on its own: 0 turns the judge off; drafts past the cap go to a reviewer, and the run says how many. A backfill (daily --since) raises it to cover every confident draft (details)
agents.curator.judgeModel claude-sonnet-5-5 The judge’s model. Empty means claude-sonnet-5-5, or claude-opus-5-5 when agents.curator.model is already claude-sonnet-5-5, so the judge is never the drafter grading itself
agents.curator.judgeEffort medium The judge’s effort
agents.curator.retractCalls 10 Most model calls per daily run that rewrite a document section citing a rule the run retires (details). 0 lists the sections instead
agents.deepDive.enabled true Run the deep dive under homeostat up
agents.deepDive.schedule 0 7 * * 1 Cron (UTC)
agents.deepDive.model claude-opus-5-5
agents.deepDive.effort medium
agents.deepDive.lookbackHours 168 Which rules count as “this week’s” for the contradiction check
agents.deepDive.staleAfterDays 180 Accepted rules not confirmed for this long are retired; older document sections are flagged
agents.deepDive.retractCalls 10 Most model calls per deep dive that rewrite a document section citing a rule it retires as stale (details). 0 lists the sections instead
agents.handoff.enabled false Ask for a handoff note at the end of sessions with real edits. Opt-in: Claude Code shows the question as a “Stop hook error”, and it costs one more turn
agents.handoff.minEdits 5 File edits before the note is asked for
Key Default Meaning
distribution.exports all four Which tools homeostat export writes for: claude, cursor, agents-md, copilot
distribution.tokenBudget 2000 Tokens of rules per session
distribution.docTokenBudget 1000 Tokens of document sections per session, on top of the rules
Key Default Meaning
notifications.slackWebhookEnv (none) Name of the environment variable or CI secret holding the Slack webhook URL for the digest and the daily run’s morning notice. Never the URL itself. When it is set here but the variable is empty in the run, the daily run and the digest print Slack: <NAME> is not set in this CI; no notice was posted (the daily run also records it in its run report)
notifications.digestDay monday Day homeostat up posts the digest (08:00 UTC); CI uses its own schedule
Key Default Meaning
security.allowedDomains [] Domains rules may link to (subdomains included). The git host is always allowed
security.eventRetentionDays 90 Days the local event log keeps events
security.teamOnlyAreas [] Areas never exported, and seen only by their members’ sessions
security.mcpWrites false Let agents save and flag rules through MCP
security.mcpWriteLimit 5 With MCP writes on: the most writes per session

Needed by the daily run, review, bootstrap and migrate, not by validation.

Key Default Meaning
sources.host (required) github or bitbucket
sources.kbRepo (required) owner/name of this KB repo: the only repo the agents write to
sources.baseBranch main Where the agents open pull requests
sources.repos [] A KB without repo folders: code repos whose merged PRs the daily run reads. With repos, leave it out; it is taken from each repo’s source
sources.exclude.repos [] Repos never read
sources.exclude.paths [] Globs: review comments on these files are never read or sent