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

# Quickstart

> Build a reusable template and launch a machine from it.

Templates capture setup once so every machine can start from a ready environment.

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

  builder = (
      Template()
      .from_python_image("3.12")
      .apt_install(["git", "curl"])
      .pip_install(["fastapi", "uvicorn"])
      .copy("./app.py", "/workspace/app.py")
      .set_workdir("/workspace")
  )

  build = Template.build(
      builder,
      name="fastapi-agent",
      tags=["stable"],
      on_log_entry=default_build_logger(),
  )

  with Machine.create(template=build.canonical_ref) as machine:
      result = machine.commands.run("python3 --version", shell=True)
      print(result.stdout)
  ```

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

  const client = new NullspaceClient();

  const template = await client.templates
    .builder()
    .fromPythonImage("3.12")
    .aptInstall(["git", "curl"])
    .pipInstall(["fastapi", "uvicorn"])
    .copy("./app.py", "/workspace/app.py")
    .setWorkdir("/workspace")
    .build({
      name: "fastapi-agent",
      tags: ["stable"],
      onLogEntry: (entry) => console.log(entry.message),
    });

  await using machine = await client.machines.create({
    template: `${template.name}:stable`,
  });
  const result = await machine.commands.run("python3 --version", { shell: true });
  console.log(result.stdout);
  ```

  ```bash CLI theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
  nullspace template build \
    --from-python-image 3.12 \
    --apt-install git,curl \
    --pip-install fastapi,uvicorn \
    --copy-src ./app.py --copy-dst /workspace/app.py \
    --set-workdir /workspace \
    --name fastapi-agent \
    --tag stable

  nullspace machine create --template fastapi-agent:stable
  ```

  ```bash HTTP API theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
  # Template builds stream structured logs over SSE; the request body is large.
  # See the API reference for the full CreateTemplateRequest schema.
  curl -N -X POST "${NULLSPACE_API_URL}/v1/templates/build" \
    -H "Authorization: Bearer ${NULLSPACE_API_KEY}" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "fastapi-agent",
      "tags": ["stable"],
      "base_image": "python:3.12",
      "steps": [
        {"action": "apt_install", "packages": ["git", "curl"]},
        {"action": "pip_install", "packages": ["fastapi", "uvicorn"]},
        {"action": "workdir", "path": "/workspace"}
      ]
    }'
  ```
</CodeGroup>

Use `Template.build_in_background()` when a build should continue while your
client disconnects or polls progress later.

<CodeGroup>
  ```python Python SDK theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
  build = Template.build_in_background(builder, name="fastapi-agent", tags=["next"])
  finished = build.wait_until_terminal()
  print(finished.build.status)
  ```

  ```bash CLI theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
  nullspace template build \
    --from-python-image 3.12 \
    --name fastapi-agent \
    --tag next \
    --background

  nullspace template wait tb_... --poll-interval-ms 500
  ```

  ```bash HTTP API theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
  # POST /v1/templates/builds accepts the same CreateTemplateRequest body and
  # returns a build handle to poll with GET /v1/templates/builds/{build_id}.
  curl -X POST "${NULLSPACE_API_URL}/v1/templates/builds" \
    -H "Authorization: Bearer ${NULLSPACE_API_KEY}" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "fastapi-agent",
      "tags": ["next"],
      "base_image": "python:3.12"
    }'
  ```
</CodeGroup>

<Note>
  The TypeScript SDK builds synchronously over the SSE stream; for
  background builds and polling, use the Python SDK, CLI, or HTTP API.
</Note>

See the [API reference](../api-reference) for the full template build request
schema and background-build polling.

## Related

* [How it works](./how-it-works)
* [Defining template](./defining)
* [Build](./build)
