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

# Processes

> Creating, running, and inspecting processes

A process is a stateful execution unit in cyrnel. When a client submits code,
cyrnel creates a process record with a stable identifier (`id`), runs it on the
active [environment module](/cyrnel/docs/environments-modules), captures its
output, and persists the result to the database. Process execution does not
block the client request unless `block: true` is set.

## Process Model

Each process has the following fields:

* `id`: stable database identifier (auto-incrementing integer, persists across restarts)
* `ref`: optional reference label (trimmed; must be non-empty if present, unique)
* `state`: lifecycle phase (see below)
* `exitState`: execution outcome (see below)
* `error`: error message if the process failed, otherwise `null`
* `code`: the submitted source
* `options.timeoutMs`: per-process timeout in milliseconds, or `null` to disable
* `output`: structured key/value payload emitted by `cyrnel.output(...)`
* `stdout`, `stderr`: captured text output
* `createdAt`: ISO-8601 timestamp of creation
* `completedAt`: ISO-8601 timestamp of completion, or `null` if still running

<Info>
  Process creation records and execution results are **persisted in the
  database**. Runtime state (running/queued/terminating) is ephemeral and
  held in memory, restarting the API clears active executions but the
  creation record and any completed results survive.
</Info>

### Process states

| State         | Meaning                                                           |
| ------------- | ----------------------------------------------------------------- |
| `queued`      | Waiting for the environment to pick it up.                        |
| `running`     | Currently executing inside the environment.                       |
| `terminating` | A `kill` signal was issued; the runtime is winding it down.       |
| `idle`        | Not executing. Either it hasn't been run yet, or it has finished. |

### Process exit states

| Exit state | Meaning                                                                |
| ---------- | ---------------------------------------------------------------------- |
| `null`     | No outcome yet.                                                        |
| `success`  | Code completed without throwing.                                       |
| `failed`   | Code threw, or the environment reported failure. `error` is populated. |
| `timeout`  | Execution exceeded `options.timeoutMs`.                                |
| `canceled` | A `kill` signal interrupted the execution.                             |

## Create a Process

`POST /processes`

```json theme={null}
{
  "code": "string",
  "ref": "optional unique reference",
  "autorun": true,
  "options": {
    "timeout": 30000
  }
}
```

Rules:

* `code` is **required** and must be a string.
* `ref` is optional, trimmed, unique if provided, and must be non-empty if present.
* `options.timeout` is in milliseconds. Must be a **positive integer**, or
  `null` to disable. Default: `30000`.
* `autorun` controls whether execution starts immediately. When `true`
  (default), the process is queued and runs right away. When `false`, the
  process is created in `idle` state and must be started via the
  [run signal](/cyrnel/docs/processes#run-an-existing-process).

Response (`201`):

```json theme={null}
{ "id": 1 }
```

If `block: true` and `autorun: true`, cyrnel polls until `state === "idle"`
before responding. The HTTP status is still `201`.

## Run an Existing Process

`POST /processes/:id/signals/run`

```json theme={null}
{ "force": false, "block": false }
```

* The process must currently be `idle`.
* If the process has stored outputs (any of `exitState`, `output`, `stdout`,
  `stderr` is non-empty), `force: true` is required to overwrite them.
* `block: true` waits until the run completes.

Response (`200`): the process record.

## Kill a Process

`POST /processes/:id/signals/kill`

* If the process is `queued`, it transitions straight to `idle` with
  `exitState = "canceled"`.
* If `running`, it moves to `terminating` first, then to `idle` with
  `exitState = "canceled"` once the environment confirms.
* If already `idle`, the call returns `409`.

Response (`200`): the process record.

## Inspect a Process

| Method | Path                    | Returns                                       |
| ------ | ----------------------- | --------------------------------------------- |
| `GET`  | `/processes`            | `{ processes: ProcessRecord[] }` (filterable) |
| `GET`  | `/processes/:id`        | the process record                            |
| `GET`  | `/processes/:id/code`   | submitted source as `text/plain`              |
| `GET`  | `/processes/:id/output` | structured output as JSON                     |
| `GET`  | `/processes/:id/stdout` | captured stdout as `text/plain`               |
| `GET`  | `/processes/:id/stderr` | captured stderr as `text/plain`               |

`/output`, `/stdout`, and `/stderr` return `409` unless the process is
`idle`.

### Filtering `/processes`

Query parameters:

* `state`: One of `idle | queued | running | terminating`
* `status`: One of `success | failed | timeout | canceled | null`
* `ref`: Exact match (trimmed, non-empty)

Results include both active in-memory processes and historical processes
from the database.

## Delete a Process

`DELETE /processes/:id`

The process must be `idle`. The record is permanently removed from the
database.
