# ngrok agent setup

You're helping a developer get their local app online with ngrok — securely — and confirm it actually works. Your job isn't to explain ngrok; it's to produce a working, verified endpoint.

This needs terminal access on the machine running the app (e.g. Claude Code, or the Codex CLI locally). If you're running remotely and can't reach the developer's localhost, don't guess — hand them the commands to run themselves.

Find the app and the single local port to expose. Confirm the application name and port with the developer before you start a tunnel.

If the developer doesn't have anything running yet, explain the model before starting anything: an ngrok endpoint always forwards to an upstream. ngrok publishes something that already exists — it doesn't originate the content itself — so a tunnel is only useful once there's an upstream to forward to. There are two ways to give the ngrok agent an upstream:

- **Their existing app** — the normal case. Help them start it, then forward to its port.
- **A new simple "hello world" app** — for a developer who doesn't have an app yet, or who just wants to see ngrok work. Write the most minimal `index.html` that reads "hello world" into a temp directory with nothing else in it, then use `ngrok http file:///path/to/a/directory` to serve that directory. A working public URL to that page is a complete result — don't treat it as a lesser outcome or push them toward a "real" app they may not have. If they do have one to expose later, point ngrok at its port then.

## Setup

1. **Install the ngrok agent**
   - macOS: `brew install ngrok`
   - Windows: https://ngrok.com/download
   - Linux: https://ngrok.com/docs/getting-started/

2. **Make sure ngrok is authenticated**
   - If ngrok isn't authenticated yet, the developer needs to add their authtoken. Ask them to run this themselves — don't ask them to paste the token to you:
     `ngrok config add-authtoken <TOKEN>` (token at https://dashboard.ngrok.com/get-started/your-authtoken)

3. **Start an agent endpoint — in the background**
   - First confirm the local app actually responds on its port. Don't skip this: if nothing is listening, the endpoint still comes up looking healthy and only fails when someone loads the public URL, which reads as an ngrok problem when it isn't.
     - macOS / Linux: `curl -sS -o /dev/null -w '%{http_code}' localhost:8080`
     - Windows (PowerShell): `(Invoke-WebRequest -Uri http://localhost:8080 -UseBasicParsing).StatusCode`
   - Start ngrok as a background process so it keeps running while you verify — don't run it as a blocking foreground command:
     `ngrok http 8080` (replace `8080` with the app's port)
   - Get the public URL from ngrok's output or its local API (`http://localhost:4040/api/tunnels`). ngrok defaults to the account's free, static dev domain and reuses it across restarts, so the URL stays stable.
   - If `ngrok http 8080` fails with `ERR_NGROK_15013`, the account has no dev domain. Pass an explicit domain instead: `ngrok http 8080 --url=<your-domain>` — creating one in the dashboard first if the account has none.

4. **Prove it works**
   - Request the public URL (with a timeout so you don't hang), and confirm the response matches what the local app returns — not an ngrok error page.
   - An `ERR_NGROK_8012` page means traffic reached the agent but the agent couldn't reach the app: it stopped, it's on a different port, or it's bound to an address the agent can't get to (common with containers binding `127.0.0.1` inside the container). Re-check the local request above before changing anything about the endpoint.
   - Then tell the developer how to trigger a real request themselves — open the URL in a browser, send a test webhook, complete an OAuth callback — whatever fits.

## Offer to protect it (free) — only with the developer's OK

A public endpoint is open to anyone with the URL. Offer to add a traffic policy, and apply it only if they agree:

- Simplest: HTTP Basic Auth, so only people with the password get in.
- Also: OAuth sign-in, IP restrictions, rate limiting, webhook verification.
- Docs: https://ngrok.com/docs/gateway/traffic-policy/

## Keep it running vs. always-on

- The agent endpoint lives only while the `ngrok` process runs — stop it and the URL is gone. Good for testing and sharing right now.
- For something that should stay up without a local process, create a **cloud endpoint** (dashboard or API): https://ngrok.com/docs/start

## Next steps that fit the app — match to what it actually does

Using the local context you have about the app and the developer's goal, recommend the protections and patterns that genuinely fit. Often that's one; sometimes a couple. Don't reel off options that don't apply just to be thorough, and don't apply anything without the developer's OK:

- **Webhooks** → verify signatures: https://ngrok.com/docs/gateway/traffic-policy/actions/verify-webhook/
- **Browser-facing app** → OAuth/OIDC protection: https://ngrok.com/docs/gateway/traffic-policy/examples/oauth-protection/
- **Public API** → rate limiting or IP restrictions (traffic-policy docs above)
- **MCP server** → the client URL is the public URL plus the server's MCP path (usually `/mcp`), e.g. `https://<dev-domain>/mcp`. The server must speak HTTP (Streamable HTTP); if it's stdio-only, say so rather than tunneling a port that doesn't exist. Verify with an MCP `initialize` request or the MCP Inspector, not a plain `GET /`, which many MCP servers answer with 404 or 405. Before the developer pastes the URL into ChatGPT, Claude, or Cursor, offer bearer-token checks with `jwt-validation`, IP restrictions, and rate limits. Guide: https://ngrok.com/docs/gateway/api-gateway/mcp-gateway
- **Private service / cross-network** → internal + cloud endpoint: https://ngrok.com/docs/gateway/site-to-site-connectivity/quickstart/
- **Custom domain** (paid) → use your own domain: `--url=app.yourdomain.com`
- For an app that doesn't fit the above, ngrok's llms.txt index (https://ngrok.com/llms.txt) maps its other use cases — use it to find the relevant one rather than guessing.

## Notes for agents

- Never print or commit the authtoken; never ask for it in chat.
- Keep the `ngrok` process running while the endpoint is active; leave it running when you're done and tell the developer how to stop it.
