Skip to content

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 ​

KeyDefaultWhat it does
Stoat:ConnectionString—A SQLite connection string. Wins over Stoat:DataPath when set.
Stoat:DataPath~/.stoat/coordinationDirectory for stoat.db when no connection string is given.
Stoat:LiveUpdatestrueLets 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 ​

KeyDefault
Stoat:RunReceiverUrl (or STOAT_RUN_RECEIVER_URL)http://localhost:5527: where Stoat receives Bobcat runs. Never 5525, which is bobcat ui's
ASPNETCORE_URLSunset: 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.

KeyDefaultWhat it does
Stoat:GitHubTokenGITHUB_TOKEN, else GH_TOKEN, else gh auth tokenToken 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:GitHubTokenFromGhtruefalse stops Stoat from asking a signed-in GitHub CLI for its token.
Stoat:GitHubPollSeconds60How 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:NuGetPollSeconds60How often the package feeds — nuget.org, npmjs.org and any configured feed — are polled.
Stoat:Feeds:{name}:Url / :Path / :RegistryA 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:RunObservationBackstopSeconds300Runs 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:BobcatPollSeconds15How often that remote console is polled.
Stoat:Pollerstruefalse runs no pollers at all: nothing is observed, which is only useful for a test host.
Stoat:ObservationHistoryEvents100How 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:ObservationRetentionHours24How often that compaction runs. The first run is Stoat:ObservationRetentionDelaySeconds (600) after startup.

Plans and sessions ​

KeyDefaultWhat it does
Stoat:PlansPath (STOAT_PLANS)~/.stoat/plansA 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/purgedWhere a purged plan's YAML is written before it is deleted.
Stoat:ClaudeConfigPathCLAUDE_CONFIG_DIR, else ~/.claudeClaude Code's directory, read for session observation.
Stoat:SessionPollSeconds5How often sessions are read.
Stoat:SessionActivitySeconds90How 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.

KeyDefaultWhat it does
Stoat:Notifications:Desktopon for questions on macOS, off elsewhereAn 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:WebhookFormatjsonjson (a text field Slack reads, plus the fields) or text (the sentence alone, as ntfy shows it).
Stoat:Notifications:Kindsquestion, 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:BaseUrlhttp://localhost:5526Where 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.

KeyEnvironment variableDefaultWhat it does
Monitor:DataPathBOBCAT_MONITOR_DATA~/.bobcat/monitor/runsRun archives and the Event Model store.
Monitor:RetentionDaysBOBCAT_MONITOR_RETENTION_DAYS14Ages 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:RetentionRunsBOBCAT_MONITOR_RETENTION_RUNS10How 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:EventModelStaleAfterDays7How 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:

VariableDefaultRead by
STOAT_URLhttp://localhost:5526stoat gate exec, stoat gate run and stoat warnings push, unless --url is given (run-plan takes --url only)
STOAT_RUN_RECEIVER_URLhttp://localhost:5527everything 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 ​

KeyEnvironment variable
JasperFx:LicenseKeyJASPERFX__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.

Licensed under the Business Source License 1.1.