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

# Forward live calls to any WebSocket

> Take a real inbound call on a voice agent that has no public answer URL yet (on your laptop, a staging box or a teammate's tunnel) with one command.

Route real incoming calls through a tunnel to your voice agent over its WebSocket connection while developing. First [log in](https://plivo.com/docs/cli/install.md#log-in-with-a-browser), start your voice agent, and [attach a number to a dedicated test application](https://plivo.com/docs/cli/voice-agent/connect-number.md). Use that number and application ID:

```bash theme={null}
plivo voice streams forward --number +14155550142 \
  --app "<app_id>" --to ws://localhost:7860/ws
```

Replace the example values, approve the routing change, then call the number from a phone. Calls use your normal Plivo billing. Keep the command running; Ctrl-C restores the saved answer URL unless you pass `--keep`.

## How it works

`--to` accepts a `ws://` or `wss://` URL on your laptop, a staging server or a colleague's tunnel. The tunnel runs on the CLI's machine.

`forward` saves the application's `answer_url`, starts a tunnel and local HTTP/WebSocket server, and updates the application to use that tunnel. It forwards call audio to your voice agent. On Ctrl-C or a tunnel failure, it restores the saved URL; a tunnel failure exits `3`. See the recovery behavior below for a process that is killed outright.

> [!WARNING]
>
> Every phone number attached to the application is redirected for as long as `forward` runs: the confirmation step tells you how many. Use a dedicated test application.

## The tunnel

The localhost.run tunnel needs an SSH client on `PATH` and no tunnel account. macOS and Linux commonly include SSH; install it if the CLI reports `ssh not found`. If `ngrok` is already on your `PATH` (or at `~/.plivo/bin/ngrok`) the CLI uses that instead, since a warmed-up ngrok is usually faster. `--tunnel` forces the choice: `auto` (the default) prefers ngrok when it is present and falls back to localhost.run, also when ngrok can't start; `ngrok` and `localhost.run` pin one provider.

> [!NOTE]
>
> The confirmation prompt and the `--dry-run` preview print a placeholder answer URL of the form `https://<ngrok-tunnel>/answer` whichever provider is chosen. The real tunnel URL is printed once the tunnel is up.

## Command and flags

**Usage**

```text theme={null}
plivo voice streams forward [flags]
```

**Flags**

| Flag | Description |
| - | - |
| `--app <string>` | application ID returned when you create the app; its answer URL is temporarily redirected (required) |
| `--bidirectional` | allow your voice agent to send audio back to the caller (default true) |
| `--codec <string>` | audio codec advertised to Plivo: mulaw \| l16 (default "mulaw") |
| `--insecure-skip-signature` | accept unsigned tunnel requests. Anyone with the tunnel URL can then drive your handler; leave signature checks enabled for real calls. |
| `--keep` | leave the application pointing to the tunnel on exit (advanced) |
| `--number <string>` | international number with country code, such as `+14155550142`, attached to `--app` (required) |
| `--print-payload` | dump full webhook bodies to terminal (verbose) |
| `--rate <int>` | sample rate in Hz (mulaw: 8000; l16: 8000 or 16000) (default 8000) |
| `--to <string>` | local WebSocket URL to forward call audio to, e.g. ws\://localhost:7860/ws (required) |
| `--tunnel <string>` | tunnel provider: auto \| ngrok \| localhost.run (default "auto") |
| `-y, --yes` | skip the confirmation prompt |

**Examples**

```bash theme={null}
  plivo voice streams forward \
    --number +14155550142 \
    --app "<app_id>" \
    --to ws://localhost:7860/ws
  # Don't restore answer_url on exit (advanced):
  plivo voice streams forward --number +14155550142 --app "<app_id>" --to ws://localhost:7860/ws --keep
```

`--codec` and `--rate` follow the same rules here as they do for `streams test`, and an unsupported pair is rejected before anything is redirected: see [The audio contract](https://plivo.com/docs/cli/voice-agent/test-websocket.md#the-audio-contract).

Nothing is purchased, created, or deleted: the only change is one field on one application, restored on exit unless you pass `--keep`. `forward` saves the original answer URL in `~/.plivo` first. If it is killed outright (`kill -9`), the next `forward` on that application restores the real answer URL and, on macOS and Linux, stops the tunnel the killed run left behind. A second `forward` on the same application is refused while one is running.

A localhost.run or trycloudflare.com URL is not saved as the original answer URL. An ngrok URL can be saved, with a warning, because ngrok also supports fixed domains.
