Full Code of phioranex/openclaw-docker for AI

main a45e13e6232a cached
12 files
59.7 KB
16.1k tokens
1 requests
Download .txt
Repository: phioranex/openclaw-docker
Branch: main
Commit: a45e13e6232a
Files: 12
Total size: 59.7 KB

Directory structure:
gitextract_uobwqc7k/

├── .github/
│   └── workflows/
│       ├── build-image.yml
│       └── openclaw-release-tracker.yml
├── .gitignore
├── .last-openclaw-version
├── Dockerfile
├── LICENSE
├── README.md
├── docker-compose.yml
├── install.ps1
├── install.sh
├── uninstall.ps1
└── uninstall.sh

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/workflows/build-image.yml
================================================
name: Build and Push Docker Image

on:
  workflow_dispatch:
    inputs:
      openclaw_version:
        description: 'OpenClaw version to build (branch/tag)'
        required: false
        default: 'main'
        type: string
      push_image:
        description: 'Push image to registry'
        required: false
        default: true
        type: boolean
  push:
    branches:
      - main
    paths:
      - 'Dockerfile'
      - '.github/workflows/build-image.yml'
  schedule:
    # Build daily at 00:00 UTC to get latest OpenClaw updates
    - cron: '0 0 * * *'

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository_owner }}/openclaw-docker

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Log in to Container Registry
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Extract metadata
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
          tags: |
            type=raw,value=latest,enable={{is_default_branch}}
            type=sha,prefix={{branch}}-
            type=ref,event=branch
            type=schedule,pattern={{date 'YYYYMMDD'}}

      - name: Determine OpenClaw version
        id: version
        run: |
          if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
            VERSION="${{ inputs.openclaw_version }}"
          else
            VERSION=$(cat .last-openclaw-version)
          fi
          echo "openclaw_version=${VERSION}" >> $GITHUB_OUTPUT
          echo "Building with OpenClaw version: ${VERSION}"

      - name: Build and push Docker image
        uses: docker/build-push-action@v5
        with:
          context: .
          file: ./Dockerfile
          push: ${{ (github.event_name != 'workflow_dispatch') || inputs.push_image }}
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          build-args: |
            OPENCLAW_VERSION=${{ steps.version.outputs.openclaw_version }}
          cache-from: type=gha
          cache-to: type=gha,mode=max
          platforms: linux/amd64,linux/arm64

      - name: Generate build summary
        run: |
          echo "### 🦞 OpenClaw Docker Build Summary" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          echo "**OpenClaw Version:** \`${{ steps.version.outputs.openclaw_version }}\`" >> $GITHUB_STEP_SUMMARY
          echo "**Image Tags:**" >> $GITHUB_STEP_SUMMARY
          echo '```' >> $GITHUB_STEP_SUMMARY
          echo "${{ steps.meta.outputs.tags }}" >> $GITHUB_STEP_SUMMARY
          echo '```' >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          echo "**Registry:** \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}\`" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
            if [ "${{ inputs.push_image }}" = "true" ]; then
              echo "✅ Image pushed to registry" >> $GITHUB_STEP_SUMMARY
            else
              echo "ℹ️ Image built but not pushed (manual trigger with push disabled)" >> $GITHUB_STEP_SUMMARY
            fi
          else
            echo "✅ Image pushed to registry" >> $GITHUB_STEP_SUMMARY
          fi


================================================
FILE: .github/workflows/openclaw-release-tracker.yml
================================================
name: OpenClaw Release Tracker

on:
  schedule:
    # Check for new OpenClaw releases every 6 hours
    - cron: '0 */6 * * *'
  workflow_dispatch:

jobs:
  check-release:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      packages: write
      actions: write
      
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Check for new OpenClaw release
        id: check_release
        run: |
          # Get the latest release from OpenClaw repository
          LATEST_RELEASE=$(curl -s https://api.github.com/repos/openclaw/openclaw/releases/latest | jq -r '.tag_name // empty')
          
          # Get the latest commit from main branch if no releases
          if [ -z "$LATEST_RELEASE" ]; then
            LATEST_COMMIT=$(curl -s https://api.github.com/repos/openclaw/openclaw/commits/main | jq -r '.sha[:7]')
            LATEST_RELEASE="main-${LATEST_COMMIT}"
          fi
          
          echo "Latest OpenClaw version: ${LATEST_RELEASE}"
          echo "latest_version=${LATEST_RELEASE}" >> $GITHUB_OUTPUT
          
          # Check if we've already built this version
          if [ -f ".last-openclaw-version" ]; then
            LAST_VERSION=$(cat .last-openclaw-version)
            echo "Last built version: ${LAST_VERSION}"
            
            if [ "$LATEST_RELEASE" = "$LAST_VERSION" ]; then
              echo "new_release=false" >> $GITHUB_OUTPUT
              echo "No new release found"
            else
              echo "new_release=true" >> $GITHUB_OUTPUT
              echo "New release detected!"
            fi
          else
            echo "new_release=true" >> $GITHUB_OUTPUT
            echo "First run - will build"
          fi

      - name: Update version tracker
        if: steps.check_release.outputs.new_release == 'true'
        run: |
          echo "${{ steps.check_release.outputs.latest_version }}" > .last-openclaw-version
          git config user.name "github-actions[bot]"
          git config user.email "github-actions[bot]@users.noreply.github.com"
          git add .last-openclaw-version
          git diff --quiet && git diff --staged --quiet || git commit -m "Update OpenClaw version tracker to ${{ steps.check_release.outputs.latest_version }}"
          git push

      - name: Trigger build workflow
        if: steps.check_release.outputs.new_release == 'true'
        uses: actions/github-script@v7
        with:
          script: |
            await github.rest.actions.createWorkflowDispatch({
              owner: context.repo.owner,
              repo: context.repo.repo,
              workflow_id: 'build-image.yml',
              ref: 'main',
              inputs: {
                openclaw_version: '${{ steps.check_release.outputs.latest_version }}',
                push_image: 'true'
              }
            });
            
            console.log('✅ Triggered build workflow for new OpenClaw release: ${{ steps.check_release.outputs.latest_version }}');

      - name: Create summary
        if: always()
        run: |
          echo "### 🦞 OpenClaw Release Check" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          echo "**Latest OpenClaw Version:** \`${{ steps.check_release.outputs.latest_version }}\`" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          if [ "${{ steps.check_release.outputs.new_release }}" = "true" ]; then
            echo "✅ **New release detected!** Build workflow triggered." >> $GITHUB_STEP_SUMMARY
          else
            echo "ℹ️ No new release. Docker image is up to date." >> $GITHUB_STEP_SUMMARY
          fi


================================================
FILE: .gitignore
================================================
# Moltbot Docker

Build artifacts and temporary files


================================================
FILE: .last-openclaw-version
================================================
v2026.5.7


================================================
FILE: Dockerfile
================================================
FROM node:22-bookworm

LABEL org.opencontainers.image.source="https://github.com/phioranex/openclaw-docker"
LABEL org.opencontainers.image.description="Pre-built OpenClaw (Clawbot) Docker image"
LABEL org.opencontainers.image.licenses="MIT"

# Install system dependencies (including Homebrew prerequisites)
RUN apt-get update && apt-get install -y \
    git \
    curl \
    ca-certificates \
    unzip \
    build-essential \
    procps \
    file \
    sudo \
    jq \
    && rm -rf /var/lib/apt/lists/*

# Install Bun (required for build)
RUN curl -fsSL https://bun.sh/install | bash
ENV PATH="/root/.bun/bin:${PATH}"

# Install Homebrew (required for first-party skills)
# Create linuxbrew user+group and grant sudo access (required for Homebrew package installations)
RUN groupadd -f linuxbrew && \
    useradd -m -s /bin/bash -g linuxbrew linuxbrew && \
    echo 'linuxbrew ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers && \
    mkdir -p /home/linuxbrew/.linuxbrew && \
    chown -R linuxbrew:linuxbrew /home/linuxbrew/.linuxbrew
# Download and install Homebrew manually (shallow clone to reduce image size)
# Note: HOMEBREW_NO_AUTO_UPDATE is set below to disable updates
RUN mkdir -p /home/linuxbrew/.linuxbrew/Homebrew && \
    git clone --depth 1 https://github.com/Homebrew/brew /home/linuxbrew/.linuxbrew/Homebrew && \
    mkdir -p /home/linuxbrew/.linuxbrew/bin && \
    ln -s /home/linuxbrew/.linuxbrew/Homebrew/bin/brew /home/linuxbrew/.linuxbrew/bin/brew && \
    chown -R linuxbrew:linuxbrew /home/linuxbrew/.linuxbrew && \
    chmod -R g+rwX /home/linuxbrew/.linuxbrew
    
ENV PATH="/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin:${PATH}"
ENV HOMEBREW_NO_AUTO_UPDATE=1
ENV HOMEBREW_NO_INSTALL_CLEANUP=1

# Enable corepack for pnpm
RUN corepack enable

WORKDIR /app

# Clone and build OpenClaw - always fetch latest from main branch
ARG OPENCLAW_VERSION=main
RUN git clone --depth 1 --branch ${OPENCLAW_VERSION} https://github.com/openclaw/openclaw.git . && \
    echo "Building OpenClaw from branch: ${OPENCLAW_VERSION}" && \
    git rev-parse HEAD > /app/openclaw-commit.txt

# Install dependencies
RUN pnpm install --frozen-lockfile

# Build
RUN OPENCLAW_A2UI_SKIP_MISSING=1 pnpm build
# Force pnpm for UI build (Bun may fail on ARM/Synology architectures)
RUN npm_config_script_shell=bash pnpm ui:install
RUN npm_config_script_shell=bash pnpm ui:build

# Clean up build artifacts to reduce image size
RUN rm -rf .git node_modules/.cache

# Create app user (node already exists in base image)
# Add node user to linuxbrew group for Homebrew access
# Fix permissions for global npm installs
RUN mkdir -p /home/node/.openclaw /home/node/.openclaw/workspace \
    && chown -R node:node /home/node /app \
    && chmod -R 755 /home/node/.openclaw \
    && usermod -aG linuxbrew node \
    && chmod -R g+w /home/linuxbrew/.linuxbrew \
    && chown -R node:node /usr/local/lib/node_modules \
    && chown -R node:node /usr/local/bin

# Install Playwright system dependencies (as root before switching to node user)
RUN npx -y playwright@latest install-deps chromium

# Copy SSL certificates to a location accessible by all users
RUN mkdir -p /usr/local/share/ca-certificates && \
    cp /etc/ssl/certs/ca-certificates.crt /usr/local/share/ca-certificates/ca-certificates.crt && \
    chmod 755 /usr/local/share/ca-certificates && \
    chmod 644 /usr/local/share/ca-certificates/ca-certificates.crt

USER node

# Install Playwright browsers for the node user
# Use NODE_EXTRA_CA_CERTS to point to accessible certificate bundle
RUN NODE_EXTRA_CA_CERTS=/usr/local/share/ca-certificates/ca-certificates.crt npx -y playwright@latest install chromium

WORKDIR /home/node

ENV NODE_ENV=production
ENV PATH="/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin:/app/node_modules/.bin:${PATH}"
ENV HOMEBREW_NO_AUTO_UPDATE=1
ENV HOMEBREW_NO_INSTALL_CLEANUP=1

# Default command
ENTRYPOINT ["node", "/app/dist/index.js"]
CMD ["--help"]


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2026 Phioranex Pvt Ltd

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

---

Note: This repository provides Docker packaging for Moltbot.
Moltbot itself is a separate project with its own license.
See: https://github.com/moltbot/moltbot


================================================
FILE: README.md
================================================
# OpenClaw (Clawbot) Docker Image

Pre-built Docker image for [OpenClaw](https://github.com/openclaw/openclaw) — run your AI assistant in seconds without building from source.

> 🔄 **Always Up-to-Date:** This image automatically builds daily and checks for new OpenClaw releases every 6 hours, ensuring you always have the latest version.

## One-Line Install (Recommended)

### Linux / macOS

```bash
bash <(curl -fsSL https://raw.githubusercontent.com/phioranex/openclaw-docker/main/install.sh)
```

### Windows (PowerShell)

```powershell
irm https://raw.githubusercontent.com/phioranex/openclaw-docker/main/install.ps1 | iex
```

> **Note for Windows users:** Make sure Docker Desktop is installed and running. You can also use WSL2 with the Linux installation command.

This will:
- ✅ Check prerequisites (Docker, Docker Compose)
- ✅ Download necessary files
- ✅ Pull the pre-built image
- ✅ Run the onboarding wizard
- ✅ Start the gateway

### Install Options

**Linux / macOS:**

### Install Options

**Linux / macOS:**

```bash
# Just pull the image (no setup)
bash <(curl -fsSL https://raw.githubusercontent.com/phioranex/openclaw-docker/main/install.sh) --pull-only

# Skip onboarding (if already configured)
bash <(curl -fsSL https://raw.githubusercontent.com/phioranex/openclaw-docker/main/install.sh) --skip-onboard

# Don't start gateway after setup
bash <(curl -fsSL https://raw.githubusercontent.com/phioranex/openclaw-docker/main/install.sh) --no-start

# Custom install directory
bash <(curl -fsSL https://raw.githubusercontent.com/phioranex/openclaw-docker/main/install.sh) --install-dir /opt/openclaw
```

**Windows (PowerShell):**

```powershell
# Just pull the image (no setup)
irm https://raw.githubusercontent.com/phioranex/openclaw-docker/main/install.ps1 | iex -PullOnly

# Skip onboarding (if already configured)
irm https://raw.githubusercontent.com/phioranex/openclaw-docker/main/install.ps1 | iex -SkipOnboard

# Don't start gateway after setup
irm https://raw.githubusercontent.com/phioranex/openclaw-docker/main/install.ps1 | iex -NoStart

# Custom install directory
$env:TEMP_INSTALL_SCRIPT = irm https://raw.githubusercontent.com/phioranex/openclaw-docker/main/install.ps1; Invoke-Expression $env:TEMP_INSTALL_SCRIPT -InstallDir "C:\openclaw"
```

## Manual Install

### Quick Start

```bash
# Pull the image
docker pull ghcr.io/phioranex/openclaw-docker:latest

# Run onboarding (first time setup)
docker run -it --rm \
  -v ~/.openclaw:/home/node/.openclaw \
  -v ~/.openclaw/workspace:/home/node/.openclaw/workspace \
  ghcr.io/phioranex/openclaw-docker:latest onboard

# Start the gateway
docker run -d \
  --name openclaw \
  --restart unless-stopped \
  -v ~/.openclaw:/home/node/.openclaw \
  -v ~/.openclaw/workspace:/home/node/.openclaw/workspace \
  -p 18789:18789 \
  ghcr.io/phioranex/openclaw-docker:latest gateway start --foreground
```

### Using Docker Compose

```bash
# Clone this repo
git clone https://github.com/phioranex/openclaw-docker.git
cd openclaw-docker

# Run onboarding
docker compose run --rm openclaw-cli onboard

# Start the gateway
docker compose up -d openclaw-gateway
```

## Configuration

During onboarding, you'll configure:
- **AI Provider** (Anthropic Claude, OpenAI, etc.)
- **Channels** (Telegram, WhatsApp, Discord, etc.)
- **Gateway settings**

Config is stored in `~/.openclaw/` and persists across container restarts.

## Available Tags

| Tag | Description |
|-----|-------------|
| `latest` | Latest OpenClaw build (updated daily and on new releases) |
| `vX.Y.Z` | Specific version (if available) |
| `main` | Latest from main branch (cutting edge) |

> **Note:** The `latest` tag is automatically rebuilt daily at 00:00 UTC and whenever OpenClaw releases a new version.

## Volumes

| Path | Purpose |
|------|---------|
| `/home/node/.openclaw` | Config and session data |
| `/home/node/.openclaw/workspace` | Agent workspace |

## Ports

| Port | Purpose |
|------|---------|
| `18789` | Gateway API + Dashboard |

## Links

- [OpenClaw Website](https://openclaw.ai/)
- [OpenClaw Docs](https://docs.openclaw.ai)
- [OpenClaw GitHub](https://github.com/openclaw/openclaw)
- [Discord Community](https://discord.gg/clawd)

## Uninstallation

### One-Line Uninstall

**Linux / macOS:**

```bash
bash <(curl -fsSL https://raw.githubusercontent.com/phioranex/openclaw-docker/main/uninstall.sh)
```

**Windows (PowerShell):**

```powershell
irm https://raw.githubusercontent.com/phioranex/openclaw-docker/main/uninstall.ps1 | iex
```

This will:
- ✅ Stop and remove all containers
- ✅ Ask before removing configuration and workspace data
- ✅ Ask before removing Docker image
- ✅ Ask before removing installation directory

### Uninstall Options

**Linux / macOS:**

```bash
# Keep configuration and workspace data
bash <(curl -fsSL https://raw.githubusercontent.com/phioranex/openclaw-docker/main/uninstall.sh) --keep-data

# Keep Docker image (useful if reinstalling later)
bash <(curl -fsSL https://raw.githubusercontent.com/phioranex/openclaw-docker/main/uninstall.sh) --keep-image

# Skip all confirmation prompts
bash <(curl -fsSL https://raw.githubusercontent.com/phioranex/openclaw-docker/main/uninstall.sh) --force

# Custom install directory
bash <(curl -fsSL https://raw.githubusercontent.com/phioranex/openclaw-docker/main/uninstall.sh) --install-dir /opt/openclaw
```

**Windows (PowerShell):**

```powershell
# Keep configuration and workspace data
& ([scriptblock]::Create((irm https://raw.githubusercontent.com/phioranex/openclaw-docker/main/uninstall.ps1))) -KeepData

# Keep Docker image (useful if reinstalling later)
& ([scriptblock]::Create((irm https://raw.githubusercontent.com/phioranex/openclaw-docker/main/uninstall.ps1))) -KeepImage

# Skip all confirmation prompts
& ([scriptblock]::Create((irm https://raw.githubusercontent.com/phioranex/openclaw-docker/main/uninstall.ps1))) -Force

# Custom install directory
& ([scriptblock]::Create((irm https://raw.githubusercontent.com/phioranex/openclaw-docker/main/uninstall.ps1))) -InstallDir "C:\openclaw"
```

### Manual Uninstall

If you prefer to uninstall manually:

```bash
# Stop and remove containers
docker stop openclaw-gateway openclaw-socat
docker rm openclaw-gateway openclaw-socat openclaw-cli

# Remove data (optional)
rm -rf ~/.openclaw

# Remove Docker image (optional)
docker rmi ghcr.io/phioranex/openclaw-docker:latest

# Remove installation directory (optional)
rm -rf ~/openclaw
```

## Troubleshooting

### Permission Issues on Synology NAS

If you encounter `EACCES: permission denied` errors when running on Synology NAS:

1. **Option 1: Run install script with sudo (Recommended)**
   ```bash
   sudo bash <(curl -fsSL https://raw.githubusercontent.com/phioranex/openclaw-docker/main/install.sh)
   ```
   The script will automatically:
   - Set proper ownership (UID 1000) for the container user
   - Configure your user account to access the files
   - Update docker-compose.yml to use the correct home directory

2. **Option 2: Fix permissions manually**
   ```bash
   # RECOMMENDED: Set ownership to UID 1000 with group access (most secure)
   sudo chown -R 1000:$(id -g) ~/.openclaw
   sudo chmod -R u+rwX,g+rwX,o-rwx ~/.openclaw
   
   # Alternative: Make directory writable by owner and group (less secure)
   chmod -R 775 ~/.openclaw
   
   # LAST RESORT ONLY: World-writable (least secure, use only if above options fail)
   # chmod -R 777 ~/.openclaw
   ```

3. **Option 3: Use host user mapping**
   Edit `docker-compose.yml` and uncomment the `user: "1000:1000"` line in both services:
   ```yaml
   user: "1000:1000"  # Uncomment this line
   ```

### Telegram Bot Connection Issues

If the Telegram bot cannot find your username or numeric ID:

1. Ensure your container has internet access:
   ```bash
   docker exec openclaw-gateway ping -c 3 api.telegram.org
   ```

2. Check if firewall or network restrictions are blocking Telegram API access

3. Verify your Telegram bot token is correct in `~/.openclaw/openclaw.json`

### Docker Permission Issues (Image Pull)

If you need root/sudo to pull Docker images:

1. Add your user to the docker group:
   ```bash
   sudo usermod -aG docker $USER
   ```

2. Log out and log back in for the changes to take effect

3. Alternatively, use `sudo` when running the install script

### Installing Skills (npm global packages)

The container is configured to allow the `node` user to install global npm packages without permission issues. You can install skills using:

```bash
# If using docker compose
docker compose exec openclaw-gateway npm install -g @package/name

# If using standalone container
docker exec -it <container_name> npm install -g @package/name

# Find your container name with:
docker ps
```

If you're using `user: "1000:1000"` in docker-compose.yml, global npm installs will work without any additional configuration.

## YouTube Tutorial

📺 Watch the installation tutorial: [Coming Soon]

## License

This Docker packaging is provided by [Phioranex](https://phioranex.com).
OpenClaw itself is licensed under MIT — see the [original repo](https://github.com/openclaw/openclaw).


================================================
FILE: docker-compose.yml
================================================
services:
  openclaw-gateway:
    image: ghcr.io/phioranex/openclaw-docker:latest
    container_name: openclaw-gateway
    restart: unless-stopped
    stdin_open: true
    tty: true
    # Uncomment the following line if running on Synology NAS or other systems with UID/GID issues
    # user: "1000:1000"
    volumes:
      - ~/.openclaw:/home/node/.openclaw
      - ~/.openclaw/workspace:/home/node/.openclaw/workspace
    ports:
      - "18789:18789"
      - "18790:18790"
    environment:
      - NODE_ENV=production
      - OPENCLAW_SKIP_SERVICE_CHECK=true
    command: ["gateway"]
  
  socat-proxy:
    image: alpine/socat
    container_name: openclaw-socat
    restart: unless-stopped
    network_mode: "service:openclaw-gateway"
    command: "TCP-LISTEN:18790,fork,bind=0.0.0.0,reuseaddr TCP:127.0.0.1:18789"

  openclaw-cli:
    image: ghcr.io/phioranex/openclaw-docker:latest
    container_name: openclaw-cli
    stdin_open: true
    tty: true
    # Uncomment the following line if running on Synology NAS or other systems with UID/GID issues
    # user: "1000:1000"
    volumes:
      - ~/.openclaw:/home/node/.openclaw
      - ~/.openclaw/workspace:/home/node/.openclaw/workspace
    environment:
      - NODE_ENV=production
    entrypoint: ["node", "/app/dist/index.js"]
    profiles:
      - cli


================================================
FILE: install.ps1
================================================
#
# OpenClaw (Clawbot) Docker Installer - Windows PowerShell Version
# One-command setup for OpenClaw on Docker for Windows
#
# Usage:
#   irm https://raw.githubusercontent.com/phioranex/openclaw-docker/main/install.ps1 | iex
#
# Or with options:
#   & ([scriptblock]::Create((irm https://raw.githubusercontent.com/phioranex/openclaw-docker/main/install.ps1))) -NoStart
#

param(
    [string]$InstallDir = "$env:USERPROFILE\openclaw",
    [switch]$NoStart,
    [switch]$SkipOnboard,
    [switch]$PullOnly,
    [switch]$Help
)

# Config
$Image = "ghcr.io/phioranex/openclaw-docker:latest"
$RepoUrl = "https://github.com/phioranex/openclaw-docker"
$ComposeUrl = "https://raw.githubusercontent.com/phioranex/openclaw-docker/main/docker-compose.yml"

# Error handling
$ErrorActionPreference = "Stop"

# Functions
function Write-Banner {
    Write-Host ""
    Write-Host "╔══════════════════════════════════════════════════════════════╗" -ForegroundColor Red
    Write-Host "║                                                              ║" -ForegroundColor Red
    Write-Host "║    ____                    _____ _                           ║" -ForegroundColor Red
    Write-Host "║   / __ \                  / ____| |                          ║" -ForegroundColor Red
    Write-Host "║  | |  | |_ __   ___ _ __ | |    | | __ ___      __           ║" -ForegroundColor Red
    Write-Host "║  | |  | | '_ \ / _ \ '_ \| |    | |/ _`` \ \ /\ / /           ║" -ForegroundColor Red
    Write-Host "║  | |__| | |_) |  __/ | | | |____| | (_| |\ V  V /            ║" -ForegroundColor Red
    Write-Host "║   \____/| .__/ \___|_| |_|\_____|_|\__,_| \_/\_/             ║" -ForegroundColor Red
    Write-Host "║         | |                                                  ║" -ForegroundColor Red
    Write-Host "║         |_|                                                  ║" -ForegroundColor Red
    Write-Host "║                                                              ║" -ForegroundColor Red
    Write-Host "║              Docker Installer by Phioranex                   ║" -ForegroundColor Red
    Write-Host "║                                                              ║" -ForegroundColor Red
    Write-Host "╚══════════════════════════════════════════════════════════════╝" -ForegroundColor Red
    Write-Host ""
}

function Write-Step {
    param([string]$Message)
    Write-Host ""
    Write-Host "▶ $Message" -ForegroundColor Blue
}

function Write-Success {
    param([string]$Message)
    Write-Host "✓ $Message" -ForegroundColor Green
}

function Write-Warning {
    param([string]$Message)
    Write-Host "⚠ $Message" -ForegroundColor Yellow
}

function Write-Error {
    param([string]$Message)
    Write-Host "✗ $Message" -ForegroundColor Red
}

function Test-Command {
    param([string]$Command)
    try {
        Get-Command $Command -ErrorAction Stop | Out-Null
        return $true
    } catch {
        return $false
    }
}

# Show help
if ($Help) {
    Write-Host "OpenClaw (Clawbot) Docker Installer - Windows"
    Write-Host ""
    Write-Host "Usage: install.ps1 [OPTIONS]"
    Write-Host ""
    Write-Host "Options:"
    Write-Host "  -InstallDir DIR   Installation directory (default: ~\openclaw)"
    Write-Host "  -NoStart          Don't start the gateway after setup"
    Write-Host "  -SkipOnboard      Skip onboarding wizard"
    Write-Host "  -PullOnly         Only pull the image, don't set up"
    Write-Host "  -Help             Show this help message"
    return
}

# Main script
Write-Banner

Write-Step "Checking prerequisites..."

# Check Docker
if (Test-Command docker) {
    Write-Success "docker found"
} else {
    Write-Error "docker not found"
    Write-Host ""
    Write-Host "Docker is required but not installed." -ForegroundColor Red
    Write-Host "Install Docker Desktop: https://docs.docker.com/desktop/install/windows-install/" -ForegroundColor Yellow
    return
}

# Check Docker Compose
$ComposeCmd = ""
if (docker compose version 2>$null) {
    Write-Success "Docker Compose found (plugin)"
    $ComposeCmd = "docker compose"
} elseif (Test-Command docker-compose) {
    Write-Success "Docker Compose found (standalone)"
    $ComposeCmd = "docker-compose"
} else {
    Write-Error "Docker Compose not found"
    Write-Host ""
    Write-Host "Docker Compose is required but not installed." -ForegroundColor Red
    Write-Host "It usually comes with Docker Desktop." -ForegroundColor Yellow
    exit 1
}

# Check Docker is running
try {
    docker info 2>$null | Out-Null
    Write-Success "Docker is running"
} catch {
    Write-Error "Docker is not running"
    Write-Host ""
    Write-Host "Please start Docker Desktop and try again." -ForegroundColor Red
    exit 1
}

# Pull only mode
if ($PullOnly) {
    Write-Step "Pulling OpenClaw image..."
    docker pull $Image
    Write-Success "Image pulled successfully!"
    Write-Host ""
    Write-Host "Done! Run the installer again without -PullOnly to complete setup." -ForegroundColor Green
    exit 0
}

Write-Step "Setting up installation directory..."
New-Item -ItemType Directory -Force -Path $InstallDir | Out-Null
Set-Location $InstallDir
Write-Success "Created $InstallDir"

Write-Step "Downloading docker-compose.yml..."
Invoke-WebRequest -Uri $ComposeUrl -OutFile "docker-compose.yml"
Write-Success "Downloaded docker-compose.yml"

Write-Step "Creating data directories..."
$ConfigDir = "$env:USERPROFILE\.openclaw"
$WorkspaceDir = "$env:USERPROFILE\.openclaw\workspace"
New-Item -ItemType Directory -Force -Path $ConfigDir | Out-Null
New-Item -ItemType Directory -Force -Path $WorkspaceDir | Out-Null
Write-Success "Created $ConfigDir (config)"
Write-Success "Created $WorkspaceDir (workspace)"

Write-Step "Pulling OpenClaw image..."
docker pull $Image
Write-Success "Image pulled successfully!"

# Onboarding
if (-not $SkipOnboard) {
    Write-Step "Initializing OpenClaw configuration..."
    Write-Host "Setting up configuration and workspace..." -ForegroundColor Yellow
    Write-Host ""
    
    Write-Step "Running onboarding wizard..."
    Write-Host "This will configure your AI provider and channels." -ForegroundColor Yellow
    Write-Host "Follow the prompts to complete setup." -ForegroundColor Yellow
    Write-Host ""
    
    # Run onboarding
    $composeParts = $ComposeCmd -split " ", 2
    if ($composeParts.Count -eq 2) {
        & $composeParts[0] $composeParts[1] run -T --rm openclaw-cli onboard
    } else {
        & $composeParts[0] run -T --rm openclaw-cli onboard
    }
    if ($LASTEXITCODE -ne 0) {
        Write-Warning "Onboarding wizard was skipped or failed"
        Write-Host "You can run it later with: cd $InstallDir && $ComposeCmd run --rm openclaw-cli onboard" -ForegroundColor Yellow
    } else {
        Write-Success "Onboarding complete!"
    }
}

# Start gateway
if (-not $NoStart) {
    Write-Step "Starting OpenClaw gateway..."
    $composeParts = $ComposeCmd -split " ", 2
    if ($composeParts.Count -eq 2) {
        & $composeParts[0] $composeParts[1] up -d openclaw-gateway
    } else {
        & $composeParts[0] up -d openclaw-gateway
    }
    
    # Wait for gateway to be ready
    Write-Host "Waiting for gateway to start" -NoNewline
    for ($i = 0; $i -lt 30; $i++) {
        try {
            $response = Invoke-WebRequest -Uri "http://localhost:18789/health" -TimeoutSec 1 -ErrorAction SilentlyContinue
            if ($response.StatusCode -eq 200) {
                Write-Host ""
                Write-Success "Gateway is running!"
                break
            }
        } catch {
            # Continue waiting
        }
        Write-Host "." -NoNewline
        Start-Sleep -Seconds 1
    }
    
    try {
        $response = Invoke-WebRequest -Uri "http://localhost:18789/health" -TimeoutSec 1 -ErrorAction SilentlyContinue
        if ($response.StatusCode -ne 200) {
            throw
        }
    } catch {
        Write-Host ""
        Write-Warning "Gateway may still be starting. Check logs with: docker logs openclaw-gateway"
    }
}

# Success message
Write-Host ""
Write-Host "╔══════════════════════════════════════════════════════════════╗" -ForegroundColor Green
Write-Host "║                                                              ║" -ForegroundColor Green
Write-Host "║              🎉 OpenClaw installed successfully! 🎉           ║" -ForegroundColor Green
Write-Host "║                                                              ║" -ForegroundColor Green
Write-Host "╚══════════════════════════════════════════════════════════════╝" -ForegroundColor Green

Write-Host ""
Write-Host "Quick reference:" -ForegroundColor White
Write-Host "  Dashboard:      http://localhost:18789" -ForegroundColor Cyan
Write-Host "  Config:         $ConfigDir" -ForegroundColor Cyan
Write-Host "  Workspace:      $WorkspaceDir" -ForegroundColor Cyan
Write-Host "  Install dir:    $InstallDir" -ForegroundColor Cyan

Write-Host ""
Write-Host "Useful commands:" -ForegroundColor White
Write-Host "  View logs:      docker logs -f openclaw-gateway" -ForegroundColor Cyan
Write-Host "  Stop:           cd $InstallDir && $ComposeCmd down" -ForegroundColor Cyan
Write-Host "  Start:          cd $InstallDir && $ComposeCmd up -d openclaw-gateway" -ForegroundColor Cyan
Write-Host "  Restart:        cd $InstallDir && $ComposeCmd restart openclaw-gateway" -ForegroundColor Cyan
Write-Host "  CLI:            cd $InstallDir && $ComposeCmd run --rm openclaw-cli <command>" -ForegroundColor Cyan
Write-Host "  Update:         docker pull $Image && cd $InstallDir && $ComposeCmd up -d" -ForegroundColor Cyan

Write-Host ""
Write-Host "Documentation:  https://docs.openclaw.ai" -ForegroundColor White
Write-Host "Support:        https://discord.gg/clawd" -ForegroundColor White
Write-Host "Docker image:   $RepoUrl" -ForegroundColor White

Write-Host ""
Write-Host "Happy automating! 🤖🦞" -ForegroundColor Yellow
Write-Host ""


================================================
FILE: install.sh
================================================
#!/bin/bash
#
# OpenClaw (Clawbot) Docker Installer
# One-command setup for OpenClaw on Docker
#
# Usage:
#   bash <(curl -fsSL https://raw.githubusercontent.com/phioranex/openclaw-docker/main/install.sh)
#
# Or with options:
#   bash <(curl -fsSL https://raw.githubusercontent.com/phioranex/openclaw-docker/main/install.sh) --no-start
#

set -e

# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m' # No Color

# Config
INSTALL_DIR="${OPENCLAW_INSTALL_DIR:-$HOME/openclaw}"
IMAGE="ghcr.io/phioranex/openclaw-docker:latest"
REPO_URL="https://github.com/phioranex/openclaw-docker"
COMPOSE_URL="https://raw.githubusercontent.com/phioranex/openclaw-docker/main/docker-compose.yml"

# Detect if we have a TTY (for Docker interactive mode)
if [ -t 0 ]; then
    DOCKER_TTY_FLAG=""
else
    DOCKER_TTY_FLAG="-T"
fi

# Flags
NO_START=false
SKIP_ONBOARD=false
PULL_ONLY=false

# Parse arguments
while [[ $# -gt 0 ]]; do
    case $1 in
        --no-start)
            NO_START=true
            shift
            ;;
        --skip-onboard)
            SKIP_ONBOARD=true
            shift
            ;;
        --pull-only)
            PULL_ONLY=true
            shift
            ;;
        --install-dir)
            INSTALL_DIR="$2"
            shift 2
            ;;
        --help|-h)
            echo "OpenClaw (Clawbot) Docker Installer"
            echo ""
            echo "Usage: install.sh [OPTIONS]"
            echo ""
            echo "Options:"
            echo "  --install-dir DIR   Installation directory (default: ~/openclaw)"
            echo "  --no-start          Don't start the gateway after setup"
            echo "  --skip-onboard      Skip onboarding wizard"
            echo "  --pull-only         Only pull the image, don't set up"
            echo "  --help, -h          Show this help message"
            exit 0
            ;;
        *)
            echo -e "${RED}Unknown option: $1${NC}"
            exit 1
            ;;
    esac
done

# Functions
print_banner() {
    echo -e "${RED}"
    echo "╔══════════════════════════════════════════════════════════════╗"
    echo "║                                                              ║"
    echo "║    ____                    _____ _                           ║"
    echo "║   / __ \\\\                  / ____| |                          ║"
    echo "║  | |  | |_ __   ___ _ __ | |    | | __ ___      __           ║"
    echo "║  | |  | | '_ \\\\ / _ \\\\ '_ \\\\| |    | |/ _\\\` \\\\ \\\\ /\\\\ / /           ║"
    echo "║  | |__| | |_) |  __/ | | | |____| | (_| |\\\\ V  V /            ║"
    echo "║   \\\\____/| .__/ \\\\___|_| |_|\\\\_____|_|\\\\__,_| \\\\_/\\\\_/             ║"
    echo "║         | |                                                  ║"
    echo "║         |_|                                                  ║"
    echo "║                                                              ║"
    echo "║              Docker Installer by Phioranex                   ║"
    echo "║                                                              ║"
    echo "╚══════════════════════════════════════════════════════════════╝"
    echo -e "${NC}"
}

# Get user's home directory, handling sudo correctly
get_user_home() {
    if [ -n "$SUDO_USER" ]; then
        # Running with sudo - use the actual user's home
        local user_home
        user_home=$(getent passwd "$SUDO_USER" | cut -d: -f6)
        if [ -z "$user_home" ]; then
            # Fallback to eval if getent fails
            user_home=$(eval echo ~"$SUDO_USER")
        fi
        echo "$user_home"
    else
        # Running normally
        echo "$HOME"
    fi
}

log_step() {
    echo -e "\n${BLUE}▶${NC} ${BOLD}$1${NC}"
}

log_success() {
    echo -e "${GREEN}✓${NC} $1"
}

log_warning() {
    echo -e "${YELLOW}⚠${NC} $1"
}

log_error() {
    echo -e "${RED}✗${NC} $1"
}

check_command() {
    if command -v "$1" &> /dev/null; then
        log_success "$1 found"
        return 0
    else
        log_error "$1 not found"
        return 1
    fi
}

# Main script
print_banner

log_step "Checking prerequisites..."

# Check Docker
if ! check_command docker; then
    echo -e "\n${RED}Docker is required but not installed.${NC}"
    echo "Install Docker: https://docs.docker.com/get-docker/"
    exit 1
fi

# Check Docker Compose
if docker compose version &> /dev/null; then
    log_success "Docker Compose found (plugin)"
    COMPOSE_CMD="docker compose"
elif command -v docker-compose &> /dev/null; then
    log_success "Docker Compose found (standalone)"
    COMPOSE_CMD="docker-compose"
else
    log_error "Docker Compose not found"
    echo -e "\n${RED}Docker Compose is required but not installed.${NC}"
    echo "Install Docker Compose: https://docs.docker.com/compose/install/"
    exit 1
fi

# Check Docker is running and capture output for better error reporting
DOCKER_INFO_OUTPUT=$(docker info 2>&1)
DOCKER_INFO_EXIT=$?

if [ $DOCKER_INFO_EXIT -ne 0 ]; then
    log_error "Docker is not running or you don't have permission to access it"
    
    # Check if it's a permission issue
    if [ "$(id -u)" -ne 0 ] && echo "$DOCKER_INFO_OUTPUT" | grep -qi "permission denied"; then
        echo -e "\n${YELLOW}Tip: You may need to run this script with sudo or add your user to the docker group:${NC}"
        echo -e "  ${CYAN}sudo usermod -aG docker \$USER${NC}"
        echo -e "  ${CYAN}(then log out and log back in)${NC}"
        echo -e "\n${YELLOW}Or run the installer with sudo:${NC}"
        echo -e "  ${CYAN}sudo bash <(curl -fsSL https://raw.githubusercontent.com/phioranex/openclaw-docker/main/install.sh)${NC}"
    else
        echo -e "\n${RED}Please start Docker and try again.${NC}"
    fi
    exit 1
fi
log_success "Docker is running"

# Pull only mode
if [ "$PULL_ONLY" = true ]; then
    log_step "Pulling OpenClaw image..."
    docker pull "$IMAGE"
    log_success "Image pulled successfully!"
    echo -e "\n${GREEN}Done!${NC} Run the installer again without --pull-only to complete setup."
    exit 0
fi

log_step "Setting up installation directory..."
mkdir -p "$INSTALL_DIR"
cd "$INSTALL_DIR"
log_success "Created $INSTALL_DIR"

log_step "Downloading docker-compose.yml..."
curl -fsSL "$COMPOSE_URL" -o docker-compose.yml

# Update docker-compose.yml to use correct home directory when running with sudo
if [ -n "$SUDO_USER" ]; then
    USER_HOME=$(get_user_home)
    # Replace ~/.openclaw with the actual user's home directory
    if grep -q "~/.openclaw" docker-compose.yml; then
        if sed -i.bak "s|~/.openclaw|$USER_HOME/.openclaw|g" docker-compose.yml; then
            rm -f docker-compose.yml.bak
            # Verify the replacement actually occurred
            if ! grep -q "~/.openclaw" docker-compose.yml; then
                log_success "Updated docker-compose.yml for sudo user ($SUDO_USER)"
            else
                log_warning "sed replacement may have failed, check docker-compose.yml manually"
            fi
        else
            log_warning "Failed to update docker-compose.yml paths"
        fi
    else
        log_warning "docker-compose.yml doesn't contain '~/.openclaw', skipping path update"
    fi
fi

log_success "Downloaded docker-compose.yml"

log_step "Creating data directories..."

# Determine the correct home directory
USER_HOME=$(get_user_home)
OPENCLAW_DIR="$USER_HOME/.openclaw"

mkdir -p "$OPENCLAW_DIR"
mkdir -p "$OPENCLAW_DIR/workspace"

# Fix permissions for container access
# Docker container runs as node user (UID 1000, GID 1000)
# Ensure the directory is writable by the container user
if [ "$(id -u)" -eq 0 ]; then
    # Running as root/sudo - set ownership to UID 1000 (node user in container)
    # and grant group access to the actual user (if using sudo)
    if [ -n "$SUDO_USER" ]; then
        # Get the sudo user's primary group
        SUDO_GID=$(id -g "$SUDO_USER")
        # Set ownership: UID 1000 (container), GID to sudo user's group
        chown -R 1000:"$SUDO_GID" "$OPENCLAW_DIR"
        # Allow group read/write access
        chmod -R u+rwX,g+rwX,o-rwx "$OPENCLAW_DIR"
        log_success "Set ownership to UID 1000 with group access for $SUDO_USER"
    else
        # Running as actual root user, not via sudo
        chown -R 1000:1000 "$OPENCLAW_DIR"
        chmod -R 755 "$OPENCLAW_DIR"
        log_success "Set ownership to UID 1000 (container user)"
    fi
else
    # Running as non-root user
    # Try 775 first (safer than 777)
    if chmod -R 775 "$OPENCLAW_DIR" 2>/dev/null; then
        ACTUAL_PERMS="775"
        log_warning "Running as non-root user, set permissions to 775"
    else
        # Fallback to 777 if 775 fails (e.g., not the owner)
        chmod -R 777 "$OPENCLAW_DIR"
        ACTUAL_PERMS="777"
        log_warning "Could not set 775 permissions (not owner?), using 777 instead"
    fi
    log_warning "For better security on Synology/NAS, consider running with sudo"
fi

log_success "Created $OPENCLAW_DIR (config)"
log_success "Created $OPENCLAW_DIR/workspace (workspace)"

log_step "Pulling OpenClaw image..."
docker pull "$IMAGE"
log_success "Image pulled successfully!"

# Onboarding
if [ "$SKIP_ONBOARD" = false ]; then
    log_step "Initializing OpenClaw configuration..."
    echo -e "${YELLOW}Setting up configuration and workspace...${NC}\n"
    
    log_step "Running onboarding wizard..."
    echo -e "${YELLOW}This will configure your AI provider and channels.${NC}"
    echo -e "${YELLOW}Follow the prompts to complete setup.${NC}\n"
    
    # Run onboarding interactively (works with bash process substitution)
    if ! $COMPOSE_CMD run --rm openclaw-cli onboard; then
        log_warning "Onboarding was cancelled or failed"
        echo -e "${YELLOW}You can run it later with:${NC} cd $INSTALL_DIR && $COMPOSE_CMD run --rm openclaw-cli onboard"
    else
        log_success "Onboarding complete!"
    fi
fi

# Start gateway
if [ "$NO_START" = false ]; then
    log_step "Starting OpenClaw gateway..."
    $COMPOSE_CMD up -d openclaw-gateway
    
    # Wait for gateway to be ready
    echo -n "Waiting for gateway to start"
    for i in {1..30}; do
        if curl -s http://localhost:18789/health &> /dev/null; then
            echo ""
            log_success "Gateway is running!"
            break
        fi
        echo -n "."
        sleep 1
    done
    
    if ! curl -s http://localhost:18789/health &> /dev/null; then
        echo ""
        log_warning "Gateway may still be starting. Check logs with: docker logs openclaw-gateway"
    fi
fi

# Success message
echo -e "\n${GREEN}╔══════════════════════════════════════════════════════════════╗${NC}"
echo -e "${GREEN}║                                                              ║${NC}"
echo -e "${GREEN}║              🎉 OpenClaw installed successfully! 🎉           ║${NC}"
echo -e "${GREEN}║                                                              ║${NC}"
echo -e "${GREEN}╚══════════════════════════════════════════════════════════════╝${NC}"

echo -e "\n${BOLD}Quick reference:${NC}"
echo -e "  ${CYAN}Dashboard:${NC}      http://localhost:18790/?token=YOUR_TOKEN"
echo -e "  ${CYAN}GET TOKEN:${NC}      http://localhost:18790/?token=YOUR_TOKEN"
echo -e "  ${CYAN}Config:${NC}         ~/.openclaw/"
echo -e "  ${CYAN}Workspace:${NC}      cat ~/.openclaw/openclaw.json| grep '"token":' | grep -v '"mode"' | cut -d '\"' -f4"
echo -e "  ${CYAN}Install dir:${NC}    $INSTALL_DIR"

echo -e "\n${BOLD}Useful commands:${NC}"
echo -e "  ${CYAN}View logs:${NC}      docker logs -f openclaw-gateway"
echo -e "  ${CYAN}Stop:${NC}           cd $INSTALL_DIR && $COMPOSE_CMD down"
echo -e "  ${CYAN}Start:${NC}          cd $INSTALL_DIR && $COMPOSE_CMD up -d openclaw-gateway"
echo -e "  ${CYAN}Restart:${NC}        cd $INSTALL_DIR && $COMPOSE_CMD restart openclaw-gateway"
echo -e "  ${CYAN}CLI:${NC}            cd $INSTALL_DIR && $COMPOSE_CMD run --rm openclaw-cli <command>"
echo -e "  ${CYAN}Update:${NC}         docker pull $IMAGE && cd $INSTALL_DIR && $COMPOSE_CMD up -d"

echo -e "\n${BOLD}Documentation:${NC}  https://docs.openclaw.ai"
echo -e "${BOLD}Support:${NC}        https://discord.gg/clawd"
echo -e "${BOLD}Docker image:${NC}   $REPO_URL"

echo -e "\n${YELLOW}Happy automating! 🤖🦞${NC}\n"


================================================
FILE: uninstall.ps1
================================================
#
# OpenClaw (Clawbot) Docker Uninstaller - Windows PowerShell Version
# Removes OpenClaw installation from your system
#
# Usage:
#   irm https://raw.githubusercontent.com/phioranex/openclaw-docker/main/uninstall.ps1 | iex
#
# Or with options:
#   & ([scriptblock]::Create((irm https://raw.githubusercontent.com/phioranex/openclaw-docker/main/uninstall.ps1))) -KeepData
#

param(
    [string]$InstallDir = "$env:USERPROFILE\openclaw",
    [switch]$KeepData,
    [switch]$KeepImage,
    [switch]$Force,
    [switch]$Help
)

# Config
$Image = "ghcr.io/phioranex/openclaw-docker:latest"

# Error handling
$ErrorActionPreference = "Stop"

# Functions
function Write-Banner {
    Write-Host ""
    Write-Host "╔══════════════════════════════════════════════════════════════╗" -ForegroundColor Red
    Write-Host "║                                                              ║" -ForegroundColor Red
    Write-Host "║    ____                    _____ _                           ║" -ForegroundColor Red
    Write-Host "║   / __ \                  / ____| |                          ║" -ForegroundColor Red
    Write-Host "║  | |  | |_ __   ___ _ __ | |    | | __ ___      __           ║" -ForegroundColor Red
    Write-Host "║  | |  | | '_ \ / _ \ '_ \| |    | |/ _`` \ \ /\ / /           ║" -ForegroundColor Red
    Write-Host "║  | |__| | |_) |  __/ | | | |____| | (_| |\ V  V /            ║" -ForegroundColor Red
    Write-Host "║   \____/| .__/ \___|_| |_|\_____|_|\__,_| \_/\_/             ║" -ForegroundColor Red
    Write-Host "║         | |                                                  ║" -ForegroundColor Red
    Write-Host "║         |_|                                                  ║" -ForegroundColor Red
    Write-Host "║                                                              ║" -ForegroundColor Red
    Write-Host "║            Docker Uninstaller by Phioranex                   ║" -ForegroundColor Red
    Write-Host "║                                                              ║" -ForegroundColor Red
    Write-Host "╚══════════════════════════════════════════════════════════════╝" -ForegroundColor Red
    Write-Host ""
}

function Write-Step {
    param([string]$Message)
    Write-Host ""
    Write-Host "▶ $Message" -ForegroundColor Blue
}

function Write-Success {
    param([string]$Message)
    Write-Host "✓ $Message" -ForegroundColor Green
}

function Write-Warning {
    param([string]$Message)
    Write-Host "⚠ $Message" -ForegroundColor Yellow
}

function Write-ErrorMessage {
    param([string]$Message)
    Write-Host "✗ $Message" -ForegroundColor Red
}

function Confirm-Action {
    param(
        [string]$Prompt,
        [string]$Default = "n"
    )
    
    if ($Force) {
        return $true
    }
    
    if ($Default -eq "y") {
        $PromptText = "$Prompt [Y/n] "
    } else {
        $PromptText = "$Prompt [y/N] "
    }
    
    while ($true) {
        Write-Host $PromptText -ForegroundColor Yellow -NoNewline
        $response = Read-Host
        if ([string]::IsNullOrEmpty($response)) {
            $response = $Default
        }
        
        switch -Regex ($response) {
            '^[Yy]' { return $true }
            '^[Nn]' { return $false }
            default { Write-Host "Please answer yes or no." }
        }
    }
}

# Show help
if ($Help) {
    Write-Host "OpenClaw (Clawbot) Docker Uninstaller - Windows"
    Write-Host ""
    Write-Host "Usage: uninstall.ps1 [OPTIONS]"
    Write-Host ""
    Write-Host "Options:"
    Write-Host "  -InstallDir DIR   Installation directory (default: ~\openclaw)"
    Write-Host "  -KeepData         Keep configuration and workspace data"
    Write-Host "  -KeepImage        Keep Docker image"
    Write-Host "  -Force            Skip confirmation prompts"
    Write-Host "  -Help             Show this help message"
    return
}

# Main script
Write-Banner

Write-Host "This will uninstall OpenClaw from your system." -ForegroundColor Yellow
Write-Host ""

# Stop and remove containers
Write-Step "Stopping and removing containers..."

$ContainersRemoved = $false
try {
    $containers = docker ps -a --format "{{.Names}}" 2>$null
    
    if ($containers -match "openclaw-gateway") {
        docker stop openclaw-gateway 2>$null | Out-Null
        docker rm openclaw-gateway 2>$null | Out-Null
        Write-Success "Removed openclaw-gateway container"
        $ContainersRemoved = $true
    }
    
    if ($containers -match "openclaw-socat") {
        docker stop openclaw-socat 2>$null | Out-Null
        docker rm openclaw-socat 2>$null | Out-Null
        Write-Success "Removed openclaw-socat container"
        $ContainersRemoved = $true
    }
    
    if ($containers -match "openclaw-cli") {
        docker rm openclaw-cli 2>$null | Out-Null
        Write-Success "Removed openclaw-cli container"
        $ContainersRemoved = $true
    }
} catch {
    # Ignore errors
}

if (-not $ContainersRemoved) {
    Write-Warning "No OpenClaw containers found"
}

# Remove data directories
$ConfigDir = "$env:USERPROFILE\.openclaw"

if (-not $KeepData -and (Test-Path $ConfigDir)) {
    Write-Step "Data directories found at $ConfigDir"
    
    if (Confirm-Action "Remove configuration and workspace data? (This cannot be undone)") {
        Remove-Item -Path $ConfigDir -Recurse -Force -ErrorAction SilentlyContinue
        Write-Success "Removed data directory: $ConfigDir"
    } else {
        Write-Warning "Keeping data directory: $ConfigDir"
    }
} elseif ($KeepData -and (Test-Path $ConfigDir)) {
    Write-Warning "Keeping data directory: $ConfigDir"
} elseif (-not (Test-Path $ConfigDir)) {
    Write-Warning "No data directory found at $ConfigDir"
}

# Remove Docker image
if (-not $KeepImage) {
    try {
        $images = docker images --format "{{.Repository}}:{{.Tag}}" 2>$null
        
        if ($images -match [regex]::Escape($Image)) {
            Write-Step "Docker image found: $Image"
            
            if (Confirm-Action "Remove Docker image? (You can re-download it later)") {
                try {
                    docker rmi $Image 2>$null | Out-Null
                    Write-Success "Removed Docker image"
                } catch {
                    Write-Warning "Could not remove image (may be in use)"
                }
            } else {
                Write-Warning "Keeping Docker image: $Image"
            }
        } else {
            Write-Warning "No Docker image found: $Image"
        }
    } catch {
        Write-Warning "Could not check for Docker image"
    }
} else {
    Write-Warning "Keeping Docker image: $Image"
}

# Remove installation directory
if (Test-Path $InstallDir) {
    Write-Step "Installation directory found at $InstallDir"
    
    if (Confirm-Action "Remove installation directory?") {
        Remove-Item -Path $InstallDir -Recurse -Force -ErrorAction SilentlyContinue
        Write-Success "Removed installation directory: $InstallDir"
    } else {
        Write-Warning "Keeping installation directory: $InstallDir"
    }
} else {
    Write-Warning "No installation directory found at $InstallDir"
}

# Success message
Write-Host ""
Write-Host "╔══════════════════════════════════════════════════════════════╗" -ForegroundColor Green
Write-Host "║                                                              ║" -ForegroundColor Green
Write-Host "║         OpenClaw has been uninstalled successfully! 👋        ║" -ForegroundColor Green
Write-Host "║                                                              ║" -ForegroundColor Green
Write-Host "╚══════════════════════════════════════════════════════════════╝" -ForegroundColor Green

if ($KeepData -or (Test-Path $ConfigDir)) {
    Write-Host ""
    Write-Host "Data preserved:" -ForegroundColor White
    Write-Host "  Config:         $ConfigDir" -ForegroundColor Cyan
    Write-Host "  Workspace:      $ConfigDir\workspace" -ForegroundColor Cyan
}

Write-Host ""
Write-Host "To reinstall OpenClaw:" -ForegroundColor White
Write-Host "  irm https://raw.githubusercontent.com/phioranex/openclaw-docker/main/install.ps1 | iex" -ForegroundColor Cyan

Write-Host ""
Write-Host "Thank you for using OpenClaw! 🦞" -ForegroundColor Yellow
Write-Host ""


================================================
FILE: uninstall.sh
================================================
#!/bin/bash
#
# OpenClaw (Clawbot) Docker Uninstaller
# Removes OpenClaw installation from your system
#
# Usage:
#   bash <(curl -fsSL https://raw.githubusercontent.com/phioranex/openclaw-docker/main/uninstall.sh)
#
# Or with options:
#   bash <(curl -fsSL https://raw.githubusercontent.com/phioranex/openclaw-docker/main/uninstall.sh) --keep-data
#

set -e

# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m' # No Color

# Config
INSTALL_DIR="${OPENCLAW_INSTALL_DIR:-$HOME/openclaw}"
IMAGE="ghcr.io/phioranex/openclaw-docker:latest"

# Flags
KEEP_DATA=false
KEEP_IMAGE=false
FORCE=false

# Parse arguments
while [[ $# -gt 0 ]]; do
    case $1 in
        --keep-data)
            KEEP_DATA=true
            shift
            ;;
        --keep-image)
            KEEP_IMAGE=true
            shift
            ;;
        --force|-f)
            FORCE=true
            shift
            ;;
        --install-dir)
            INSTALL_DIR="$2"
            shift 2
            ;;
        --help|-h)
            echo "OpenClaw (Clawbot) Docker Uninstaller"
            echo ""
            echo "Usage: uninstall.sh [OPTIONS]"
            echo ""
            echo "Options:"
            echo "  --install-dir DIR   Installation directory (default: ~/openclaw)"
            echo "  --keep-data         Keep configuration and workspace data"
            echo "  --keep-image        Keep Docker image"
            echo "  --force, -f         Skip confirmation prompts"
            echo "  --help, -h          Show this help message"
            exit 0
            ;;
        *)
            echo -e "${RED}Unknown option: $1${NC}"
            exit 1
            ;;
    esac
done

# Functions
print_banner() {
    echo -e "${RED}"
    echo "╔══════════════════════════════════════════════════════════════╗"
    echo "║                                                              ║"
    echo "║    ____                    _____ _                           ║"
    echo "║   / __ \\\\                  / ____| |                          ║"
    echo "║  | |  | |_ __   ___ _ __ | |    | | __ ___      __           ║"
    echo "║  | |  | | '_ \\\\ / _ \\\\ '_ \\\\| |    | |/ _\\\` \\\\ \\\\ /\\\\ / /           ║"
    echo "║  | |__| | |_) |  __/ | | | |____| | (_| |\\\\ V  V /            ║"
    echo "║   \\\\____/| .__/ \\\\___|_| |_|\\\\_____|_|\\\\__,_| \\\\_/\\\\_/             ║"
    echo "║         | |                                                  ║"
    echo "║         |_|                                                  ║"
    echo "║                                                              ║"
    echo "║            Docker Uninstaller by Phioranex                   ║"
    echo "║                                                              ║"
    echo "╚══════════════════════════════════════════════════════════════╝"
    echo -e "${NC}"
}

# Get user's home directory, handling sudo correctly
get_user_home() {
    if [ -n "$SUDO_USER" ]; then
        # Running with sudo - use the actual user's home
        local user_home
        user_home=$(getent passwd "$SUDO_USER" | cut -d: -f6)
        if [ -z "$user_home" ]; then
            # Fallback to eval if getent fails
            user_home=$(eval echo ~"$SUDO_USER")
        fi
        echo "$user_home"
    else
        # Running normally
        echo "$HOME"
    fi
}

log_step() {
    echo -e "\n${BLUE}▶${NC} ${BOLD}$1${NC}"
}

log_success() {
    echo -e "${GREEN}✓${NC} $1"
}

log_warning() {
    echo -e "${YELLOW}⚠${NC} $1"
}

log_error() {
    echo -e "${RED}✗${NC} $1"
}

confirm() {
    if [ "$FORCE" = true ]; then
        return 0
    fi
    
    local prompt="$1"
    local default="${2:-n}"
    
    if [ "$default" = "y" ]; then
        prompt="$prompt [Y/n] "
    else
        prompt="$prompt [y/N] "
    fi
    
    while true; do
        read -p "$(echo -e "${YELLOW}$prompt${NC}")" -r response
        response=${response:-$default}
        case "$response" in
            [Yy]* ) return 0;;
            [Nn]* ) return 1;;
            * ) echo "Please answer yes or no.";;
        esac
    done
}

# Main script
print_banner

echo -e "${YELLOW}This will uninstall OpenClaw from your system.${NC}"
echo ""

# Stop and remove containers
log_step "Stopping and removing containers..."

CONTAINERS_REMOVED=false
if docker ps -a --format '{{.Names}}' | grep -q "openclaw-gateway"; then
    docker stop openclaw-gateway 2>/dev/null || true
    docker rm openclaw-gateway 2>/dev/null || true
    log_success "Removed openclaw-gateway container"
    CONTAINERS_REMOVED=true
fi

if docker ps -a --format '{{.Names}}' | grep -q "openclaw-socat"; then
    docker stop openclaw-socat 2>/dev/null || true
    docker rm openclaw-socat 2>/dev/null || true
    log_success "Removed openclaw-socat container"
    CONTAINERS_REMOVED=true
fi

if docker ps -a --format '{{.Names}}' | grep -q "openclaw-cli"; then
    docker rm openclaw-cli 2>/dev/null || true
    log_success "Removed openclaw-cli container"
    CONTAINERS_REMOVED=true
fi

if [ "$CONTAINERS_REMOVED" = false ]; then
    log_warning "No OpenClaw containers found"
fi

# Remove data directories
USER_HOME=$(get_user_home)
OPENCLAW_DIR="$USER_HOME/.openclaw"

if [ "$KEEP_DATA" = false ] && [ -d "$OPENCLAW_DIR" ]; then
    log_step "Data directories found at $OPENCLAW_DIR"
    
    if confirm "Remove configuration and workspace data? (This cannot be undone)"; then
        rm -rf "$OPENCLAW_DIR"
        log_success "Removed data directory: $OPENCLAW_DIR"
    else
        log_warning "Keeping data directory: $OPENCLAW_DIR"
    fi
elif [ "$KEEP_DATA" = true ] && [ -d "$OPENCLAW_DIR" ]; then
    log_warning "Keeping data directory: $OPENCLAW_DIR"
elif [ ! -d "$OPENCLAW_DIR" ]; then
    log_warning "No data directory found at $OPENCLAW_DIR"
fi

# Remove Docker image
if [ "$KEEP_IMAGE" = false ]; then
    if docker images --format '{{.Repository}}:{{.Tag}}' | grep -q "$IMAGE"; then
        log_step "Docker image found: $IMAGE"
        
        if confirm "Remove Docker image? (You can re-download it later)"; then
            docker rmi "$IMAGE" 2>/dev/null || log_warning "Could not remove image (may be in use)"
            log_success "Removed Docker image"
        else
            log_warning "Keeping Docker image: $IMAGE"
        fi
    else
        log_warning "No Docker image found: $IMAGE"
    fi
else
    log_warning "Keeping Docker image: $IMAGE"
fi

# Remove installation directory
if [ -d "$INSTALL_DIR" ]; then
    log_step "Installation directory found at $INSTALL_DIR"
    
    if confirm "Remove installation directory?"; then
        rm -rf "$INSTALL_DIR"
        log_success "Removed installation directory: $INSTALL_DIR"
    else
        log_warning "Keeping installation directory: $INSTALL_DIR"
    fi
else
    log_warning "No installation directory found at $INSTALL_DIR"
fi

# Success message
echo -e "\n${GREEN}╔══════════════════════════════════════════════════════════════╗${NC}"
echo -e "${GREEN}║                                                              ║${NC}"
echo -e "${GREEN}║         OpenClaw has been uninstalled successfully! 👋        ║${NC}"
echo -e "${GREEN}║                                                              ║${NC}"
echo -e "${GREEN}╚══════════════════════════════════════════════════════════════╝${NC}"

if [ "$KEEP_DATA" = true ] || [ -d "$OPENCLAW_DIR" ]; then
    echo -e "\n${BOLD}Data preserved:${NC}"
    echo -e "  ${CYAN}Config:${NC}         $OPENCLAW_DIR"
    echo -e "  ${CYAN}Workspace:${NC}      $OPENCLAW_DIR/workspace"
fi

echo -e "\n${BOLD}To reinstall OpenClaw:${NC}"
echo -e "  ${CYAN}bash <(curl -fsSL https://raw.githubusercontent.com/phioranex/openclaw-docker/main/install.sh)${NC}"

echo -e "\n${YELLOW}Thank you for using OpenClaw! 🦞${NC}\n"
Download .txt
gitextract_uobwqc7k/

├── .github/
│   └── workflows/
│       ├── build-image.yml
│       └── openclaw-release-tracker.yml
├── .gitignore
├── .last-openclaw-version
├── Dockerfile
├── LICENSE
├── README.md
├── docker-compose.yml
├── install.ps1
├── install.sh
├── uninstall.ps1
└── uninstall.sh
Condensed preview — 12 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (67K chars).
[
  {
    "path": ".github/workflows/build-image.yml",
    "chars": 3598,
    "preview": "name: Build and Push Docker Image\n\non:\n  workflow_dispatch:\n    inputs:\n      openclaw_version:\n        description: 'Op"
  },
  {
    "path": ".github/workflows/openclaw-release-tracker.yml",
    "chars": 3645,
    "preview": "name: OpenClaw Release Tracker\n\non:\n  schedule:\n    # Check for new OpenClaw releases every 6 hours\n    - cron: '0 */6 *"
  },
  {
    "path": ".gitignore",
    "chars": 54,
    "preview": "# Moltbot Docker\n\nBuild artifacts and temporary files\n"
  },
  {
    "path": ".last-openclaw-version",
    "chars": 10,
    "preview": "v2026.5.7\n"
  },
  {
    "path": "Dockerfile",
    "chars": 3959,
    "preview": "FROM node:22-bookworm\n\nLABEL org.opencontainers.image.source=\"https://github.com/phioranex/openclaw-docker\"\nLABEL org.op"
  },
  {
    "path": "LICENSE",
    "chars": 1240,
    "preview": "MIT License\n\nCopyright (c) 2026 Phioranex Pvt Ltd\n\nPermission is hereby granted, free of charge, to any person obtaining"
  },
  {
    "path": "README.md",
    "chars": 9132,
    "preview": "# OpenClaw (Clawbot) Docker Image\n\nPre-built Docker image for [OpenClaw](https://github.com/openclaw/openclaw) — run you"
  },
  {
    "path": "docker-compose.yml",
    "chars": 1309,
    "preview": "services:\n  openclaw-gateway:\n    image: ghcr.io/phioranex/openclaw-docker:latest\n    container_name: openclaw-gateway\n "
  },
  {
    "path": "install.ps1",
    "chars": 9898,
    "preview": "#\n# OpenClaw (Clawbot) Docker Installer - Windows PowerShell Version\n# One-command setup for OpenClaw on Docker for Wind"
  },
  {
    "path": "install.sh",
    "chars": 12263,
    "preview": "#!/bin/bash\n#\n# OpenClaw (Clawbot) Docker Installer\n# One-command setup for OpenClaw on Docker\n#\n# Usage:\n#   bash <(cur"
  },
  {
    "path": "uninstall.ps1",
    "chars": 8200,
    "preview": "#\n# OpenClaw (Clawbot) Docker Uninstaller - Windows PowerShell Version\n# Removes OpenClaw installation from your system\n"
  },
  {
    "path": "uninstall.sh",
    "chars": 7839,
    "preview": "#!/bin/bash\n#\n# OpenClaw (Clawbot) Docker Uninstaller\n# Removes OpenClaw installation from your system\n#\n# Usage:\n#   ba"
  }
]

About this extraction

This page contains the full source code of the phioranex/openclaw-docker GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 12 files (59.7 KB), approximately 16.1k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!