Use this guide before you open a pull request or cut a release. Every command runs from the repository root unless a step says otherwise.
Prerequisites
- Bun 1.4 or later (the repository pins
bun@1.4.2). - Dependencies installed with
bun install. - For the smoke tests only: a local dev server (see Run it locally), plus
curl,python3and ripgrep (rg) on yourPATH. The smoke scripts callrgdirectly and fail without it.
Run everything at once
bun run checkcheck runs the typecheck, the format check, the Worker tests and the script tests in that order, and stops at the first failure. It does not run the smoke tests. Run it before every push.
Run one part
Typecheck
bun run typecheckRuns
tsc --noEmitover the project.Check formatting
bun run lintRuns
prettier --checkoversrc/,test/, the setup, deploy and eval scripts,vitest.config.ts,tsconfig.jsonandpackage.json. If it reports files, fix them with:bun run formatRun the Worker tests
bun run testRuns Vitest with
@cloudflare/vitest-pool-workers, so the tests intest/**/*.test.tsexecute inside workerd, the same runtime as a deployed Worker. The pool readswrangler.local.jsonc, applies the schema inschema/to a local D1 database, and uses synthetic bindings set invitest.config.ts(passwordlocal-dummy-password,example.comsenders). Remote bindings are off andtest/setup.tsreplacesfetchwith a stub that throws, so no test reaches the network. Test files run one at a time.To run one file, or the tests whose name matches a pattern, pass Vitest arguments after
--:bun run test -- test/csv.test.ts bun run test -- -t "pending imports"Run the script tests
bun run test:scriptsRuns
bun test scripts/. This covers the deploy helpers, the schema check, the release versioning (scripts/version.test.ts) and the extraction eval (scripts/eval-extraction.test.ts, see Measure extraction quality). To run only the release tests:bun run test:release
Smoke test a running dev server
The smoke tests send real HTTP requests to a running app. They upload scripts/sample-receipts/sample.pdf, import scripts/sample-receipts/bank.csv, check the match on the Bank page and the monthly CSV, then send synthetic emails to the local email endpoint and check which are kept, held for review or dropped.
Start the dev server
In one terminal:
bun run migrate bun run devwrangler.local.jsoncsetsAI_MODEtomock, so no Workers AI calls are made.Run the smoke scripts
In a second terminal, pass the password from your
.dev.vars:NUITS_PASSWORD='your-local-password' bun run smokesmokerunsscripts/smoke.shand thenscripts/smoke-email.sh. Both read these environment variables:Variable Default What it sets SMOKE_URLhttp://localhost:8787The app to test NUITS_PASSWORDlocal-dummy-passwordThe sign-in password SMOKE_USERownerThe sign-in user name Responses are saved under
.audit/smoke/and.audit/smoke-email/, which git ignores.
Check it worked
bun run checkexits with status 0 and the last Vitest and Bun summaries report no failures.bun run smokeprints two lines that start withPASS, one per script.
If a smoke step fails, open the saved response for that step in .audit/smoke/ to see what the app returned.
Build the docs site
The docs live in docs-site/, a separate Bun project. To preview and build them:
cd docs-site
bun install
bun run dev
bun run buildbun run dev serves the site locally with live reload. bun run build builds the site, nests it under the /docs/ base, then runs scripts/check-copy.mjs, which fails the build on banned phrases and long dashes. To run only the copy check on the page sources:
bun run check:copyThe rules for what to write, and the page map that internal links must follow, are in docs-site/WRITING.md.