Cursor BYOK + ngrok
Use this API as a custom OpenAI-compatible endpoint for Cursor Chat, Cmd+K, and Agent. Tab autocomplete ignores custom endpoints.
Localhost doesn’t work
Cursor BYOK goes through Cursor’s cloud. Private addresses get rejected:
Access to private networks is forbidden
Don’t set the base URL to http://127.0.0.1:8088/v1 or http://localhost:8088/v1. You’ll often see an OpenAI key error and nothing in your local server logs — Cursor never reached you.
You need a public HTTPS tunnel. This repo’s Compose overlay assumes a free ngrok domain you reserve yourself.
Prerequisites
- Clone, auth, and start the API (Compose or
go run). - An ngrok authtoken.
Confirm the API locally first (curl only):
curl -s http://127.0.0.1:8088/health
Use your own free ngrok domain
Reserve a free domain in the ngrok dashboard, then set NGROK_DOMAIN to that hostname — for example:
YOUR_SUBDOMAIN.ngrok-free.dev
Please don’t commit a personal reserved domain into this repo.
Background via Docker (recommended)
NGROK_AUTHTOKEN=... docker compose -f docker-compose.yml -f docker-compose.ngrok.yml up -d
- API + ngrok restart with
unless-stopped - Inspector: http://127.0.0.1:4041
- Cursor base URL:
https://YOUR_SUBDOMAIN.ngrok-free.dev/v1
Host ngrok
If the API is already on 127.0.0.1:8088:
ngrok http --url=YOUR_SUBDOMAIN.ngrok-free.dev 8088
Cursor settings
| Field | Value |
|---|---|
| OpenAI API Key | local-open-agent-api (any non-empty string) |
| Override OpenAI Base URL | https://YOUR_SUBDOMAIN.ngrok-free.dev/v1 |
| Model | Exact public ID — see catalog |
Again: no http://127.0.0.1… or http://localhost… base URL.
Handy slugs to add in Cursor:
gpt-5.6-terra
gpt-5.6-sol-high
gpt-5.6-sol-fast
gpt-5.6-terra-fast
gpt-5.6-luna-fast
gpt-5.4-fast
gemini-3.1-flash-lite
gemini-3.1-pro-high
claude-sonnet-4-6
haiku
sonnet
opus
fable
gpt-5.3-codex-spark
| Use case | Model ID |
|---|---|
| Everyday Agent | gpt-5.6-terra |
| Hard tasks | gpt-5.6-sol-high |
| Fast frontier Agent | gpt-5.6-sol-fast |
| Fast everyday Agent | gpt-5.6-terra-fast |
| Fast lightweight Agent | gpt-5.6-luna-fast |
| Fastest cheap turn | gemini-3.1-flash-lite |
| Claude Code fast | haiku |
Codex -fast aliases request the upstream priority service tier (advertised
as roughly 1.5× speed with increased usage); they are not merely low-effort
shortcuts.
After changing the base URL or models, open a new Agent chat — old ones can keep poisoned history.
How Agent tool calling works over the wire: Cursor tool conventions.
Validate the tunnel
curl -s https://YOUR_SUBDOMAIN.ngrok-free.dev/health
curl -s https://YOUR_SUBDOMAIN.ngrok-free.dev/v1/models | jq '.data[].id'
In a new Agent chat:
List the files in this repo.
You should see real tool execution and matching POST /v1/chat/completions lines in docker compose logs -f api.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
Access to private networks is forbidden | Localhost / private base URL | Use the ngrok https://…/v1 URL |
Unauthorized User Openai API key and no server log | Cursor never reached you | Non-empty dummy key; confirm /v1/models via the tunnel |
[error: upstream error] on first Agent turn | Missing codex login / bad auth | Re-login; check server stream_error logs |
[error: upstream error] in an existing chat | Poisoned history | Start a new Agent chat |
| Several Agent chats stall | Queue / concurrency | Keep the queue on, CODEX_AGENT_MAX_ACTIVE_PER_KEY=1 |
Alternatives
cloudflared tunnel --url http://127.0.0.1:8088 or tailscale funnel 8088 also work if they give you public HTTPS. We document ngrok because a reserved free domain keeps the Cursor base URL stable.