Getting started
brew install adrianmross/tap/pursuit
pursuit serveLinux and Windows binaries, and the browser extension zip, are on GitHub Releases . To build from source you need Go 1.26 and Node 22: make build builds the embedded dashboard and docs, then bin/pursuit.
With no database URL the daemon creates ~/.local/share/pursuit/pursuit.db and listens on :8787. The first start logs a bootstrap token once — save it, it is not written to disk.
export PURSUIT_TOKEN=pst_...
export PURSUIT_SERVER=http://127.0.0.1:8787
pursuit import seed
pursuit list --status to_apply --fields id,company,title,statusOr sign the CLI in through the dashboard instead of exporting a token. pursuit auth login opens the dashboard’s /authorize page; sign in, check the scopes, and approve. On a machine with no browser (SSH, no display) or with --device, it prints a short code; type it at /device yourself (links never pre-fill it). The token is stored per server in the OS keyring (macOS Keychain or Linux Secret Service) or, without one, in ~/.config/pursuit/credentials.json (mode 0600). It gets read and write, or less with --scope read. It never gets approve: approving stays in the dashboard, or in an approve token you mint yourself and pass as PURSUIT_TOKEN. PURSUIT_TOKEN and --token still win over a stored login. Any process running as you that calls the CLI without them, an agent included, uses the stored login; that is at most read,write, the same as an agent token. A Keychain item written by /usr/bin/security can be read back by any process running as your user, so on macOS it protects no better than the 0600 file against a local agent.
pursuit auth login --server http://127.0.0.1:8787
pursuit auth status
pursuit auth logoutOn a deployment with account sign-in (Neon Auth), “Forgot password?” on the sign-in card emails a 6-digit code; enter it with a new password and you are signed in.
To hand Pursuit to a coding agent, open Connect an agent (/agents) in the dashboard. It has a prompt to paste (the agent installs the CLI and starts a device login, with no token in the prompt), the Agent Skill (served at GET /skill.md; npx skills add adrianmross/pursuit --skill pursuit), and a read,write token for headless agents.
Agents can also get a read or read,write token from a human; the server’s GET /auth.md (AUTH.md ) explains tokens, scopes, and approval.
Applicant profile
Answers and the résumé file stay outside the repo:
export PURSUIT_PROFILE=$HOME/.config/pursuit/profile.json
export PURSUIT_RESUME_FILE=$HOME/.config/pursuit/resume.pdf
export PURSUIT_CONTACT_EMAIL=you@example.comprofile.json is {"answers": {"email": "...", "work_authorization": "..."}}. Keys match form questions after lowercasing and turning other characters into underscores (why_us, cover_letter).
Postgres, for more than one replica
export PURSUIT_DATABASE_URL='postgres://pursuit:pursuit@127.0.0.1:5432/pursuit?sslmode=disable'
pursuit serveUse sslmode=require for Neon. Queue claims use SELECT ... FOR UPDATE SKIP LOCKED; the link sweep takes a Postgres advisory lock so only one replica checks postings. devenv up --profile postgres starts Postgres and two replicas on ports 8787 and 8788. docker compose up --build runs the same stack in Docker; docker-compose.yml is generated from devenv.nix (devenv tasks run dev:compose).
The dashboard
pursuit serve embeds a small web dashboard at the same address as the API. Open it and paste a token once — the browser keeps it in localStorage and sends it as Authorization: Bearer. A read token can browse; Approve and Reject need approve; re-checking a posting needs write.
Browser extension
extension/ is a Manifest V3 extension that saves the posting you have open and fills Greenhouse, Ashby and Lever application forms. It does not crawl, and it never clicks Submit.
cd extension
npm install
npm run buildPair it from the popup with the server URL and a token that has write and not approve (mint one with pursuit tokens create).