Claude
Skills
Sign in
Back

openclaw-control-center

Included with Lifetime
$97 forever

Local-first, security-first control center for OpenClaw agents — visibility dashboard with readonly defaults, token attribution, collaboration tracing, and safe write operations.

Security

What this skill does


# openclaw-control-center

> Skill by [ara.so](https://ara.so) — Daily 2026 Skills collection

OpenClaw Control Center transforms OpenClaw from a black box into a local, auditable control center. It provides visibility into agent activity, token spend, task execution chains, cross-session collaboration, memory state, and document sources — with security-first defaults that keep all mutations off by default.

## What It Does

- **Overview**: System health, pending items, risk signals, and operational summary
- **Usage**: Daily/7d/30d token spend, quota, context pressure, subscription window
- **Staff**: Who is actively executing vs. queued — not just "has tasks"
- **Collaboration**: Parent-child session handoffs and verified cross-session messages (e.g. `Main ⇄ Pandas`)
- **Tasks**: Task board, approvals, execution chains, run evidence
- **Memory**: Per-agent memory health, searchability, and source file editing
- **Documents**: Shared and agent-core documents opened from actual source files
- **Settings**: Connector wiring status, security risk summary, update status

## Installation

```bash
git clone https://github.com/TianyiDataScience/openclaw-control-center.git
cd openclaw-control-center
npm install
cp .env.example .env
npm run build
npm test
npm run smoke:ui
npm run dev:ui
```

Open:
- `http://127.0.0.1:4310/?section=overview&lang=zh`
- `http://127.0.0.1:4310/?section=overview&lang=en`

> Use `npm run dev:ui` over `UI_MODE=true npm run dev` — more stable, especially on Windows shells.

## Project Structure

```
openclaw-control-center/
├── control-center/          # All modifications must stay within this directory
│   ├── src/
│   │   ├── runtime/         # Core runtime, connectors, monitors
│   │   └── ui/              # Frontend UI components
│   ├── .env.example
│   └── package.json
├── docs/
│   └── assets/              # Screenshots and documentation images
├── README.md
└── README.en.md
```

> **Critical constraint**: Only modify files inside `control-center/`. Never modify `~/.openclaw/openclaw.json`.

## Environment Configuration

Copy `.env.example` to `.env` and configure:

```env
# Security defaults — do NOT change without understanding implications
READONLY_MODE=true
LOCAL_TOKEN_AUTH_REQUIRED=true
IMPORT_MUTATION_ENABLED=false
IMPORT_MUTATION_DRY_RUN=false
APPROVAL_ACTIONS_ENABLED=false
APPROVAL_ACTIONS_DRY_RUN=true

# Connection
OPENCLAW_GATEWAY_URL=http://127.0.0.1:PORT
OPENCLAW_HOME=~/.openclaw

# UI
PORT=4310
DEFAULT_LANG=zh
```

### Security Flag Meanings

| Flag | Default | Effect |
|------|---------|--------|
| `READONLY_MODE` | `true` | All state-changing endpoints disabled |
| `LOCAL_TOKEN_AUTH_REQUIRED` | `true` | Import/export and write APIs require local token |
| `IMPORT_MUTATION_ENABLED` | `false` | Import mutations blocked entirely |
| `IMPORT_MUTATION_DRY_RUN` | `false` | Dry-run mode for imports when enabled |
| `APPROVAL_ACTIONS_ENABLED` | `false` | Approval actions hard-disabled |
| `APPROVAL_ACTIONS_DRY_RUN` | `true` | Approval actions run as dry-run when enabled |

## Key Commands

```bash
# Development
npm run dev:ui          # Start UI server (recommended)
npm run dev             # One-shot monitor run, no HTTP UI

# Build & Test
npm run build           # TypeScript compile
npm test                # Run test suite
npm run smoke:ui        # Smoke test the UI endpoints

# Lint
npm run lint            # ESLint check
npm run lint:fix        # Auto-fix lint issues
```

## TypeScript Code Examples

### Connecting to the Runtime Monitor

```typescript
import { createMonitor } from './src/runtime/monitor';

const monitor = createMonitor({
  gatewayUrl: process.env.OPENCLAW_GATEWAY_URL ?? 'http://127.0.0.1:4310',
  readonlyMode: process.env.READONLY_MODE !== 'false',
  localTokenAuthRequired: process.env.LOCAL_TOKEN_AUTH_REQUIRED !== 'false',
});

// Fetch current system overview
const overview = await monitor.getOverview();
console.log(overview.systemStatus);      // 'healthy' | 'degraded' | 'critical'
console.log(overview.pendingItems);      // number
console.log(overview.activeAgents);      // Agent[]
```

### Reading Agent Staff Status

```typescript
import { StaffConnector } from './src/runtime/connectors/staff';

const staff = new StaffConnector({ gatewayUrl: process.env.OPENCLAW_GATEWAY_URL });

// Get agents actively executing (not just queued)
const activeAgents = await staff.getActiveAgents();
activeAgents.forEach(agent => {
  console.log(`${agent.name}: ${agent.status}`);
  // 'executing' | 'queued' | 'idle' | 'blocked'
  console.log(`Current task: ${agent.currentTask?.title ?? 'none'}`);
  console.log(`Last output: ${agent.lastOutput}`);
});

// Get the full staff roster including queue depth
const roster = await staff.getRoster();
```

### Tracing Cross-Session Collaboration

```typescript
import { CollaborationTracer } from './src/runtime/connectors/collaboration';

const tracer = new CollaborationTracer({ gatewayUrl: process.env.OPENCLAW_GATEWAY_URL });

// Get parent-child session handoffs
const handoffs = await tracer.getSessionHandoffs();
handoffs.forEach(handoff => {
  console.log(`${handoff.parentSession} → ${handoff.childSession}`);
  console.log(`Delegated task: ${handoff.taskTitle}`);
  console.log(`Status: ${handoff.status}`);
});

// Get verified cross-session messages (e.g. Main ⇄ Pandas)
const crossSessionMessages = await tracer.getCrossSessionMessages();
crossSessionMessages.forEach(msg => {
  console.log(`${msg.fromAgent} ⇄ ${msg.toAgent}: ${msg.messageType}`);
  // messageType: 'sessions_send' | 'inter-session message'
});
```

### Fetching Token Usage and Spend

```typescript
import { UsageConnector } from './src/runtime/connectors/usage';

const usage = new UsageConnector({ gatewayUrl: process.env.OPENCLAW_GATEWAY_URL });

// Today's usage
const today = await usage.getUsageSummary('today');
console.log(`Tokens used: ${today.tokensUsed}`);
console.log(`Cost: $${today.costUsd.toFixed(4)}`);
console.log(`Context pressure: ${today.contextPressure}`);
// contextPressure: 'low' | 'medium' | 'high' | 'critical'

// Usage trend over 7 days
const trend = await usage.getUsageTrend(7);
trend.forEach(day => {
  console.log(`${day.date}: ${day.tokensUsed} tokens, $${day.costUsd.toFixed(4)}`);
});

// Token attribution by task (who ate the scheduled task tokens)
const attribution = await usage.getTokenAttribution();
attribution.tasks.forEach(task => {
  console.log(`${task.title}: ${task.tokensUsed} (${task.percentOfTotal}%)`);
});
```

### Reading Memory State

```typescript
import { MemoryConnector } from './src/runtime/connectors/memory';

const memory = new MemoryConnector({
  openclawHome: process.env.OPENCLAW_HOME ?? '~/.openclaw',
});

// Get memory health per active agent (scoped to openclaw.json)
const memoryState = await memory.getMemoryState();
memoryState.agents.forEach(agent => {
  console.log(`${agent.name}:`);
  console.log(`  Available: ${agent.memoryAvailable}`);
  console.log(`  Searchable: ${agent.memorySearchable}`);
  console.log(`  Needs review: ${agent.needsReview}`);
});

// Read daily memory for an agent
const dailyMemory = await memory.readDailyMemory('main-agent');
console.log(dailyMemory.content);

// Edit memory (requires READONLY_MODE=false and valid local token)
await memory.writeDailyMemory('main-agent', updatedContent, { token: localToken });
```

### Checking Wiring Status

```typescript
import { WiringChecker } from './src/runtime/connectors/wiring';

const wiring = new WiringChecker({ gatewayUrl: process.env.OPENCLAW_GATEWAY_URL });

const status = await wiring.getWiringStatus();
status.connectors.forEach(connector => {
  console.log(`${connector.name}: ${connector.status}`);
  // status: 'connected' | 'partial' | 'disconnected'
  if (connector.status !== 'connected') {
    console.log(`  Fix: ${connector.nextStep}`);
  }
});
```

### Approving Tasks (Gated Endpoint)

```typescript
import { TaskConnector } from './src/runtime/connectors/tasks';

const tasks = ne

Related in Security