Processes

Run one-off commands, background servers, and interactive shells inside a sandbox — and manage them long after the client disconnects.

A process is a command running inside a sandbox. Tektona runs and tracks processes for you: start one, walk away, and come back later to fetch its exit code, tail its logs, or stop it. Processes are sandbox-owned — a dropped connection never kills them; the sandbox owns their lifetime — and reachable from the CLI, the HTTP API, the TypeScript SDK, and, from inside the sandbox, tektonactl.

Every surface acts on the same set of processes, so a background server an agent starts with tektonactl process run shows up in tektona sandbox process ls and can be stopped or tailed from outside — and vice versa.

Process state lives in the sandbox. Running processes and their output survive pause/resume. Finished-process records and logs also survive a reboot, a disk-only suspend, and crash recovery — bounded to roughly the 200 most-recent processes. A process still running when the sandbox goes down comes back recorded as interrupted (finish_reason=interrupted) with whatever output it had produced. Deleting the sandbox removes everything — there is no durable archive, so capture what you need before deleting.

Run a one-off command

run executes a command and streams its output to your terminal, exiting with the command's own exit code:

tektona sandbox process run 01J9F3ZK7QW4B2Y8N5T1QAZ6RX -- npm test

Everything after -- is the command. run waits by default; local stdin is piped through when the process isn't a TTY. The remote exit code becomes the CLI's exit code, so run drops straight into a script or CI step. A process that was killed instead of exiting cleanly still reports non-zero: 128 + signal for a signal (SIGKILL → 137), 124 for a --timeout kill.

The command is an argument vector, not a shell line — &&, pipes, and globs are not interpreted. For a shell one-liner, pass -s/--shell to run it through a shell inside the sandbox (bash when the image has it, sh otherwise):

tektona sandbox process run 01J9F3ZK7QW4B2Y8N5T1QAZ6RX -s -- 'apt update && apt install -y nginx'

The SDKs' process.run() takes a shell command line already, so they need no equivalent flag.

Set the environment, working directory, and run-as user inline:

tektona sandbox process run 01J9F3ZK7QW4B2Y8N5T1QAZ6RX \
  --env NODE_ENV=production --env PORT=8080 \
  --cwd /workspace --user dev \
  -- npm run build

--env is repeatable. --user defaults to the image's default user; it is a convenience, not a security boundary (root is allowed — same trust model as SSH into your own sandbox).

Kill a runaway command with --timeout (a Go-style duration; sub-second values round up to the 1s minimum). On expiry the whole process group is killed and the result is recorded as timed-out:

tektona sandbox process run 01J9F3ZK7QW4B2Y8N5T1QAZ6RX --timeout 10m -- ./slow-job.sh

Start a background process

--detach (-d) starts a process and returns immediately, printing its id. Give it a --name (short: -n) to address it later without copying the ULID around:

tektona sandbox process run 01J9F3ZK7QW4B2Y8N5T1QAZ6RX -d --name dev-server -- npm run dev

A name is [a-z0-9_-], must start and end alphanumeric, and is unique among running processes (starting a second dev-server while the first runs is a conflict). A name resolves to its running holder, or — if none is running — to the most-recent finished process with that name; a ULID always resolves to its exact record. So get/logs <name> keep working after the process finishes.

If you don't pass --name, a memorable one is generated for you (like quantum-phoenix), so every process is addressable by something friendlier than its ULID.

List, inspect, and stop by name or ULID:

tektona sandbox process ls 01J9F3ZK7QW4B2Y8N5T1QAZ6RX
tektona sandbox process get 01J9F3ZK7QW4B2Y8N5T1QAZ6RX dev-server
tektona sandbox process stop 01J9F3ZK7QW4B2Y8N5T1QAZ6RX dev-server

ls shows running process instances newest first and hides finished ones (a footer notes how many). An AUTOSTART column shows * for autostart-managed instances. Add -a/--all to also show finished instances after a blank line, or --autostart to list the autostart definitions themselves.

Interactive shells

Pass --tty (-t) to allocate a real PTY. run puts your terminal into raw mode and forwards keystrokes, resize events, and Ctrl-C to the remote process:

tektona sandbox process run 01J9F3ZK7QW4B2Y8N5T1QAZ6RX -t -- bash

Start an interactive process detached and reconnect to it later with attach. Attach replays a screenful of recent output, then streams live; multiple clients can attach to the same process at once:

tektona sandbox process run 01J9F3ZK7QW4B2Y8N5T1QAZ6RX -d -t --name repl -- python
tektona sandbox process attach 01J9F3ZK7QW4B2Y8N5T1QAZ6RX repl

Detaching from attach never stops the process — it keeps running. (Ctrl-C is forwarded to the process; close the connection to leave.)

Logs

Every non-TTY process keeps stdout and stderr separated in a capped, disk-backed log store inside the sandbox. Fetch the buffered log, or tail it live:

tektona sandbox process logs 01J9F3ZK7QW4B2Y8N5T1QAZ6RX dev-server            # buffered
tektona sandbox process logs 01J9F3ZK7QW4B2Y8N5T1QAZ6RX dev-server -f          # follow
tektona sandbox process logs 01J9F3ZK7QW4B2Y8N5T1QAZ6RX dev-server --tail 100  # last 100 lines

logs -f tails until the process ends; Ctrl-C stops tailing without touching the process. The store is capped per process (--max-log-bytes, default 128 MiB); old output is evicted once the cap is reached. Pass --max-log-bytes 0 at start time to disable logging entirely and save disk — logs then can't be fetched or followed for that process, though you can still attach.

Stop and signal

stop escalates gracefully: SIGTERM, a grace period, then SIGKILL, delivered to the whole process group. --force skips straight to SIGKILL:

tektona sandbox process stop 01J9F3ZK7QW4B2Y8N5T1QAZ6RX dev-server
tektona sandbox process stop 01J9F3ZK7QW4B2Y8N5T1QAZ6RX dev-server --force

To deliver one specific signal instead of stopping, use signal:

tektona sandbox process signal 01J9F3ZK7QW4B2Y8N5T1QAZ6RX dev-server SIGHUP

Signals are delivered to the process group and accepted from this set (with or without the SIG prefix): SIGHUP, SIGINT, SIGQUIT, SIGTERM, SIGKILL, SIGUSR1, SIGUSR2, SIGSTOP, SIGCONT. Terminal resizing is not a signal — it goes through attach.

Keep the sandbox awake

A sandbox auto-pauses after a period without boundary-crossing traffic (see Sandbox lifecycle). A silent in-VM process — a build, a long test run — looks idle and can get paused mid-work. Pin the sandbox awake for the process's lifetime with --prevent-auto-pause:

tektona sandbox process run 01J9F3ZK7QW4B2Y8N5T1QAZ6RX --prevent-auto-pause -- ./train.sh

While a pinned process runs, the sandbox counts as active and is exempt from auto-pause. It defaults off, so a forgotten daemon can't silently defeat auto-pause; once the process exits, the idle timer resumes.

What happens when the sandbox pauses

A hibernate pause snapshots the sandbox's RAM, so processes survive the pause in memory. --on-hibernate controls what happens to each process across a hibernate pause:

ValueBehavior
preserve (default)Preserved intact in the RAM snapshot; continues after resume. Re-tail the logs after resume to keep following.
stopGracefully stopped (TERM→grace→KILL) just before the snapshot and finalized.
restart_after_resumeKept running into the RAM snapshot, then stopped and re-executed fresh once the guest resumes — same name and command, new ULID, linked back to its predecessor. For servers whose connections die during a pause.
tektona sandbox process run 01J9F3ZK7QW4B2Y8N5T1QAZ6RX \
  -d --name dev-server --on-hibernate restart_after_resume -- npm run dev

--on-hibernate applies only to a hibernate pause. A suspend pause instead persists only the disk, so the guest cold-boots on resume and every process is gone regardless of --on-hibernate — a process comes back only if it was started with --autostart (see below).

Autostart on every boot

--autostart persists the process definition to the sandbox disk and relaunches it (fresh process, same name) on every boot — after a stop/start, reboot, crash recovery, or a filesystem-fork child's first boot. It requires --name and captures the full spec (command, env, cwd, user, tty, on-hibernate, prevent-auto-pause, log cap).

tektona sandbox process run 01J9F3ZK7QW4B2Y8N5T1QAZ6RX \
  -d --name dev-server --autostart -- npm run dev

The definition outlives its instances: stopping the running process does not remove it — the process comes back next boot. List the persisted definitions, each with its last launch outcome, to answer "did my autostarts come up?":

tektona sandbox process ls 01J9F3ZK7QW4B2Y8N5T1QAZ6RX --autostart

Disabling is explicit and sticks:

tektona sandbox process autostart 01J9F3ZK7QW4B2Y8N5T1QAZ6RX dev-server off
tektona sandbox process autostart 01J9F3ZK7QW4B2Y8N5T1QAZ6RX dev-server on

Autostart doesn't apply on hibernate resume (the RAM is restored, so --on-hibernate governs there) — only on a fresh boot.

Paused sandboxes

Every process operation except run (which always wakes the sandbox to run your command) returns a conflict on a paused sandbox, so a status check never silently costs you a resume. Pass --resume to wake it and serve the request:

tektona sandbox process ls 01J9F3ZK7QW4B2Y8N5T1QAZ6RX --resume

From inside the sandbox

Agents and scripts running inside a sandbox use tektonactl process, which takes no sandbox id — it targets its own sandbox — and runs the same commands:

tektonactl process run -d --name dev-server -- npm run dev
tektonactl process ls
tektonactl process logs dev-server -f
tektonactl process stop dev-server

This is the primary way an in-sandbox agent runs background work. From outside, wrap it over SSH — tektona ssh <id> -- tektonactl process ls — or use the tektona sandbox process commands above against the same processes.

See also

On this page