Skip to main content
The whole desk runs locally: Vite serves the dashboard and the widget, and the Worker runs in the real Workers runtime with local D1, R2, Queues and Durable Objects. Only Workers AI calls go to Cloudflare.

Run the desk

You need Node 22.18 or later and a Cloudflare account (for Workers AI).
1

Clone and install

2

Set a local setup token

Open .dev.vars and set SETUP_TOKEN to any passphrase of 16 or more characters:
.dev.vars
3

Sign in to Cloudflare for Workers AI

Locally, Workers AI still calls Cloudflare, so Wrangler needs a login:
If your login can see more than one Cloudflare account, put the one to use in a .env file at the repo root (it’s gitignored):
.env
4

Start the dev server

This applies the D1 migrations to the local database, then starts Vite with the Worker. Open http://localhost:5173 and create the owner account with your local SETUP_TOKEN.
The dev server listens on 127.0.0.1, because Sign in with ChatGPT must return to a 127.0.0.1 loopback address. Open the desk as http://localhost:5173 all the same: browsers don’t allow passkeys on a bare IP address. The ChatGPT sign-in returns through 127.0.0.1 and lands you back on localhost.
Local state (database, files, Durable Objects) lives in .wrangler/. Delete .wrangler/state to start over with a fresh desk.

Sign in with ChatGPT locally

Locally, ChatGPT sign-in returns to the dev server by itself: in Settings → AI, choose ChatGPT sign-in (your plan), press Sign in with ChatGPT, approve, and you’re back on the desk. Replies spend your own ChatGPT plan. It’s for your own use only, per OpenAI’s terms. See Models.

Try the widget

public/demo.html is a test page that pretends to be a customer site. Open it with your widget key (from Chat widget → Install):
  • Pay invoice calls a request that fails with a server error, so you can see debug context reach the AI and the inbox.
  • Add &consent=required to try consent mode, then run JunDesk.consent(true) in the browser console.
In development the widget frame runs on React. The built frame runs on Preact. After widget changes, check them on a build too: npm run build, then npm run preview.

Commands

End-to-end tests

The end-to-end suites drive a real dev server: they create the owner with a software passkey, open widget sockets, wait for real AI answers and run the jun CLI. They run on their own server and database, so your own local desk isn’t wiped.
1

Log in to ChatGPT for the AI (once)

The suites answer with real AI through your ChatGPT login:
To use Workers AI instead, set E2E_AI_PROVIDER=workers-ai when you run the tests.
2

Start a separate server

JUN_STATE_DIR gives Vite its own local state folder; --persist-to points the migrations at the same one.
3

Run the suites

In another terminal:
npm run test:e2e runs these suites in order: e2e-auth, e2e-chat, e2e-ai, e2e-debug, e2e-agent, e2e-visitors, e2e-polish, e2e-inbox, e2e-metrics, e2e-issues, e2e-knowledge, e2e-assignment, e2e-topics, e2e-notifications, e2e-openers, e2e-actions and e2e-widgets. You can run one on its own, for example BASE_URL=http://localhost:5174 node scripts/e2e-chat.ts. The tests read SETUP_TOKEN from the environment or from .dev.vars. e2e-agent and e2e-visitors call httpbin.org as a stand-in for your API. Crawl tests use a public URL, because the local Worker can’t fetch its own dev server. scripts/bench-models.ts compares Workers AI chat models on five support questions; run it against the e2e server. scripts/upgrade-check.ts checks an upgrade from an older version; see Upgrade.

Project layout

packages/ TypeScript runs directly on Node with type stripping, with no build step: use only erasable syntax (no enums or namespaces) and .ts extensions on relative imports. CLAUDE.md in the repo has the full conventions.

Contributing

Run npm test, npm run typecheck and the end-to-end suites before you open a pull request. Outside contributions will need a contributor licence agreement (CLA); the agreement and its bot aren’t set up yet, so open an issue before starting a large change. See CONTRIBUTING.md.

How it works

The architecture behind the code.

Deploy to Cloudflare

Ship your local checkout to your account.