openclaw-manager
Deploy, harden, and operate OpenClaw across local and hosted environments (Fly.io, Render, Railway, Hetzner, GCP) with secure defaults, channel setup guidance, integration onboarding, and troubleshooting workflows grounded in official OpenClaw documentation. Use when users need install/deploy help, migration support, runtime hardening, memory/agent operations tuning, or incident response.
Packaged view
This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.
Install command
npx @skill-hub/cli install openclaw-skills-openclaw-manager
Repository
Skill path: skills/hollaugo/openclaw-manager
Deploy, harden, and operate OpenClaw across local and hosted environments (Fly.io, Render, Railway, Hetzner, GCP) with secure defaults, channel setup guidance, integration onboarding, and troubleshooting workflows grounded in official OpenClaw documentation. Use when users need install/deploy help, migration support, runtime hardening, memory/agent operations tuning, or incident response.
Open repositoryBest for
Primary workflow: Run DevOps.
Technical facets: Full Stack, DevOps, Integration.
Target audience: everyone.
License: Unknown.
Original source
Catalog source: SkillHub Club.
Repository owner: openclaw.
This is still a mirrored public skill entry. Review the repository before installing into production workflows.
What it helps with
- Install openclaw-manager into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
- Review https://github.com/openclaw/skills before adding openclaw-manager to shared team environments
- Use openclaw-manager for development workflows
Works across
Favorites: 0.
Sub-skills: 0.
Aggregator: No.
Original source / Raw SKILL.md
---
name: openclaw-manager
description: Deploy, harden, and operate OpenClaw across local and hosted environments (Fly.io, Render, Railway, Hetzner, GCP) with secure defaults, channel setup guidance, integration onboarding, and troubleshooting workflows grounded in official OpenClaw documentation. Use when users need install/deploy help, migration support, runtime hardening, memory/agent operations tuning, or incident response.
runtime_metadata:
deployment_modes:
- local
- hosted
supported_providers:
- local
- fly
- render
- railway
- hetzner
- gcp
supported_operating_systems:
- macos
- linux
- windows-wsl2
supported_channels:
- telegram
- discord
- slack
supported_integrations:
- email
- calendar
security_gates:
- env_validation_passed
- security_checklist_passed
- rollback_plan_documented
- ledger_updated
privileged_operations:
- provider_secret_writes
- public_network_exposure
- persistent_state_changes
required_env_vars:
- OPENCLAW_GATEWAY_TOKEN
---
# OpenClaw Manager
## Overview
Build and operate OpenClaw with production-safe defaults across both local and hosted environments. This skill is optimized for operators with limited platform expertise and enforces hard security gates before rollout completion.
Primary references:
- Docs map: `references/openclaw-doc-map.md`
- Security gates checklist: `references/openclaw-security-checklist.md`
- Mode matrix: `references/openclaw-mode-matrix.md`
- OS matrix: `references/openclaw-os-matrix.md`
- Integrations playbook: `references/openclaw-integrations-playbook.md`
- Ops ledger schema: `references/openclaw-ops-ledger-schema.md`
Automation helpers:
- `scripts/plan_openclaw_rollout.py`
- `scripts/validate_openclaw_env.py`
- `scripts/update_openclaw_ops_ledger.py`
Default ops ledger path:
- `./openclaw-manager-operations-ledger.md` (or operator specified)
## Hard-Stop Rules (Never Bypass)
Stop and block deployment/install progression if any condition is true:
1. Required secrets profile fails validation.
2. Security checklist mandatory gates are not all passing.
3. Rollback path is not documented and owned.
4. Ops ledger was not updated for the current phase.
5. Public exposure requested without auth boundary and token controls.
## Workflow
### 1) Intake and Scope Lock
Collect and confirm:
- `mode`: `local` or `hosted`
- `provider`: `local`, `fly`, `render`, `railway`, `hetzner`, `gcp`
- `os`: `macos`, `linux`, `windows-wsl2`
- `channels`: subset of `telegram`, `discord`, `slack`
- `integrations`: subset of `email`, `calendar`
- `environment`: `dev`, `staging`, `prod`
- `exposure`: `private` or `public`
Before proceeding, write a `scope_lock` ledger entry:
```bash
python3 scripts/update_openclaw_ops_ledger.py \
--ledger-file ./openclaw-manager-operations-ledger.md \
--event scope_lock \
--operator codex \
--mode hosted \
--provider fly \
--os linux \
--environment prod \
--secrets-profile hosted-fly \
--channels telegram,slack \
--integrations email,calendar \
--security-status pending \
--rollback-tested no \
--blocking-issues "none" \
--next-owner operator \
--next-action-date 2026-02-20
```
### 2) Generate a Decision-Complete Plan
Always generate a plan first:
```bash
python3 scripts/plan_openclaw_rollout.py \
--mode hosted \
--provider fly \
--os linux \
--channels telegram,slack \
--integrations email,calendar \
--environment prod \
--exposure public \
--ledger-file ./openclaw-manager-operations-ledger.md \
--output /tmp/openclaw-rollout.md
```
The plan output is the execution contract. Do not skip sections.
### 3) Validate Secrets and Config Profile Before Any Infra Change
Validate environment using profile-aware gates:
```bash
python3 scripts/validate_openclaw_env.py \
--env-file .env \
--profile hosted-fly \
--json
```
Validation enforces:
- required keys by profile
- required provider/model alternatives
- malformed and duplicate env keys
- placeholder values
- weak gateway/setup tokens
- legacy alias warnings
Write a `predeploy_validation` ledger entry immediately after validation.
### 4) Execute Mode Branch
#### Branch A: Local install (`mode=local`)
1. Use official install/onboarding docs for local setup.
2. Apply OS-specific commands from `references/openclaw-os-matrix.md`.
3. Validate startup, persistence path, and local auth boundaries.
4. If local public exposure is requested, apply gateway hardening gates from security checklist first.
#### Branch B: Hosted clone + deploy (`mode=hosted`)
1. Clone the selected OpenClaw source repo.
2. Follow provider playbook from `references/openclaw-doc-map.md`.
3. Configure persistent storage before production traffic.
4. Configure ingress/auth, secrets, and health checks.
5. Verify runtime logs for startup/auth errors and secret leakage.
Write a `deploy_complete` ledger entry once deployment/install is complete.
### 5) Configure Channels and Integrations Safely
For each selected channel/integration:
- inject credentials via secret manager/env only
- run a minimal smoke test
- verify auth boundaries and error logging safety
Track each item as:
- `configured`
- `pending_credentials`
- `blocked`
Use `references/openclaw-integrations-playbook.md` for email/calendar specifics.
### 6) Agent + Memory Baseline
Document and validate:
- memory persistence strategy
- retention expectations
- restart and recovery behavior
- agent behavior boundaries
Update ledger with operational baseline decisions.
### 7) Mandatory Security Gate
Run `references/openclaw-security-checklist.md` and produce pass/fail per gate.
No go-live if any mandatory gate fails.
Write a `security_gate` ledger entry with explicit blockers (if any).
### 8) Handover and Incident Readiness
Produce:
- provider status summary
- channel + integration matrix
- security gate table
- rollback and escalation ownership
- follow-up actions by risk order
Write `handover` ledger entry. For incidents/troubleshooting, append `incident` entries as events happen.
## Output Contract
Always return:
1. Mode/provider/OS/environment status summary
2. Security gate results (hard pass/fail)
3. Channel + integration matrix
4. Agent + memory configuration summary
5. Ops ledger update confirmation (event names written)
6. Follow-up actions ordered by risk
---
## Referenced Files
> The following files are referenced in this skill and included for context.
### scripts/update_openclaw_ops_ledger.py
```python
#!/usr/bin/env python3
"""Append structured events to the OpenClaw operations ledger."""
from __future__ import annotations
import argparse
import datetime as dt
import re
from pathlib import Path
EVENT_CHOICES = {
"scope_lock",
"predeploy_validation",
"deploy_complete",
"security_gate",
"handover",
"incident",
}
DATE_RE = re.compile(r"^\d{4}-\d{2}-\d{2}$")
def parse_csv(value: str) -> str:
parts = [part.strip() for part in value.split(",") if part.strip()]
return ",".join(parts) if parts else "none"
def ensure_ledger_exists(path: Path) -> None:
if path.exists():
return
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(
"# OpenClaw Manager Operations Ledger\n\n"
"This file records operational metadata for OpenClaw management workflows.\n\n"
"Required schema: `docs/product/skills/openclaw-manager/references/openclaw-ops-ledger-schema.md`\n"
)
def main() -> int:
parser = argparse.ArgumentParser(description="Append an OpenClaw ops ledger event")
parser.add_argument("--ledger-file", required=True, help="Path to ledger markdown file")
parser.add_argument("--event", required=True, choices=sorted(EVENT_CHOICES))
parser.add_argument("--operator", required=True)
parser.add_argument("--mode", required=True)
parser.add_argument("--provider", required=True)
parser.add_argument("--os", required=True)
parser.add_argument("--environment", required=True)
parser.add_argument("--secrets-profile", required=True)
parser.add_argument("--channels", default="")
parser.add_argument("--integrations", default="")
parser.add_argument("--security-status", required=True, choices=["pending", "passed", "failed"])
parser.add_argument("--blocking-issues", default="none")
parser.add_argument("--rollback-tested", required=True, choices=["yes", "no"])
parser.add_argument("--next-owner", required=True)
parser.add_argument("--next-action-date", required=True, help="YYYY-MM-DD")
args = parser.parse_args()
if not DATE_RE.match(args.next_action_date):
print("[ERROR] --next-action-date must be in YYYY-MM-DD format")
return 1
# Also validate logical date formatting.
try:
dt.date.fromisoformat(args.next_action_date)
except ValueError:
print("[ERROR] --next-action-date is not a valid date")
return 1
ledger_path = Path(args.ledger_file)
ensure_ledger_exists(ledger_path)
timestamp = dt.datetime.now(dt.timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
channels = parse_csv(args.channels)
integrations = parse_csv(args.integrations)
entry = (
f"\n## {timestamp} | {args.event}\n"
f"- operator: {args.operator}\n"
f"- mode: {args.mode}\n"
f"- provider: {args.provider}\n"
f"- os: {args.os}\n"
f"- environment: {args.environment}\n"
f"- secrets_profile: {args.secrets_profile}\n"
f"- channels: {channels}\n"
f"- integrations: {integrations}\n"
f"- security_status: {args.security_status}\n"
f"- blocking_issues: {args.blocking_issues}\n"
f"- rollback_tested: {args.rollback_tested}\n"
f"- next_owner: {args.next_owner}\n"
f"- next_action_date: {args.next_action_date}\n"
)
with ledger_path.open("a", encoding="utf-8") as handle:
handle.write(entry)
print(f"[OK] Appended ledger event: {args.event}")
return 0
if __name__ == "__main__":
raise SystemExit(main())
```
### scripts/plan_openclaw_rollout.py
```python
#!/usr/bin/env python3
"""Generate a mode-aware OpenClaw rollout checklist with hard security gates."""
from __future__ import annotations
import argparse
from datetime import datetime, timezone
from pathlib import Path
PROVIDER_LINKS = {
"local": "https://docs.openclaw.ai/start/getting-started",
"fly": "https://docs.openclaw.ai/install/fly",
"render": "https://docs.openclaw.ai/install/render",
"railway": "https://docs.openclaw.ai/install/railway",
"hetzner": "https://docs.openclaw.ai/install/hetzner",
"gcp": "https://docs.openclaw.ai/install/gcp",
}
MODE_PROVIDER_ALLOWED = {
"local": {"local"},
"hosted": {"fly", "render", "railway", "hetzner", "gcp"},
}
CHANNEL_LINKS = {
"telegram": "https://docs.openclaw.ai/channels/telegram",
"discord": "https://docs.openclaw.ai/channels/discord",
"slack": "https://docs.openclaw.ai/channels/slack",
}
INTEGRATION_LINKS = {
"email": "https://docs.openclaw.ai/integrations/gmail",
"calendar": "https://docs.openclaw.ai/integrations/google-calendar",
}
OS_NOTES = {
"macos": "Use Homebrew-first install paths and verify shell PATH exports.",
"linux": "Use distro package manager/system tooling and verify daemon startup strategy.",
"windows-wsl2": "Run commands inside WSL2 Linux shell and avoid mixed Windows/WSL paths.",
}
DEFAULT_LEDGER_FILE = "openclaw-manager-operations-ledger.md"
def parse_csv(raw: str, *, allowed: set[str], label: str) -> list[str]:
values = [value.strip().lower() for value in raw.split(",") if value.strip()]
invalid = sorted({value for value in values if value not in allowed})
if invalid:
raise ValueError(f"Unsupported {label}: {', '.join(invalid)}")
return values
def build_profile(mode: str, provider: str) -> str:
if mode == "local":
return "local"
return f"hosted-{provider}"
def validate_mode_provider(mode: str, provider: str) -> None:
allowed = MODE_PROVIDER_ALLOWED[mode]
if provider not in allowed:
allowed_list = ", ".join(sorted(allowed))
raise ValueError(f"Provider '{provider}' is invalid for mode '{mode}'. Allowed: {allowed_list}")
def render(
*,
mode: str,
provider: str,
os_name: str,
channels: list[str],
integrations: list[str],
environment: str,
exposure: str,
ledger_file: str,
) -> str:
now = datetime.now(timezone.utc).isoformat()
profile = build_profile(mode, provider)
lines = [
"# OpenClaw Rollout Plan",
"",
f"- Generated: {now}",
f"- Mode: {mode}",
f"- Provider: {provider}",
f"- OS: {os_name}",
f"- Environment: {environment}",
f"- Exposure: {exposure}",
f"- Secrets profile: {profile}",
f"- Ops ledger: {ledger_file}",
"",
"## 1. Scope Lock",
"- [ ] Confirm operator intent and rollback owner.",
"- [ ] Confirm mode/provider/OS matrix is valid for this run.",
"- [ ] Append `scope_lock` entry to ops ledger.",
"",
"## 2. Preflight Validation",
f"- [ ] Validate `.env` with `scripts/validate_openclaw_env.py --env-file .env --profile {profile}`.",
"- [ ] Block progression on any validation failure.",
"- [ ] Append `predeploy_validation` entry to ops ledger.",
"",
"## 3. Deployment or Install",
]
if mode == "local":
lines.extend(
[
f"- [ ] Follow local install/onboarding guide: {PROVIDER_LINKS['local']}",
f"- [ ] Apply OS notes: {OS_NOTES[os_name]}",
"- [ ] Verify local startup, state path permissions, and auth boundaries.",
"- [ ] If exposure is public, complete security gates before enabling ingress.",
]
)
else:
lines.extend(
[
f"- [ ] Clone OpenClaw source and follow provider guide: {PROVIDER_LINKS[provider]}",
"- [ ] Configure persistent state before first traffic.",
"- [ ] Deploy and capture URL + health endpoint evidence.",
"- [ ] Verify runtime logs for startup/auth issues and token leakage.",
]
)
lines.extend(
[
"- [ ] Append `deploy_complete` entry to ops ledger.",
"",
"## 4. Channels",
]
)
if channels:
for channel in channels:
lines.append(f"- [ ] Configure {channel}: {CHANNEL_LINKS[channel]}")
lines.append(f"- [ ] Smoke-test {channel} and mark status (`configured`/`pending_credentials`/`blocked`).")
else:
lines.append("- [ ] No channels selected for this rollout.")
lines.extend(["", "## 5. Integrations"])
if integrations:
for integration in integrations:
lines.append(f"- [ ] Configure {integration}: {INTEGRATION_LINKS[integration]}")
lines.append(f"- [ ] Smoke-test {integration} and record status in ops ledger.")
else:
lines.append("- [ ] No integrations selected for this rollout.")
lines.extend(
[
"",
"## 6. Agent + Memory",
"- [ ] Document memory persistence strategy and retention expectations.",
"- [ ] Verify restart/recovery behavior.",
"- [ ] Confirm agent behavior boundaries for selected environment.",
"",
"## 7. Hard Security Gates (Go/No-Go)",
"- [ ] Gate 1: Secrets profile validation passed.",
"- [ ] Gate 2: Network/exposure boundaries validated.",
"- [ ] Gate 3: Channel/integration auth boundaries validated.",
"- [ ] Gate 4: Runtime/persistence safety validated.",
"- [ ] Gate 5: Incident readiness and rollback ownership documented.",
"- [ ] Gate 6: Supply chain patch posture documented.",
"- [ ] Gate 7: Ops ledger completeness validated.",
"- [ ] Append `security_gate` entry to ops ledger.",
"",
"## 8. Handover",
"- [ ] Produce provider status summary.",
"- [ ] Produce channel/integration matrix.",
"- [ ] Produce security pass/fail table with blockers.",
"- [ ] Produce next actions ordered by risk.",
"- [ ] Append `handover` entry to ops ledger.",
"",
"## 9. Explicit Blockers",
"Stop rollout immediately if any are true:",
"- [ ] Missing required secrets profile key(s).",
"- [ ] Security gate has any failed mandatory item.",
"- [ ] Rollback plan or owner missing.",
"- [ ] Ops ledger missing required phase entries.",
]
)
return "\n".join(lines)
def main() -> int:
parser = argparse.ArgumentParser(description="Generate OpenClaw rollout checklist")
parser.add_argument("--mode", required=True, choices=sorted(MODE_PROVIDER_ALLOWED))
parser.add_argument("--provider", required=True, choices=sorted(PROVIDER_LINKS))
parser.add_argument("--os", required=True, choices=sorted(OS_NOTES), dest="os_name")
parser.add_argument("--channels", default="", help="Comma-separated channels: telegram,discord,slack")
parser.add_argument("--integrations", default="", help="Comma-separated integrations: email,calendar")
parser.add_argument("--environment", default="prod", help="Environment label (dev/staging/prod)")
parser.add_argument("--exposure", required=True, choices=["private", "public"])
parser.add_argument("--ledger-file", default=DEFAULT_LEDGER_FILE, help="Path to ops ledger markdown file")
parser.add_argument("--output", required=True, help="Output markdown file")
args = parser.parse_args()
try:
validate_mode_provider(args.mode, args.provider)
channels = parse_csv(args.channels, allowed=set(CHANNEL_LINKS), label="channels") if args.channels else []
integrations = (
parse_csv(args.integrations, allowed=set(INTEGRATION_LINKS), label="integrations")
if args.integrations
else []
)
except ValueError as err:
print(f"[ERROR] {err}")
return 1
content = render(
mode=args.mode,
provider=args.provider,
os_name=args.os_name,
channels=channels,
integrations=integrations,
environment=args.environment,
exposure=args.exposure,
ledger_file=args.ledger_file,
)
output = Path(args.output)
output.parent.mkdir(parents=True, exist_ok=True)
output.write_text(content)
print(f"[OK] Wrote rollout plan: {output}")
return 0
if __name__ == "__main__":
raise SystemExit(main())
```
### scripts/validate_openclaw_env.py
```python
#!/usr/bin/env python3
"""Validate OpenClaw env files for profile-aware deployment readiness."""
from __future__ import annotations
import argparse
import json
import re
import sys
from pathlib import Path
PLACEHOLDER_PATTERNS = (
"changeme",
"todo",
"your-key",
"your_token",
"example",
"replace-me",
"placeholder",
)
KEY_RE = re.compile(r"^[A-Za-z_][A-Za-z0-9_]*$")
HEX_RE = re.compile(r"^[0-9a-fA-F]+$")
PROFILE_CONFIG = {
"local": {
"required": ["OPENCLAW_GATEWAY_TOKEN"],
"require_any": [["OPENAI_API_KEY", "ANTHROPIC_API_KEY"]],
"recommended": [],
},
"hosted-fly": {
"required": ["OPENCLAW_GATEWAY_TOKEN"],
"require_any": [["OPENAI_API_KEY", "ANTHROPIC_API_KEY"]],
"recommended": ["FLY_API_TOKEN"],
},
"hosted-render": {
"required": ["OPENCLAW_GATEWAY_TOKEN"],
"require_any": [["OPENAI_API_KEY", "ANTHROPIC_API_KEY"]],
"recommended": ["RENDER_API_KEY"],
},
"hosted-railway": {
"required": ["OPENCLAW_GATEWAY_TOKEN"],
"require_any": [["OPENAI_API_KEY", "ANTHROPIC_API_KEY"]],
"recommended": ["RAILWAY_TOKEN"],
},
"hosted-hetzner": {
"required": ["OPENCLAW_GATEWAY_TOKEN"],
"require_any": [["OPENAI_API_KEY", "ANTHROPIC_API_KEY"]],
"recommended": ["HCLOUD_TOKEN"],
},
"hosted-gcp": {
"required": ["OPENCLAW_GATEWAY_TOKEN"],
"require_any": [["OPENAI_API_KEY", "ANTHROPIC_API_KEY"]],
"recommended": ["GCP_SERVICE_ACCOUNT_JSON", "GOOGLE_APPLICATION_CREDENTIALS"],
},
}
def parse_env(env_path: Path):
values: dict[str, str] = {}
duplicates: list[str] = []
malformed: list[tuple[int, str]] = []
for idx, raw_line in enumerate(env_path.read_text().splitlines(), start=1):
line = raw_line.strip()
if not line or line.startswith("#"):
continue
if "=" not in line:
malformed.append((idx, raw_line))
continue
key, value = line.split("=", 1)
key = key.strip()
value = value.strip()
if not KEY_RE.match(key):
malformed.append((idx, raw_line))
continue
if key in values:
duplicates.append(key)
values[key] = value
return values, duplicates, malformed
def is_placeholder(value: str) -> bool:
lowered = value.lower()
return any(pattern in lowered for pattern in PLACEHOLDER_PATTERNS)
def parse_require_any(values: list[str]) -> list[list[str]]:
groups: list[list[str]] = []
for raw in values:
parts = [part.strip() for part in raw.split(",") if part.strip()]
if len(parts) < 2:
raise ValueError("--require-any must include at least two comma-separated keys")
groups.append(parts)
return groups
def check_secret_strength(values: dict[str, str]):
weak: list[str] = []
gateway = values.get("OPENCLAW_GATEWAY_TOKEN", "")
if gateway:
if len(gateway) < 32:
weak.append("OPENCLAW_GATEWAY_TOKEN (too short; expected >=32 chars)")
elif HEX_RE.match(gateway) and len(gateway) < 64:
weak.append("OPENCLAW_GATEWAY_TOKEN (hex token shorter than 64 chars)")
for key, value in values.items():
if not value:
continue
lowered = key.lower()
sensitive = any(token in lowered for token in ["token", "secret", "password", "api_key"])
if sensitive and len(value) < 16:
weak.append(f"{key} (too short for sensitive credential)")
return sorted(set(weak))
def main() -> int:
parser = argparse.ArgumentParser(description="Validate .env file for OpenClaw deployments")
parser.add_argument("--env-file", required=True, help="Path to .env file")
parser.add_argument(
"--profile",
required=True,
choices=sorted(PROFILE_CONFIG),
help="Validation profile (local or hosted provider profile)",
)
parser.add_argument(
"--require",
action="append",
default=[],
help="Additional required key (can be passed multiple times)",
)
parser.add_argument(
"--require-any",
action="append",
default=[],
help="Additional key group requirement; pass as comma-separated list (e.g. A,B)",
)
parser.add_argument("--json", action="store_true", help="Emit machine-readable JSON output")
args = parser.parse_args()
env_path = Path(args.env_file)
if not env_path.exists():
payload = {"ok": False, "errors": [f"Env file not found: {env_path}"]}
if args.json:
print(json.dumps(payload, indent=2))
else:
print(f"[ERROR] Env file not found: {env_path}")
return 1
values, duplicates, malformed = parse_env(env_path)
normalized = values
profile = PROFILE_CONFIG[args.profile]
required_keys = sorted(set(profile["required"] + args.require))
try:
dynamic_require_any = parse_require_any(args.require_any)
except ValueError as err:
if args.json:
print(json.dumps({"ok": False, "errors": [str(err)]}, indent=2))
else:
print(f"[ERROR] {err}")
return 1
require_any_groups = profile["require_any"] + dynamic_require_any
missing_required = [key for key in required_keys if key not in normalized or not normalized[key]]
missing_any_groups: list[list[str]] = []
for group in require_any_groups:
if not any(normalized.get(key) for key in group):
missing_any_groups.append(group)
placeholders = [key for key, value in normalized.items() if value and is_placeholder(value)]
weak_secrets = check_secret_strength(normalized)
recommended_missing = [
key for key in profile.get("recommended", []) if key not in normalized or not normalized[key]
]
errors = []
warnings = []
if malformed:
errors.append("malformed env lines detected")
if duplicates:
errors.append("duplicate env keys detected")
if missing_required:
errors.append("required keys missing")
if missing_any_groups:
errors.append("required alternative key groups unsatisfied")
if placeholders:
errors.append("placeholder values detected")
if weak_secrets:
errors.append("weak secrets detected")
if recommended_missing:
warnings.append(
"recommended keys missing for profile: " + ", ".join(recommended_missing)
)
payload = {
"ok": len(errors) == 0,
"profile": args.profile,
"parsed_keys": len(normalized),
"required_keys": required_keys,
"missing_required": missing_required,
"require_any_groups": require_any_groups,
"missing_require_any_groups": missing_any_groups,
"malformed_lines": [{"line": line_no, "content": line} for line_no, line in malformed],
"duplicate_keys": sorted(set(duplicates)),
"placeholder_keys": sorted(placeholders),
"weak_secrets": weak_secrets,
"warnings": warnings,
"errors": errors,
}
if args.json:
print(json.dumps(payload, indent=2))
else:
print(f"Parsed keys (normalized): {payload['parsed_keys']}")
if malformed:
print("\nMalformed lines:")
for line_no, line in malformed:
print(f" - line {line_no}: {line}")
if duplicates:
print("\nDuplicate keys:")
for key in sorted(set(duplicates)):
print(f" - {key}")
if missing_required:
print("\nMissing required keys:")
for key in missing_required:
print(f" - {key}")
if missing_any_groups:
print("\nUnsatisfied required key groups (need at least one key from each):")
for group in missing_any_groups:
print(f" - {', '.join(group)}")
if placeholders:
print("\nPotential placeholder values:")
for key in sorted(placeholders):
print(f" - {key}")
if weak_secrets:
print("\nWeak secret checks:")
for issue in weak_secrets:
print(f" - {issue}")
if warnings:
print("\nWarnings:")
for warning in warnings:
print(f" - {warning}")
if payload["ok"]:
print("\n[OK] Env validation passed.")
else:
print("\n[FAIL] Env validation failed.")
return 0 if payload["ok"] else 1
if __name__ == "__main__":
sys.exit(main())
```
### references/openclaw-doc-map.md
```markdown
# OpenClaw Doc Map
Use official OpenClaw docs as the source of truth.
## Core
- Features: https://docs.openclaw.ai/concepts/features
- Getting started: https://docs.openclaw.ai/start/getting-started
- Setup guide: https://docs.openclaw.ai/setup-guide
- Onboarding CLI: https://docs.openclaw.ai/start/onboarding-cli
- Skills overview: https://docs.openclaw.ai/skills
## Deployment
- Install overview: https://docs.openclaw.ai/install
- Fly.io install: https://docs.openclaw.ai/install/fly
- Render install: https://docs.openclaw.ai/install/render
- Railway install: https://docs.openclaw.ai/install/railway
- Hetzner install: https://docs.openclaw.ai/install/hetzner
- GCP install: https://docs.openclaw.ai/install/gcp
## Platforms and OS
- Platforms: https://docs.openclaw.ai/platforms
- Linux support: https://docs.openclaw.ai/platforms/linux
- Windows support: https://docs.openclaw.ai/platforms/windows
## Agent and Memory
- Agent concepts: https://docs.openclaw.ai/concepts/agent
- Memory concepts: https://docs.openclaw.ai/concepts/memory
## Channels
- Telegram: https://docs.openclaw.ai/channels/telegram
- Discord: https://docs.openclaw.ai/channels/discord
- Slack: https://docs.openclaw.ai/channels/slack
## Integrations
- Gmail: https://docs.openclaw.ai/integrations/gmail
- Google Calendar: https://docs.openclaw.ai/integrations/google-calendar
## Security
- Security overview: https://docs.openclaw.ai/security
- Remote access hardening: https://docs.openclaw.ai/remote-access
- VPN/Tailscale: https://docs.openclaw.ai/vpn/tailscale
## Legacy/Open Source Compatibility
- Open source repo: https://github.com/openclaw/openclaw
- Moltbot Fly baseline (legacy reference): https://github.com/hollaugo/moltbot-fly-deployer
```
### references/openclaw-security-checklist.md
```markdown
# OpenClaw Security Checklist
Use this checklist before considering deployment complete.
## Gate 1: Secrets Profile Validation (Mandatory)
Fail conditions:
- missing required keys for active profile
- placeholder values
- duplicate/malformed env keys
- weak gateway/setup tokens
Pass criteria:
- `scripts/validate_openclaw_env.py` exits 0 for active profile
- required model/provider alternatives are satisfied
## Gate 2: Network and Exposure Boundaries (Mandatory)
Fail conditions:
- public exposure without gateway auth token
- unnecessary open ports/routes
- debug/admin endpoints accessible from public internet
Pass criteria:
- TLS enforced for public exposure
- ingress routes scoped to required surfaces
- private mode uses restricted network boundaries
## Gate 3: Channel and Integration Auth Boundaries (Mandatory)
Fail conditions:
- channel/integration credentials stored in plaintext config committed to git
- missing signature/token checks where supported
- auth failure logs leak sensitive payloads
Pass criteria:
- channel + integration credentials sourced from secret manager/env
- smoke tests confirm authenticated message/event path
## Gate 4: Runtime and Persistence Safety (Mandatory)
Fail conditions:
- no persistent state configuration where required
- restart corrupts state/memory
- backups unencrypted or broadly accessible
Pass criteria:
- persistent path and permissions validated
- restart behavior tested and documented
- backup controls documented
## Gate 5: Incident Readiness (Mandatory)
Fail conditions:
- rollback path missing or owner undefined
- token revocation flow undefined
- no operator runbook for common outages
Pass criteria:
- rollback, revocation, and escalation path documented
- on-call owner/date captured in ops ledger
## Gate 6: Supply Chain and Patch Posture (Mandatory)
Fail conditions:
- untracked runtime image/dependency versions
- no policy for critical vulnerability updates
Pass criteria:
- deployment artifact version tracked
- critical vulnerability patch/redeploy process documented
## Gate 7: Ops Ledger Completeness (Mandatory)
Fail conditions:
- missing required ledger events (`scope_lock`, `predeploy_validation`, `deploy_complete`, `security_gate`, `handover`)
- missing required metadata fields for latest run
Pass criteria:
- ledger entries exist for all mandatory events
- blockers and next actions are recorded with owner/date
## Go/No-Go Rule
Production go-live is blocked unless **all mandatory gates pass**.
```
### references/openclaw-mode-matrix.md
```markdown
# OpenClaw Mode Matrix
Use this matrix to choose the correct setup branch.
| Dimension | Local Mode | Hosted Mode |
|---|---|---|
| Primary path | Install + onboard on operator machine | Clone repo + provider deploy |
| Best for | Single operator, private workflows, rapid trial | Team/shared access, durable operations |
| Infra ownership | Local machine/WSL resources | Cloud account + provider runtime |
| Exposure defaults | Private-first | Provider ingress with explicit auth controls |
| Required profile | `local` | `hosted-fly`, `hosted-render`, `hosted-railway`, `hosted-hetzner`, `hosted-gcp` |
| Rollback model | Restore local config/state snapshot | Redeploy prior revision + restore persisted state |
## Decision Rules
1. If user wants minimal setup and no cloud account, prefer `local`.
2. If user needs always-on access, team usage, or managed ingress, prefer `hosted`.
3. If user has no rollback owner/runbook, block `prod` in either mode.
## Mode-Specific Hard Stops
### Local
- No profile validation pass for `local`
- Public exposure requested without gateway protections
### Hosted
- Provider-specific profile validation fails
- Persistent volume/state not configured before traffic
- Public ingress configured without token/auth boundaries
```
### references/openclaw-os-matrix.md
```markdown
# OpenClaw OS Matrix
Use this matrix to adapt commands and caveats for each platform.
| OS | Supported Path | Key Notes |
|---|---|---|
| macOS | local + hosted CLI workflows | Prefer Homebrew package installs where available; verify shell path exports. |
| Linux | local + hosted CLI workflows | Prefer distro package manager + systemd for daemonized local workflows. |
| Windows (WSL2) | local (inside WSL2) + hosted CLI workflows | Run OpenClaw tooling inside WSL2 Linux environment; avoid mixed host/WSL path assumptions. |
## Command Adaptation Guidance
1. Normalize path assumptions before writing state/config files.
2. Keep provider CLIs installed in the same environment where commands run.
3. For Windows users, require explicit confirmation that terminal is WSL2 before local install steps.
## OS-Specific Verification
- Confirm CLI binaries resolve (`which`/`command -v`) in active shell.
- Confirm state directory read/write behavior.
- Confirm restart behavior and local process persistence approach.
## Hard Stops
- Platform mismatch between declared OS and active execution environment.
- State path not writable in selected OS runtime.
- Required CLI missing and no secure install path chosen.
```
### references/openclaw-integrations-playbook.md
```markdown
# OpenClaw Integrations Playbook
This playbook covers integration onboarding for `email` and `calendar`.
## Integration Status Vocabulary
- `configured`
- `pending_credentials`
- `blocked`
## Email (Gmail) Path
Reference: https://docs.openclaw.ai/integrations/gmail
Checklist:
1. Confirm OAuth/API credentials are provisioned for active environment.
2. Store secrets in env/provider secret manager.
3. Validate account authorization and token refresh behavior.
4. Run a smoke test (fetch inbox metadata only).
5. Verify logs avoid sensitive payload/token leakage.
Blockers:
- OAuth/client credentials missing
- refresh token flow failing
- auth errors not observable in logs
## Calendar (Google Calendar) Path
Reference: https://docs.openclaw.ai/integrations/google-calendar
Checklist:
1. Confirm calendar API credentials are provisioned for active environment.
2. Store credentials in env/provider secret manager.
3. Validate authorization scope minimums.
4. Run a smoke test (list upcoming events metadata only).
5. Verify logs avoid sensitive payload/token leakage.
Blockers:
- missing API access/scope
- failed refresh/consent flow
- unbounded privileged scopes
## Recording Requirements
For each selected integration, record in the ops ledger:
- status
- credentials source (name only)
- smoke-test result
- blockers and owner
```
### references/openclaw-ops-ledger-schema.md
```markdown
# OpenClaw Ops Ledger Schema
Use this schema for every ledger entry.
## Required Fields
- `timestamp_utc`
- `event`
- `operator`
- `mode`
- `provider`
- `os`
- `environment`
- `secrets_profile`
- `channels`
- `integrations`
- `security_status`
- `blocking_issues`
- `rollback_tested`
- `next_owner`
- `next_action_date`
## Event Types
- `scope_lock`
- `predeploy_validation`
- `deploy_complete`
- `security_gate`
- `handover`
- `incident`
## Rules
1. Never record secret values.
2. Record profile and key names only.
3. Keep one entry per event occurrence.
4. If `security_status=failed`, include actionable blockers.
5. `next_action_date` must be ISO date (`YYYY-MM-DD`).
## Example Entry
```markdown
## 2026-02-15T21:20:00Z | security_gate
- operator: codex
- mode: hosted
- provider: fly
- os: linux
- environment: prod
- secrets_profile: hosted-fly
- channels: telegram,slack
- integrations: email,calendar
- security_status: failed
- blocking_issues: gateway token rotation policy missing
- rollback_tested: no
- next_owner: platform-oncall
- next_action_date: 2026-02-16
```
```
---
## Skill Companion Files
> Additional files collected from the skill directory layout.
### _meta.json
```json
{
"owner": "hollaugo",
"slug": "openclaw-manager",
"displayName": "Openclaw Manager",
"latest": {
"version": "0.1.1",
"publishedAt": 1772174636860,
"commit": "https://github.com/openclaw/skills/commit/796870c5d8ce1590ceb964f7ae2a9ee505550edf"
},
"history": []
}
```