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

# How It Works

> End-to-end walkthrough of how Clawup provisions and runs your agents

Clawup uses [Pulumi](https://pulumi.com) to provision cloud infrastructure as code, deploying each agent on a dedicated Ubuntu server with persistent storage, secure networking, and all the tools defined by its identity.

## Deploy Flow

When you run `clawup deploy`, here's what happens:

```
clawup.yaml         identity.yaml
   (Manifest)            (Per-agent)
  • Provider, region     • Model, coding agent
  • Instance type        • Plugins & deps
  • Agent list           • Skills
  • Owner info           • Workspace files
        │                      │
        └──────────┬───────────┘
                   ▼
             Pulumi Stack           Cloud Provider
             (TypeScript)    ────▶  (AWS / Hetzner)
                   │
                   ▼
          Per-agent resources:
          • Server (Ubuntu 24.04)
          • Security group / firewall
          • SSH keypair
          • Gateway token
          • Cloud-init script
```

1. **Load manifest** — The CLI reads your `clawup.yaml` config and shows a deployment summary.
2. **Fetch identities** — For each agent with an `identity` field, the CLI fetches the identity from the Git repo or local path, validates `identity.yaml`, and collects all workspace files and skills.
3. **Select Pulumi stack** — Creates or selects a stack matching your config name.
4. **Sync config** — Copies the manifest to the project root and sets provider-specific Pulumi config.
5. **Run resolve hooks** — Swarm, identity, and plugin resolve hooks run on your machine to auto-derive secrets. Most-specific-wins on key conflicts (plugin > identity > swarm).
6. **Provision resources** — Pulumi creates infrastructure for each agent: server, firewall, SSH key, and injects a cloud-init bootstrap script as user data.
7. **Cloud-init runs** — On first boot, each server executes the bootstrap sequence (see below) to install tools, configure OpenClaw, and join the Tailscale mesh. Lifecycle hooks (postProvision, preStart) execute in order: swarm → identity → plugin.
8. **Show outputs** — The CLI displays each agent's Tailscale URL, public IP, and instance ID.

## Cloud-Init Bootstrap Sequence

Every agent server runs the same bootstrap script on first boot. The sequence takes a few minutes and handles everything from base packages to a running OpenClaw daemon.

### 1. System Setup

* Set non-interactive mode
* `apt-get update && apt-get upgrade`
* Install `unzip`
* Create `ubuntu` user (Hetzner only — AWS AMIs already have one)

### 2. Docker

* Install via `get.docker.com`
* Enable and start the Docker service
* Add `ubuntu` to the `docker` group

### 3. Node.js

* Install NVM (v0.40.1)
* Install Node.js 22
* Set as default version
* Install OpenClaw CLI globally via npm

### 4. Dependencies (from dep registry)

System dependencies declared in the identity's `deps` field are installed. For example:

* `gh` — GitHub CLI from the official apt repository, authenticated with the provided token
* `brave-search` — Brave Search API key configured as an environment variable

The dep registry (`packages/core/src/dep-registry.ts`) maps each dep name to its install script.

### 5. Coding Agent

The coding agent CLI declared in the identity's `codingAgent` field is installed. For example:

* `claude-code` — Claude Code installed via `claude.ai/install.sh`, added to `~/.local/bin`

The coding agent registry (`packages/core/src/coding-agent-registry.ts`) maps each agent name to install and model configuration scripts.

### 6. Tailscale

* Install via `tailscale.com/install.sh`
* Join the mesh: `tailscale up --authkey=<key> --ssh --hostname=<stack>-<agent-name>`
* See [Networking & Security](/architecture/networking) for details

### 7. Deno + Linear CLI (if Linear configured)

* Install Deno to `~/.deno`
* Install Linear CLI: `deno install --global jsr:@schpet/linear-cli`

### 8. OpenClaw Onboard

* Enable systemd linger for the `ubuntu` user
* Run `openclaw onboard --non-interactive --accept-risk` (local mode, gateway on loopback)

### 9. PostProvision Hooks

* Run swarm-level `postProvision` hook (from `clawup.yaml`)
* Run identity-level `postProvision` hook (from `identity.yaml`)
* Run plugin-level `postProvision` hooks (from plugin manifests)
* Hooks execute sequentially: swarm → identity → plugin. See [Lifecycle Hooks](/guides/hooks) for details.

### 10. Identity File Injection

* Fetch workspace files from the agent's identity (Git repo or local path)
* Inject files into `~/.openclaw/workspace/` (SOUL.md, IDENTITY.md, HEARTBEAT.md, TOOLS.md, USER.md, AGENTS.md, BOOTSTRAP.md)
* Inject skill files into `~/.openclaw/workspace/skills/`
* Substitute template variables (`{{OWNER_NAME}}`, `{{TIMEZONE}}`, etc.) with values from the manifest
* Files are gzipped and base64-encoded in the cloud-init script for efficiency

### 11. OpenClaw Configuration & Plugins

* Patch `openclaw.json` with gateway, heartbeat, sandbox, and integration settings (see below)
* Configure the AI model and backup model from the identity's `model` and `backupModel` fields
* Configure `cliBackends` from the coding agent registry entry
* Install plugins declared in the identity's `plugins` field (e.g., openclaw-linear, slack)
* Install the OpenClaw daemon service

### 12. PreStart Hooks

* Run swarm-level `preStart` hook (from `clawup.yaml`)
* Run identity-level `preStart` hook (from `identity.yaml`)
* Run plugin-level `preStart` hooks (from plugin manifests)
* Hooks execute sequentially: swarm → identity → plugin. See [Lifecycle Hooks](/guides/hooks) for details.

### 13. Tailscale Serve

* Proxy the gateway port over HTTPS: `tailscale serve --bg 18789`
* Creates a public URL on your tailnet for the OpenClaw web UI

### 14. Post-Setup Commands

* Run any custom commands from `postSetupCommands` in the manifest

## What Gets Installed

Each agent server ends up with:

| Software          | Version      | Purpose                                                                       |
| ----------------- | ------------ | ----------------------------------------------------------------------------- |
| Docker            | Latest       | Sandbox code execution                                                        |
| Node.js           | 22           | Runtime for OpenClaw                                                          |
| OpenClaw          | Latest (npm) | Agent framework — gateway, heartbeat, plugins, daemon                         |
| Coding agent CLI  | Latest       | AI coding assistant (e.g., Claude Code) — from identity's `codingAgent` field |
| Tailscale         | Latest       | Mesh VPN, SSH, HTTPS proxy                                                    |
| System deps       | Latest       | Per-identity — e.g., GitHub CLI, Brave Search (from `deps` field)             |
| Deno + Linear CLI | Latest       | Linear ticket management (if Linear plugin configured)                        |

## OpenClaw Configuration

After onboarding, the bootstrap script patches `openclaw.json` with your deployment settings:

### Gateway

* Binds to `127.0.0.1` (loopback only — not publicly accessible)
* Trusted proxies: `["127.0.0.1"]`
* Token-based authentication (auto-generated per agent)
* Control UI enabled with `allowInsecureAuth: true` (safe behind Tailscale)

### Heartbeat

```json theme={null}
{
  "every": "1m",
  "session": "main"
}
```

The heartbeat fires every minute in the `main` session, executing each agent's `HEARTBEAT.md` checklist. For most agents this is minimal (bootstrap detection only) — the primary work trigger is the [Linear plugin queue system](/architecture/identities#linear-plugin-queue-system).

### Sandbox

Docker-based sandbox is enabled by default (`enableSandbox: true`), providing isolated code execution.

### Integrations

**Slack** (if configured):

* Socket mode with bot token and app token
* DMs enabled with open policy
* Group policy: open

**Linear** (if configured):

* **openclaw-linear plugin** installed and configured with API key, webhook secret, agent mapping, and per-role queue routing rules (from `pluginDefaults` in the identity)
* Linear CLI available via Deno

### Environment Variables

Credentials are auto-detected and set:

* OAuth tokens (`sk-ant-oat*`) → `CLAUDE_CODE_OAUTH_TOKEN`
* API keys → `ANTHROPIC_API_KEY`
* Plus `LINEAR_API_KEY`, `GITHUB_TOKEN`, `SLACK_BOT_TOKEN`, `SLACK_APP_TOKEN` as configured

## Identity File Injection

Each agent gets workspace files injected from its identity source (Git repo or local path):

### Identity-Specific Files

| File           | Purpose                                                          |
| -------------- | ---------------------------------------------------------------- |
| `SOUL.md`      | Personality, approach, core truths, superpowers, boundaries      |
| `IDENTITY.md`  | Name, role, emoji, avatar                                        |
| `HEARTBEAT.md` | Periodic checklist — bootstrap detection and polling-based tasks |
| `TOOLS.md`     | Tool-specific notes and common commands                          |

### Shared Files

| File           | Purpose                                                                                 |
| -------------- | --------------------------------------------------------------------------------------- |
| `USER.md`      | Owner information (name, timezone, working hours, notes)                                |
| `AGENTS.md`    | Shared operational instructions — memory management, safety rules, group chat etiquette |
| `BOOTSTRAP.md` | First-run integration checks with self-cleanup                                          |

### Template Variables

Workspace files support template variables that get replaced at deploy time:

| Variable            | Example                               |
| ------------------- | ------------------------------------- |
| `{{OWNER_NAME}}`    | `"Jane"`                              |
| `{{TIMEZONE}}`      | `"America/New_York"`                  |
| `{{WORKING_HOURS}}` | `"9am-6pm"`                           |
| `{{USER_NOTES}}`    | `"No additional notes provided yet."` |
| `{{LINEAR_TEAM}}`   | `"ENG"`                               |
| `{{GITHUB_REPO}}`   | `"org/repo"`                          |

Custom template variables declared in the identity's `templateVars` are also supported.

## Provider-Specific Differences

Both AWS and Hetzner follow the same bootstrap sequence, with a few differences:

| Aspect              | AWS                              | Hetzner                   |
| ------------------- | -------------------------------- | ------------------------- |
| Base image          | Ubuntu 24.04 LTS (Canonical AMI) | `ubuntu-24.04`            |
| User creation       | `ubuntu` user exists by default  | Created during cloud-init |
| Networking          | VPC + subnet + internet gateway  | Flat networking           |
| Firewall            | Security group                   | Hetzner firewall          |
| Metadata security   | IMDSv2 enforced                  | N/A                       |
| Cloud-init delivery | Gzipped + base64 user data       | Plain user data           |

See [Cloud Providers](/architecture/cloud-providers) for region, instance type, and cost details.
