Written to be executed by a person or handed to an AI assistant with terminal access ("set this up for me, ask me only for what you need"). Every step says what to run, what you should see, and what to do if you don't. Steps marked [ASK THE HUMAN] need the owner's input or account action; an assistant must stop and ask rather than guess.
python3 --version # need 3.11 or newer
claude --version # need the Claude Code CLI installed
If claude is missing, install it from https://claude.com/claude-code and
[ASK THE HUMAN] to sign in: they run claude once interactively, or
for a headless machine claude setup-token, then put the printed token in
~/.scout/env as one line: CLAUDE_CODE_OAUTH_TOKEN=<token>. An assistant
must never handle the token value itself.
Verify judgment works before continuing:
echo "Reply with exactly: ok" | claude -p - --output-format json
Expect a JSON envelope whose result is ok. A 401 here means sign-in is
incomplete; fix that first — nothing downstream works without it.
git clone https://github.com/ammarphp/scout scout && cd scout
python3 -m pip install -e ".[test]"
python3 -m pytest # expect: all tests pass; takes ~10 seconds
If tests fail on a fresh clone, stop and open an issue; do not continue.
Option A — the interview (recommended). [ASK THE HUMAN] for their resume as a text or markdown file (any PDF can be exported to text first):
python3 -m scout.cli interview --resume /path/to/resume.txt
The judge drafts your pack, then asks 3–6 questions in the terminal (work authorization if unclear, location flexibility, hard anti-targets). The human answers; enter skips a question. The command ends by validating.
Option B — by hand. Copy the example and edit every file:
cp -r candidate-example candidate
The eight files are commented; constraints.toml matters most — it is the
switchboard deciding which disqualifiers (visa sponsorship, citizenship,
clearance, PhD) are hard kills for you versus mere annotations.
Either way, finish with:
python3 -m scout.cli validate # expect: "validates clean"
Fix anything it names; the messages say which file and what to add.
candidate/universe.json is your company list. The example ships a small
starter; add companies as {"name", "slug", "tier": "1"|"2"|"3", "thesis", "boards": [{"ats", "token"}]} — for greenhouse the token is the company
slug in their job-board URL. Then:
python3 -m scout.cli seed --probe # loads companies, probes each board
python3 -m scout.cli poll # fetches postings + JDs, scores
First poll on a large universe can run a while and may pause at your plan's usage window — that is by design; the next poll resumes where it stopped. Check results:
python3 -m scout.cli status
python3 -m scout.cli serve & # dashboard at http://127.0.0.1:8777
macOS:
python3 -m scout.cli sched install # launchd: 6 polls/day, digest, doctor
python3 -m scout.cli sched status
Linux (cron equivalent — the commands are plain CLI calls):
crontab -e
# 5 7,10,13,16,19,22 * * * cd /path/to/scout && python3 -m scout.cli poll
# 45 7 * * * cd /path/to/scout && python3 -m scout.cli digest
# 30 8 * * * cd /path/to/scout && python3 -m scout.cli doctor
- Phone pushes: install the ntfy app, pick a long random topic name,
subscribe to it in the app, and add
SCOUT_NTFY_TOPIC=<topic>to~/.scout/env. Treat the topic like a password. - Email digest: [ASK THE HUMAN] for a Gmail app password (Google
Account → Security → App passwords) and add
SCOUT_SMTP_USER,SCOUT_SMTP_APP_PASSWORD,SCOUT_DIGEST_TOto~/.scout/env. Until then the digest saves to~/.scout/digests/.
python3 -m scout.cli doctor # exit 0 clean; every failure names its fix
The pipeline also checks itself at the end of every poll (fetch starved, scoring starved, judge failing, backlog rising) and pages your ntfy topic on a fault. Board APIs drift; a failing board shows on the dashboard's System page with its error, and auto-disables after ~5 days of continuous failure rather than failing silently forever.