# Reaching a computer

A computer has no address of its own, and nothing outside can reach it until you ask. The ways in: a shell from your own terminal, SSH (for VS Code, Cursor, scp and rsync too), files copied in and out, a port you share on the web, a TCP port on the internet, and the project's private network from your laptop.

```diagram computer-access
Three ways in go through Alf, with nothing open on the internet. A shell: alf shell (or the dashboard) goes through Alf to the computer's server and opens a shell as dev. SSH: alf ssh goes the same way to the computer's SSH server on port 22. A shared port: anyone with the address, like …--5173.smartalfred.com, goes through Alf to the server and to localhost:5173 inside the computer. Two go straight to the computer's server. A public port: any client connects to the server's IP on a port between 20000 and 29999, and only the addresses on the allowlist get through to the port. Network access: alf connect joins your laptop to the project's network over WireGuard (UDP 51820), and every port of the computer is reachable.
```

## From your own terminal

With the [command-line tool](/docs/cli), it's one command, which the computer's page shows along the bottom (**Connect from your own terminal**) with its name filled in:

```bash
alf shell shop/computer
```

Without installing anything, **Or a one-time line, nothing to install** there gives you a line to paste instead:

```bash
curl -fsSL https://runalf.com/connect.sh | sh -s -- 'wss://api.runalf.com/api/v1/sessions/attach?token=…'
```

It opens a shell in the same container as the one on the computer's page, so what you start in one is there in the other. The window follows your terminal's size, and the shell's exit code is the command's.

- The link is good for a few minutes and for one connection. Once you're connected it stays open for as long as you are; for another shell, get another command.
- It needs `python3` on your machine, which does the talking. Nothing is installed and nothing is left behind.

Closing the terminal — here or on the computer's page — ends that shell and what it was running in the foreground. The computer carries on, and so does anything you [started to outlive the shell](/docs/computers#it-runs-until-you-stop-it).

## Sharing a port

A shell is where you build the thing you then want somebody to look at. Start it on a port — `npm run dev`, say — and share that port: it gets an https address of its own.

```bash
alf share 5173
```

prints the address, `https://<computer>-<project>-<organization>--5173.smartalfred.com`. It answers within about 15 seconds, for as long as something listens on the port.

- **Localhost works.** Most dev servers (Vite, for one) only listen on `localhost`. A shared port is reached from inside the computer, so that's fine as it is: no `--host 0.0.0.0` needed.
- **Dev servers' host checks pass.** Requests arrive as `Host: localhost:<port>`, which Vite, webpack's dev server and Angular's accept, with the address the visitor used in `X-Forwarded-Host`. Hot reload over WebSockets works.
- **In its settings too.** **Ports**, in the computer's **Settings**, lists what's listening, with **Share** and **Stop sharing** for each port. `alf ports` shows the same in the terminal; `alf unshare 5173` takes a port off again.
- **Agents know.** Installing Claude Code, Codex or opencode tells it about `alf share`, so asking an agent to "show me" ends in an address you can open.
- **Nothing restarts.** Sharing a port, or stopping, doesn't touch what's running.

**Anyone with the address can reach the port.** Nothing is shared until you or something in the computer asks. **Share every port automatically**, under **Ports**, shares each port as something starts listening on it, except debuggers' (9229, 9222), databases' (5432, 3306, 6379, 27017) and SSH's — a debugger's port lets whoever finds it run code in the computer. Those can still be shared by name.

What you build in a computer goes to production as a service in the project, with its own domain there.

## SSH, VS Code and Cursor

Every computer has an SSH server, reached through Alf — nothing is open to the internet, and whoever may open a shell in it may SSH into it. With the [command-line tool](/docs/cli):

```bash
alf ssh shop/computer
```

logs you in as `dev`, the computer's user, with `sudo`. Anything after the name goes to ssh: `alf ssh shop/computer -L 3000:localhost:3000` forwards your port 3000 to the computer's, `-A` forwards your SSH agent (for `git push` from the computer with your own key), and `alf ssh shop/computer uptime` runs one command.

For everything else that speaks SSH, make the computer an SSH host once:

```bash
alf ssh-config shop/computer --add
```

It goes into `~/.ssh/config` as `computer.shop.smartalfred`, and then `ssh computer.shop.smartalfred`, `scp notes.txt computer.shop.smartalfred:`, `rsync -a site/ computer.shop.smartalfred:site/` work, and so does **Remote-SSH: Connect to Host…** in VS Code or Cursor, with the editor's server running in the computer. Without `--add` it prints the entry for you to put there yourself.

- The key is the tool's own, made the first time (in its config directory) and given to the computer each time you connect. Your own keys work too: put them in `~/.ssh/authorized_keys` in the computer.
- An SSH session gets the computer's variables, as a shell from the dashboard does.
- The computer's host key is kept with it, so ssh knows it's the same machine next time.

```diagram ssh
ssh (or VS Code, scp, rsync) runs alf as its ProxyCommand. The tool puts its own key in the computer's authorized_keys, then opens a stream signed in as you: a WebSocket over HTTPS to Alf, and on from there over the connection the computer's server keeps open. In the computer, alf pipe 22 connects that stream to the computer's SSH server on port 22, which is never on the internet, and it logs you in as dev. SSH runs end to end inside the stream, from your ssh to the computer's SSH server: Alf only carries the bytes. Whoever may open a shell in the computer may SSH into it.
```

## Files in and out

```bash
alf cp ./site shop/computer:            # into /workspace
alf cp ./notes.txt shop/computer:/tmp/
alf cp shop/computer:report.pdf .       # out
```

One side is the computer and a path in it, as with scp; a path that isn't absolute is in `/workspace`, and a folder goes with everything in it. In the dashboard, drop files on the computer's shell to copy them into `/workspace`, or use **Files** at the top of its page for another folder, and to download a file (a folder comes as a `.tar`).

## A TCP port on the internet

For something that isn't HTTP — a database you're trying out, a game server, an SSH server of a different kind — **Settings → Public ports** opens a TCP or UDP port on the computer's server to the addresses you allow, as for [any service](/docs/tcp-ports). It reaches the computer's port even if what listens there only listens on `localhost`.

## Every port, from your laptop

With [network access](/docs/network-access), your laptop joins the computer's project network, and every port of the computer is reachable at its own name while it runs, without sharing anything on the web:

```bash
alf connect shop --all
```

Then any program at `computer.shop.internal` (`computer` being the computer's name, `shop` its project's) — `ssh dev@computer.shop.internal` included, with a key in its `~/.ssh/authorized_keys`. Making the network interface needs `sudo`; the names go into `/etc/hosts` and come out again when you leave.
