Skip to content
This repository was archived by the owner on Mar 30, 2026. It is now read-only.

Repository files navigation

Clawup

This project is archived and no longer maintained.

Clawup was built on top of OpenClaw, which has undergone frequent breaking changes that made it impractical to keep this framework stable and reliable. Rather than leave users with a broken tool, this repo has been archived.

If you are currently using Clawup, please migrate away. Deployments that are already running may continue to work, but no fixes, updates, or support will be provided.

The documentation below is preserved for reference only.


 ____ _ ___ ___ _ ____
/ ___| | / \ \ / / | | | _ \
| | | | / _ \ \ /\ / /| | | | |_) |
| |___| |___ / ___ \ V V / | |_| | __/
\____|_____/_/ \_\_/\_/ \___/|_|

npmlicense

The secure golden path for deploying OpenClaw agent swarms — identity-driven, infrastructure-as-code, zero public ports.

Watch the demo on X

What Is This?

Clawup provisions autonomous AI agents with persistent memory, role-specific behavior, and secure-by-default networking. Each agent runs in a Docker sandbox with its own identity — personality, skills, tools, and model preferences — connected over a Tailscale mesh VPN with no public port exposure.

You define what your agents do. Clawup handles where and how they run — securely.

Security Guarantees

  • Zero public ports — all agent ports bind to 127.0.0.1, accessible only via Tailscale
  • Encrypted secrets — API keys and tokens stored via Pulumi encrypted config
  • Mesh VPN — agents communicate over Tailscale's encrypted peer-to-peer network
  • Docker isolation — each agent runs in a sandboxed container
  • Token-based auth — gateway access requires authentication
┌─────────────────────────────────────────────────────────────────────┐
│ AWS VPC / Hetzner Cloud │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Agent A │ │ Agent B │ │ Agent C │ │
│ │ │ │ │ │ │ │
│ │ • OpenClaw │ │ • OpenClaw │ │ • OpenClaw │ │
│ │ • Docker │ │ • Docker │ │ • Docker │ │
│ │ • Tailscale │ │ • Tailscale │ │ • Tailscale │ │
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
│ └──────────────────┼──────────────────┘ │
└────────────────────────────┼────────────────────────────────────────┘
│
┌────────────▼────────────┐
│ Tailscale Mesh VPN │
│ (Encrypted P2P) │
└────────────┬────────────┘
│
┌────────────▼────────────┐
│ Your Machine │
└─────────────────────────┘

Identity System

Agents are defined by identities — composable, self-contained packages that include everything an agent needs to operate: personality, skills, model preferences, plugin configuration, and dependencies.

How Identities Work

An identity is a directory with an identity.yaml manifest and workspace files:

my-identity/
├── identity.yaml # Manifest: model, plugins, deps, skills, template vars
├── SOUL.md # Personality, role, approach, communication style
├── IDENTITY.md # Name, role, emoji
├── HEARTBEAT.md # Periodic tasks and state machine logic
├── TOOLS.md # Tool reference (integrations, local env)
├── AGENTS.md # Multi-agent coordination instructions
├── BOOTSTRAP.md # First-run setup instructions
├── USER.md # Owner-specific info (templated)
└── skills/ # Bundled skills
└── my-skill/
└── SKILL.md

Identities can live in a Git repo, a monorepo subdirectory, or a local path. Point any agent at any identity:

# clawup.yamlagents:
- name: agent-researcherdisplayName: Atlasrole: researcheridentity: "https://github.com/your-org/your-identities#researcher"identityVersion: "v1.0.0"# optional: pin to a tag or commitvolumeSize: 20

identity.yaml

The identity manifest declares the agent's defaults:

name: researcherdisplayName: Atlasrole: researcheremoji: telescopedescription: Deep research, source analysis, report generationvolumeSize: 20model: anthropic/claude-opus-4-6codingAgent: claude-codedeps:
- brave-searchplugins:
- slackpluginDefaults:
slack:
mode: socketdm:
enabled: truepolicy: openskills:
- research-reporttemplateVars:
- OWNER_NAME
- TIMEZONE
- WORKING_HOURS
- USER_NOTES# Additional secrets not covered by plugins/depsrequiredSecrets:
- notionApiKey # → <ROLE>_NOTION_API_KEY in .env

Creating Your Own Identity

The easiest way to create a new identity is with army-create:

npx army-create

This interactively scaffolds all required files — identity.yaml, workspace files, and skill stubs. See the examples/identity/ directory for a minimal single-agent example, or examples/multi-agent/ for a production-ready 3-agent fleet. The Creating Identities guide covers the full authoring reference including:

  • Identity structure and required files
  • identity.yaml field reference
  • Workspace file conventions
  • Skill authoring (private and public)
  • Template variable substitution
  • Available registries (deps, plugins, coding agents)

Lifecycle Hooks

Hooks are shell scripts that run at specific points during deployment and provisioning. They're available at three levels — swarm (clawup.yaml), identity (identity.yaml), and plugin (plugin manifest) — letting you scope automation from fleet-wide concerns down to individual plugin setup. Hooks can auto-resolve derived secrets, install server-side tools, run interactive onboarding, and perform pre-launch configuration.

# clawup.yaml — swarm-level hooks (run for all agents)hooks:
postProvision: | echo "Installing fleet monitoring..." curl -sSL https://get.datadoghq.com/agent | sh
# identity.yaml — identity-level hooks (run for agents using this identity)hooks:
postProvision: | echo "Installing engineering tools..." npm install -g turbo prettierpreStart: | echo "Verifying repo access..." gh auth status

Lifecycle hooks execute in order: swarm → identity → plugin. Resolve hooks use most-specific-wins on key conflicts. See the Lifecycle Hooks guide for the full reference.

Plugins

Agents use OpenClaw plugins for integrations with external services. Built-in plugins (Linear, Slack) have curated manifests in the plugin registry and work out of the box — just list them in identity.yaml. For third-party or custom plugins, bundle a manifest in plugins/<name>.yaml inside the identity directory to define secrets, hooks, and configuration. See the Plugins guide for installation, authoring, and the full manifest reference.

Quick Start

1. Install

npm install -g clawup

2. Generate Config

clawup init

Discovers local identity directories and scaffolds a clawup.yaml manifest and .env.example with sensible defaults (AWS, us-east-1). Edit clawup.yaml by hand to customize your provider, region, instance type, owner info, and agents.

3. Fill in Secrets

cp .env.example .env
# Edit .env and fill in your API keys

4. Deploy

clawup deploy

Validates all secrets from .env, configures Pulumi, and deploys your agents. If any secrets are missing, it prints exactly what's needed.

5. Validate

Wait 3-5 minutes for cloud-init to complete, then:

clawup validate

6. Access Your Agents

clawup ssh <agent-name># SSH by name, role, or alias

CLI Reference

Run clawup --help for the full list.

CommandDescription
clawup initGenerate clawup.yaml scaffold (or refresh from identity changes)
clawup deployValidate secrets, configure Pulumi, and deploy agents
clawup deploy --localDeploy to local Docker containers
clawup statusShow agent statuses and outputs
clawup status --localShow local Docker container status
clawup ssh <agent>SSH to an agent by name, role, or alias
clawup ssh <agent> --localShell into a local Docker container
clawup validateHealth check all agents via Tailscale
clawup validate --localHealth check local Docker containers
clawup redeployUpdate agents in-place (pulumi up --refresh)
clawup redeploy --localRedeploy local Docker containers
clawup destroyTear down all resources (with confirmation)
clawup destroy --localDestroy local Docker containers only
clawup listShow project config
clawup config showDisplay current config
clawup config show --jsonConfig in JSON format
clawup config set <key> <value>Update a config value
clawup config set <key> <value> -a <agent>Update a per-agent config value
clawup secrets set <key> <value>Set a Pulumi secret (e.g. API keys)
clawup secrets listShow which secrets are configured (redacted)
clawup pushPush workspace files, skills, and config to running agents
clawup onboardRun plugin onboard hooks for interactive first-time setup
clawup webhooks setupConfigure Linear webhooks for deployed agents
clawup updateUpdate clawup CLI to the latest version

Agent resolution is flexible — all of these target the same agent:

clawup ssh pm # by role
clawup ssh agent-pm # by resource name
clawup ssh juno # by displayName

Cloud Providers

Provider Comparison

FeatureAWSHetzner Cloud
3x Agents (monthly)~$99~$18-22
Instance Typet3.medium (2 vCPU, 4GB)CX22 (2 vCPU, 4GB)
Storage~$2.40/month per 30GBIncluded
Data Transfer~$5-10/month20TB included
RegionsGlobal (25+)EU & US (5 locations)
Setup ComplexityModerate (VPC, IAM)Simple (API token)

Use Hetzner for development and cost savings (~80% cheaper). Use AWS for production or global reach.

What Gets Provisioned

Each agent gets:

  • Cloud instance (EC2 or Hetzner server) with Ubuntu 24.04 LTS
  • Docker (for OpenClaw sandbox)
  • Node.js v22, OpenClaw CLI, coding agent CLI (from registry), GitHub CLI
  • Tailscale VPN (encrypted mesh, no public ports)
  • Workspace files and skills injected from its identity
  • AI model configured per-identity (with fallback support)
  • Plugins and deps installed per-identity

All agents share a single VPC/network for cost optimization.

Dependencies

You need the following installed on your local machine before running clawup init.

Required (all providers)

DependencyWhyInstall
Node.js 18+Runtime for CLI and Pulumi programnodejs.org
Pulumi CLIInfrastructure provisioningpulumi.com/docs/iac/download-install
Pulumi AccountState management and encrypted secretsapp.pulumi.com/signup
TailscaleSecure mesh VPN to reach your agentstailscale.com/download

Required (provider-specific)

Pick one depending on where you want to deploy:

ProviderDependencyInstall
AWSAWS CLI (configured with credentials)aws.amazon.com/cli — then run aws configure
HetznerAPI token with Read & Write permissionsconsole.hetzner.cloud → Project → Security → API Tokens

Tailscale Setup

Tailscale requires a few one-time setup steps:

  1. Create an account
  2. Enable HTTPS certificates (required for OpenClaw web UI)
  3. Generate a reusable auth key with tags — enable both "Reusable" and "Ephemeral" (ephemeral nodes auto-remove when offline)
  4. Note your tailnet DNS name (e.g., tail12345.ts.net)

Installed on agents automatically

These are provisioned on the cloud instances via cloud-init — you do not need them locally:

  • Docker, Node.js v22, OpenClaw CLI, coding agent CLI (e.g., Claude Code)
  • Tailscale (agent-side)
  • GitHub CLI, Brave Search, and other deps (per-identity)
  • OpenClaw plugins: Linear, Slack (per-identity)

Required API Keys

KeyRequiredWhere to Get
Anthropic CredentialsYesAPI Key or OAuth token (claude setup-token)
Tailscale Auth KeyYesTailscale Admin (reusable, with tags)
Slack Bot TokenNoSlack API — per agent
Linear API TokenNoLinear Settings — per agent
GitHub TokenNoGitHub Settings — per agent

Claude Code Authentication

Two authentication methods are supported:

MethodToken FormatBest For
API Keysk-ant-api03-...Pay-as-you-go API usage
OAuth Tokensk-ant-oat01-...Pro/Max subscription (flat rate)

The system auto-detects which type you provide and sets the correct environment variable.

Updating & Redeploying

For in-place updates that preserve Tailscale devices and existing infrastructure:

clawup redeploy

This runs pulumi up --refresh to sync cloud state and apply changes. If the stack doesn't exist yet, it falls back to a fresh deploy automatically.

For local Docker containers:

clawup redeploy --local

For a clean rebuild (when in-place update can't recover):

clawup destroy -y && clawup deploy -y

Configuration

Viewing & Modifying Config

View your current configuration without opening the manifest file:

clawup config show # Human-readable summary
clawup config show --json # Full JSON output

Modify config values with validation (no need to re-run init):

clawup config set region us-west-2
clawup config set instanceType t3.large
clawup config set instanceType cx32 -a atlas # Per-agent override
clawup config set volumeSize 50 -a atlas # Per-agent volume

Run clawup redeploy after changing config to apply.

clawup.yaml

Generated by clawup init. This manifest drives the entire deployment:

stackName: devprovider: awsregion: us-east-1instanceType: t3.mediumownerName: Your Nametimezone: America/New_YorkworkingHours: 9am-6pmsecrets:
anthropicApiKey: "${env:ANTHROPIC_API_KEY}"tailscaleAuthKey: "${env:TAILSCALE_AUTH_KEY}"tailnetDnsName: "${env:TAILNET_DNS_NAME}"tailscaleApiKey: "${env:TAILSCALE_API_KEY}"agents:
- name: agent-pmdisplayName: Junorole: pmidentity: "https://github.com/your-org/army-identities#pm"volumeSize: 30secrets:
slackBotToken: "${env:PM_SLACK_BOT_TOKEN}"slackAppToken: "${env:PM_SLACK_APP_TOKEN}"plugins:
openclaw-linear:
agentId: agent-pmslack:
mode: socket
- name: agent-researcherdisplayName: Atlasrole: researcheridentity: "./my-identities/researcher"volumeSize: 20

The secrets section uses ${env:VAR} references — actual values are loaded from a .env file at init time. A .env.example is generated alongside the manifest. Model, backup model, and coding agent are configured in the identity (not the manifest). The manifest defines which agents to deploy and where.

Pulumi Config

Secrets are stored encrypted in Pulumi config, set automatically by clawup deploy. You can also manage them directly:

pulumi config set --secret anthropicApiKey sk-ant-xxxxx
pulumi config set --secret tailscaleAuthKey tskey-auth-xxxxx
pulumi config set tailnetDnsName tail12345.ts.net

Pulumi ESC

For more advanced secret management, use Pulumi ESC. See esc/clawup-secrets.yaml.example for the full template.

Project Structure

clawup/
├── packages/
│ ├── core/ # @clawup/core — shared types, constants, registries
│ │ └── src/
│ │ ├── schemas/ # Zod schemas (source of truth for types)
│ │ ├── constants.ts
│ │ ├── identity.ts # Identity loader (Git repos, local paths)
│ │ ├── plugin-registry.ts
│ │ ├── coding-agent-registry.ts
│ │ ├── dep-registry.ts
│ │ └── skills.ts
│ ├── cli/ # clawup CLI (published npm package)
│ │ ├── bin.ts # Entry point (Commander.js)
│ │ ├── commands/ # init, deploy, redeploy, status, ssh, validate, destroy, config, list, push, secrets, webhooks, update
│ │ ├── tools/ # Tool implementations (adapter-based)
│ │ ├── lib/ # CLI-only: config, pulumi, ui, tailscale, exec
│ │ └── adapters/ # Runtime adapters (CLI vs API)
│ ├── pulumi/ # @clawup/pulumi — infrastructure as code
│ │ └── src/
│ │ ├── components/
│ │ │ ├── openclaw-agent.ts # AWS EC2 agent component
│ │ │ ├── hetzner-agent.ts # Hetzner Cloud agent component
│ │ │ ├── local-docker-agent.ts # Local Docker agent component
│ │ │ ├── cloud-init.ts # Cloud-init script generation
│ │ │ └── config-generator.ts # OpenClaw config builder
│ │ ├── shared-vpc.ts
│ │ └── index.ts # Main Pulumi stack program
│ └── web/ # Next.js dashboard (clawup-web)
├── examples/ # Example identities for reference
│ ├── identity/ # Minimal single-agent "researcher" example
│ └── multi-agent/ # Production 3-agent fleet (PM, Engineer, Tester)
├── docs/ # Documentation (Mintlify site + guides)
├── esc/ # Pulumi ESC secret templates
├── scripts/ # Shell script helpers
├── Pulumi.yaml # Pulumi project config (points to packages/pulumi/)
└── pnpm-workspace.yaml # Monorepo workspace config

Security

  • All agent ports bind to 127.0.0.1 — access is via Tailscale only
  • No public port exposure; Tailscale Serve proxies traffic
  • Token-based gateway authentication
  • Secrets encrypted via Pulumi config
  • Cloud-init scripts use environment variable interpolation
  • SSH available as fallback for debugging

Troubleshooting

Agents not appearing in Tailscale

  1. Wait 3-5 minutes for cloud-init to complete
  2. Check logs: clawup ssh <agent> 'sudo cat /var/log/cloud-init-output.log | tail -100'
  3. Verify your Tailscale auth key is valid and reusable

OpenClaw gateway not running

clawup ssh <agent>'openclaw gateway status'
clawup ssh <agent>'journalctl -u openclaw -n 50'
clawup ssh <agent>'openclaw gateway restart'

SSH connection refused

  1. Check Tailscale is running locally: tailscale status
  2. Verify the agent appears in your tailnet
  3. Ensure you're using the correct tailnet DNS name

Pulumi state issues

pulumi refresh # Refresh state from actual infrastructure
pulumi cancel # Force unlock if locked

Development

For contributing to Clawup itself:

git clone https://github.com/stepandel/clawup.git
cd clawup
pnpm install
pnpm build # Build all packages
pnpm test# Run all tests# Individual packages
pnpm --filter @clawup/core build # Build core
pnpm --filter clawup build # Build CLI
pnpm --filter @clawup/pulumi build # Build Pulumi
pnpm --filter clawup-web dev # Web dev server

License

MIT

Related

About

Deploy fleets of specialized OpenClaw agents to your cloud. Define identities in YAML, provision with one command, track changes in git.

Topics

Resources

Contributing

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages