# Start Codex Pooler Locally

Use this guide to get from a fresh checkout to a local Pool API key you can put in a Codex or OpenAI-compatible client.

## Quick Setup Summary

To start Codex Pooler locally, generate a private `.env`, start the Docker Compose stack, create the first owner, create a Pool, assign one upstream account, create a Pool API key, and point a client at `/backend-api/codex` or `/v1`. Use `/mcp` only for operator metadata with a separate MCP token.

## What You Need

- Docker with Compose
- Git, if you are cloning the repository
- `openssl`
- A browser for the owner setup and admin UI
- At least one Codex account to link with OpenAI OAuth or import from `auth.json` when you create your first upstream
- For hosted invite onboarding or OAuth device-code fallback, access to the account's ChatGPT settings so device-code authorization can be enabled

## 1. Start Codex Pooler

Clone the repository, generate local secrets, and start the app with Postgres.
For normal use, select a versioned, tagged stable release from [GitHub Releases](https://github.com/icoretech/codex-pooler/releases). The `latest` image tag follows verified stable releases and does not move backward when an older version is published again. A version tag keeps the installation reproducible. Run from source only for local development.

```bash
git clone https://github.com/icoretech/codex-pooler.git
cd codex-pooler

# Run the latest tagged stable release. Find its version at
# https://github.com/icoretech/codex-pooler/releases, then substitute it here.
export CODEX_POOLER_IMAGE_TAG=<release-tag>

scripts/self-host/generate-env.sh
docker compose pull
docker compose up -d
```

The first run pulls the app and Postgres images, waits for Postgres health, runs the migration container, then starts the web app.

Open [http://localhost:4000](http://localhost:4000). The first page should take you to owner setup.

To verify that before opening a browser:

```bash
curl -sS -D - -o /dev/null http://localhost:4000/ | grep -i '^location: /bootstrap'
curl -fsS http://localhost:4000/bootstrap/status
```

The status endpoint should return `{"status":"ok","bootstrap":"pending"}` on a fresh database.

If the page does not load, check the containers and app logs:

```bash
docker compose ps
docker compose logs -f app
```

Use [http://localhost:4000](http://localhost:4000) for the default Compose stack even if the Phoenix startup banner prints an endpoint URL such as `https://localhost`; the Compose port mapping is the local URL to open.

## 2. Create The Owner Account

Create the first account from the bootstrap screen. This account is the instance owner, so store the password somewhere safe.

After setup, sign in and keep these admin pages open as your first-run checklist:

- [Pools](http://localhost:4000/admin/pools)
- [Upstreams](http://localhost:4000/admin/upstreams)
- [API keys](http://localhost:4000/admin/api-keys)

Use separate operator accounts later for day-to-day work. Keep the bootstrap owner for instance-wide administration.

## 3. Create A Pool

Open [Pools](http://localhost:4000/admin/pools) and create your first Pool.

A Pool is the capacity boundary your clients use. API keys attach to a Pool, and Codex Pooler chooses an eligible upstream account inside that Pool for each request.

For a local trial, one Pool is enough. Use a plain name such as `local-dev` or `default`.

## 4. Add An Upstream Account

Open [Upstreams](http://localhost:4000/admin/upstreams) and link, import, or invite a Codex account.

Treat linked or imported Codex account material as owned by Codex Pooler after setup. Do not keep the same imported credential active in other automation unless you accept that provider refresh-token rotation can force one copy to reauthenticate.

For new operator-managed upstream accounts, prefer `OAuth` on `/admin/upstreams` when browser authorization is practical. If you use a Pool invite or the OAuth device-code fallback, the user must enable OpenAI's device-code approval for Codex first. For a personal ChatGPT account, open Settings, then Security, and turn on `Enable device code authorization for Codex`. For workspace-managed accounts, ask a workspace admin to enable device-code login for Codex in the workspace permissions. Browser OAuth linking does not depend on that setting. OpenAI's [Login on headless devices](https://developers.openai.com/codex/auth#login-on-headless-devices) docs describe device-code login.

After linking or import, assign the upstream to the Pool you created when needed. The upstream should show as usable before you expect client requests to route successfully.

## 5. Create A Pool API Key

Open [API keys](http://localhost:4000/admin/api-keys) and create a key for your Pool.

Copy the raw key immediately. Codex Pooler shows it only once. Store it in the client environment variable you plan to use, for example:

```bash
export CODEX_POOLER_API_KEY="<pool-api-key>"
```

The Pool API key represents the Pool, not one upstream account. Do not use this key for `/mcp`; operator MCP tokens are separate.

## 6. Point Your First Client At The Gateway

For Codex backend clients, use the backend compatibility route:

```text
Base URL: http://localhost:4000/backend-api/codex
Authorization: Bearer <pool-api-key>
```

For OpenAI-compatible SDK clients, use the narrow `/v1` route:

```text
Base URL: http://localhost:4000/v1
Authorization: Bearer <pool-api-key>
```

For trusted operator metadata tools, use `/mcp` with an operator MCP token, not a Pool API key:

```text
MCP URL: http://localhost:4000/mcp
Authorization: Bearer <operator-mcp-token>
```

For deployed instances, replace `http://localhost:4000` with your deployed host, for example `https://codex-pooler.example.com`.

## If Something Is Stuck

Use these checks only when the page or client path is not behaving as expected.

```bash
docker compose ps
docker compose logs -f app
curl -fsS http://localhost:4000/healthz
curl -fsS http://localhost:4000/readyz
```

If the app is running but client requests fail, check the Pool assignment first: the Pool needs an active API key, at least one usable upstream assignment, and a model the upstream account can serve.

To stop the local stack:

```bash
docker compose down
```

To remove the local database too:

```bash
docker compose down -v
```

## Safety Notes

Give Pool API keys only to trusted clients. Keep MCP tokens separate from runtime credentials. Do not paste prompts, tokens, cookies, account secrets, or imported account material into support requests.