> ## 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.

# End a session's program.

> Terminates the program (not the sessions it created). The session stays, and becomes `exited` once the program is gone; revive brings it back.




## OpenAPI

````yaml /api-reference/openapi.yaml post /v1/sessions/{id}/kill
openapi: 3.1.0
info:
  title: Rakumux external API
  version: '1'
  summary: Sessions and folders of the local Rakumux daemon, over HTTP.
  description: >
    `rakumux-api` exposes a subset of the session operations of the running

    Rakumux daemon (`rakumux-ptyd`). It listens on **127.0.0.1** and, with

    remote access on, on a **remote listener** too (see below). It is a thin

    adapter: the daemon decides permissions and folder confinement.


    **Discovery.** While it runs, the API writes

    `<RAKUMUX_HOME or ~/.rakumux>/api.json` (mode 0600):

    `{"url": "http://127.0.0.1:<port>", "token": "<64 hex>", "pid": <int>,
    "version": "<x.y.z>", "remote_urls": ["http://<addr>:<port>"]}`

    (`remote_urls` only while a remote listener runs). A file whose `pid` no

    longer exists is stale.


    **Authentication.** Every route except `GET /v1/health` needs

    `Authorization: Bearer <token>`. On the loopback listener the token is

    api.json's; requests whose `Host` is not a loopback name (`127.0.0.1`,

    `localhost`, `[::1]`, any port) and requests carrying an `Origin` or

    `Sec-Fetch-Site` header (browsers) are refused with 403. No CORS headers

    are ever sent.


    **Remote access.** `rakumux remote on` writes

    `<home>/remote.json` (mode 0600):

    `{"enabled": true, "port": 7337, "token": "<26 chars a-z2-7>", "listen":
    []}`.

    While it is enabled the API adds a remote listener on every Tailscale

    address of the machine (IPv4 in `100.64.0.0/10`, IPv6 in

    `fd7a:115c:a1e0::/48`) at `port`, or on `remote.json`'s `listen` /

    `--remote-listen ADDR:PORT` addresses instead. There the bearer is the

    remote token (constant-time compared); `Host` isn't checked and `Origin`

    is allowed; the caller is always the user, so the identity headers below

    are refused (403 `permission_denied`). The loopback listener keeps its

    rules. Same routes on both.


    **Streams.** `GET /v1/events` and `GET /v1/sessions/{id}/attach` are

    WebSockets (RFC 6455, version 13) on the same port, with the same checks;

    errors before the upgrade are ordinary JSON answers, and a request

    without the upgrade headers gets 426 `upgrade_required`. Their messages

    are the `EventMessage`, `AttachMessage` and `AttachCommand` schemas. The

    server pings every 30 s and drops a client that didn't answer the

    previous ping; it closes the socket when the stream ends.


    **Identity.** Without identity headers the API acts as the user. With both

    `X-Rakumux-Session-Id` and `X-Rakumux-Session-Token` (the

    `RAKUMUX_SESSION_ID` / `RAKUMUX_SESSION_TOKEN` of a process running in

    a Rakumux session) it acts as that session: the daemon confines it to

    its own folder and applies its agent policy (today: read anything in the

    folder, create sessions in it within limits, rename only itself). With

    both `X-Rakumux-Agent` and `X-Rakumux-Agent-Conversation` instead

    (for agents whose tool calls don't carry the session's environment, such

    as OpenCode 2.x) it acts as the running session that bound that

    conversation with `rakumux session bind`; 401 if none did. That needs

    the daemon's `auth.delegated` capability (501 without it).


    **Folders.** A session's folder is the canonical directory it was started

    in (the daemon's protocol calls it `scope`, and its folder operations

    `project_*`). Wherever a `folder` is accepted it may be an absolute

    directory (`~/` is expanded) or the name of a known folder; names and

    listing every folder need the daemon's `projects` capability (see

    `GET /v1/health`), and answer 501 / 400 until it has it.


    **Deprecated `project` names.** Earlier builds said "project": they are

    still accepted and returned. `GET /v1/projects` is an alias of

    `GET /v1/folders`; the `project` query parameter and body field are

    aliases of `folder` (`folder` wins; both given and naming different

    folders is a 400); responses carry `project` next to `folder` and

    `projects` next to `folders`, with the same values.


    **Errors** use one envelope, `{"error": {"code", "message", "details"?}}`.

    Daemon error codes map to statuses: `not_found` 404, `invalid_argument`

    400, `unauthenticated` 401, `out_of_scope` and `permission_denied` 403,

    `session_not_live` and `session_in_use` 409, `limit_exceeded` 429,

    `timeout` 504,

    `daemon_unavailable` 503, `unsupported` 501, anything else 500. The API's

    own codes: `method_not_allowed` 405, `payload_too_large` 413,

    `unsupported_media_type` 415, `upgrade_required` 426.


    **Compatibility.** Fields may be added to responses; clients must ignore

    unknown fields. Request bodies reject unknown fields, and routes reject

    unknown query parameters (400), so typos never pass silently.
servers:
  - url: http://127.0.0.1:{port}
    variables:
      port:
        default: '0'
        description: The port in api.json.
  - url: http://{host}:{port}
    description: The remote listener (remote access on); see api.json `remote_urls`.
    variables:
      host:
        default: machine.tailnet.ts.net
        description: The machine's MagicDNS name or Tailscale address.
      port:
        default: '7337'
        description: remote.json `port`.
security:
  - bearer: []
tags:
  - name: health
  - name: folders
  - name: sessions
  - name: streams
paths:
  /v1/sessions/{id}/kill:
    parameters:
      - $ref: '#/components/parameters/SessionId'
      - $ref: '#/components/parameters/SessionIdentityId'
      - $ref: '#/components/parameters/SessionIdentityToken'
      - $ref: '#/components/parameters/AgentIdentityKind'
      - $ref: '#/components/parameters/AgentIdentityConversation'
    post:
      tags:
        - sessions
      summary: End a session's program.
      description: >
        Terminates the program (not the sessions it created). The session stays,
        and becomes `exited` once the program is gone; revive brings it back.
      operationId: killSession
      responses:
        '204':
          description: The program was told to end.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/NotLive'
        '503':
          $ref: '#/components/responses/DaemonUnavailable'
components:
  parameters:
    SessionId:
      name: id
      in: path
      required: true
      description: >-
        Opaque session id (letters, digits, `-`, `_`). Never derive anything
        from it.
      schema:
        type: string
        pattern: ^[A-Za-z0-9_-]{1,128}$
    SessionIdentityId:
      name: X-Rakumux-Session-Id
      in: header
      required: false
      description: Act as this session (with X-Rakumux-Session-Token).
      schema:
        type: string
    SessionIdentityToken:
      name: X-Rakumux-Session-Token
      in: header
      required: false
      description: The session's RAKUMUX_SESSION_TOKEN.
      schema:
        type: string
    AgentIdentityKind:
      name: X-Rakumux-Agent
      in: header
      required: false
      description: >
        Act for the session that bound this agent's conversation (with
        X-Rakumux-Agent-Conversation), e.g. `opencode`. Not with the session
        headers.
      schema:
        type: string
        pattern: ^[a-z0-9_-]{1,32}$
    AgentIdentityConversation:
      name: X-Rakumux-Agent-Conversation
      in: header
      required: false
      description: The agent's conversation id, e.g. OpenCode's `ses_…`.
      schema:
        type: string
  responses:
    Unauthenticated:
      description: >-
        `unauthenticated`: missing or wrong API token, or a session identity the
        daemon rejects.
      headers:
        WWW-Authenticate:
          schema:
            type: string
            const: Bearer
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Forbidden:
      description: >
        `permission_denied` (non-loopback Host, browser request, or the daemon's
        policy) or `out_of_scope` (a session acting outside its folder).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    NotFound:
      description: '`not_found`: no such session, folder or route.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    NotLive:
      description: >-
        `session_not_live`: the session has no running terminal (it is `exited`
        or `dead`).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    DaemonUnavailable:
      description: >-
        `daemon_unavailable`: the daemon is not running and could not be
        started.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  schemas:
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              examples:
                - not_found
                - invalid_argument
                - unauthenticated
                - out_of_scope
                - unsupported
            message:
              type: string
            details: {}
  securitySchemes:
    bearer:
      type: http
      scheme: bearer
      description: >
        The `token` from api.json on the loopback listener; the remote token
        from remote.json (`rakumux remote token`) on the remote listener.

````

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