This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
ClawFleet — deploy and manage a fleet of isolated OpenClaw instances on a single machine, from a browser dashboard. Built on ClawSandbox, a purpose-built infrastructure layer for container orchestration and instance lifecycle management. Open-sourced on GitHub.
ClawFleet is built on top of ClawSandbox, a purpose-built infrastructure layer for container orchestration and instance lifecycle management.
Packages: container/, state/, port/, config/, assets/, snapshot/, version/ Responsible for: Docker orchestration, instance state persistence, port allocation, container networking, image management, snapshot archival. Standard: production-grade reliability, defensive coding, thorough test coverage.
Packages: web/, cli/ Responsible for: REST API, WebSocket real-time updates, Dashboard UI, CLI commands, asset management (models/channels/characters), skill management, i18n. Standard: user experience, feature velocity, accessibility.
Dependency rule: ClawFleet → ClawSandbox (never reverse).
This is a multi-contributor project with rapid iteration. Before planning or starting any task in a session:
- Sync to latest main — always pull the latest remote main branch first:
git fetch origin git checkout main git pull origin main
- Build full context — read the codebase, documentation (CLAUDE.md, README, SYSTEM_DESIGN, etc.), and project memory thoroughly. Understand recent changes by reviewing git log and any files touched by recent commits.
- Design from current state — ensure all design decisions and implementation plans are based on a comprehensive understanding of the project's latest state, not assumptions from prior sessions.
Then create a feature branch from the up-to-date main. Never work directly on a stale branch.
Never push directly to main. All changes must go through a pull request, even for docs or config-only changes.
One PR = one branch, all commits before merge. Never push additional commits to a branch after its PR has been merged — those commits will not be on main. If you have more changes to make, create a new branch from the latest main and open a new PR. Always check gh pr view <number> --json state before pushing to a PR branch.
# Download dependencies
go mod tidy
# Build CLI binary → bin/clawfleet
make build
# Run tests
make test
# Build Docker image (first time, ~1.4GB, takes several minutes)
make docker-build
# or via the CLI itself (uses embedded Dockerfile):
./bin/clawfleet build
# Cross-compile for all platforms
make build-allGo CLI tool (cobra) that manages Docker containers with an embedded Web Dashboard. Key packages:
cmd/clawfleet/— binary entry pointinternal/cli/— cobra commands (build, create, list, start, stop, restart, destroy, desktop, logs, dashboard, config, version)internal/container/— Docker SDK wrappers (client, image build/check/pull, network, container lifecycle, stats)internal/port/— TCP port availability checker and allocatorinternal/state/— instance metadata store (~/.clawfleet/state.json), mutex-protectedinternal/config/— config file loader (~/.clawfleet/config.yaml)internal/assets/— embedded Docker build context (Dockerfile, supervisord.conf, entrypoint.sh)internal/web/— Web Dashboard: HTTP server, REST API handlers, WebSocket endpoints (stats/logs/events), embedded frontendinternal/version/— build version info (injected via ldflags)
Each claw instance is a Docker container running: XFCE4 desktop + TigerVNC + noVNC (browser access on port 690N) + OpenClaw Gateway (port 1878N).
Container data is persisted at ~/.clawfleet/data/<name>/openclaw/ → /home/node/.openclaw inside the container.
ClawFleet manages OpenClaw instances via docker exec CLI commands. Key integration points:
- OpenClaw uses
SOUL.md(Markdown) at~/.openclaw/SOUL.mdfor character/persona definition - Gateway watches this file — hot-reloads on change, no restart needed
- ClawFleet renders
CharacterAssetfields into SOUL.md and writes viadocker exec
- Bundled Skills (52): Ship with OpenClaw, status depends on binary/env requirements
- Managed Skills: Installed via
clawhubCLI to~/.openclaw/skills/ openclaw skills list --jsonreturns structured skill datanpx clawhub --workdir ~/.openclaw --dir skills install/uninstall <slug>manages community skills- ClawHub has rate limits (~20 requests/minute) — handle errors gracefully
openclaw skills list --json— list all skills with statusopenclaw plugins list— list all plugins (41 stock plugins)openclaw config set <path> <value>— set any config valuenpx clawhub search "<query>"— search community skillsnpx clawhub --workdir /home/node/.openclaw --dir skills install <slug> --no-input— install skill
All design decisions, project structure, and code implementation must follow best engineering practices. Specifically:
- Never use overly permissive settings (e.g.
chmod 0777) as shortcuts. Solve permission problems by understanding the ownership model and applying minimal necessary access. - Container processes must run with the correct user for the operation: system management commands (e.g.
supervisorctl) run asroot, application commands (e.g.openclaw) run as the unprivilegednodeuser. - Never embed secrets or credentials in code, images, or config files.
- Understand the tools you're automating. Read
--help, check actual behavior, and verify assumptions (e.g. model name formats, plugin enablement, API readiness) before writing integration code. - Prefer explicit configuration over implicit defaults. If a third-party tool has a default that doesn't suit our use case (e.g.
dmPolicy: "pairing"), set the desired value explicitly rather than hoping users will figure it out. - When orchestrating multi-step processes, respect ordering dependencies and readiness checks (e.g. wait for a service to be healthy before issuing commands against it).
- ClawFleet's core value to users is shielding them from OpenClaw's rapid release cadence and potential instability. Every ClawFleet release (e.g.
v0.4.0) must pin a specific, tested OpenClaw version (RecommendedOpenClawVersionininternal/version/version.go). - The pre-built Docker image on GHCR must contain exactly that pinned version — never
@latest. CI extractsRecommendedOpenClawVersionfrom source and passes it as theOPENCLAW_VERSIONbuild-arg. If this is missing or broken, users get an untested OpenClaw version, defeating the entire purpose of our version management. - Before bumping
RecommendedOpenClawVersion, the new OpenClaw version must be tested end-to-end (instance creation, configuration, bot startup, channel connectivity) on at least one platform. - The Dashboard's "Build" flow lets advanced users opt into a different OpenClaw version at their own risk. The "Pull" flow and
install.shalways deliver the pinned version.
- Don't add abstractions, flags, or config options for hypothetical future needs. Solve the current problem directly.
- Prefer calling existing CLI tools (
docker exec+openclawCLI) over writing config files directly — this keeps the integration resilient to upstream format changes.
- SOUL.md drives bot persona and behavior at runtime. Treat its content with the same rigor as source code — not "good enough" prose.
- Every prompt section must have: explicit judgment criteria (when to act), negative constraints (when NOT to act), and dense, scannable information (no lore dumps).
- Expect iteration. The first draft of a prompt section is never the final version. Test actual LLM behavior, observe output, adjust wording.
- When modifying SOUL.md rendering logic (e.g.
RenderSoulMarkdown, roster injection), verify the generated Markdown reads correctly as a prompt — not just that the Go code compiles. - This principle applies to any Markdown file that is consumed by an LLM at runtime (SOUL.md today, potentially others in the future).
When researching an external technology (framework, tool, protocol, or platform), every evaluation must deliver:
- Ecological niche comparison — where does it sit relative to ClawFleet? Same layer (competitor) or different layer (potential complement)?
- If competitor — can we beat it? Where are our advantages and disadvantages? Should we compete head-on, differentiate, or avoid the overlap?
- If complement — can the two work together? What's the integration path? Does it require our users to adopt additional skills or tools (e.g., Python, YAML pipelines) that conflict with ClawFleet's "Dashboard-first" ethos?
- Capability transfer — can we use this technology to directly strengthen ClawFleet? If integration is impractical, are there validated design patterns worth borrowing and reimplementing in our own architecture?
- Design inspiration — does it have novel concepts (e.g., shared scratchpad, checkpointing, conditional routing) that solve problems we face or will face? Document these as candidates for future versions with a clear "borrow the pattern, not the framework" stance.
The output of any tech research should be a clear recommendation: compete / integrate / borrow / ignore — with reasoning.
ClawFleet is an infrastructure-layer product. Every time we integrate a new runtime (e.g. Hermes Agent) or depend on a new external tool, we must first build a thorough understanding of that component's internals and document it in a spec — before writing any integration code:
- Read the source code of the subsystem being integrated (auth, config, provider resolution, credential storage). The source is always available — inside containers, in repos, or in installed packages.
- Map the complete data flow: where credentials are read, how providers are resolved, what env vars are checked, what config keys are honored, and in what priority order.
- Document findings in the spec with concrete details: exact provider names, env var names, config paths, resolution fallback chains. No assumptions carried over from other systems.
- Validate manually in the target environment (e.g.
docker execinto the container, set config, test the API call) before writing any Go/JS code.
Skipping this step and guessing from analogies with other systems (e.g. assuming Hermes works like OpenClaw) leads to repeated debugging cycles that waste engineering time and user patience.
The user's role is to set goals, review designs, and do final acceptance testing — not to participate in debug iterations. The correct human-in-the-loop workflow is:
- Set a clear success criterion (e.g. "DM the bot, get an LLM-generated reply").
- Implement and self-test end-to-end until that criterion is met. Self-testing means: build → configure via API → verify config in container → trigger the exact user flow (send a message, check logs for success) → confirm the full chain works.
- Only then present to the user for acceptance. If the user finds a bug, fix it and self-test the fix before asking them to re-test.
Never ask the user to "try it and see" as a substitute for your own testing. Every handoff to the user must be a confident "this works, please verify" — not "I think this might work, let me know".
All Marketer-Sessions (growth, content, distribution) MUST re-read growth/STRATEGY_BULLETIN.md before every action cycle (writing content, publishing, making distribution decisions). This file contains the live strategy, target user definition, active decisions, and constraints. It is updated by the lead Marketer-Session; the version comment above is bumped on each update to trigger CLAUDE.md change notifications to all running sessions.
The project wiki lives in a separate repo (git@github.com:clawfleet/ClawFleet.wiki.git) and is browsable at https://github.com/clawfleet/ClawFleet/wiki. It is the primary documentation hub beyond the README.
| File | Purpose |
|---|---|
_Sidebar.md |
Navigation sidebar shown on every page |
_Footer.md |
Footer with repo link |
Home.md |
Landing page — value prop, quickstart roadmap, page index |
Getting-Started.md |
Prerequisites, install, first instance end-to-end |
Dashboard-Guide.md |
Sidebar navigation, asset management, fleet management, image management |
CLI-Reference.md |
All CLI commands with descriptions and examples |
FAQ.md |
Common issues grouped by install / config / resource / operations |
Provider-{Anthropic,OpenAI,Google,DeepSeek}.md |
LLM provider guides (one per provider) |
Channel-{Telegram,Discord,Slack,Lark}.md |
Messaging channel guides (one per channel) |
- Provider pages follow a consistent template: Overview → Get API Key (step-by-step) → Add in Dashboard → Assign to Instance → Pricing Notes → Troubleshooting.
- Channel pages follow: Overview → Create Bot (step-by-step) → Add in Dashboard → Assign to Instance → Test → Notes → Troubleshooting.
- Key facts to keep consistent across pages:
- Models are shared — multiple instances can use the same model config simultaneously.
- Channels are exclusive — each channel can only be assigned to one instance at a time.
- Validation required — must click "Test" and see validation pass before saving.
- Lark is different — uses App ID + App Secret, not a single token.
- Auto-configuration — ClawFleet sets DM/group policies to "open" and allows all senders automatically.
- Preset models are defined in
internal/web/static/js/components/model-asset-dialog.js(MODEL_PRESETS). When models change there, update the wiki provider pages andDashboard-Guide.md. - Validation logic is in
internal/web/validate.go. If validation endpoints change, update the corresponding channel/provider troubleshooting sections.
Screenshots in docs/images/ serve dual purposes: README documentation and external promotion (website, social media). When updating screenshots:
- Keep filenames stable — never rename files in
docs/images/; README references depend on them. - Sync to all consumers —
fleet.pngis also used asdemo-dashboard.pngon the website (clawfleet.github.io). After updating, copy to the website repo and push both. - Reflect latest product state — screenshots must match the current UI. When features are added or styling changes, re-capture all affected screenshots in one batch.
- Image mapping:
| Source (docs/images/) | External consumer | Notes |
|---|---|---|
fleet.png |
clawfleet.github.io/demo-dashboard.png |
Dashboard overview for landing page |
You must update the wiki whenever a code change affects user-facing behavior. Specifically:
- New or removed CLI command → update
CLI-Reference.md, andGetting-Started.md/FAQ.mdif relevant. - New LLM provider → create
Provider-<Name>.mdusing the existing template, add to_Sidebar.md, updateHome.mdpage index andDashboard-Guide.mdpreset table. - New messaging channel → create
Channel-<Name>.mdusing the existing template, add to_Sidebar.md, updateHome.mdpage index. - Dashboard UI changes (new sections, renamed labels, changed workflows) → update
Dashboard-Guide.mdandGetting-Started.md. - Model preset changes → update
Dashboard-Guide.mdpreset table and the relevantProvider-*.mdpage. - README wiki links — both
README.mdandREADME.zh-CN.mdhave a "Documentation" section linking to wiki pages. Update these links if wiki page names change.
git clone git@github.com:clawfleet/ClawFleet.wiki.git /tmp/ClawFleet.wiki
cd /tmp/ClawFleet.wiki
# Edit files...
git add . && git commit -m "describe the change" && git pushThe wiki repo uses master as its default branch.