Documentation
¶
Overview ¶
Package config loads beekeeper's machine configuration: where its state lives, which shared resources sessions lease, the GitHub budget floor, the thresholds of the machine watch and which installations' alerts it reads.
The file is $XDG_CONFIG_HOME/beekeeper/config.yaml (or --config, or $BEEKEEPER_CONFIG). Every field is optional; a missing file is the defaults. The defaults are the numbers proven on an 86 GiB workstation running a Claude Desktop scope capped at 48 GiB: tune them to the machine.
Index ¶
- Constants
- Variables
- func DefaultQuietFor(team string) []alerts.Quiet
- func Path(flag string) (string, error)
- type Agents
- type Alerts
- type Claude
- type Config
- type Duration
- type Flap
- type GitHub
- type Guide
- type Installation
- type Lane
- type Memcap
- type Merge
- type Metrics
- type Model
- type Notify
- type Ollama
- type Overlaps
- type Reporter
- type Role
- type Runaway
- type Supervisor
- type Tokens
- type Watch
Constants ¶
const Browser = "browser"
Browser is the resource every machine has: the one Chrome the Claude in Chrome extension drives.
const ModelServer = "model-server"
ModelServer is the resource of the host's model server: a claim carries the GiB its models may hold.
Variables ¶
var DefaultIgnore = []string{"Heartbeat", "InhibitionOutsideWorkingHours", "Watchdog"}
DefaultIgnore are the alerts that always fire or only route others.
var DefaultModels = map[string]Model{
"claude-fable-5-1": {Input: 10, Output: 50, CacheWrite5m: 12.5, CacheWrite1h: 20, CacheRead: 0.25, ContextWindow: 1_000_000},
"claude-fable-5": {Input: 10, Output: 50, CacheWrite5m: 12.5, CacheWrite1h: 20, CacheRead: 1, ContextWindow: 1_000_000},
"claude-opus-5-5": {Input: 4, Output: 20, CacheWrite5m: 5, CacheWrite1h: 8, CacheRead: 0.2, ContextWindow: 1_000_000},
"claude-opus-5": {Input: 5, Output: 25, CacheWrite5m: 6.25, CacheWrite1h: 10, CacheRead: 0.5, ContextWindow: 1_000_000},
"claude-opus-4-8": {Input: 5, Output: 25, CacheWrite5m: 6.25, CacheWrite1h: 10, CacheRead: 0.5, ContextWindow: 1_000_000},
"claude-opus-4-7": {Input: 5, Output: 25, CacheWrite5m: 6.25, CacheWrite1h: 10, CacheRead: 0.5, ContextWindow: 1_000_000},
"claude-opus-4-6": {Input: 5, Output: 25, CacheWrite5m: 6.25, CacheWrite1h: 10, CacheRead: 0.5, ContextWindow: 1_000_000},
"claude-sonnet-5": {Input: 2, Output: 10, CacheWrite5m: 2.5, CacheWrite1h: 4, CacheRead: 0.2, ContextWindow: 1_000_000},
"claude-sonnet-4-6": {Input: 3, Output: 15, CacheWrite5m: 3.75, CacheWrite1h: 6, CacheRead: 0.3, ContextWindow: 1_000_000},
"claude-haiku-4-5": {Input: 1, Output: 5, CacheWrite5m: 1.25, CacheWrite1h: 2, CacheRead: 0.1, ContextWindow: 200_000},
}
DefaultModels are the Claude API list prices (platform.claude.com/docs/en/ about-claude/pricing): cache writes cost 1.25 times the input price for the 5-minute TTL and twice for the 1-hour TTL, cache reads a tenth, except where a model's own rate differs (Opus 5.5 $0.20, Fable 5.1 $0.25).
var DefaultQuiet = []alerts.Quiet{{Cluster: "t-*"}}
DefaultQuiet are the alerts of other teams' e2e test clusters.
var DefaultQuietSessions = []string{"test: *"}
DefaultQuietSessions are the sessions of beekeeper's own tests.
var OtherTeamsNotify = alerts.Quiet{Severity: "notify"}
OtherTeamsNotify are other teams' and team-less notify alerts: notify pages nobody, and the rule never quiets the team's alerts, a page or an installation in play.
Functions ¶
func DefaultQuietFor ¶ added in v0.37.0
DefaultQuietFor are the default quiet rules of team: DefaultQuiet, and OtherTeamsNotify once there is a team whose alerts it leaves out.
Types ¶
type Agents ¶ added in v0.23.0
type Agents struct {
// RelayAt is an agent's session context, in tokens, at which the watch
// says its hand-over due (default: supervisor.relayAt).
RelayAt Tokens `yaml:"relayAt"`
// NoteWait bounds how long `agents handover` waits for the agent's
// note on what is in flight (3m).
NoteWait Duration `yaml:"noteWait"`
}
Agents configures the hand-over of registered agents.
type Alerts ¶ added in v0.7.0
type Alerts struct {
// Installations are read always; a held lease whose name resolves to a
// kube context is read too.
Installations []Installation `yaml:"installations"`
// Ignore are alert names that never appear; setting it replaces the
// default (Heartbeat, InhibitionOutsideWorkingHours, Watchdog).
Ignore []string `yaml:"ignore"`
// Team is the team whose alerts are marked in capitals and counted.
Team string `yaml:"team"`
// Collapse is the number of changes of one alertname in one run above
// which they are one line with a count.
Collapse int `yaml:"collapse"`
// Every is the watch's reading interval.
Every Duration `yaml:"every"`
// Timeout bounds the reading of one installation, port-forwards included.
Timeout Duration `yaml:"timeout"`
// Kubectl is the kubectl binary.
Kubectl string `yaml:"kubectl"`
// Flap is the flap damper.
Flap Flap `yaml:"flap"`
// Quiet are the rules whose alerts' changes are no wake-up: the watch
// logs them (watch.quiet) instead of printing them. A rule never
// quiets an alert of the team, one on an installation in play (leased,
// claimed or merged into within the last half hour, or with a merge
// settling), or a page unless it names a cluster. Setting it replaces
// the default, Giant Swarm's e2e test clusters ({cluster: "t-*"}) and,
// once Team is set, every other team's and team-less notify alert
// ({severity: notify}). An alert back after a reading that missed it,
// with its old start, is quiet too.
Quiet []alerts.Quiet `yaml:"quiet"`
}
Alerts configures the reading of the installations' Alertmanagers: watch reads them every Every and prints NEW and RESOLVED lines, snapshot adds the current set as a section.
type Claude ¶
type Claude struct {
ProjectsDir string `yaml:"projectsDir"`
// SessionsDir holds the record every running CLI keeps of the session
// it runs (<pid>.json), what `claude agents` lists.
SessionsDir string `yaml:"sessionsDir"`
DesktopDir string `yaml:"desktopDir"`
// DesktopLog is the desktop app's main log: its latest focus change
// says which session the main window shows.
DesktopLog string `yaml:"desktopLog"`
}
Claude locates what Claude Code and the desktop app keep on disk.
type Config ¶
type Config struct {
// StateDir holds state.json, events.jsonl and the last snapshot.
StateDir string `yaml:"stateDir"`
// LeaseDir holds one directory per held lease (mkdir is the lock).
LeaseDir string `yaml:"leaseDir"`
// Resources are the environments sessions lease besides the browser:
// kind labs and shared installations.
Resources []string `yaml:"resources"`
// GrantTTL is how long a grant stays claimable once its resource is free.
GrantTTL Duration `yaml:"grantTTL"`
GitHub GitHub `yaml:"github"`
Watch Watch `yaml:"watch"`
Overlaps Overlaps `yaml:"overlaps"`
Claude Claude `yaml:"claude"`
Memcap Memcap `yaml:"memcap"`
Lanes []Lane `yaml:"lanes"`
Merge Merge `yaml:"merge"`
Alerts Alerts `yaml:"alerts"`
Notify Notify `yaml:"notify"`
Metrics Metrics `yaml:"metrics"`
Ollama Ollama `yaml:"ollama"`
// Supervisor is what `handover --prompt` tells a successor supervisor,
// how long a relay to it stays open and at what context it is due.
Supervisor Supervisor `yaml:"supervisor"`
// Guide is the role that walks the person through the decisions
// waiting on them, never in the supervisor's session.
Guide Guide `yaml:"guide"`
// Agents configures how a registered agent near its context limit is
// handed over to a fresh session.
Agents Agents `yaml:"agents"`
// Reporter is the one-off status reporter session the standby watch
// starts once per interval.
Reporter Reporter `yaml:"reporter"`
}
Config is the parsed configuration with the defaults applied.
func (*Config) IsLeasable ¶
IsLeasable reports whether name is a configured resource or the browser.
type Flap ¶ added in v0.12.0
Flap holds back an alert that changes too often: its Changes-th NEW or RESOLVED within Window is one FLAPPING line, and its changes print nothing until it has been stable for Window.
type GitHub ¶
type GitHub struct {
// Floor is the remaining core budget under which GitHub work stops.
Floor int `yaml:"floor"`
// ProbeRepo is the repository whose conditional GET reads the budget
// headers; any repository the token can read.
ProbeRepo string `yaml:"probeRepo"`
}
GitHub configures the budget reading.
type Guide ¶ added in v0.21.1
type Guide struct {
Role `yaml:",inline"`
// Person is the name the guide's notes are filed for (note add --for,
// or an older note's "[for <person>]" prefix), matched without regard
// to case. Its queue and feed show only that person's notes; empty,
// they show every note filed --for anyone.
Person string `yaml:"person"`
}
Guide configures the guide: its role and the person it guides.
type Installation ¶ added in v0.7.0
type Installation struct {
Name string `yaml:"name"`
Context string `yaml:"context"`
// Floor is the lowest severity printed (alerts.Severities: none, info,
// warning, notify, critical, page); empty prints every alert.
Floor string `yaml:"floor"`
}
Installation is an installation and, optionally, the kube context that reaches it and the lowest severity printed of its alerts; written as a name alone or as {name, context, floor}. Without a context it is teleport.giantswarm.io-<name>, else <name>, else the one ending in @<name>.
func (*Installation) UnmarshalYAML ¶ added in v0.7.0
func (i *Installation) UnmarshalYAML(n *yaml.Node) error
UnmarshalYAML accepts a plain name.
type Lane ¶ added in v0.6.0
type Lane struct {
Name string `yaml:"name"`
// Repositories are owner/repo; a bare name matches it under any owner.
// A repository's name is also the chart name of its HelmReleases.
Repositories []string `yaml:"repositories"`
// Installation is where the lane's HelmReleases run; empty: none to wait for.
Installation string `yaml:"installation"`
// Context is the kubeconfig context of the installation (default: the
// one named after it, or ending in -<installation>).
Context string `yaml:"context"`
}
Lane is a set of repositories whose merges roll the same components of an installation: one merge at a time, the next once they rolled. A repository in no lane is a lane of its own, with no installation to wait for.
type Merge ¶ added in v0.6.0
type Merge struct {
// Cap is the most devctl processes the machine runs when a merge starts.
Cap int `yaml:"cap"`
// QueueTTL is how long a queued merge keeps its place after its run ended,
// and how long after it the place holds up the merges behind it.
QueueTTL Duration `yaml:"queueTTL"`
// SeedTTL is how long a place queued on a session's behalf is kept from
// its seeding or the session's last arrival, and a failed run's from the
// failure.
SeedTTL Duration `yaml:"seedTTL"`
// Settle is how long a lane waits after a merge whose release is unknown.
Settle Duration `yaml:"settle"`
// SettleTimeout is how long a lane waits for a release to roll before
// the next merge is refused.
SettleTimeout Duration `yaml:"settleTimeout"`
// BudgetFresh is how old the last budget reading may be to gate on.
BudgetFresh Duration `yaml:"budgetFresh"`
// StallAfter is how long a lane's first arrived merge may wait behind
// places whose merges are not in the gate before the lane is stalled.
StallAfter Duration `yaml:"stallAfter"`
// DevctlOwners are the owners whose repositories devctl pr merge serves
// (its GitHub App login reaches the giantswarm organisation only); a
// repository of any other owner takes the plain squash merge as the gh
// login instead.
DevctlOwners []string `yaml:"devctlOwners"`
}
Merge configures the gate on devctl pr merge.
func (Merge) DevctlServes ¶ added in v0.31.2
DevctlServes says whether devctl pr merge serves repo's owner.
type Metrics ¶ added in v0.14.0
type Metrics struct {
// Models maps a model id, or the prefix of one, to its price and context
// window. A configured entry replaces the default of the same key; a
// model no entry matches has no cost ("cost unknown").
Models map[string]Model `yaml:"models"`
// Runaway holds the watch's thresholds; a negative one turns its
// figure off.
Runaway Runaway `yaml:"runaway"`
}
Metrics prices the tokens of the sessions' transcripts and sets the thresholds at which the watch reports a runaway session.
type Model ¶ added in v0.14.0
type Model struct {
Input float64 `yaml:"input" json:"input"`
Output float64 `yaml:"output" json:"output"`
CacheWrite5m float64 `yaml:"cacheWrite5m" json:"cacheWrite5m"`
CacheWrite1h float64 `yaml:"cacheWrite1h" json:"cacheWrite1h"`
CacheRead float64 `yaml:"cacheRead" json:"cacheRead"`
// Fast multiplies every price of a request in fast mode; zero (the
// defaults): a fast request's cost is unknown.
Fast float64 `yaml:"fast" json:"fast,omitempty"`
ContextWindow int `yaml:"contextWindow" json:"contextWindow"`
}
Model is a model's price in US dollars per million tokens and its context window in tokens.
type Notify ¶ added in v0.13.0
type Notify struct {
// Kinds are the kinds that notify (notify.Kinds, the default: due,
// oom-line, oom-kill, budget, stale-lease, no-supervisor).
Kinds []string `yaml:"kinds"`
// QuietHours ("22:00-07:00", local time) hold every notification but a
// critical one until they end.
QuietHours string `yaml:"quietHours"`
// Urgency is a kind's urgency (low, normal, critical); oom-line,
// oom-kill and no-supervisor are critical, the others normal.
Urgency map[string]string `yaml:"urgency"`
// Repeat is how often a lasting condition (oom-line, budget,
// no-supervisor) notifies again while it lasts.
Repeat Duration `yaml:"repeat"`
}
Notify configures what `watch --notify` sends to the desktop.
type Ollama ¶ added in v0.38.0
type Ollama struct {
// URL is its API; a machine without one answers nothing and shows none.
URL string `yaml:"url"`
// Unit is its systemd unit, whose journal names the client that
// loaded a model.
Unit string `yaml:"unit"`
// BudgetGiB is what a model-server claim may load without --gib;
// MaxBudgetGiB the most a claim may ask for.
BudgetGiB int `yaml:"budgetGiB"`
MaxBudgetGiB int `yaml:"maxBudgetGiB"`
// NameOnly keeps the watch from unloading a model no lease covers: it
// only names it.
NameOnly bool `yaml:"nameOnly"`
// LabTests are the agentlab subcommands that run turns on the host's
// models; the hook refuses them outside the model-server lease.
LabTests []string `yaml:"labTests"`
}
Ollama is the host's ollama server, whose loaded models live in the iGPU's GTT.
type Overlaps ¶
type Overlaps struct {
// Ignore lists repositories whose issues and name form no overlap:
// issue trackers and notebooks every session writes to.
Ignore []string `yaml:"ignore"`
// ActiveWithin leaves out sessions idle for longer.
ActiveWithin Duration `yaml:"activeWithin"`
}
Overlaps tunes which sessions count as working on the same thing.
type Reporter ¶ added in v0.26.0
type Reporter struct {
// Every is the interval; the reports start on its multiples (on the
// hour for 1h). Unset, no reporter runs.
Every Duration `yaml:"every"`
// Brief is the reporter's brief file (~/ allowed): what to report and
// where to post it.
Brief string `yaml:"brief"`
// Model is the session's model (default: Claude Code's).
Model string `yaml:"model"`
// Person is who the report is for (default: guide.person).
Person string `yaml:"person"`
// Dir is the session's working directory (~/ allowed; default: home).
Dir string `yaml:"dir"`
// Timeout is how long a reporter may run without posting before it is
// stopped (20m).
Timeout Duration `yaml:"timeout"`
}
Reporter configures the scheduled status reporter: once per Every the standby watch starts one headless session with Brief, which posts one report to Person and ends; beekeeper then takes it off the roster.
type Role ¶ added in v0.20.0
type Role struct {
// Skill is the name of the skill the successor runs (supervise, guide).
Skill string `yaml:"skill"`
// Instructions is a file (~/ allowed) whose content opens the prompt
// instead.
Instructions string `yaml:"instructions"`
// RelayAt is the role's session context, in tokens, at which the watch
// reports the relay due ("400k").
RelayAt Tokens `yaml:"relayAt"`
// RelayTTL is how long a relay stays open for the successor's start.
RelayTTL Duration `yaml:"relayTTL"`
// RestartGrace is how long beekeeper waits after it first saw the
// role's CLI gone: a CLI back under the same session within it is a
// restart and keeps the role; past it, the watch says the supervisor
// is gone and notifies. The grant rule holds throughout.
RestartGrace Duration `yaml:"restartGrace"`
}
Role configures a relayed role, the supervisor's or the guide's: the successor's session prompt (the instructions it follows, a skill or a file, not both) and the relay.
type Runaway ¶ added in v0.14.0
type Runaway struct {
// GitHubCallsPerHour: gh and devctl commands and GitHub MCP tool calls
// in the last hour.
GitHubCallsPerHour int `yaml:"githubCallsPerHour"`
// SameErrorRepeats: the same failing tool call in the last hour.
SameErrorRepeats int `yaml:"sameErrorRepeats"`
// ContextFill: the last request's context over the model's window.
ContextFill float64 `yaml:"contextFill"`
}
Runaway are the per-session figures over which the watch prints one line.
type Supervisor ¶ added in v0.9.0
type Supervisor struct {
Role `yaml:",inline"`
// Scope says what the supervisor watches, in a sentence or two; empty,
// the prompt names the resources, lanes and installations configured.
Scope string `yaml:"scope"`
// KeepAwake is how long the recorded spare may sit idle before the
// standby watch sends it a keep-awake message (25m): under the desktop
// app's 30-minute idle timeout for an off-screen CLI, so a command-line
// message still reaches it. The supervisor's restartGrace defaults to
// 30s: past it the standby watch hands the role to the spare.
KeepAwake Duration `yaml:"keepAwake"`
}
Supervisor configures the supervisor: its role and the scope it supervises.
type Tokens ¶ added in v0.16.0
type Tokens int64
Tokens is a token count written as "400k", "1m" or "400000" in YAML.
func ParseTokens ¶ added in v0.16.0
ParseTokens parses "400k", "1m" or "400000" (case-insensitive).
type Watch ¶
type Watch struct {
Interval Duration `yaml:"interval"`
// Repeat paces how often a lasting condition is handed to the
// notifier (which sends it again after notify.repeat); the watch
// prints it once when it starts and once when it ends.
Repeat Duration `yaml:"repeat"`
BudgetEvery Duration `yaml:"budgetEvery"`
AvailMinMiB int `yaml:"availMinMiB"`
SwapMaxMiB int `yaml:"swapMaxMiB"`
// OOMDHeadroomMinMiB and OOMDWithin decide when systemd-oomd's swap
// kill is imminent, the one memory condition that notifies a person
// (oom-line): less swap growth left before its SwapUsedLimit than
// OOMDHeadroomMinMiB, or the trigger reached within OOMDWithin at the
// last hour's growth rate. Every other memory threshold is a watch
// line for the supervisor only.
OOMDHeadroomMinMiB int `yaml:"oomdHeadroomMinMiB"`
OOMDWithin Duration `yaml:"oomdWithin"`
ScopeAnonMaxMiB int `yaml:"scopeAnonMaxMiB"`
// GTTMaxMiB is the iGPU GTT (system RAM the GPU driver pins, which no
// cgroup counts) above which the watch prints IGPU GTT and names it
// with the host ollama's models as the cause of LOW RAM and OOMD
// IMMINENT.
GTTMaxMiB int `yaml:"gttMaxMiB"`
// LoadMax is the 1-minute load average over which the watch says HIGH
// LOAD; unset (0), it is LoadPerCoreMax × the machine's cores
// (LoadLimit).
LoadMax float64 `yaml:"loadMax"`
LoadPerCoreMax float64 `yaml:"loadPerCoreMax"`
PSIMax float64 `yaml:"psiMax"`
// CPUPSIMax is the CPU pressure ("some avg10" of /proc/pressure/cpu,
// in percent) over which the watch says CPU PRESSURE once two samples
// in a row read it, and over which, like over LoadLimit, the machine is
// strained: the installation reads (upgrades, alerts, lane settling)
// then run four times less often and at nice 10 (READS SLOWED).
CPUPSIMax float64 `yaml:"cpuPSIMax"`
TmpMaxMiB int `yaml:"tmpMaxMiB"`
DiskMinMiB int `yaml:"diskMinMiB"`
// QuietSessions are globs (* matches any run) of the names of
// short-lived sessions whose start, end and restart are no wake-up:
// the watch logs them (watch.quiet) instead of printing them. Setting
// it replaces the default, beekeeper's own tests ("test: *").
QuietSessions []string `yaml:"quietSessions"`
}
Watch holds the thresholds of `beekeeper watch` (MiB unless noted).