A coding, helping, documenting teammate in Slack
Work in public, so everyone can help and learn.
Mention @Scout in a public Slack channel and it reads the
code, runs the tests, makes the change and opens a pull request, in a
thread anyone can follow, join, redirect and learn from. It declines
direct messages and private channels. Each thread is a durable
conversation with its own sandbox, credentials never leave the host,
and what Scout knows lives in a profile of plain files that people
review like any other change.
One Slack thread is one piece of work. Scout keeps a single message up to date while it works, and replaces it with the answer. The reaction on the request follows along: 🧠 thinking, 📖 reading, 🧪 testing, ending ✅, ⚠️ or 🙋. Anyone in the thread can add context or change course while it runs.
npm run job for one-off work.
Credit where it's due
River is the coding agent Shopify's people work with in public Slack channels. It works only in the open, so everyone learns from watching everyone else's sessions, and teams teach it what they know. Tobi Lütke and Shopify Engineering wrote about it generously and in detail, and Scout is built from what they described.
Scout is an independent, open-source take on that idea, for teams outside Shopify. It isn't affiliated with or endorsed by Shopify. Thank you to Tobi and the River team for showing the way so openly.
One Node process, SQLite and Slack's Socket Mode: no public address, no Postgres, no job queue. Pi Durable runs the agent, checkpointing every model call and tool call, so a crash or a deploy carries on mid-run, and a second person can steer work already in progress.
anything can start a thread
npm run job, no Slackone Node process, on the host
Socket Mode; roles, requester checks, spend limits and capacity, before work starts
Every model call and tool call is checkpointed, so runs survive restarts and the people in the thread can steer
Prompts, skills and channel instructions, in a git repository Scout keeps pulled
Pushes, pull requests and reviews from a host-owned mirror; MCP servers (Grafana, CI logs, Gatus), writes behind approval
Notes while it works, a nightly reflection, then pull requests against the profile
One Slack message per run; dashboard
:8893, /metrics, OTLP
traces
the host holds the keys
.scout/setup.sh; sleeps when quiet
In short: requests arrive from Slack, the code host, alerts, schedules and one-off jobs. Scout, a single process on the host, checks who may ask, runs the agent on Pi Durable, and answers in Slack. Its tools reach a sandbox per thread, a model provider or gateway, the code host and Litestream's backup, and only Scout holds credentials.
Every file operation and command goes through a pi-env daemon in the sandbox, and git crosses as bundles: a host-owned mirror fetches the thread's commits and pushes them. The host never runs git inside a thread's clone.
Scout learns from its own work. As it goes, it keeps notes on what it found out; each night it reflects on the day's threads and proposes what it should know from now on, as a pull request against its own profile. People review that like any other change, and once it's merged, Scout knows it in every thread.
River showed why this matters: its merge rate rose because people noticed where it got stuck or could do more and told it. Scout remembers the lesson so it can improve.
Scout remembers what it learns in a thread and can forget it again. Unreviewed notes are on the dashboard, and they retire once a merged proposal covers them.
Every night it reads each thread with new activity: who asked what, what it did, which steps failed and how it ended, plus its notes and what reviewers said about its last proposals.
It edits a clone of its profile repository, with file tools only, and opens a pull request that explains each change with the thread it came from.
Scout keeps its profile pulled, so the next request in every thread gets the change. Each Monday it reports its merge rate and each channel's week.
The profile is files in git: a system prompt, skills, and each channel's instructions, repositories and zones. One team's skill can be reused by every other.
Each thread is a durable conversation on Pi Durable: it survives
restarts, and the people who may ask for work can redirect it. 🔁
on an answer tries again, and editing a request steers the run. A
change made through a tool that needs approval waits for one of
its approvers' “approve” or 👍, or the Approve button, and the
approval covers that one change. “Ask Scout about
this” on any message, or 🔍, starts a thread there, and
/scout and the Home tab show what Scout is doing and
what's waiting on you. Each channel gets a canvas of what's open,
and a Slack List tracks all of Scout's work.
Its own clone in its own Docker container or spoond microVM, with nothing worth stealing in it. Network is off by default, or a per-repository allowlist where spoond enforces one. A sandbox that can't reach a host asks, and one of the named egress approvers allows or declines it from Slack.
Before any pull request, Scout reviews its own diff in a separate conversation that can only read. It refuses changes over a size limit, scans the diff for credentials, and asks the code's owners to review.
It watches CI on its pull requests and fixes red builds, keeps them mergeable as the base moves, asks about quiet ones before closing them, deletes merged branches, and never pushes over a teammate's commits.
Ask Scout for a review on the code host as you would a person. It reviews like a colleague, with line comments, again on each new push, and says so in the repository's channel. Its reviews are comments, never approvals, so a person still approves the merge.
On Forgejo or GitHub, assign Scout an issue or mention
@scout in an issue, pull request or comment. It
works in a thread in the repository's channel and answers there
too.
Not every request is a change. Ask how the code works, where something is documented, or how a service has been running in production, and Scout answers in the thread, with a pull request only when there's a change to make. It reads the repositories and their docs and its earlier threads, and, through read-only MCP servers on the host, Grafana (metrics, logs, dashboards, alerts), CI logs and Gatus checks. A tool that changes things waits for an approval first.
Scout watches Gatus and Grafana and looks into each new alert in a public thread in the channel that owns it, mentioning whoever is on call. It says when the alert clears, and a flapping alert stays in its thread.
On Slack plans with custom steps, Workflow Builder gets an Ask Scout step. Give it a public channel, who's asking, a request and any context, such as a form's answers or an alert, and it starts a Scout thread there and hands the thread's link on to the next step. The request is checked like anyone's, and the thread says it came through a workflow.
“Every Monday at 9, check for dependency updates.” Each run is a new thread in the channel, and anyone there can list, change, pause or remove the channel's schedules by asking.
Any thread can search and read every repository Scout works in, and its earlier threads. MCP servers for the data warehouse, traces and CI run on the host, read-only by default.
Requests can be limited to people who can change the repository, found through your identity provider and the code host. Groups decide who approves changes made through tools, one approval per change, and every request, tool call and approval goes to an append-only audit trail.
Weekly budgets per channel, in dollars, and per-run limits on tool calls and cost. Each answer says what it cost against the week's budget, and requests over the concurrency limits queue, with Scout saying where they are in line and roughly how long.
One setting decides how much Scout does without being asked, and Scout says which when it starts. Requests from people are never affected.
Ask Scout to try a few ways and it works on them side by side, then lets you pick one from a comparison in the thread.
Scout is meant to be installed and run by people who didn't build it, on a small machine: two cores and 4 GB is plenty, since the work happens in sandboxes.
npm run deploy refuses a commit CI hasn't passed,
then drains Scout: running steps finish, no new ones start, and
after the restart each run carries on from the step it stopped
at.
When a model's provider goes down, its calls go to the first fallback that's answering, and threads carry on instead of failing. Scout tries the model again after a while, and says in the thread which model answered.
Litestream copies both databases off the machine. If a change goes uncopied for 15 minutes, the doctor fails, the dashboard shows a red line and Scout says so in its home channel.
Each run is an OTLP trace, with a span per tool call and Pi
Durable's own spans for every model call, plus Prometheus
metrics at /metrics and /healthz for
uptime monitors.
npm run doctor, or /scout doctor, checks
Slack, the code host, every repository, the model, backups and
the running Scout, one line each, and says how to fix what isn't
right.
Any secret can come from a file, a systemd credential or
1Password, and kill -HUP reads them again. Sandboxes
never get one.
A read-only dashboard, after spoond's, live over a stream: what Scout is working on now, its merge rate this week and the week before, which model is answering and what it falls back to, runs and sandboxes against their limits, recent threads, the learning loop, spend by model and by channel against its budget, the notes nobody has reviewed yet, reviews in progress and the schedules.
Node 24, Docker and git with access to your repositories. Give Scout its own code host account, token and SSH key, so its work is its own. The setup guide goes from nothing to Scout answering in a channel.
$ git clone https://github.com/jrimmer/scout.git && cd scout $ npm ci $ docker build -t scout-sandbox:latest sandbox # your repos' toolchains go in sandbox/Dockerfile $ cp .env.example .env # create the Slack app from slack-manifest.yaml $ npm run doctor # checks everything, says how to fix it $ npm start
Tell it who may ask for work (step 8 of the guide), then invite
Scout to a public channel and mention it. For the
learning loop, put profile/ in a repository of its own.