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

# Commands and SSH

> Run commands, stream output, connect over SSH, transfer files, and manage systemd services

## Execute commands

```bash theme={null}
beam vm exec devbox -- uname -a
beam vm exec --cwd /root devbox -- pwd
beam vm exec --timeout 60 devbox -- sh -c 'echo hello; sleep 1'
```

Put `exec` options **before the VM name**. Everything after the name is the remote command. `--` makes the boundary explicit. Arguments are literal; use `sh -c` or `bash -lc` for shell variables, pipes, and redirection.

Foreground execution streams stdout and stderr and returns the command's exit status. `--timeout` sets a command deadline in seconds; `0`, the default, waits indefinitely. This deadline is separate from the VM's [idle TTL](/v2/vm/lifecycle#idle-ttl-and-automatic-resume).

```bash theme={null}
printf 'hello\n' | beam vm exec devbox -- cat
beam vm exec --json devbox -- python3 -c 'print(6 * 7)'
```

Noninteractive stdin is forwarded to the command. JSON execution returns the VM ID, current container ID, PID, exit code, stdout, and stderr instead of streaming output.

## Processes in Python

```python theme={null}
from beam import VM

with VM.connect("devbox") as vm:
    with vm.keep_alive():
        process = vm.process.exec(
            "python3", "-c", "import sys; print(sys.stdin.read().upper())",
            stdin="hello from stdin\n",
        )
        print(process.wait(timeout=30))
        print(process.stdout.read())
        print(process.stderr.read())
```

`process.exec()` returns a handle immediately. Supply text, bytes, or a binary file as stdin; SDK input is uploaded before execution and followed by EOF. Use SSH for an interactive terminal.

For live logs:

```python theme={null}
from beam import VM

with VM.connect("devbox") as vm:
    with vm.keep_alive():
        process = vm.process.exec("python3", "-u", "-c", "print('ready')")
        for line in process.logs:
            print(line, end="")
        print(process.wait())
```

Stream reads consume output. `process.wait(timeout=30)` bounds how long the caller waits; it does not itself kill the command. Use `process.kill()` to cancel it. See [process management](/v2/sandbox/processes) for `run_code`, environment overrides, process handles, and async behavior. The same process API is available through `vm.process` and `vm.aio.process`.

## Detached commands and logs

```bash theme={null}
beam vm exec --detach --json devbox -- python3 -u /workspace/job.py
beam vm ps devbox
beam vm logs devbox --pid PID -f
beam vm kill devbox PID --container-id CONTAINER_ID
```

Save the PID and container ID returned by detached JSON execution. `--container-id` prevents killing a reused PID after the VM has restarted. Managed process handles belong to the current runtime; use a systemd unit for a service that must start again after a cold boot.

Use only one log selector at a time: `--pid`, `--unit`, or `--session`. Without a selector, `logs` reads the systemd journal. Detached work does not maintain an idle lease after the CLI exits; disable the TTL for unattended jobs.

## SSH and browser terminal

```bash theme={null}
beam vm ssh devbox
beam vm ssh devbox -- sh -c 'id; pwd'
beam vm terminal devbox
beam vm terminal devbox --url
```

SSH connects as root through an authenticated Beam tunnel. You do not need to expose an SSH port publicly. The CLI manages a local Ed25519 identity and known-host records; your private key stays on your machine. Install local OpenSSH (`ssh`, `ssh-keygen`, and `scp`) to use these commands.

The browser terminal uses port **7681**. `terminal` opens your browser; `--url` prints the entry URL instead. Protect browser access as described in [networking](/v2/vm/networking#protect-a-published-port).

## Copy and sync files

```bash theme={null}
beam vm scp local.txt devbox:/workspace/local.txt
beam vm scp devbox:/workspace/result.txt ./result.txt
beam vm scp -r ./project devbox:/workspace/project
beam vm sync devbox ./project
beam vm sync --watch devbox ./project
```

SCP requires exactly one remote `NAME:/path` argument. Quote paths with spaces. Sync uploads the local directory's **contents** to `/workspace/`, excludes `.git`, and can watch for local changes. Install `rsync` locally to use sync; it is installed in the prepared VM image. Sync is an upload operation, not bidirectional synchronization, and does not delete remote files absent locally.

## Systemd services

VMs boot systemd and support your own units. For example, create a service that starts a web server on every cold boot:

```python theme={null}
from beam import VM

unit = """[Unit]
Description=Project web server
After=network.target

[Service]
WorkingDirectory=/workspace
ExecStart=/usr/bin/python3 -m http.server 8000 --bind 0.0.0.0
Restart=on-failure

[Install]
WantedBy=multi-user.target
"""

with VM.connect("devbox") as vm:
    vm.fs.write_text("/etc/systemd/system/project-web.service", unit)
    process = vm.process.exec(
        "sh", "-c",
        "systemctl daemon-reload && systemctl enable --now project-web.service",
    )
    if process.wait() != 0:
        raise RuntimeError(process.stderr.read())
    print(vm.expose(8000, protected=True))
```

Inspect its state and journal:

```bash theme={null}
beam vm exec devbox -- systemctl status project-web.service
beam vm logs devbox --unit project-web.service -f
```

The unit file and enabled state persist. Stop/start cold-boots and starts enabled units; pause/resume restores the running process state.

## Coding agents

Prepared VM images include Claude Code and Codex CLIs. Configure the selected agent's authentication or provider credentials inside the VM; `beam vm prompt` does not supply an agent subscription or API key.

```bash theme={null}
beam vm prompt devbox "Inspect this project and explain how to run its tests" --agent codex
beam vm prompt devbox "Run the tests and fix the failing case" --agent claude --background
```

Background mode returns a `prompt-...` session ID and starts a systemd transient unit. Read its durable output with:

```bash theme={null}
beam vm logs devbox --session PROMPT_SESSION -f
```

Session log files live at `/workspace/.beam-vm/logs/`. Those files survive stop/start; an agent launched as a transient unit does not automatically rerun after a cold boot.

## Metrics

```bash theme={null}
beam vm metrics devbox
```

`vm.metrics()` samples guest CPU, memory, and root-disk usage over one second. It counts as activity and can wake a VM with automatic resume enabled. It is a current sample, not historical billing data; use the dashboard Usage page for costs.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.