# Run commands and files

> Run a command on your box and get its exit code back, leave one running and check on it later, and copy files in either direction, from the CLI or from any script that holds a CLI token. Nothing to install on the box.

URL: https://prized.dev/docs/exec

## Run a command [#run-a-command]

```bash
prized exec -- make test
```

The command runs on the box under `sh -c` in your home directory; stdout, stderr, and the exit code come straight back, and your local stdin is connected. A suspended box wakes first. A box name before the `--` picks a box other than the configured one.

| Command                                                  | What it does                                                                                                                                                                |
| -------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `prized exec -- npm test`                                | Run in your home on the default box; the exit code is `npm test`'s.                                                                                                         |
| `prized exec box-a7f3 --cwd app -- npm test`             | Run on a named box, in `~/app` (`--cwd` is relative to your home, or absolute).                                                                                             |
| `prized exec --timeout 10m -- ./build.sh`                | Kill the command after 10 minutes (TERM, then KILL 5 s later): exit 124, and stderr ends with a `prized: command timed out after 600s (SIGTERM)` line. No limit by default. |
| `prized exec --env CI=1 --env NODE_ENV=test -- npm test` | Add environment variables (repeatable, up to 32).                                                                                                                           |
| `prized exec --json -- make`                             | Capture instead of stream: one object with `exitCode`, `signal`, `timedOut`, `stdout`, `stderr`.                                                                            |

* The words after `--` are joined and handed to `sh -c`, so quote as for ssh: `prized exec -- 'cd app && npm test'` runs both halves on the box. The shell is a plain `sh`, not your login shell; tools that only your `.bashrc` puts on PATH need `prized exec -- bash -lc 'npm test'`.
* Here `--timeout` is the command's time limit, not the network timeout the other commands use the flag for.
* Exit code: the remote command's, or ssh's 255 when the box was unreachable. With `--json`, `ok` says whether the command ran and `exitCode` what it returned; `timedOut` is true only when the time limit ended the command, so a command that exits 124 on its own is `exitCode: 124, timedOut: false`.

## Detached processes [#detached-processes]

```bash
prized exec --detach -- ./train.sh
# started p_3f9c0a1b2d4e (pid 41213) in /home/ubuntu
```

`--detach` starts the command and returns at once with a process id. The process outlives your terminal and the ssh session; its output goes to log files on the box.

| Command                               | What it does                                                                                  |
| ------------------------------------- | --------------------------------------------------------------------------------------------- |
| `prized exec --detach -- CMD`         | Start `CMD` detached (`--cwd` and `--env` apply) and print its id.                            |
| `prized exec --status p_3f9c0a1b2d4e` | Running or exited, the exit code or signal, start and finish times, and the tail of each log. |
| `prized exec --status p_… --tail 1m`  | How much of each log to show: bytes, or `4k`, `1m` (default `16k`, cap `1m`).                 |
| `prized exec --kill p_3f9c0a1b2d4e`   | Stop it: TERM to its process group, then KILL if it is still there after 5 s.                 |
| `prized exec --ps`                    | Every detached process on the box, running or finished.                                       |

`--status`, `--kill` and `--ps` never wake a suspended box (they exit 5 and say so); running a command does.

Everything about a detached process lives in one directory on the box, so `ls`, `tail -f`, and your own scripts see what the CLI sees:

| File in `~/.prized/processes/<id>/` | Contents                                                                                                                                                                                                                                                                                                       |
| ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `cmd`, `cwd`                        | The command line as given, and the absolute directory it ran in.                                                                                                                                                                                                                                               |
| `pid`                               | The process id (also its process group id).                                                                                                                                                                                                                                                                    |
| `boot_id`                           | The box's boot id at start. After a reboot the pid is not trusted: the process reads as `lost` and is never signalled. Medium and larger boxes reboot when they resume from a pause; any box does after a resize, a region move, or a wake from deep sleep ([Pause and resume](https://prized.dev/docs/boxes#pause-and-resume)). |
| `started_at`                        | Start time, RFC 3339 UTC.                                                                                                                                                                                                                                                                                      |
| `stdout.log`, `stderr.log`          | The output, appended as it happens.                                                                                                                                                                                                                                                                            |
| `exit`                              | Written when the command ends: the exit code, or 128 + signal.                                                                                                                                                                                                                                                 |

> Log directories are never deleted for you. `rm -r ~/.prized/processes/p_…` on the box when you are done with one.

## Copy files [#copy-files]

```bash
prized cp ./notes.md :notes.md
```

`prized cp` works like scp: exactly one side is on the box, written `BOX:PATH`, and a bare `:PATH` means the configured box. Paths on the box are relative to your home there unless absolute. Files are written whole (a temp file, then a rename), so an interrupted copy never leaves a half-written target; modes are preserved, and symlinks are skipped and counted, a symlink named as `SRC` included: name the file it points at instead. A hard link (a second name for a file that may live outside the tree, which pnpm and Nix trees are made of) is skipped and counted the same way, and refused when named as `SRC`; copy it to a new name to send it. A download writes only under `DST`: an entry that would land outside it stops the copy, and so does a target directory that is itself a symlink; name the directory it points at.

| Command                              | What it does                                              |
| ------------------------------------ | --------------------------------------------------------- |
| `prized cp ./file.txt :`             | Copy a file into your home on the box, keeping its name.  |
| `prized cp -r ./site box-a7f3:www`   | Copy a directory tree (`-r` is required for directories). |
| `prized cp box-a7f3:logs/app.log ./` | Copy a file from the box into the current directory.      |
| `prized cp -r :proj/dist ./dist`     | Copy a directory tree from the box.                       |

For a live view of the whole box in Finder rather than copies, see [Mount](https://prized.dev/docs/mount).

## The edge API [#the-edge-api]

Everything above is also HTTP, for scripts and agents that hold a CLI token and have no `prized` installed. The token comes from **Dashboard → Workspace → CLI tokens**; the base URL is `edge.url` in `GET /api/v1/me`, and every route sits under `$EDGE/v1/box/{box}/` (the box's name or id) with the token as the bearer.

```bash
export PRIZED_TOKEN=dcp_…
EDGE=$(curl -s -H "Authorization: Bearer $PRIZED_TOKEN" https://api.prized.dev/api/v1/me | jq -r .edge.url)
```

Paths are read the way `prized cp` reads them, and every answer echoes the real path it touched. Only `POST /exec` wakes a suspended box; the other routes answer `box_not_running`. The routes for commands, detached processes, and files are on [API reference: The edge](https://prized.dev/docs/api#the-edge); the box's coding agent has its own, described on [Prompt an agent remotely](https://prized.dev/docs/remote-agents#the-edge-api).

## Errors [#errors]

A failed request answers `{"ok": false, "error": {"code", "message"}}`. Every code and what it means is on [API reference: Errors](https://prized.dev/docs/api#errors).

## Limits [#limits]

Every cap for runs, files, and the edge API, the request rate included, is on [Limits](https://prized.dev/docs/limits#commands-and-files).
