7b0315940b13b301b83405abb55661c850444482
CodexDash
CodexDash is a mobile-first dashboard for monitoring multiple OpenAI Codex accounts from one place.
Stack
- Frontend: React + Vite + TypeScript + Tailwind CSS + shadcn/ui-style components
- Backend: NestJS
- Database: Prisma + SQLite
- Auth: CodexDash email/password auth with JWT
What it does
- Create a CodexDash account and sign in
- Connect multiple OpenAI Codex accounts under one CodexDash account
- Start an integrated OpenAI login popup instead of pasting cookies manually
- Refresh Codex usage data and merge numeric usage fields into one aggregate dashboard
- Inspect each connected account individually with raw API payload details
OpenAI/Codex login flow
CodexDash now reuses the public-client OAuth/PKCE shape found in darvell/codex-pool, but wraps it in an app-native flow:
- The user clicks Connect OpenAI account.
- CodexDash API creates a short-lived PKCE login attempt.
- The web app opens the OpenAI authorization page in a popup.
- After successful login, OpenAI redirects back to the local callback bridge at
http://localhost:1455/auth/callback. - The callback bridge exchanges the authorization code for tokens, encrypts the session JSON in SQLite, and posts the result back to the main app window.
- If the callback bridge is unavailable, the user can copy the final
localhost:1455URL from the browser address bar and paste it back into CodexDash to finish the same login attempt manually. - CodexDash refreshes usage using the saved OAuth session and shows both the aggregate view and per-account details.
Important local-dev note
This flow works best when the local callback bridge is reachable on localhost:1455, but CodexDash now also supports a manual fallback where the user pastes the final callback URL if that port is unavailable. In local development, make sure that port is free if you want the automatic popup completion path.
Local development
bun install
cd apps/api && DATABASE_URL=file:./dev.db bunx prisma db push --accept-data-loss
cd ../..
bun run dev:api
bun run dev:web -- --host 0.0.0.0
Docker image
The production image uses a multi-stage build:
bun install+ frontend build in the builder stagebun build --compileto emit a single API executable atapps/api/dist/codexdash- the Prisma query engine shared library copied alongside the binary so the compiled app can still talk to SQLite
- the container auto-bootstraps the SQLite schema for fresh
file:databases before Prisma connects - a distroless non-root runtime image that only contains the compiled binary, Prisma engine library, and the built web assets
Build the image:
docker build -t codexdash:latest .
Run it:
docker run --rm \
-p 3001:3001 \
-p 1455:1455 \
-e JWT_SECRET=*** \
-e ENCRYPTION_SECRET=replac...hars \
-e DATABASE_URL=file:/app/data/codexdash.db \
-e CODEXDASH_FRONTEND_ORIGIN=http://localhost:3001 \
-e CODEX_OAUTH_REDIRECT_URI=http:/...back \
-v ./codexdash-data:/app/data \
codexdash:latest
Notes:
- The container serves the built React app from the same process on port
3001. - The bundled frontend now defaults to the browser's current origin for API calls, so the production image can be deployed behind any host name without rebuilding the web bundle.
VITE_API_BASE_URLis now optional and mainly useful for local development when Vite runs on a different origin than the API.CODEX_OAUTH_CALLBACK_BIND_HOST=*** keeps the callback bridge reachable through Docker port publishing while the public redirect URL can still stay onlocalhost:1455`.- Fresh SQLite
file:databases are initialized automatically on first boot, so a brand-new named volume can be used without runningprisma db pushinside the container. - Runtime assets now live under
/app: the compiled server is/app/codexdash, the built SPA is/app/web, the Prisma engine is/app/prisma/libquery_engine.so.node, and writable app data defaults to/app/data. - If you want host persistence, bind-mount a host directory to
/app/data(for example-v /home/processor/codexdash:/app/data) and keepDATABASE_URL=file:/app/data/codexdash.db. - If the callback bridge is still unreachable in your setup, the manual callback URL paste fallback remains available.
Environment variables
Root .env
JWT_SECRET=replace-me
ENCRYPTION_SECRET=replace-with-at-least-32-characters
DATABASE_URL=file:./dev.db
CODEXDASH_FRONTEND_ORIGIN=http://localhost:5173
CODEX_OAUTH_REDIRECT_URI=http://localhost:1455/auth/callback
# Optional in local dev when the web app does not share the API origin.
VITE_API_BASE_URL=http://localhost:3001
Verification
bun run lint
bun run test
bun run build
curl http://localhost:3001/health
API overview
POST /auth/registerPOST /auth/loginGET /auth/meGET /codex/accountsPOST /codex/accounts/login/startGET /codex/accounts/login/attempts/:attemptIdDELETE /codex/accounts/login/attempts/:attemptIdGET /codex/accounts/login/callbackGET /codex/accountsDELETE /codex/accounts/:accountIdGET /codex/usage-summary
Description
Languages
TypeScript
86.9%
JavaScript
11.3%
Dockerfile
1%
CSS
0.4%
HTML
0.4%