Configuration
Stoat is an ASP.NET Core application, so everything below is ordinary .NET configuration: an appsettings.json in the folder you start it from, environment variables (Stoat__DataPath, with a double underscore for each :), or command-line configuration. Every key has a working default, so nothing needs to be set to get started.
The store
| Key | Default | What it does |
|---|---|---|
Stoat:ConnectionString | — | A SQLite connection string. Wins over Stoat:DataPath when set. |
Stoat:DataPath | ~/.stoat/coordination | Directory for stoat.db when no connection string is given. |
Stoat:LiveUpdates | true | Lets the await_* tools wake the moment a fact changes, and pushes changes to the web UI. Leave it on: with it off, waiting agents and open pages no longer hear about changes as they happen. Plan status stays correct either way. |
The store is one SQLite file, created on first run. There is no database server to install.
Ports
| Key | Default |
|---|---|
Stoat:RunReceiverUrl (or STOAT_RUN_RECEIVER_URL) | http://localhost:5527: where Stoat receives Bobcat runs. Never 5525, which is bobcat ui's |
ASPNETCORE_URLS | unset: Stoat binds http://localhost:5526 and the run receiver |
To move only the receiver, set Stoat:RunReceiverUrl or STOAT_RUN_RECEIVER_URL. To move coordination off 5526, set ASPNETCORE_URLS. It replaces both addresses, so list the receiver in it too (http://localhost:6526;http://localhost:6527). Use the environment variable: a --urls argument on the command line has no effect. Every route is served on every bound port.
Binding an address other machines can reach (http://0.0.0.0:5526, a LAN address) serves them, and a Stoat that other machines reach is Stoat Team, which needs a licence: see Licence. On localhost, the default, it is free.
Observation
Stoat watches GitHub, nuget.org, npmjs.org and the runs it receives, and records something only when what it sees differs from what it last saw.
| Key | Default | What it does |
|---|---|---|
Stoat:GitHubToken | GITHUB_TOKEN, else GH_TOKEN, else gh auth token | Token for issue and PR observation, and for the GitHub text a zoomed-in node shows. With none of these, GitHub is not observed at all, issue and PR nodes read unknown, and the startup log says so. |
Stoat:GitHubTokenFromGh | true | false stops Stoat from asking a signed-in GitHub CLI for its token. |
Stoat:GitHubPollSeconds | 60 | How often GitHub is swept: one GraphQL query per repository a plan references. Open issues and pull requests are read on every sweep; closed and merged ones every 15 minutes, so a reopened issue can take that long to show. When GitHub's rate limit is spent, sweeps pause until it resets, and the plan page says so. |
Stoat:NuGetPollSeconds | 60 | How often the package feeds — nuget.org, npmjs.org and any configured feed — are polled. |
Stoat:Feeds:{name}:Url / :Path / :Registry | A named feed a publish node can reference: a NuGet V3 service index, a local folder of .nupkg files, or an npm registry. Username/Password authenticate it; for npm, Password is the auth token. nuget.org and npmjs.org need no configuration. | |
Stoat:RunObservationBackstopSeconds | 300 | Runs are observed as they arrive, so this is only a safety net. It catches a run whose publisher went silent (an orphaned run), which no arriving event can announce. |
Stoat:BobcatUrl | — | Read runs from a run console on another server instead of this process's own receiver. Leave it unset unless runs are received somewhere else. |
Stoat:BobcatPollSeconds | 15 | How often that remote console is polled. |
Stoat:Pollers | true | false runs no pollers at all: nothing is observed, which is only useful for a test host. |
Stoat:ObservationHistoryEvents | 100 | How many recent observations Stoat keeps for each observed thing (an issue, a feed, a session) beside its latest state. Once a day older ones are compacted away; nothing reads them. A negative value turns compaction off. |
Stoat:ObservationRetentionHours | 24 | How often that compaction runs. The first run is Stoat:ObservationRetentionDelaySeconds (600) after startup. |
Plans and sessions
| Key | Default | What it does |
|---|---|---|
Stoat:PlansPath (STOAT_PLANS) | ~/.stoat/plans | A directory of plan YAML, imported at startup and on POST /api/plans/rescan. It only seeds: a file creates a plan the store has never had, and is otherwise ignored, because the store is the master copy. |
Stoat:PurgedPath | ~/.stoat/purged | Where a purged plan's YAML is written before it is deleted. |
Stoat:ClaudeConfigPath | CLAUDE_CONFIG_DIR, else ~/.claude | Claude Code's directory, read for session observation. |
Stoat:SessionPollSeconds | 5 | How often sessions are read. |
Stoat:SessionActivitySeconds | 90 | How recently a transcript must have changed to read as activity. |
Notifications
When an agent waits on a person, the person should hear about it wherever they are. The top bar's waiting on you badge is on every page; these reach further. Nothing leaves the machine unless a webhook is set.
| Key | Default | What it does |
|---|---|---|
Stoat:Notifications:Desktop | on for questions on macOS, off elsewhere | An OS notification on this machine (osascript on macOS, notify-send on Linux). On a Mac with nothing configured it is on, for question only, so an agent waiting on you is never waiting unseen. false turns it off. |
Stoat:Notifications:Webhook | — | A URL each notification is POSTed to: ntfy, a Slack incoming webhook, anything that takes a POST. Always opt-in. |
Stoat:Notifications:WebhookFormat | json | json (a text field Slack reads, plus the fields) or text (the sentence alone, as ntfy shows it). |
Stoat:Notifications:Kinds | question, give-up (question alone for the macOS default) | Which callouts notify: any of question, give-up, fix, main-red, usage-limit, merge, unmergeable, drift, cloud, go-ahead, review, limit. |
Stoat:Notifications:BaseUrl | http://localhost:5526 | Where the plan page is, for the link. |
A callout notifies when it appears, and again only after it went away and came back. A disconnected runner's callouts never notify. An agent's ask_person question waiting on a person notifies as question with no runner at all.
Runs and the Event Model
The run receiver uses the same Monitor: / BOBCAT_MONITOR_* names as Bobcat's own run console.
| Key | Environment variable | Default | What it does |
|---|---|---|---|
Monitor:DataPath | BOBCAT_MONITOR_DATA | ~/.bobcat/monitor/runs | Run archives and the Event Model store. |
Monitor:RetentionDays | BOBCAT_MONITOR_RETENTION_DAYS | 14 | Ages out run archives that have not changed for this many days. The only setting that ever deletes an archive file. 0 turns aging off. |
Monitor:RetentionRuns | BOBCAT_MONITOR_RETENTION_RUNS | 10 | How many runs the receiver lists per job (a repository plus a suite), so a busy repository cannot push a quiet one's runs out. Older runs are ejected: their archive moves to ejected/ and is not deleted. |
Stoat:EventModelStaleAfterDays | 7 | How far a producer's Event Model half may trail the newest half of its model before it is flagged stale. Flagged, never dropped. |
The command-line tools
stoat gate exec, stoat gate run, stoat warnings push, stoat run-plan and stoat runner are clients of a running Stoat, and find it from the environment:
| Variable | Default | Read by |
|---|---|---|
STOAT_URL | http://localhost:5526 | stoat gate exec, stoat gate run and stoat warnings push, unless --url is given (run-plan takes --url only) |
STOAT_RUN_RECEIVER_URL | http://localhost:5527 | everything that adds Stoat's receiver to BOBCAT_MONITOR_URL, and stoat runner |
BOBCAT_RUN_TAG | — | stoat gate exec: the gate to report for, {plan}/{node}; run-plan sets it for each agent |
Launcher profiles for run-plan are ~/.stoat/launchers.json (or --launchers); see Launchers.
Licence
| Key | Environment variable |
|---|---|
JasperFx:LicenseKey | JASPERFX__LICENSEKEY |
Stoat needs no key on its own machine. A server other machines reach is Stoat Team, which needs a CritterStack licence; one key serves Stoat and CritterWatch. The key is read once at startup, so restart after setting it, and a server in the Development environment needs none. This preview does not check it yet. See Installation.
Memory recall
recall is a full-text search over each memory's title, tags and body, matching whole words and the start of longer ones (wolverine finds WolverineFx), best match first. The stoat tool ships without an embedding model, so there is no semantic search and nothing to configure.