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

# Logging

> Stream template build logs, reconnect to builds, and poll incrementally.

Use a log callback when the client should display build progress immediately:

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

  build = Template.build(
      builder,
      name="my-template",
      tags=["stable"],
      on_log_entry=default_build_logger(),
  )
  ```

  ```typescript TypeScript SDK theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
  const template = await client.templates.builder()
    .fromPythonImage("3.12")
    .build({
      name: "my-template",
      tags: ["stable"],
      onLogEntry: (entry) => console.log(entry.level, entry.message),
    });
  ```

  ```bash CLI theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
  # The default text log format streams progress to stderr during the build.
  nullspace template build --from-python-image 3.12 --name my-template --tag stable
  ```

  ```bash HTTP API theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
  # POST /v1/templates/build returns a text/event-stream of structured log
  # entries. Use -N to disable buffering. See the API reference for the
  # TemplateBuildLogEntry schema.
  curl -N -X POST "${NULLSPACE_API_URL}/v1/templates/build" \
    -H "Authorization: Bearer ${NULLSPACE_API_KEY}" \
    -H "Content-Type: application/json" \
    -H "Accept: text/event-stream" \
    -d '{"name": "my-template", "tags": ["stable"], "base_image": "python:3.12"}'
  ```
</CodeGroup>

Reconnect to a background build by ID:

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

  build = TemplateBuild.connect("tb_...")
  status = build.get_status(offset=0)
  for entry in status.entries:
      print(entry.kind, entry.message)
  print(status.next_offset)
  ```

  ```bash CLI theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
  nullspace template build-status tb_... --offset 0
  nullspace template logs tb_...
  ```

  ```bash HTTP API theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
  # GET /v1/templates/builds/{build_id}/logs replays durable entries from offset
  # and follows live entries with follow=true. See the API reference for the
  # TemplateBuildLogEntry schema.
  curl -N "${NULLSPACE_API_URL}/v1/templates/builds/tb_.../logs?offset=0&follow=true" \
    -H "Authorization: Bearer ${NULLSPACE_API_KEY}" \
    -H "Accept: text/event-stream"
  ```
</CodeGroup>

<Note>
  The TypeScript SDK builds synchronously and streams logs via `onLogEntry`; it
  does not reconnect to background builds. Use the Python SDK, CLI, or HTTP API.
</Note>

Save `status.next_offset` after each poll and pass it to the next
`get_status()` or `wait_until_terminal()` call to fetch only new entries.

## More CLI Examples

```bash theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
nullspace template build-status tb_...
nullspace template build-status tb_... --offset 10
nullspace template logs tb_...
nullspace template wait tb_... --offset 10 --poll-interval-ms 500 --log-format jsonl
```

## Related

* [Build](./build)
* [Caching](./caching)
* [Error handling](./errors)
