Skip to main content
Your app runs inside Bankroll on a phone, and the host opens only public HTTPS origins — so the development loop is not localhost:3000 in a browser tab. It is one command:
npm run dev is bankroll dev, from @joinbankroll/cli — a devDependency the starter already carries. It opens the app in Bankroll Desktop, which runs your app on your Mac the way the Bankroll app runs it on a phone: the same screen, taps and approval sheets, as a test user with test cash. No real money moves. Beside the app, Bankroll Desktop lists every call your app makes and every payment. Where the phone would stop and ask its user — consent, a payment, identity verification, a deposit — a sheet appears for you to answer, and a refusal reaches the app with the same error code it would get on a phone.

Bankroll Desktop

The command hands your project to Bankroll Desktop and ends once the app is up, printing its address. Bankroll Desktop runs your app’s dev server itself, with its log in its Server tab, and keeps running after the command returns. It starts the server with the settings a test user needs: your routes accept the test user’s session, and your server confirms test-cash payments with the SDK’s real code. Nothing made there is valid anywhere else, and your dev signing key is never used. The port is 3000 when it is free, so settings written for localhost:3000 work. The first npm run dev on a Mac with no Bankroll Desktop installs it, from downloads.joinbankroll.com, after asking; from then on it updates itself. Bankroll Desktop runs on macOS. On another computer, develop on your phone.

On your phone

The same app on a phone running Bankroll, with real sessions and real money. It starts your dev server on a free port, raises a public tunnel in front of it, reads your live manifest, and prints a QR code that opens the app inside Bankroll at its launch path. Scan it and you are developing against the real host — session, payments, and hot reload included.

The tunnel

The tunnel is a Cloudflare quick tunnel, and it gets a new URL on every restart — the host cannot reopen a previous one. “Can’t open this app” almost always means a dead tunnel: restart npm run dev -- --phone and scan the new QR. The dev server’s port doesn’t matter — the tunnel hides it — so the command picks any free one. Pass -p, --port <port> to pin it.

The QR outside a terminal

On a TTY the QR is drawn with ANSI colors. When stdout is not a TTY, a piped or backgrounded run, the command prints plain block glyphs instead, with the full play link under them, so the output can be re-printed into a chat and still scan. Setting NO_COLOR forces the same rendering on a TTY.

The dev signing key

The first npm run dev -- --phone creates a signing key at ~/.config/bankroll/keypair.json and injects it into the dev server’s environment as the treasury. It is never written into your project, so it cannot be committed. Pass -k, --keypair <path> to use a different one. That key is your app’s wallet while you develop: it receives every charge() and signs every payout, and it moves real mainnet HSUSD.
Fund the dev key with only what you are willing to risk, and give a deployment its own key — see Deploy. To exercise the whole money loop without spending real money, mint an app token and charge in that instead.

Plain localhost

npx next dev still works, for layout and UI work in a browser. It is the exception rather than the loop: a browser has no host bridge, so status() reads 'unavailable', session() and charge() are off the table, and your token-guarded routes answer 401. That is the app working as designed, not a bug.

The rest of the CLI

npx bankroll --help is the authority; the commands today:

Where local state lives

.env.local holds STORE=fs, BANKROLL_MOCK=1, and your app’s name (the Quickstart shows the three lines), and it is gitignored, so none of it reaches a deployment. With STORE=fs the store keeps its documents in plain files under bankroll/development/ in your project: open them and read what your app recorded. Tests write to bankroll/test/ instead, so a test run can never touch the store you develop against.