Runbook: local development setup on Windows
This runbook sets up sesame-bun on a Windows machine, runs it, and covers common problems. The short version is in the README. Commands are given for PowerShell unless marked Git Bash. Run them from the repository root.1. Install the prerequisites
The
OpenJS.NodeJS.LTS package follows the current LTS line. If it installs a version
other than 24, install Node 24 from https://nodejs.org instead.
Close and reopen the terminal so the new PATH applies, then check:
openssl, which the Git Bash commands below
use.
2. Install the dev tools and prepare the repo
task tools installs the dev tools the other tasks call: linters, formatters and code
generators. task setup prepares a fresh clone: dependencies and git hooks. Both are
defined in Taskfile.yml; read it for the exact steps and versions.
Go tools installed with go install go to the bin folder under go env GOPATH
(by default %USERPROFILE%\go\bin). That folder must be on PATH. Check with:
task tools again after pulling a change to the tool versions.
3. Create .env
.env is ignored by git. Never commit it and never paste its contents into an issue,
PR or log.
Task loads the root .env when it runs a task. The backend reads only environment
variables and does not open .env itself. If you run the backend binary directly, set
the variables in the shell first.
Required variables
UI_PASSWORD_HASH: the argon2id hash of the password you log in with.
$argon2id$. Put
it in .env in single quotes:
$name in unquoted and double-quoted
values, which would remove parts of the hash. Single-quoted values are read as they are.
SESSION_SECRET: at least 32 bytes, hex or base64 encoded. To generate 32 random
bytes as hex:
PowerShell:
Optional variables
.env.example has the defaults and accepted values for each variable. The backend
refuses to start while GEOBLOCK_URL, POLYMARKET_PRIVATE_KEY, or any
POLYMARKET_RELAYER_* or POLYMARKET_BRIDGE_URL variable is set; delete them from an
older .env.
Leave POLYMARKET_SESSION_KEY empty on this development server. It is in a blocked
location, so the Session Key has no use here (security finding F8). The public
POLYMARKET_WALLET_ADDRESS alone is enough for positions, activity and P&L; open orders
and cash then report credentials_unavailable. Otherwise use task dev:fake for account
screens. Setting up real credentials on a host in a permitted location is covered in
session-key-setup.md.
4. First run
- the Go backend on
127.0.0.1:8080, serving the REST API under/apiand the WebSocket at/ws; - the Vite dev server on
localhost:5173, which serves the frontend and proxies/apiand/wsto the backend.
localhost,
not 127.0.0.1 or the machine’s IP address: the Vite dev server binds to localhost
only.
Check that the backend is up:
curl -s http://127.0.0.1:8080/api/health. In PowerShell 5.1, curl is
an alias for Invoke-WebRequest; use curl.exe for the real curl.
The public health check returns only {"status": "ok"} or {"status": "degraded"}.
The version, trading state, geoblock result and feed health are on GET /api/status,
which needs a session
(ADR 0008). After logging in, open
http://localhost:5173/api/status in the same browser, or look at the status indicator
in the app.
On a machine in a location that Polymarket blocks, /api/status shows
"trading_enabled": false and "blocked": true, and the startup log records the
geoblock status. This is expected; see
ADR 0005. Read-only work is unaffected.
Stop task dev with Ctrl+C.
Run on a fake venue
For UI work that does not need Polymarket, start the app with:SESAME_FAKE_VENUE=1 so
it takes market data from a fake venue instead of Polymarket. Use it for UI work only;
check anything that depends on real venue behaviour with task dev.
5. Everyday commands
6. Regenerate code from the API spec
api/openapi.yaml is the source of truth. The generated code lives in:
backend/internal/httpapi/gen(Go,oapi-codegen)frontend/src/lib/api/gen(TypeScript,openapi-typescript)
task gen overwrites them. If the Go or
TypeScript build reports a type that does not match the spec after a pull, run
task gen.
7. Reset the local database
The SQLite database lives indata/ (or DATA_DIR). Deleting it removes settings,
login sessions, the watchlist, layouts, the order audit log and cached market data.
The migrations recreate an empty database on the next start.
-
Stop
task dev. -
Delete the folder:
Git Bash:
rm -rf data -
Run
task devagain and log in.
8. Troubleshooting
A port is already in use
The backend needs port 8080 and Vite needs port 5173. Find the process holding a port:netstat -ano | findstr :8080, then look up the PID in Task Manager.
Usually it is an earlier task dev that did not exit. Stop it:
HTTP_ADDR to another port. The Vite proxy target is
configured in the frontend; check frontend/vite.config.ts so that it points at the same
port.
The backend exits at startup with a missing or invalid variable
The backend validates its configuration at startup and exits when a required variable is missing or invalid. Check that:.envexists in the repository root (not inbackend/);UI_PASSWORD_HASHandSESSION_SECRETare set and not empty;SESSION_SECRETdecodes to at least 32 bytes (64 hex characters);- you started the backend through Task, which loads
.env.go runon its own does not.
Login fails with the right password
UI_PASSWORD_HASHis not in single quotes, so$parts were expanded. Quote it and restarttask dev..envwas edited whiletask devwas running. Task reads.envonly at start; restart it.- Too many failed attempts. Login is rate limited and returns HTTP 429; wait and try again.
Requests fail with 403 after login
Mutating requests need the session cookie and a CSRF token. If the session has expired, reload the page and log in again.task or a tool is not recognized
task: reopen the terminal after installing, or checkwinget list --id Task.Task.golangci-lint,gofumpt,oapi-codegenand other Go tools: add the Gobinfolder toPATH(section 2) and reopen the terminal.
Trading shows as disabled
Log in, then checkGET /api/status (open http://localhost:5173/api/status in the
same browser):
geoblock.blocked: true: the location is blocked, or the check has not succeeded yet (geoblock.errorthen holds the reason). Trading stays off. The app has no setting that changes this.LIVE_TRADINGis anything other than the exact stringtrue.
Files show as changed right after checkout
.gitattributes checks text out with LF line endings. If your editor saves CRLF, set it
to use LF for this repository. Files under testdata/ are kept byte for byte; do not
reformat or re-save them.