haystack verify
Run your app with and without a change, explore both side by side, and see what the change broke.
Set up
npm install -g @haystackeditor/cli
haystack login # GitHub sign-in: open the URL it prints and enter the code
haystack init # shows what it will change, then starts onboarding your app
There is no configuration file. Haystack works out how to run your app from what the repository already keeps working: lockfiles, Dockerfiles, compose files, package scripts.
haystack init shows each change it will make as a diff and makes them when you agree: a Claude Code Stop hook that prepares each change for haystack verify (per developer, kept out of commits), and a short note in AGENTS.md telling coding agents to run haystack verify after a change. Then it starts onboarding: Haystack reads the repository, builds the app, starts it with its databases and services, prepares its data and test accounts, and proves one workflow works. The first onboarding can take half an hour, and runs in the background.
Or let your coding agent do all of it. Paste this into Claude Code, Codex or Cursor:
Set up Haystack for me: fetch https://haystack.sh/agents.md and follow it
How a crawl works
A crawl builds your app twice, once at the base (the merge base of your HEAD and origin's default branch) and once with your change, starts from the code you changed, and explores outward with both side by side. It double-checks and judges every difference it finds. The only difference between the two copies is your change, so a difference in behaviour is caused by it.
Both copies run on Haystack's isolated machines with no internet access, with stand-in data and test accounts made during onboarding. Nothing touches your production systems.
Running it
haystack verify # your change, as it is in your checkout right now
haystack verify --minutes 10 # give the crawl longer
haystack verify --json # the same report as one JSON document
Run it inside your checkout; nothing needs committing or pushing. It names the changed files it checks, waits for the crawl, and prints each step and each bug as the crawl finds it. The answer often comes 10 to 15 minutes after you start, most of it spent building and preparing both versions of the app. Ctrl-C stops waiting, never the crawl: run it again to pick up the same crawl.
| Option | Purpose |
|---|---|
| --minutes <n> | How long the crawl may take, 1 to 30. Default 3 |
| --no-wait | Print the crawl's current state and return |
| --json | The report as one JSON document (see haystack schema verify) |
| --raw | The crawl's whole record as one JSON document, for scripts (large) |
| --repo <owner/repo> | GitHub repository, when origin is not it |
| --account <login> | Use a specific saved Haystack account |
| Exit code | Meaning |
|---|---|
| 0 | The crawl answered; the bugs it found are in the output |
| 1 | The command failed |
| 2 | The crawl or onboarding stopped before finishing; run it again |
| 3 | Onboarding is blocked; the output says what would unblock it |
| 4 | The handshake: run it again with --intent (and any --idea) |
| 5 | The app copy is broken; the change could not be tested |