Admin Guide

Setup, configuration, CLI reference, cron integration, and fleet management.

Prerequisites

Install these before running the installer. Quick check:

node --version && npm --version && zstd --version && node --input-type=module -e "import 'lbug'" && echo "✅ all good"
DependencyVersionmacOSUbuntu / DebianFedora
Node.js18+brew install node@22NodeSource (see below)sudo dnf install -y nodejs npm
lbug0.14.3+npm install -g lbug
zstd1.5+brew install zstdsudo apt-get install -y zstdsudo dnf install -y zstd
curlanypre-installedsudo apt-get install -y curlpre-installed
OpenClawlatestgithub.com/openclaw/openclaw

macOS — step by step

# 1. Install Homebrew (skip if already installed)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# 2. Install Node.js 22 LTS (includes npm)
brew install node@22
echo 'export PATH="/opt/homebrew/opt/node@22/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc

# 3. Install lbug globally
npm install -g lbug

# 4. Install zstd
brew install zstd

# curl is pre-installed on macOS — no action needed

Ubuntu / Debian — step by step

# 1. Install curl
sudo apt-get update && sudo apt-get install -y curl

# 2. Add NodeSource repo and install Node.js 22 LTS (includes npm)
#    (apt's default nodejs is often too old — NodeSource guarantees v22)
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt-get install -y nodejs

# 3. Install lbug globally
npm install -g lbug

# 4. Install zstd
sudo apt-get install -y zstd

Fedora — step by step

# 1. Install Node.js 22 and npm
sudo dnf install -y nodejs npm

# 2. Install lbug globally
npm install -g lbug

# 3. Install zstd
sudo dnf install -y zstd

# curl is pre-installed on Fedora — no action needed

Installation

One-command install

# Lite — skills + embeddings (~300 MB compressed)
curl -fsSL https://raw.githubusercontent.com/alphaonedev/openclaw-graph/main/install.sh | bash -s -- --lite

# Full — skills + 545k DevDocs reference nodes (~500 MB compressed)
curl -fsSL https://raw.githubusercontent.com/alphaonedev/openclaw-graph/main/install.sh | bash -s -- --full

# From a cloned repo
bash install.sh --lite          # skills only
bash install.sh --full          # skills + DevDocs
bash install.sh --version v1.3  # pin a specific release
bash install.sh --verify        # check an existing DB

Manual install

git clone https://github.com/alphaonedev/openclaw-graph.git
cd openclaw-graph
npm install

# Download and decompress the DB
curl -L https://github.com/alphaonedev/openclaw-graph/releases/download/v1.3/alphaone-skills-full.db.zst \
  | zstd -d > ladybugdb/db/alphaone-skills.db

# Verify
node ladybugdb/scripts/query.js --stats

What the DB contains (v1.3)

TableNodesDescription
Skill316Skills across 27 clusters
Reference545,072DevDocs entries (718 docsets) — full tier only
Soul4Prime Directive, Identity, Safety, Heartbeat Protocol
Memory2Principal (placeholder), Infrastructure (placeholder)
AgentConfig9Every Session, Delegation, Safety, Heartbeats, Memory, TOON, Search Resilience, Schema Rules, Path Aliases
Tool26All standard OpenClaw tools
QueryMetricsgrowsAuto-recorded by query.js on every GRAPH directive resolution — view with sync-metrics.mjs

Table sizes: Workspace tables (Soul, Memory, AgentConfig) hold 4–30 nodes each. Full table scans are sub-millisecond at this scale. lbug 0.14.x does not expose a secondary-index DDL for regular node properties; indexes will be added here when lbug support lands.

Import Your Workspace

Already running OpenClaw with flat markdown files? One command loads them into LadybugDB.

Quick start

# From your openclaw-graph directory — reads ~/.openclaw/workspace/ by default
node ladybugdb/scripts/import-workspace.mjs

# Preview what will be imported without writing anything
node ladybugdb/scripts/import-workspace.mjs --dry-run

# Import + replace flat files with GRAPH stubs (originals backed up to *.bak)
node ladybugdb/scripts/import-workspace.mjs --write-stubs

# Custom path or workspace name
node ladybugdb/scripts/import-workspace.mjs --workspace-dir ~/my/path --workspace-name myagent

# Replace existing nodes
node ladybugdb/scripts/import-workspace.mjs --overwrite

File → Node mapping

FileNode typeSection → fieldNotes
SOUL.mdSoul## headingsectionOrdered by priority (file order)
MEMORY.mdMemory## headingdomainTimestamped on import date
USER.mdMemory## headingUser: <heading>Queryable separately via STARTS WITH 'User:'
TOOLS.mdTool## headingnameNo workspace column — tools are global
AGENTS.mdAgentConfig## headingkeyDrives AGENTS.md stub query

Format requirement: Each file is parsed by ## headings — each heading becomes one graph node. Files with no ## headings are imported as a single node titled Main. Files that already contain a GRAPH stub directive are automatically skipped.

What --write-stubs does

# Before: flat file (~1,800 bytes)
~/.openclaw/workspace/SOUL.md

# After --write-stubs:
~/.openclaw/workspace/SOUL.md      # ← single-line GRAPH stub (144 bytes)
~/.openclaw/workspace/SOUL.md.bak  # ← original backed up automatically

OpenClaw resolves the stub at runtime from LadybugDB — your content is preserved in the graph, not the file.

Database Layout

ladybugdb/
├── db/
│   └── alphaone-skills.db       # Single-file embedded DB (no daemon)
├── schema/
│   ├── nodes.cypher             # Skill + Reference DDL
│   ├── edges.cypher             # Relationship DDL
│   └── workspace-nodes.cypher   # Soul, Memory, AgentConfig, Tool DDL
└── scripts/
    ├── query.js                 # CLI query tool (auto-records QueryMetrics)
    ├── loader.js                # Load SKILL.md files into DB
    ├── seed-default-workspace.mjs  # Seed default workspace nodes
    ├── import-workspace.mjs     # Load flat SOUL/MEMORY/USER/TOOLS/AGENTS.md into DB
    ├── sync-metrics.mjs         # View / reset QueryMetrics dashboard
    └── seed-workspace.js        # Custom workspace seeder

LadybugDB is an embedded graph database (KuzuDB). The entire DB is a single file — no daemon, no port, no configuration. Queries execute in-process via the lbug Node.js bindings.

CLI Reference

All commands use node ladybugdb/scripts/query.js:

Skill queries

# Text search — matches against name, description, embedding hints
node ladybugdb/scripts/query.js "build a SwiftUI watchOS app"

# Cluster filter — list all skills in a cluster
node ladybugdb/scripts/query.js --cluster devops-sre
node ladybugdb/scripts/query.js --cluster financial

# Skill graph traversal — show a skill and its relationships
node ladybugdb/scripts/query.js --skill cloudflare --hops 2

# Stats — total skills, clusters, auth-required flags
node ladybugdb/scripts/query.js --stats

Raw Cypher queries

# Standard mode — labeled output for debugging
node ladybugdb/scripts/query.js --cypher "MATCH (s:Skill) RETURN count(s) AS total"

# Workspace mode — clean markdown output (used by workspace.ts)
node ladybugdb/scripts/query.js --workspace --cypher \
  "MATCH (a:AgentConfig {workspace:'openclaw'}) RETURN a.key, a.value ORDER BY a.id"

Workspace node queries

# List all Soul nodes
node ladybugdb/scripts/query.js --cypher \
  "MATCH (s:Soul {workspace:'openclaw'}) RETURN s.section, s.priority ORDER BY s.priority"

# List all AgentConfig nodes
node ladybugdb/scripts/query.js --cypher \
  "MATCH (a:AgentConfig {workspace:'openclaw'}) RETURN a.key ORDER BY a.id"

# List available tools
node ladybugdb/scripts/query.js --cypher \
  "MATCH (t:Tool) WHERE t.available = true RETURN t.name, t.notes ORDER BY t.name"

# Query DevDocs references
node ladybugdb/scripts/query.js --cypher \
  "MATCH (r:Reference) WHERE r.source = 'python~3.12' AND r.path STARTS WITH 'library/' RETURN r.title, r.path LIMIT 20"

Output formats

The --workspace flag activates clean markdown output (no labels), which is what workspace.ts uses when resolving GRAPH directives. Without it, output is labeled for human reading.

Data shapeFormat
section + contentSoul markdown (## Section\n\nContent)
domain + contentMemory markdown (## Domain\n\nContent)
key + valueAgentConfig markdown (- **Key**: Value)
name + notesTool list (- **Name**: Notes)
OtherJSON (debug/dev use)

Workspace Setup

1. Apply the workspace.ts patch

The patch modifies OpenClaw's workspace.ts to resolve GRAPH directives:

cd /path/to/openclaw
git apply path/to/openclaw-graph/patches/workspace-cache-fix.patch
pnpm build

What the patch does:

2. Deploy workspace stubs

cp workspace-stubs/*.md ~/.openclaw/workspace/

Each stub is a single-line file like:

<!-- GRAPH: MATCH (s:Soul) WHERE s.workspace = 'openclaw' RETURN s.section AS section, s.content AS content ORDER BY s.priority ASC -->

3. Verify resolution

# Test that the directive resolves correctly
node ladybugdb/scripts/query.js --workspace --cypher \
  "MATCH (s:Soul {workspace:'openclaw'}) RETURN s.section, s.content ORDER BY s.priority"

# Expected: formatted markdown with Prime Directive, Identity, Safety, Heartbeat Protocol

4. Customize your workspace

See the User Guide → Customizing for step-by-step personalization.

Cron Job Integration

openclaw-graph supports scheduled tasks (cron jobs) that query the graph database. Cron jobs typically run as lightweight OpenClaw sessions that:

  1. Load workspace context via GRAPH directives (same as interactive sessions)
  2. Execute domain-specific prompts (intel, monitoring, alerts)
  3. Write output to files or send notifications

Cron architecture

Cron Scheduler (crontab / launchd / systemd)
  └── Every N minutes: run openclaw session
        │
        ▼
OpenClaw Session (cron mode)
  ├── Load AGENTS.md → GRAPH: AgentConfig
  ├── Load TOOLS.md  → GRAPH: Tool
  ├── Execute prompt (task-specific)
  └── Write output / send alerts
        │  --workspace --cypher
        ▼
LadybugDB (alphaone-skills.db)
  ├── AgentConfig → session behavior
  ├── Skill → task-relevant skills
  └── Reference → documentation context

Cron session bootstrap

Cron/sub-agent sessions use a minimal bootstrap. OpenClaw's MINIMAL_BOOTSTRAP_ALLOWLIST loads only:

SOUL.md and MEMORY.md are skipped for cron sessions to reduce prompt size.

AgentConfig nodes relevant to cron

NodePurpose
agentcfg-*-every-sessionBootstrap instructions (read SOUL, USER, memory)
agentcfg-*-delegationSub-agent spawning rules
agentcfg-*-search-resilienceRetry/fallback when web_search fails
agentcfg-*-schema-rulesOutput validation requirements
agentcfg-*-path-aliasesCompact path notation ($PY, $DB, etc.)
agentcfg-*-toonJSON compression for large payloads

Example: cron job definition

{
  "name": "daily-report",
  "schedule": "0 8 * * *",
  "workspace": "openclaw",
  "prompt": "Generate today's daily report. Query relevant skills with: node ladybugdb/scripts/query.js --cluster financial",
  "output": "~/.openclaw/workspace/reports/daily-$(date +%Y-%m-%d).md"
}

Querying skills from cron prompts

# Find relevant skills for a domain
node ladybugdb/scripts/query.js "kubernetes monitoring alerts"

# Get specific skill content
node ladybugdb/scripts/query.js --skill kubernetes-ops --hops 1

# Query reference docs
node ladybugdb/scripts/query.js --cypher \
  "MATCH (r:Reference {source:'kubernetes'}) WHERE r.path STARTS WITH 'api/' RETURN r.title, r.content LIMIT 5"

Fleet Management

For multi-instance deployments, each OpenClaw instance gets its own workspace ID. All instances share the same DB file (no lock contention — LadybugDB is read-heavy).

Seed separate workspaces

node ladybugdb/scripts/seed-default-workspace.mjs --workspace intel-agent
node ladybugdb/scripts/seed-default-workspace.mjs --workspace code-agent
node ladybugdb/scripts/seed-default-workspace.mjs --workspace ops-agent

Point stubs to the correct workspace

# Instance A stubs (~/.openclaw/workspace-intel/)
# SOUL.md:
#   <!-- GRAPH: MATCH (s:Soul) WHERE s.workspace = 'intel-agent' RETURN s.section AS section, s.content AS content ORDER BY s.priority ASC -->

Fleet topology example

PortInstanceWorkspace ID
18790A — Intel/OSINTintel-agent
18791B — Computecompute-agent
18792C — Browserbrowser-agent
18793D — Code/GitHubcode-agent
18794E — Infrainfra-agent
18795F — Memory/Graphgraph-agent
18796G — Generalgeneral-agent
18797H — Standbystandby-agent

Each instance runs its own DB copy (install.sh --full). No shared DB, no lock contention.

Per-workspace tool overrides

# Disable delegation for the browser-only instance
node ladybugdb/scripts/query.js --cypher \
  "MATCH (t:Tool {id:'tool-sessions-spawn'}) \
   WHERE EXISTS { MATCH (a:AgentConfig {workspace:'browser-agent'}) } \
   SET t.available = false"

Service Management

Architecture note: openclaw-graph has no daemon of its own. It is embedded directly inside the OpenClaw gateway process. "Restarting the graph" means restarting the OpenClaw gateway. The LadybugDB file is always accessible directly via query.js --stats regardless of gateway state.

macOS (launchd)

OpenClaw installs a launchd service with label ai.openclaw.gateway.

# Start
launchctl bootstrap gui/$UID \
  ~/Library/LaunchAgents/ai.openclaw.gateway.plist

# Stop
launchctl bootout gui/$UID/ai.openclaw.gateway

# Restart (stop + start in one command)
launchctl kickstart -k gui/$UID/ai.openclaw.gateway

# Status — look for "state = running" and "pid ="
launchctl print gui/$UID/ai.openclaw.gateway | grep -E "state|pid"

macOS log files

# Structured log (stdout) — primary log
tail -f ~/.openclaw/logs/gateway.log

# Error log (stderr)
tail -f ~/.openclaw/logs/gateway.err.log

# macOS unified log stream (real-time, subsystem ai.openclaw)
log stream --predicate 'subsystem == "ai.openclaw"' --level info

# Or use the bundled clawlog utility from the openclaw directory
bash scripts/clawlog.sh

Ubuntu (systemd)

OpenClaw installs a user-scope systemd unit: openclaw-gateway.service.

# Start
systemctl --user start openclaw-gateway.service

# Stop
systemctl --user stop openclaw-gateway.service

# Restart
systemctl --user restart openclaw-gateway.service

# Status
systemctl --user status openclaw-gateway.service

Ubuntu log files

# Live log stream via journald
journalctl --user -u openclaw-gateway.service -f

# Or read the flat log files directly
tail -f ~/.openclaw/logs/gateway.log
tail -f ~/.openclaw/logs/gateway.err.log

Fedora (systemd)

Same commands as Ubuntu — both use user-scope systemd.

# Start
systemctl --user start openclaw-gateway.service

# Stop
systemctl --user stop openclaw-gateway.service

# Restart
systemctl --user restart openclaw-gateway.service

# Status
systemctl --user status openclaw-gateway.service

Fedora log files

# Live log stream via journald
journalctl --user -u openclaw-gateway.service -f

# Or read the flat log files directly
tail -f ~/.openclaw/logs/gateway.log
tail -f ~/.openclaw/logs/gateway.err.log

DB health check (all platforms)

These run directly against the LadybugDB file — no gateway required.

# Full stats: node count, edge count, DB file size
node ~/openclaw-graph/ladybugdb/scripts/query.js --stats

# Quick workspace sanity check
node ~/openclaw-graph/ladybugdb/scripts/query.js --cypher \
  "MATCH (s:Soul {workspace:'openclaw'}) RETURN count(s) AS souls"

# Check all workspace node counts
node ~/openclaw-graph/ladybugdb/scripts/query.js --cypher \
  "MATCH (n) WHERE n.workspace = 'openclaw' RETURN labels(n)[0] AS type, count(n) AS n ORDER BY type"

Log file locations (all platforms)

FileContains
~/.openclaw/logs/gateway.logGateway stdout — normal operational output
~/.openclaw/logs/gateway.err.logGateway stderr — errors and warnings

Query Metrics

query.js automatically records a row into QueryMetrics every time a GRAPH directive resolves from a workspace stub (--workspace mode). No configuration needed — it just works after install.

New install? QueryMetrics starts empty and fills itself automatically. The first entry appears after OpenClaw loads any workspace stub for the first time.

View the dashboard

# Dashboard — top 20 queries by hit count
node ladybugdb/scripts/sync-metrics.mjs

# Show top 40
node ladybugdb/scripts/sync-metrics.mjs --top 40

# Include queries that returned 0 results
node ladybugdb/scripts/sync-metrics.mjs --zero

# Raw JSON (for scripting or export)
node ladybugdb/scripts/sync-metrics.mjs --json

# Clear all metrics (e.g. after a workspace reset)
node ladybugdb/scripts/sync-metrics.mjs --reset

What the dashboard shows

ColumnMeaning
hitsTimes this Cypher query returned ≥1 row
missTimes this Cypher query returned 0 rows
rateHit rate percentage (hits / total)
avgRolling mean execution time (hits only, Welford algorithm)
p95High-water mark — rises instantly on slow queries, decays slowly
last_hitUTC timestamp of most recent successful hit

Upgrading

When you upgrade to a new release, the DB is replaced. Workspace nodes live in the DB.

Upgrade workflow

# 1. Backup current workspace nodes
node ladybugdb/scripts/query.js --cypher \
  "MATCH (s:Soul {workspace:'myworkspace'}) RETURN s.id, s.section, s.content, s.priority" \
  > workspace-backup.json

# 2. Run install.sh (downloads new DB, overwrites old)
bash install.sh --full

# 3. Re-seed your workspace
node ladybugdb/scripts/seed-default-workspace.mjs --workspace myworkspace
# or: node ladybugdb/scripts/seed-myagent.mjs

# 4. Verify
node ladybugdb/scripts/query.js --cypher \
  "MATCH (a:AgentConfig {workspace:'myworkspace'}) RETURN count(a) AS n"

Recommended: Keep your workspace customizations in a seed script (forked from seed-default-workspace.mjs). After any DB upgrade, re-run the script. This is more reliable than manual backup/restore.

Backup & Restore

Full DB backup

# The DB is a single file — just copy it
cp ladybugdb/db/alphaone-skills.db ladybugdb/db/alphaone-skills.db.bak

Export workspace nodes to JSON

# Export each table
for table in Soul Memory AgentConfig Tool; do
  node ladybugdb/scripts/query.js --cypher \
    "MATCH (n:${table}) RETURN n.*" > backup-${table}.json
done

Environment Variables

VariableDefaultDescription
OPENCLAW_GRAPH_NODE_BINnodePath to Node.js binary for query.js
OPENCLAW_GRAPH_QUERY_SCRIPT~/openclaw-graph/ladybugdb/scripts/query.jsPath to CLI query script
NODE_BINnodeUsed by install.sh
RELEASE_VERSIONlatestPin install.sh to a specific release

Troubleshooting

GRAPH directive returns empty

Symptom: Workspace file loads but content is empty.

Check:

# 1. Is the DB present?
ls -lh ladybugdb/db/alphaone-skills.db

# 2. Can query.js connect?
node ladybugdb/scripts/query.js --stats

# 3. Does the workspace have nodes?
node ladybugdb/scripts/query.js --cypher \
  "MATCH (a:AgentConfig {workspace:'openclaw'}) RETURN count(a) AS n"

# 4. Is the directive syntax correct?
# Must be: <!-- GRAPH: <cypher> -->
# Must be the FIRST LINE of the file
# Cypher must be a single line

"Table X does not exist"

Cause: The workspace tables haven't been created. This happens if you installed a pre-v1.3 DB.

Fix:

node ladybugdb/scripts/seed-default-workspace.mjs

Stale workspace content

Cause: Graph query cache hasn't expired (60s TTL).

Fix: Wait 60 seconds, or restart the OpenClaw process. The cache is in-memory only.

CLI subprocess slow (~100ms+)

This is expected. The ~100ms cost is Node.js process startup + lbug init — not the query itself (which takes <1ms). The cache ensures this cost is paid at most once per 60 seconds per unique query.

DB file locked / corrupted

# Check for WAL files
ls ladybugdb/db/alphaone-skills.db*

# If .wal files exist, the DB may have been interrupted during a write
# Backup and re-install
mv ladybugdb/db/alphaone-skills.db ladybugdb/db/alphaone-skills.db.corrupted
bash install.sh --full
node ladybugdb/scripts/seed-default-workspace.mjs

Performance Reference

QueryIn-processCLI subprocess
Skill PK lookup0.18ms~111ms
AgentConfig (9 nodes)0.33ms~127ms
Tool query (26 nodes)0.41ms~106ms
Reference PK (545k table)0.11ms
Full skill scan (316)2.02ms

All in-process queries are sub-millisecond. CLI subprocess cost (~104ms) is amortized by the 60–180s adaptive TTL cache. All 5 workspace GRAPH directives resolve in parallel via Promise.allSettled() — cold workspace load is ~104ms total, not 5×104ms.

Workspace tables (Soul, Memory, AgentConfig) hold 4–30 nodes each — full table scans are sub-millisecond at this scale. lbug 0.14.x does not expose a secondary-index DDL for non-PK properties; the scan cost is negligible today and indexes will be added when lbug support lands.

Full benchmark data: benchmarks/results.md