Run Polo locally
The local launcher, scripts/local_product.py, runs every Polo process on one computer: the API, the outbox relay, the scheduler, the Python worker and the services they depend on. Use it to try Polo, to develop against it and to verify changes. It is not a deployment tool; for a server, use Docker Compose or the Helm chart.
Requirements
Section titled “Requirements”- Node 24 or newer
- Python 3.12 with uv
- Docker
- The Temporal CLI
- A MinIO server binary
- An OpenAI-compatible model endpoint, or a Claude or ChatGPT subscription (see below)
Start a local model
Section titled “Start a local model”Any OpenAI-compatible endpoint on loopback works. For a free local model, run llama-server:
llama-server -m /path/to/Qwen3.5-9B-Q5_K_M.gguf --alias polo-local-qwen35 \ --host 127.0.0.1 --port 8097 -c 32768 -ngl 99 -fa on --jinja --no-ui --reasoning offInitialise and serve
Section titled “Initialise and serve”-
Install the Python dependencies from the repository root:
Terminal window uv sync --locked -
Initialise once. This writes the private configuration and generates every local secret:
Terminal window python3 scripts/local_product.py init --minio /path/to/minio \--local-model-url http://127.0.0.1:8097/v1 --local-model-id polo-local-qwen35--local-model-urland--local-model-idgo together, and the URL must be a loopback address. Leave both out if you will only use a subscription.initrefuses to overwrite an existing configuration. -
Serve:
Terminal window python3 scripts/local_product.py serve --allow-local-probes -
Open
http://127.0.0.1:8088(orhttp://localhost:8088; both loopback names are accepted) and choose Create a workspace.
serve builds the API and starts:
- PostgreSQL and Redis in a private Compose project (
compose.product.local.yaml) - a Temporal dev server
- MinIO
- the API on
http://127.0.0.1:8088 - the relay, the scheduler and the Python worker
It stops with an error if Node, npm, Docker, the Temporal CLI or the configured MinIO binary is missing, or if one of its ports is already in use.
Launcher options
Section titled “Launcher options”| Option | Purpose |
|---|---|
--directory |
The private state directory. Default ~/.local/share/polo/product-local. |
--minio |
Path of the MinIO server binary. Defaults to minio on your PATH. |
--local-model-url, --local-model-id |
The loopback model endpoint and the model name it serves (init). |
--embedding-model |
Path of a local embedding model file; serve then also needs llama-server. |
--allow-local-probes |
Lets uptime monitors probe loopback endpoints and lets MCP fixture servers on loopback be registered (serve). |
A loopback model route gets a placeholder credential, and three times the hosted activity time limits and run claim, because local models answer slowly.
Where state lives
Section titled “Where state lives”Everything the launcher keeps is under ~/.local/share/polo/product-local/ (or the directory you passed with --directory). The directory must have mode 0700 and must not be a symbolic link.
| Path | Content |
|---|---|
config.json |
Ports, generated passwords, worker tokens and encryption keys |
models.json |
The model registry the worker reads |
logs/ |
One log per process |
workspaces/ |
Task workspaces of the engineering sandbox |
snapshots/ |
Workspace snapshots |
objects/ |
MinIO object storage (artifacts) |
temporal/ |
The Temporal dev server’s state |
codex-home/ |
Polo’s own Codex sign-in, when you add a ChatGPT subscription |
The default ports are 8088 (API), 55438 (PostgreSQL), 6398 (Redis), 7238 (Temporal), 8238 (Temporal UI), 9008 and 9009 (MinIO and its console).
The API serves the ui/ folder from an in-memory snapshot, so a change to the UI needs an API restart: stop serve and start it again.
Use your own Claude or ChatGPT subscription
Section titled “Use your own Claude or ChatGPT subscription”Instead of an API key or a local model, Polo can think with your own Claude plan (through Claude Code) or ChatGPT plan (through Codex).
-
Start
serveand create your workspace. -
Name the workspace by the address in its sign-in link:
Terminal window python3 scripts/local_product.py subscription --provider claude --workspace <workspace address>python3 scripts/local_product.py subscription --provider codex --workspace <workspace address> -
Restart
serve. -
Open Settings → AI models. The model shows as “Claude subscription” or “ChatGPT subscription (Codex)”. Choose it for an agent on the Agents page.
What each provider uses:
- Claude uses the Claude Code sign-in already on this computer. Sign in first with
claude auth loginand your Claude plan. The model defaults tosonnet; pass--model opusor a model ID to change it. - Codex gets its own sign-in for Polo, in
codex-homeinside the state directory. The first run opens a ChatGPT sign-in there. Polo never copies your own~/.codexsign-in, because two copies of one sign-in invalidate each other when Codex refreshes it. The model defaults to the one your Codex uses.
Other options of the subscription action: --cli names the claude or codex executable when it is not found on its own, --effort low|medium|high sets the model’s reasoning effort, and --remove takes a workspace off, or removes the route when no workspace is named.
How a subscription call runs
Section titled “How a subscription call runs”Each call runs the CLI in an empty directory with no tools, none of your own CLI settings, hooks, plugins or MCP servers, and none of Polo’s credentials. It returns only a typed answer. Calls are counted in tokens, not dollars, and your plan’s own limits apply: when the plan’s limit is reached, the task stops and says when it resets.
Next steps
Section titled “Next steps”- Quickstart: give Polo its first task.
- Runners: start a customer runner next to the launcher so agents can propose real changes.
- Testing: run the test suites against disposable services.