Catalog npm
Back to packageRELEASE DETAILS

2.0.0-alpha.0

npm

0xai-openclaw-guardian

Real-time cost tracking, security monitoring, and settings dashboard for OpenClaw AI agent deployments

ai-agentscost-trackingdashboardmonitoringobservabilityopenclawanthropicbilling-proxyclaudegeminikill-switchllm-observabilityollamaopenairate-limiting
Published16 Apr 2026
Direct dependencies2
Transitive dependenciesNot calculated

README

Current package documentation

0xAI OpenClaw Guardian

Real-time observability, cost tracking, kill-switches and configuration dashboard for OpenClaw AI agent deployments.

npm version npm downloads license Node GitHub Sponsors Buy Me a Coffee

  • 🔍 Intercepts every AI call from OpenClaw to any provider (Anthropic, OpenAI, Google, OpenRouter, Groq, Cerebras, xAI, Ollama, HuggingFace)
  • 💰 Real per-call cost calculation via noosphere pricing catalog (45+ models, auto-synced)
  • 🛡 Kill-switches: USD caps (daily/weekly/monthly), per-agent/per-model caps, rate limits for zero-cost providers (ollama), loop detector, emergency pause
  • 📊 Dashboard at http://localhost:3847 with tabs: Spend · Calls · Crons · Limits · Settings · Security
  • 🔗 Stateful: SQLite-backed calls.db for live queries and aggregations
  • 🪙 Subscription-aware: shows SUB vs API per call, always prints the API-equivalent cost (even for Claude Max)

Dashboard — Spend tab

Real-time spend breakdown by agent, model, and source. API-equivalent cost is displayed even for subscription (Claude Max) calls, so you always see the economic value consumed.


Install

Zero setup if you just want to run it:

# Global CLI
npm install -g openclaw-observability
openclaw-obs

# Or without install
npx openclaw-observability

Then open http://localhost:3847 in your browser.

The proxy starts automatically on http://127.0.0.1:18801 the first time it detects Claude credentials at ~/.claude/.credentials.json.


Wire it into OpenClaw

Edit ~/.openclaw/openclaw.json so each provider's baseUrl points at the local proxy. That makes every call route through observability, pricing, kill-switches, and the logger.

{
  "models": {
    "providers": {
      "anthropic": { "baseUrl": "http://127.0.0.1:18801" },
      "openai":    { "baseUrl": "http://127.0.0.1:18801/openai/v1" },
      "google":    { "baseUrl": "http://127.0.0.1:18801/google" },
      "openrouter":{ "baseUrl": "http://127.0.0.1:18801/openrouter/v1" },
      "groq":      { "baseUrl": "http://127.0.0.1:18801/groq/openai/v1" },
      "cerebras":  { "baseUrl": "http://127.0.0.1:18801/cerebras/v1" },
      "xai":       { "baseUrl": "http://127.0.0.1:18801/xai/v1" },
      "ollama":    { "baseUrl": "http://127.0.0.1:18801/ollama", "api": "ollama" }
    }
  }
}

Restart the OpenClaw gateway so the new baseUrls take effect.


Environment variables

All optional.

VariableDefaultDescription
OPENCLAW_DIR~/.openclawPath to your OpenClaw directory
OBS_PORT3847Dashboard server port
OBS_HOST0.0.0.0Bind address
OBS_LIMITS_FILE$OPENCLAW_DIR/observability/limits.jsonSpend + rate limit config
OBS_BILLING_PROXY_AUTOSTART1Start the proxy on boot when Claude creds are present
OBS_BILLING_PROXY_PORT18801Proxy port (all providers multiplex here)
OBS_BILLING_PROXY_HOST127.0.0.1Proxy bind address

Dashboard tabs

💸 Spend

Historical spend aggregated by agent / model / source / day / cron. Reads from session JSONL files. Works even for subscription calls (API-equivalent cost is always computed).

📋 Calls

Every single call captured by the proxy, live. Filters: provider, model, billing mode (SUB/API). Columns:

ColMeaning
Timelocal timestamp
Provider / Modelwho served the call
Agentderived from request body / openclaw.json whitelist
Querylast user message (tooltip has full text)
In / Out / Cache / Totaltoken counts
Cost / $/1kAPI-equivalent USD
Latround-trip latency
BillingSUB (subscription plan) or API (pay-per-token)

⏰ Crons

List every OpenClaw cron with schedule, agent, last-run status, consecutive errors. Enable/disable or permanently delete any cron from the UI.

🛡 Limits — Kill-switches

Edit ~/.openclaw/observability/limits.json with a form. Proxy hot-reloads on mtime change.

  • Emergency pause — single-click kill-switch. Auto-saves immediately. Sticks a red banner across the dashboard while active.
  • Global USD caps — daily / weekly / monthly. Blocks upstream requests with HTTP 429 when exceeded. Does NOT trigger for zero-cost providers (see next).
  • Rate + token caps per provider — required for Ollama / local inference. Supports callsPerMinute, callsPerHour, callsPerDay, tokensPerDay.
  • Loop detector — if any single session makes more than N calls in X seconds, further calls are auto-blocked.

Example limits.json:

{
  "enabled": true,
  "paused": false,
  "global": { "dailyUsd": 10, "weeklyUsd": 50, "monthlyUsd": 200 },
  "perAgent":  { "anhelo": { "dailyUsd": 3 } },
  "perModel":  { "claude-opus-4-6": { "dailyUsd": 5 } },
  "rateLimits": {
    "perProvider": {
      "ollama": { "callsPerMinute": 120, "callsPerHour": 2000, "tokensPerDay": 50000000 }
    }
  },
  "loopDetector": { "enabled": true, "windowSec": 60, "maxCalls": 30 }
}

⚙️ Settings

Select each agent's model. Toggle crons. Inspect provider connectivity.

🔐 Security

Audit: exposed secrets in config files, file permissions, encryption status.


REST API

All endpoints are local, no auth needed (bind to loopback by default).

MethodPathPurpose
GET/api/dashboardSpend aggregate for range/filters
GET/api/calls?from&to&provider&agent_id&model&limit&offsetPaginated call log
GET`/api/calls/aggregate?by=providermodel
GET/api/limitsCurrent limits + spend snapshot
POST/api/limitsAtomic write to limits.json
GET/api/cronsList every cron, enabled or not
POST/api/crons/:id/toggle`{enable:true
DELETE/api/crons/:idPermanent delete
GET/api/billing-proxyProxy health + guard snapshot
GET/api/securitySecurity audit

Deep-linkable URLs

Every tab and section has a hash slug. Hover any heading to reveal a 🔗 icon — click to copy a shareable URL.

#spend
#calls              #calls/filters
#crons
#limits             #limits/caps       #limits/loop        #limits/rates
#settings
#security

Kill-switch codes

When the proxy blocks a request it returns HTTP 429 with a structured payload. Useful for debugging and alerting:

CodeTrigger
pausedEmergency switch is ON
global_daily_cap · global_weekly_cap · global_monthly_capGlobal USD cap reached
agent_daily_cap · model_daily_cap · provider_daily_capPer-dimension USD cap
loop_detectedSession fired too many calls too fast
provider_rpm_cap · provider_rph_cap · provider_rpd_capRate-limit for zero-cost provider
provider_tpd_cap · agent_id_tpd_cap · model_tpd_capToken-budget cap

How costs are computed

  • Pricing table comes from noosphere (@mariozechner/pi-ai generated catalog, ~45 models) plus a small fallback table.
  • For subscription calls (e.g. Claude Max) the proxy still prices at API rates, so the dashboard shows the economic value consumed even though nothing is charged.
  • Google uses the double-counting-safe formula: uncached = input − cacheRead.
  • Ollama / local inference is always priced at $0. Those providers are protected by rate limits instead.

Hooks (optional, for auto-launch)

Copy the 3 hook handlers into your OpenClaw hooks directory to automate startup and spend enforcement:

mkdir -p ~/.openclaw/hooks/{observability,spend-guard,model-guard}
cp node_modules/openclaw-observability/hooks/observability/handler.ts ~/.openclaw/hooks/observability/
cp node_modules/openclaw-observability/hooks/spend-guard/handler.ts   ~/.openclaw/hooks/spend-guard/
cp node_modules/openclaw-observability/hooks/model-guard/handler.ts   ~/.openclaw/hooks/model-guard/
HookTriggerEffect
observabilityGateway startupLaunches the dashboard server
spend-guardBefore each agent turnRejects the call if caps are breached
model-guardBefore each agent turnPrevents drift to more expensive models

Security notes

  • The proxy binds to loopback (127.0.0.1) by default. Do not expose it publicly — it relays OAuth tokens.
  • ~/.claude/.credentials.json is read in-memory; never logged or echoed.
  • limits.json and calls.db live inside ~/.openclaw/observability/. The repo .gitignore excludes every user-specific directory.
  • Run git log -p against this repo to verify: zero secrets committed.

Development

git clone https://github.com/<your-org>/openclaw-observability
cd openclaw-observability
npm install
node bin/cli.mjs

Source layout:

src/
├── server.mjs           # Dashboard HTTP + REST API
├── billing-proxy.mjs    # Anthropic proxy (OAuth rewriting)
├── multi-provider.mjs   # Generic router for OpenAI/Google/Ollama/etc
├── usage-parser.mjs     # Per-provider token extractor
├── logger.mjs           # SQLite call log (better-sqlite3, JSONL fallback)
├── guards.mjs           # Kill-switch evaluator (caps + rate + loop detector)
├── pricing.mjs          # noosphere-backed cost calculator
└── dashboard.html       # Single-file SPA, Tailwind + vanilla JS

License

MIT

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Declared dependencies 2

Native requirements
2 direct targetsNot calculated transitive count
Package / targetRequirementRelationship
noosphere
Environment
{
  "local_name": "noosphere",
  "alias": false,
  "peer_metadata": null
}
*runtime
better-sqlite3
Environment
{
  "local_name": "better-sqlite3",
  "alias": false,
  "peer_metadata": null
}
^11.10.0runtime

Distribution files

1 collected
Distribution 1

Source distribution

Source file
Checksums from source
{
  "shasum": "15e6b9d8d95d7727aa536b1f0e7778b6e9033706",
  "tarball": "https://registry.npmjs.org/0xai-openclaw-guardian/-/0xai-openclaw-guardian-2.0.0-alpha.0.tgz",
  "fileCount": 15,
  "integrity": "sha512-HeibV6Bh54FUFDgCMUGH6zf0ywni5faq4GrG82nNMagETuErc/HforY3SyPEI+MKJLkIEF9Z3Th6dORxR4bvDQ==",
  "signatures": [
    {
      "sig": "MEYCIQCXRYFwAXPtafKlN7WeUEUbRU5fLpRT5jqEsSYqtQDRDQIhAMhefoRuFbwF0CO1Xwx4SOPURFjJeYvjGewnQ6RsjC7h",
      "keyid": "SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"
    }
  ],
  "unpackedSize": 240453
}

Repository

PENDING
0xai-builders/0xai-openclaw-guardian

Shared repository data · GitHub

License detected in repository
Not collected

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 17:49 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package_version:a63b01e3a27c1f6224e2041d21998c8e744dd0baceebd2c3a0839cfaea09ed0e

Other collected versions

2.0.0-alpha.216 Apr2.0.0-alpha.116 AprView all collected versions →