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

# Dev instances

> Spin up an ephemeral copy of an environment from your terminal with sw dev.

A **dev instance** is a full, isolated copy of a base [environment](/environments/overview) that you spin up from the `sw` CLI to exercise a feature branch end-to-end. It builds every component from a committed ref (default: your current branch), gets its own isolated environment and public URLs, and stays alive only as long as the CLI keeps it alive — when you press <kbd>Ctrl-C</kbd> (or the CLI loses its connection) it's reaped automatically.

It's the same idea as a PR preview, but on demand and bound to your terminal session rather than a pull request.

## Spin one up

Run `sw dev up` from inside a repo checkout:

```bash theme={"system"}
cd ~/code/acme-api      # on branch feat/checkout-v2
sw dev up
# [sw] spinning up dev instance of "acme" @ feat/checkout-v2 …
# [sw] instance 3f9a1c20 (acme-dev-ben-feat-checkout)
# [sw] creating
# [sw] deploying
# [sw] healthy
#
# Services:
#   api/api    https://acme-api-3f9a1c20.apps.slipway.sh
#   api/web    https://acme-web-3f9a1c20.apps.slipway.sh
#
# Port-forwards:
#   localhost:3000 → api/web:3000
#   localhost:5432 → api/postgres:5432
#
# [sw] dev instance is live — heartbeating to keep it alive. Press Ctrl-C to tear down.
```

`sw dev up`:

1. **Detects the environment** from your repo's `origin` remote — it matches `owner/name` against each base environment's components. Pass `--env <slug>` to choose explicitly; if more than one environment includes the repo you'll be prompted to pick.
2. **Detects the ref** from your current git branch. Override with `--ref <branch|tag|sha>`.
3. **Builds from the committed ref** — exactly like every other slipway deploy, cloning from your provider. Uncommitted local changes are *not* uploaded; commit and re-run `sw dev up` to pick them up.
4. **Prints every service URL** once the instance is healthy.
5. **Forwards every service to `localhost`** automatically (see [below](#automatic-port-forwarding)) so you can reach them directly — including internal services like databases. Pass `--no-forward` to skip, or `--forward` to pick specific ones.
6. **Heartbeats every \~30s** to keep the instance alive, until you press <kbd>Ctrl-C</kbd> — then it stops the forwards and tears the instance down on the way out.

<Note>
  The instance copies the base environment's component shape, variables, and
  secrets. The component bound to *your* repo is re-pointed to your ref; sibling
  components stay on the base environment's tracked refs.
</Note>

### Flags

| Flag               | Default                | Meaning                                                                                                                                        |
| ------------------ | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `--ref`            | current git branch     | Ref to build (branch, tag, or commit SHA)                                                                                                      |
| `--env`            | auto-detect from repo  | Base environment slug to copy                                                                                                                  |
| `--ttl`            | server default (5 min) | Rolling heartbeat window, in seconds                                                                                                           |
| `--forward` / `-L` | every service          | Forward only these, e.g. `--forward api:3000 --forward db:5433:5432`. Repeatable. Format: `<service-or-component/service>:<local>[:<remote>]`. |
| `--no-forward`     | off                    | Don't forward any ports (useful in scripts / CI)                                                                                               |

## Automatic port-forwarding

Once the instance is healthy, `sw dev up` forwards **every service that declares a port** to `localhost` and keeps the tunnels open for the life of the session — so `localhost:5432` hits the instance's database, `localhost:3000` hits your web service, and so on. Internal services (no public URL) are forwarded too; that's usually exactly what you want to connect to from your machine.

* **Local port** defaults to the service's own port. If that port is already in use on your machine, slipway picks the next free one and prints the real mapping — it never fails the bring-up over a port clash.
* **Tunnels close on <kbd>Ctrl-C</kbd>**, right before teardown.

Override the default with flags — it's never an interactive prompt, so `sw dev up` stays scriptable:

```bash theme={"system"}
sw dev up --no-forward                       # forward nothing (CI / scripts)
sw dev up --forward api:3000                 # only api → localhost:3000
sw dev up --forward web:8080 --forward db:5432   # pick a few
sw dev up --forward api/postgres:5433:5432   # disambiguate by component, remap the local port
```

Each `--forward` entry is `<service>:<local>[:<remote>]`. Use `<component>/<service>` when the same service name exists in more than one component. With no `:<remote>`, the service's declared container port is used. Giving any `--forward` flags replaces the auto-forward-everything default with exactly your list.

You can still open additional or ad-hoc forwards by hand against a running instance with [`sw port-forward`](/cli/overview#port-forward--exec).

## Lifetime: heartbeat + TTL

Dev instances don't live forever, and they don't depend on a healthy network either:

* While `sw dev up` runs, it sends a heartbeat every \~30s that pushes the instance's expiry forward by the rolling **TTL** (5 minutes by default).
* When you press <kbd>Ctrl-C</kbd>, the CLI tears the instance down immediately.
* If the CLI crashes or loses connectivity, heartbeats stop, the TTL lapses, and the server **reaps the instance** within a few minutes — nothing is left running.
* A **hard maximum lifetime** (8 hours) caps any instance regardless of heartbeats, so a forgotten `sw dev up` can't keep one alive indefinitely.

This is the opposite of a PR preview, which lives until the PR closes. A dev instance is tied to your session.

## List and tear down

```bash theme={"system"}
sw dev ls                       # live dev instances across the org
sw dev ls --env acme            # limit to one environment

sw dev down 3f9a1c20            # tear one down by id (or slug, or short prefix)
```

`sw dev ls` shows the owner, ref, status, and time-to-expiry for each live instance:

```
ID        ENV   REF                STATUS   OWNER  EXPIRES
3f9a1c20  acme  feat/checkout-v2   healthy  ben    4m
```

## Tail logs

Stream a component's container logs — the same stream as the dashboard log viewer:

```bash theme={"system"}
sw dev logs 3f9a1c20 api
```

## Working against the instance

Services are already [forwarded to `localhost`](#automatic-port-forwarding) while `sw dev up` runs, so you can hit them directly. For an extra forward against an already-running instance, or to run commands inside a container, use [`sw port-forward` and `sw exec`](/cli/overview#port-forward--exec):

```bash theme={"system"}
sw port-forward 3f9a1c20 api/postgres 5432:5432   # an extra/ad-hoc forward
sw exec 3f9a1c20 api/api -- printenv               # one-shot command
sw exec 3f9a1c20 api/api                           # interactive shell
```

## Where they show up

Live dev instances appear on the base environment's detail page in the dashboard, in a **Live dev instances** rail alongside PR previews — showing the owner, ref, last heartbeat, and time-to-expiry, with a **Tear down** button. They're scoped to the environment, so anyone with access can see what's currently running.

## Permissions

Starting, heartbeating, and tearing down a dev instance requires the **developer** role on the org. Listing them requires **viewer**.
