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

# Lifecycle Events

> List and stream machine and snapshot lifecycle transitions.

Lifecycle history and webhooks require hosted or local Supabase-backed state.

## List recent events

Account-wide listing is available from the Python SDK, CLI, and HTTP API. The
TypeScript SDK exposes lifecycle history per machine (`machine.lifecycle.list`),
shown under [Per-machine events](#per-machine-events).

<CodeGroup>
  ```python Python SDK theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
  from nullspace import Lifecycle

  lifecycle = Lifecycle()
  events = lifecycle.list_events(limit=20)
  for event in events.events:
      print(event.operation, event.status, event.machine_id)
  lifecycle.close()
  ```

  ```bash CLI theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
  nullspace lifecycle events --limit 20
  ```

  ```bash HTTP API theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
  curl "${NULLSPACE_API_URL}/v1/lifecycle/events?limit=20" \
    -H "Authorization: Bearer ${NULLSPACE_API_KEY}"
  ```
</CodeGroup>

## Per-machine events

<CodeGroup>
  ```python Python SDK theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
  from nullspace import Machine

  with Machine.create(template="base") as machine:
      machine.commands.run("true", shell=True)
      events = machine.list_lifecycle(limit=10)
      for event in events.events:
          print(event.operation, event.status)
  ```

  ```typescript TypeScript SDK theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
  import { Machine } from "nullspace";

  const machine = await Machine.create({ template: "base" });
  await machine.commands.run("true", { shell: true });
  const events = await machine.lifecycle.list({ limit: 10 });
  for (const event of events.events) {
    console.log(event.operation, event.status);
  }
  ```

  ```bash CLI theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
  nullspace lifecycle events --machine-id mch_123 --limit 10
  ```

  ```bash HTTP API theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
  curl "${NULLSPACE_API_URL}/v1/machines/mch_123/lifecycle?limit=10" \
    -H "Authorization: Bearer ${NULLSPACE_API_KEY}"
  ```
</CodeGroup>

## Stream events

The lifecycle stream is a WebSocket channel (`/v1/lifecycle/ws`). The SDKs and
CLI handle the upgrade and replay for you; raw HTTP clients perform the upgrade
described in the [WebSocket protocol](../reference/websocket-protocol).

<CodeGroup>
  ```python Python SDK theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
  from nullspace import Lifecycle

  lifecycle = Lifecycle()
  for event in lifecycle.stream_events(
      machine_id="mch_123",
      live_only=False,
      replay_limit=100,
      metadata={"run": "docs"},
  ):
      print(event.id, event.operation, event.status)
  lifecycle.close()
  ```

  ```typescript TypeScript SDK theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
  import { Machine } from "nullspace";

  const machine = await Machine.connect("mch_123");
  for await (const event of machine.lifecycle.subscribe({
    liveOnly: false,
    replayLimit: 100,
  })) {
    console.log(event.id, event.operation, event.status);
  }
  ```

  ```bash CLI theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
  nullspace lifecycle stream --machine-id mch_123 --replay-limit 100
  ```

  ```bash HTTP API theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
  # WebSocket upgrade; send a `subscribe` message after connecting.
  # See ../reference/websocket-protocol for message shapes.
  wscat -c "${NULLSPACE_API_URL}/v1/lifecycle/ws" \
    -H "Authorization: Bearer ${NULLSPACE_API_KEY}"
  ```
</CodeGroup>

Use `subscribe()` when you want callbacks in a background reader:

```python theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
subscription = lifecycle.subscribe(
    machine_id="mch_...",
    on_event=lambda event: print(event.operation, event.status),
    on_error=lambda error: print(error.message),
)
subscription.stop()
```

## Filters

`list_events` supports operation, status, audience, machine ID, snapshot ID,
source machine ID, target machine ID, time range, ordering, offset, and limit
filters.

`stream_events` supports machine ID, snapshot ID, operation, status, audience,
metadata matching, `after_event_id`, `live_only`, and `replay_limit`. It does
not support source/target machine filters, time range, ordering, offset, or
limit. Use `after_event_id` to resume from a known event ID after reconnecting.

## Event fields

| Field                                    | Notes                                                                                                                                       |
| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `operation`                              | `create`, `destroy`, `timeout_updated`, `timeout_expired`, `hibernate`, `snapshot_created`, `resume_from_snapshot`, `fork`, or `reconcile`. |
| `status`                                 | `requested`, `succeeded`, or `failed`.                                                                                                      |
| `audience`                               | Public SDK helpers expose customer-visible events.                                                                                          |
| `machine_id`, `snapshot_id`              | Present when the operation is tied to that resource.                                                                                        |
| `source_machine_id`, `target_machine_id` | Present for fork and resume-style transitions.                                                                                              |
| `error_code`, `error_message`            | Populated for failed transitions.                                                                                                           |

## Snapshot events

<CodeGroup>
  ```python Python SDK theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
  events = lifecycle.list_snapshot_events("snap_123", limit=20)
  for event in events.events:
      print(event.operation, event.status, event.machine_id)
  ```

  ```bash CLI theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
  nullspace lifecycle events --snapshot-id snap_123 --limit 20
  ```

  ```bash HTTP API theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
  curl "${NULLSPACE_API_URL}/v1/snapshots/snap_123/lifecycle?limit=20" \
    -H "Authorization: Bearer ${NULLSPACE_API_KEY}"
  ```
</CodeGroup>

## Related

* [Webhooks](./webhooks)
* [Monitor](./monitor)
* [Persistence](../machines/persistence)
