Skip to main content
Lifecycle hooks are experimental and subject to change. Multi-level hooks (swarm and identity) are new — the API may evolve in future releases.
Hooks are shell scripts that run at specific points during deployment and provisioning. They let you automate secret resolution, server setup, and pre-launch configuration without modifying the core deployment pipeline. Hooks are available at three levels — swarm, identity, and plugin — so you can scope automation to exactly where it belongs.

Three Levels

Swarm-Level Hooks

Defined in clawup.yaml, swarm hooks run for every agent in your deployment. Use them for fleet-wide concerns.

Identity-Level Hooks

Defined in identity.yaml, identity hooks run for all agents using that identity. Use them for role-specific setup.

Plugin-Level Hooks

Defined in a plugin’s manifest, plugin hooks run for that plugin only. Resolve hooks at this level must match an autoResolvable secret key in the plugin manifest.

Execution Order

Lifecycle Hooks (postProvision, preStart)

All levels run sequentially, broadest first:
For a deployment with two agents using different identities and plugins:

Resolve Hooks

Resolve hooks use most-specific-wins on key conflicts:
If the same environment variable key is defined at multiple levels, the most specific definition wins. Plugin-level resolve keys must match an autoResolvable: true secret in the plugin manifest. Swarm and identity-level resolve keys are environment variable names directly.

Onboard Hooks

Onboard hooks run sequentially, broadest first. Swarm onboard runs once, then per agent: identity onboard followed by plugin onboards.

Execution Timeline

The following shows where each hook type fires during the deployment lifecycle:
Deps run as postProvision hooks. When an identity declares deps (e.g., gh, brave-search), their install and post-install scripts are prepended to the postProvision hooks array. Install scripts run as root (for apt-get, etc.), post-install scripts run as ubuntu (for auth/config). They execute before swarm, identity, and plugin hooks.

Hook Types

Clawup supports four hook types, each running at a different stage: All four hook types are available at all three levels (swarm, identity, plugin).

Resolve Hooks

Resolve hooks auto-derive secret values from other secrets. They run on your machine during clawup deploy, before infrastructure is provisioned. When: During deploy, after .env is loaded Input: Environment variables (including other secrets already in .env) Output: stdout is captured as the resolved value (must be non-empty) Timeout: 30 seconds

How It Works

Each resolve hook is a shell script keyed by a secret name. At the plugin level, the key must match a secret marked autoResolvable: true in the plugin manifest. At the swarm and identity levels, keys are environment variable names directly. During deploy, Clawup runs each script and stores stdout as the secret’s value. If the same key appears at multiple levels, the most specific definition wins (plugin > identity > swarm).

Example: Plugin-Level Resolve (Linear User UUID)

The built-in openclaw-linear plugin resolves the Linear user UUID from the API key:

Example: Identity-Level Resolve (Notion Workspace ID)

An engineering identity that resolves a workspace ID for all agents with this role:

Example: Swarm-Level Resolve (Shared Webhook URL)

A swarm-level resolve hook that fetches a shared value for all agents:

Rules

  • Plugin level: The resolve hook key must match a secret key with autoResolvable: true in the plugin manifest
  • Swarm/identity level: The resolve hook key is the environment variable name directly
  • The script must print exactly one value to stdout (trailing whitespace is trimmed)
  • If the script exits non-zero or prints nothing, the deploy fails with an error
  • All environment variables from .env are available in the script

Onboard Hooks

Onboard hooks run interactive first-time setup — like registering webhook URLs or configuring external services that require post-deploy information. When: During clawup onboard or clawup deploy --onboard Input: User-provided values (prompted interactively) + existing secrets Output: stdout is displayed as follow-up instructions Timeout: 120 seconds

How It Works

  1. Clawup checks each level (swarm, identity, plugin) for an onboard hook definition
  2. For each input defined in inputs, the user is prompted (or the value is read from .env)
  3. The hook script runs with all inputs and existing secrets as environment variables
  4. stdout is displayed as follow-up instructions to the user

Example: Webhook Registration

Options

Each input in inputs supports: For more on running onboard hooks, see the clawup onboard CLI reference.

PostProvision Hooks

PostProvision hooks run on the agent server during cloud-init, after base packages (Node.js, Docker, coding agent) are installed but before workspace files are injected. When: Cloud-init, after Node.js/Docker/coding agent installation Where: Agent server, as the ubuntu user (dep install scripts run as root) Output: Streamed to cloud-init log (/var/log/cloud-init-output.log)

Use Cases

  • Installing custom system tools or CLI utilities
  • Downloading ML models or large data files
  • Setting up database clients or drivers
  • Configuring system-level settings
  • Fleet-wide monitoring (swarm level)
  • Role-specific tooling (identity level)

Example: Swarm-Level PostProvision

Example: Identity-Level PostProvision

Example: Plugin-Level PostProvision

How Deps Integrate with PostProvision

When an identity declares deps (e.g., gh, brave-search), those deps are automatically converted into postProvision hooks that run before swarm, identity, and plugin hooks. Each dep can produce up to two hooks:
  1. Install hook (dep:<name>:install) — runs as root for system-level installation (e.g., apt-get)
  2. Post-install hook (dep:<name>:post) — runs as ubuntu for authentication and configuration
For example, an identity with deps: [gh, brave-search] and a swarm-level postProvision hook produces this execution order:
This means identity and plugin hooks can safely depend on deps being installed. For example, an identity preStart hook can use gh:

Environment

PostProvision hooks have access to:
  • Environment variables from .profile (API keys, tokens)
  • System tools installed in earlier phases (Node.js, npm, Docker)
  • Network access (Tailscale is connected at this point)
  • Deps installed earlier in the postProvision phase (e.g., gh CLI)

PreStart Hooks

PreStart hooks run on the agent server during cloud-init, after workspace files are injected and OpenClaw is configured, but before the gateway starts. When: Cloud-init, after workspace files + openclaw config set commands Where: Agent server, as the ubuntu user Output: Streamed to cloud-init log (/var/log/cloud-init-output.log)

Use Cases

  • Reading workspace config to generate derived files
  • Running database migrations
  • Pre-warming caches or indexes
  • Validating the full configuration before launch

Example: Generating a Config File from Workspace Data

Example: Pre-warming a Search Index

Environment

PreStart hooks have access to everything postProvision hooks have, plus:
  • Workspace files in /home/ubuntu/.openclaw/workspace/
  • OpenClaw configuration (set via openclaw config set)
  • Installed plugins

Complete Examples

Swarm-Level: Fleet Monitoring

Identity-Level: Engineering Setup

Plugin-Level: Full Analytics Plugin

Tips and Best Practices

Make hooks idempotent. Deploys can be retried. Write hooks so that running them twice produces the same result — use mkdir -p instead of mkdir, check if files exist before downloading, etc. Handle errors gracefully. If a hook script exits with a non-zero code, the deploy fails. Use explicit error checks and helpful error messages:
Keep hooks focused. Each hook should do one thing well. If you need complex setup, consider splitting across postProvision (system setup) and preStart (app config). Use the right level. Put fleet-wide concerns (monitoring, shared tooling) at the swarm level. Put role-specific setup (engineering tools, research APIs) at the identity level. Put plugin-specific automation (secret resolution, plugin CLI) at the plugin level. Test locally. You can test hook scripts locally before deploying:
Use stderr for progress, stdout for values. In resolve and onboard hooks, stdout is captured as the result. Use >&2 to print progress messages that won’t interfere with the captured value: