> ## Documentation Index
> Fetch the complete documentation index at: https://docs.useswarm.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Testing Local Apps

> How Swarm tunnels your localhost to the cloud for testing, including split frontend/backend setups.

# Testing Local Apps

Swarm's AI agents run in the cloud. To test a local development server, the CLI automatically creates a secure tunnel from your machine to the cloud.

## Basic local testing

Just pass your localhost URL:

```bash theme={null}
swarm test --url localhost:3000 --goal "Sign up for an account"
```

The CLI detects that the URL is local, opens a tunnel, and rewrites the URL for the cloud agents. No configuration needed.

## Persistent tunnel hostnames

If your Swarm workspace has persistent tunnels enabled, `swarm login` automatically provisions a stable hostname for your local tests:

```text theme={null}
https://<user-id>-<org-slug>.swarmtunnel.com
```

Future localhost tests reuse that hostname instead of creating a fresh temporary tunnel URL each time. This is especially useful for OAuth callbacks and other redirect flows.

Learn more in [Persistent Tunnels](/guides/persistent-tunnels).

## Tunnel providers

Swarm supports two tunnel providers:

### Cloudflare Tunnel (default)

Free, no bandwidth limits, no account required. Requires the `cloudflared` binary:

```bash theme={null}
# macOS
brew install cloudflared

# Linux
curl -fsSL https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 \
  -o /usr/local/bin/cloudflared && chmod +x /usr/local/bin/cloudflared

# Windows
winget install Cloudflare.cloudflared
```

### ngrok

Bundled with the CLI — works out of the box with your Swarm account. Has bandwidth limits on free ngrok plans.

### Choosing a provider

```bash theme={null}
# Auto (tries cloudflare first, falls back to ngrok)
swarm test --url localhost:3000 --goal "Sign up"

# Force cloudflare
swarm test --url localhost:3000 --goal "Sign up" --tunnel-provider cloudflare

# Force ngrok
swarm test --url localhost:3000 --goal "Sign up" --tunnel-provider ngrok
```

## Split frontend/backend

Many apps run the frontend and backend on separate ports. For example, a React app on port 3000 and an Express API on port 8080.

The problem: the tunnel only exposes one port. If your frontend makes API calls to `localhost:8080`, the cloud browser can't reach it.

The solution: Swarm's built-in reverse proxy routes API paths to your backend through the same tunnel.

```bash theme={null}
swarm test --url localhost:3000 --backend localhost:8080 --goal "Create a project"
```

This starts a proxy that routes:

* `/api/*`, `/auth/*`, `/graphql`, `/trpc/*` → `localhost:8080` (backend)
* Everything else → `localhost:3000` (frontend)

### Custom API paths

If your backend uses different path prefixes:

```bash theme={null}
swarm test --url localhost:3000 \
  --backend localhost:8080 \
  --backend-paths "/v1,/webhooks,/uploads" \
  --goal "Upload a file"
```

## Skipping the tunnel

If your URL is already publicly accessible:

```bash theme={null}
swarm test --url https://staging.myapp.com --goal "Sign up" --no-tunnel
```

## Framework notes

### Next.js / Nuxt / SvelteKit / Remix

These full-stack frameworks serve both frontend and API routes on the same port. You typically **don't need** the `--backend` flag — a single tunnel covers everything.

### Django

Add the tunnel URL to your `ALLOWED_HOSTS` and `CSRF_TRUSTED_ORIGINS` in `settings.py`. The CLI prints a reminder with the exact values after the tunnel opens.

### Vite / Create React App

If your frontend proxies API calls in development (e.g., Vite's `server.proxy`), the proxy already handles routing and a single tunnel works. Only use `--backend` if you're making direct cross-origin requests to a separate backend port.
