# CLI Commands + Daemon / Service Architecture

GoClaw is one binary: run with no subcommand it is the gateway, and its subcommands either call the REST API of a running gateway or work on their own (`chat`, `setup`, `doctor`, `config`). On Linux and macOS it installs itself as a systemd or launchd service.

## Architecture

```mermaid
flowchart TD
    subgraph BIN["goclaw (single binary, Cobra subcommand CLI, internal/cli)"]
        GW["<b>Gateway Mode (default)</b><br/>HTTP server + channels"]
        CLI["<b>CLI Commands</b><br/>Calls REST API of running gateway"]
        DIR["<b>Direct Mode (no gateway needed)</b><br/>chat, setup, doctor, config"]
        SVC["<b>OS Service &amp; Lock</b><br/>systemd (Linux) / launchd (macOS)<br/>Lock file: ~/.goclaw/gateway.lock (PID + port + time)"]

        GW --> SVC
        CLI --> SVC
        DIR --> SVC
    end
```

## CLI Commands

OpenClaw has 25+ command groups. GoClaw has one binary with top-level commands and nested subcommands.

| # | Command | Subcommands | Description | Status |
|---|---------|:-----------:|-------------|--------|
| 3.1 | (default) | — | Start gateway server | Done |
| 3.2 | `setup` | — | Interactive setup wizard (provider, API test, channels, summary); `--non-interactive` writes config.yaml from flags | Done |
| 3.3 | `--debug` | — | Debug mode (structured LLM/tool/gateway logging) | Done |
| 3.4 | `status` | — | Query running gateway (`GET /api/stats`) — provider, model, sessions, uptime, channels | Done |
| 3.5 | `pairing` | `approve`, `list`, `pending`, `revoke`, `link` | Pairing management (reads and writes the pairing files directly; a running gateway sees the change after a restart) | Done |
| 3.6 | `config get` | — | Read config value (dot-notation) | Done |
| 3.7 | `config set` | — | Write config value (AST-preserving YAML update) | Done |
| 3.8 | `config append` | — | Append to config list (e.g. `tools.shell.allow`) | Done |
| 3.9 | `config remove` | — | Remove from config list | Done |
| 3.10 | `doctor` | — | Health checks: config, state/workspace/memory dirs, vault, database, memory schema, integrations (live provider call), gateway, service boot (Linux) | Done |
| 3.11 | `message` | `[channel] <content>` | Run one agent turn through the running gateway (`POST /api/webhook`, peer `cli`, gateway token) and print the reply; nothing is posted to the channel | Done |
| 3.12 | `sessions` | `list`, `inspect` | Session management | Done |
| 3.13 | `agents` | `list`, `add`, `bind`, `unbind`, `delete` | Multi-agent CRUD + config save | Done |
| 3.14 | `chat` | — | Interactive terminal chat (direct LLM, no gateway, streaming) | Done |
| 3.15 | `skills` | `list`, `check`, `scan`, `install`, `add`, `remove`, `show` (see below) | Skill management + security | Done |
| 3.16 | `tools` | `list`, `exec`, `bench` | List, execute, and benchmark registered tools | Done |
| 3.17 | `service install` | — | Install as OS service (systemd/launchd); `--system [--run-as <user>]` for a system service run by an unprivileged user | Done |
| 3.18 | `service uninstall` | — | Uninstall OS service | Done |
| 3.19 | `service` | `start`, `stop`, `restart`, `status` | Control the installed service | Done |
| 3.20 | `quickstart` | — | Short setup wizard | Done |
| 3.21 | `version` | — | Version, commit and build date | Done |
| 3.22 | `config delete` | — | Remove a key, including keys the schema does not know | Done |
| 3.23 | `memory` | `check`, `stats`, `reindex`, `replay`, `relearn`, `revise`, `revisions`, `prune`, `dedupe`, `forget`, `clear`, `clear-user`, `backfill-metadata`, `notes`, `migrate`, `export`, `import` | Memory maintenance through the running gateway (`/api/memory/*`); `check` and `migrate` open the database directly | Done |
| 3.24 | `graph` | `migrate`, `reindex`, `check`, `stats`, `cleanup` | Knowledge graph (`kg.sqlite`) maintenance | Done |
| 3.25 | `db` | `export`, `import`, `inspect` | `.gclaw` database snapshots | Done |
| 3.26 | `secret` | `gen`, `set`, `get`, `list`, `delete` | Encrypted vault | Done |
| 3.27 | `genpass` | — | Print strong random passwords (aliases `gp`, `password`) | Done |
| 3.28 | `gitlab hook` | `setup`, `list`, `test`, `remove` | GitLab webhook wizard and helpers | Done |
| 3.29 | `teams` | `setup`, `package` | Teams setup wizard and app package (.zip) | Done |
| 3.30 | `transcribe` | — | Transcribe an audio or video file | Done |
| 3.31 | `sbom` | — | SBOM: summary, CycloneDX, SPDX, JSON | Done |
| 3.32 | `update` | — | Download, verify and install a release; restart the service | Done |
| 3.33 | `completion` | `bash`, `zsh`, `fish`, `powershell` | Shell completion scripts | Done |

The user-facing reference for every command is [CLI Reference](../user-guide/cli-reference.md).

### Skills Subcommands

| Subcommand | Description |
|-----------|-------------|
| `list` | List all loaded skills with tags, status, source |
| `check` | Check skill binary dependencies (pure Go detection) |
| `check <name>` | Compatibility report for one skill |
| `scan` | Security scan all skills (prompt-injection, data-exfiltration and dangerous-code rules) |
| `scan <name>` | Security scan a specific skill |
| `install <URL>` | Install from URL (HTTP/HTTPS); the response is saved as the SKILL.md |
| `install github:<ref>` | Install from GitHub (single file from `main`, or repo clone) |
| `install <path>` | Install from local path (file or directory) |
| `install ... --force` | Install even when the compatibility check says FAIL |
| `add github:<user>/<repo>` | Clone a repository and pick its skills interactively (`--force` as for install) |
| `remove <name>` | Remove user-installed skill |
| `show <name>` | Show skill content + metadata |

**Post-install security scan:** After every install, skills are automatically scanned. Critical findings = **blocked + auto-removed**.

### Doctor Checks

| # | Check | Description |
|---|-------|-------------|
| 1 | Config file | `<state dir>/config.yaml` exists (state dir: `GOCLAW_STATE_DIR`, default `~/.goclaw`) |
| 2 | State directory | `~/.goclaw/` exists |
| 3 | Workspace | `~/.goclaw/workspace/` exists |
| 4 | Memory directory | `~/.goclaw/workspace/memory/` exists |
| 5 | Config and vault | Config loads; the secrets vault opens (with a note when `GOCLAW_SECRET_KEY` is unset); `${secret:…}` references resolved for the checks below |
| 6 | Database | `database.path` (default `~/.goclaw/gc_state.sqlite`) exists or will be created |
| 7 | Memory health | Schema migrations and critical findings, as `goclaw memory check` reports them |
| 8 | Integrations | `doctor.RunSystemChecks`: datasources, Zabbix/Uptrace/Grafana per agent, GitLab, SonarQube, MCP servers, enabled channels, SMTP/IMAP, and a live call to the AI provider |
| 9 | Gateway | Running gateway reachable + PID |
| 10 | Service boot | Linux only: an installed service starts at boot (lingering, `WantedBy` target) |

---

## Daemon / Service Architecture

OpenClaw runs as a background daemon with CLI-to-gateway IPC. GoClaw uses HTTP REST for CLI→Gateway communication.

| # | Feature | OpenClaw | GoClaw | Status |
|---|---------|----------|---------|--------|
| 3b.1 | Foreground server | HTTP/WS server | `gateway.Claim` takes the state directory and listens on its ports before anything starts; `httpSrv.Serve` on the claimed listener | Done |
| 3b.2 | Graceful shutdown | SIGINT/SIGTERM | SIGINT/SIGTERM handler | Done |
| 3b.3 | Lock file (PID) | `gateway.<hash>.lock` with stale detection | `<state dir>/gateway.lock` (PID+port+timestamp, stale detection: process alive and `/health` answers). A second gateway on the same state dir exits with "another GoClaw gateway is already running" | Done |
| 3b.4 | CLI → Gateway IPC | WebSocket JSON-RPC | **HTTP REST** (simpler, reuses API routes) | Done |
| 3b.5 | OS service install | launchd / systemd / schtasks | `goclaw service install` for systemd + launchd | Done |
| 3b.6 | OS service uninstall | Platform-specific | `goclaw service uninstall` | Done |
| 3b.7 | SIGUSR1 restart | Hot restart without downtime | — | **TODO** |
| 3b.8 | Bind modes | loopback / lan / tailnet / auto / custom | loopback / lan / all / custom IP | Done |
| 3b.9 | Gateway auth | Token/password + challenge handshake | Token auth (X-GoClaw-Token / Bearer) | Done |
| 3b.10 | Rate limiting | `AuthRateLimiter` | Per-IP token bucket (configurable req/min) | Done |
| 3b.11 | Remote gateway | `OPENCLAW_GATEWAY_URL` | — | **TODO** |
| 3b.12 | Public ingress | External tunnel/proxy | `gateway.ingress` (`type` ngrok or proxy, `url`, `authtoken`, allow list, optional dedicated `port`/`bind`); the deprecated `gateway.ngrok` and `channels.msteams.ngrok` are mapped onto it when `gateway.ingress.type` is unset | Done |

---

## GoClaw CLI → Gateway Flow

```mermaid
flowchart TD
    DAEMON["<b>goclaw (daemon — foreground or OS service)</b><br/>• Lock file: ~/.goclaw/gateway.lock (PID + port)<br/>• HTTP server (bind: loopback / lan / all / custom)<br/>• Middleware: rate limit → token auth → router<br/>• SIGINT/SIGTERM → graceful stop<br/>• OS service: systemd (Linux) / launchd (macOS)"]

    subgraph REST["Gateway HTTP REST + OpenAI-compat Endpoints"]
        R1["<b>goclaw status</b> → GET /api/stats"]
        R2["<b>goclaw sessions list</b> → GET /api/sessions"]
        R3["<b>goclaw memory …</b> → /api/memory/*"]
        R4["<b>goclaw message</b> → POST /api/webhook (agent turn)"]
        R5["<b>POST /v1/chat/completions</b> → OpenAI-compatible API"]
        R6["<b>GET /health</b> → health probe"]
    end

    subgraph LOCAL["Direct CLI Operations (no gateway required)"]
        L1["<b>goclaw chat</b> → direct LLM chat"]
        L2["<b>goclaw agents / skills / tools</b> → local CRUD &amp; inventory"]
        L3["<b>goclaw config get / set</b> → AST-preserving YAML"]
        L4["<b>goclaw doctor</b> → health checks"]
    end

    DAEMON <-->|"HTTP REST + OpenAI-compat"| REST
```

---

## OpenClaw vs GoClaw CLI Comparison

| Aspect | OpenClaw | GoClaw |
|--------|----------|---------|
| **CLI style** | Command groups (`openclaw gateway run`) | Single binary with subcommands (`goclaw status`) |
| **Commands** | 25+ command groups | Top-level commands + nested config, memory, graph, db, secret, skills, tools, service, pairing, teams, gitlab groups |
| **IPC** | WebSocket JSON-RPC | **HTTP REST** (reuses API routes) |
| **Config management** | CLI config set/get | **get/set/append/remove/delete** with AST-preserving YAML |
| **Skill management** | npm/Clawhub | **list/check/scan/install/add/remove/show** |
| **Install sources** | npm | **3 sources: URL, GitHub, local** |
| **Post-install scan** | — | ✅ Auto security scan, critical → blocked |
| **Tools CLI** | — | `goclaw tools list`, `goclaw tools exec`, `goclaw tools bench` |
| **Doctor** | `openclaw doctor` | `goclaw doctor` (local files, vault, database, integrations, gateway, service boot) |
| **OS service** | launchd/systemd/schtasks | systemd + launchd |
| **Self-update** | `openclaw update` | `goclaw update` (checksum-verified, restarts the service) |

Not implemented: SIGUSR1 hot restart (3b.7) and a remote gateway for the CLI (3b.11; `goclaw setup --mode remote` has no effect).
