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

# Local HTTP API

> rakumux-api: sessions and folders over HTTP and WebSockets on 127.0.0.1.

`rakumux-api` exposes the session operations of the running Rakumux server over HTTP/1.1 and JSON,
plus WebSocket streams for a live terminal and for session events. It's a thin adapter: the server
still decides folder confinement, permissions and the audit log. The [MCP server](https://rakumux.com/docs/agents/mcp.md) is
its main client, and scripts can use it directly. The endpoint pages in this section are generated
from its OpenAPI 3.1 document.

> [!NOTE]
>
> The API answers only on `127.0.0.1`, and refuses browsers, so these pages show requests to copy
> rather than a live playground.

## Running

```bash theme={null}
rakumux-api                      # foreground, any free port; Ctrl-C stops it
rakumux-api --port 7420          # a fixed port (still 127.0.0.1 only)
rakumux-api --detach             # background; returns once it answers /v1/health
```

* One API runs per Rakumux home. `--detach` with a healthy API already running just prints its URL.
* The API starts the Rakumux server on the first request when none runs. It never stops the
  server, so stopping the API leaves every session running.
* `SIGINT` and `SIGTERM` stop it cleanly. A detached API logs to `~/.rakumux/logs/api.log`.

## Finding it: `api.json`

While it runs, the API writes `~/.rakumux/api.json` (mode 0600):

```json theme={null}
{ "url": "http://127.0.0.1:39123", "token": "<64 hex chars>", "pid": 4242, "version": "0.1.9" }
```

The token is new on every start. A file whose `pid` is gone is stale.

## Authentication

* **Bearer token.** Every route except `GET /v1/health` needs `Authorization: Bearer <token>`, with
  the token from `api.json`.
* **Loopback only.** `Host` must be `127.0.0.1`, `localhost` or `[::1]` (any port), which defeats
  DNS rebinding.
* **No browsers.** A request with an `Origin` or `Sec-Fetch-Site` header gets 403, and the API never
  sends CORS headers.
* **Bodies** must be `Content-Type: application/json`, at most 64 KiB. Unknown fields and query
  parameters are rejected.

The token keeps other local users and web pages out. Like the server's own tokens, it doesn't stop
a hostile process running as your user, which can read `api.json`.

## Identity

Without identity headers the API acts as **you**. With both of these, the variables Rakumux sets in
every session, it acts as **that session**, confined to its own folder:

```text theme={null}
X-Rakumux-Session-Id: $RAKUMUX_SESSION_ID
X-Rakumux-Session-Token: $RAKUMUX_SESSION_TOKEN
```

Session callers may create sessions in their folder within limits (4 running per creating session,
nesting 2 deep, 8 running agent-created sessions per folder, 10 creates a minute); beyond that the
answer is 429 `limit_exceeded`. For agents whose tool calls arrive without the session's environment
(OpenCode 2.x), `X-Rakumux-Agent: opencode` and `X-Rakumux-Agent-Conversation: <id>` act as the
session that bound that conversation.

## Folders and sessions

A session's **folder** is the directory it was started in. Wherever a `folder` is accepted it may be
an absolute directory (`~/` expanded) or the name of a known folder. Sessions come back as
`{"session": {...}}` or `{"sessions": [...]}`, with `folder`, `status` (`live`, `exited`, `dead`),
`lifecycle` (`working`, `blocked`, `done`, `idle`, `unknown`, `none`), `command`, `git`, `terminal`
and RFC 3339 times. Earlier builds said `project`; those names still work and are marked deprecated.

## Errors

Errors are `{"error": {"code", "message", "details"?}}`.

| Code | Status |
| - | - |
| `invalid_argument` | 400 |
| `unauthenticated` | 401 |
| `out_of_scope`, `permission_denied` | 403 |
| `not_found` | 404 |
| `session_not_live`, `session_in_use` | 409 |
| `limit_exceeded` | 429 |
| `unsupported` | 501 |
| `daemon_unavailable` | 503 |
| `timeout` | 504 |

The API's own: `method_not_allowed` 405, `payload_too_large` 413, `unsupported_media_type` 415, and
`upgrade_required` 426 (a WebSocket route without the upgrade).

## Streams

`GET /v1/events` and `GET /v1/sessions/{id}/attach` are WebSockets on the same port, with the same
checks. The server pings every 30 seconds.

* **`/v1/events`** sends `{"type":"subscribed"}`, then
  `{"type":"event","folder":"/path","session_id":"01J…","at":<unix ms>,"event":{…}}`, where `event`
  is `created`, `updated`, `removed`, `exited`, `lifecycle`, `reported` or `activity`.
* **`/v1/sessions/{id}/attach?role=observer|controller&cols=&rows=`** first sends `attached`, with a
  base64 checkpoint to feed a fresh terminal of `cols`×`rows`, then terminal output as binary frames.
  Send input as binary frames (as controller), and `resize`, `promote`, `demote` or `fit` as text.
  Closing the socket detaches.

## Remote access

With [phone access](https://rakumux.com/docs/phone/remote-access.md) on, the API adds a **remote listener** on the machine's
Tailscale addresses, at `remote.json`'s port (7337 by default), or on `remote.json`'s `listen`
addresses or `--remote-listen ADDR:PORT` instead.

* Its bearer is the **remote token** from `remote.json`, not the `api.json` token.
* It doesn't check `Host` and allows `Origin` (the phone app's WebSocket sends one).
* The caller is always **you**: identity headers are refused (403).
* It serves the same routes.

## Example

```bash theme={null}
API=$(jq -r .url ~/.rakumux/api.json); TOKEN=$(jq -r .token ~/.rakumux/api.json)
auth=(-H "Authorization: Bearer $TOKEN")

curl -s "$API/v1/health"
curl -s "${auth[@]}" "$API/v1/sessions?all=true"
curl -s "${auth[@]}" -X POST "$API/v1/sessions" -H 'Content-Type: application/json' \
  -d "{\"folder\": \"$PWD\", \"name\": \"tests\", \"startup_commands\": [\"cargo test\"]}"
curl -s "${auth[@]}" "$API/v1/sessions/01JAB…/content?source=scrollback&lines=50" | jq -r .text
```

(`jq` is used only by this example; Rakumux doesn't need it.)


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