{"id":50388922,"url":"https://github.com/adityonugrohoid/openclaw-dashboard","last_synced_at":"2026-06-16T08:00:49.558Z","repository":{"id":359744943,"uuid":"1157031594","full_name":"adityonugrohoid/openclaw-dashboard","owner":"adityonugrohoid","description":"Observability dashboard for OpenClaw AI agent framework: FastAPI backend, Tailwind, and Alpine.js","archived":false,"fork":false,"pushed_at":"2026-05-23T07:56:01.000Z","size":693,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-23T09:33:20.086Z","etag":null,"topics":["ai-agent","alpinejs","dashboard","fastapi","observability","openclaw","python","tailwindcss"],"latest_commit_sha":null,"homepage":null,"language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/adityonugrohoid.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-13T10:48:37.000Z","updated_at":"2026-05-23T07:56:02.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/adityonugrohoid/openclaw-dashboard","commit_stats":null,"previous_names":["adityonugrohoid/openclaw-dashboard"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/adityonugrohoid/openclaw-dashboard","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adityonugrohoid%2Fopenclaw-dashboard","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adityonugrohoid%2Fopenclaw-dashboard/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adityonugrohoid%2Fopenclaw-dashboard/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adityonugrohoid%2Fopenclaw-dashboard/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/adityonugrohoid","download_url":"https://codeload.github.com/adityonugrohoid/openclaw-dashboard/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adityonugrohoid%2Fopenclaw-dashboard/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34396429,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-16T02:00:06.860Z","response_time":126,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agent","alpinejs","dashboard","fastapi","observability","openclaw","python","tailwindcss"],"created_at":"2026-05-30T17:00:24.151Z","updated_at":"2026-06-16T08:00:49.553Z","avatar_url":"https://github.com/adityonugrohoid.png","language":"HTML","funding_links":[],"categories":["Mission Control \u0026 Dashboards"],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n# OpenClaw Dashboard\n\n[![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)\n[![uv](https://img.shields.io/badge/uv-package%20manager-blueviolet)](https://github.com/astral-sh/uv)\n[![FastAPI](https://img.shields.io/badge/FastAPI-0.115+-009688.svg)](https://fastapi.tiangolo.com/)\n[![Tailwind CSS](https://img.shields.io/badge/Tailwind-CDN-38bdf8.svg)](https://tailwindcss.com/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n\n**Observability dashboard for the OpenClaw AI agent framework: FastAPI backend, Tailwind + Alpine.js frontend, no build step**\n\n[Getting Started](#getting-started) | [Usage](#usage) | [API Reference](#api-reference)\n\n\u003c/div\u003e\n\n---\n\n## Table of Contents\n\n- [Features](#features)\n- [Tech Stack](#tech-stack)\n- [Architecture](#architecture)\n- [Demo](#demo)\n- [Getting Started](#getting-started)\n  - [Prerequisites](#prerequisites)\n  - [Installation](#installation)\n  - [Configuration](#configuration)\n- [Usage](#usage)\n- [How It Works](#how-it-works)\n- [API Reference](#api-reference)\n- [Architectural Decisions](#architectural-decisions)\n- [Project Structure](#project-structure)\n- [Security](#security)\n- [License](#license)\n- [Author](#author)\n\n## Features\n\n- **Session Status** - live hero metric cards (model, thinking level, reasoning, active sessions) fed from `openclaw status`\n- **Smart noise filtering** - automatically hides Tailscale, Node Service, Probes, and empty Events sections when irrelevant\n- **Security audit view** - severity-badged findings with fix recommendations from `openclaw security audit`\n- **Configuration viewer** - full `openclaw.json` display with secrets automatically redacted (token/key/auth fields masked)\n- **Memory file browser** - workspace `.md` files, `SOUL.md`, `IDENTITY.md`, and daily logs with inline viewer\n- **Skills grid** - installed OpenClaw skill directories with titles and descriptions parsed from `SKILL.md` frontmatter\n- **System info** - real-time CPU, memory, and disk usage via `psutil` with progress bars\n- **Workspace file tree** - 4-level deep directory tree with per-file size display\n- **Dark glassmorphism UI** - animated mesh background, monochrome icon/value color system, skeleton loading, smooth page transitions\n\n## Tech Stack\n\n| Component | Technology |\n|-----------|------------|\n| Language | Python 3.11+ |\n| Backend | FastAPI 0.115+ + uvicorn |\n| Frontend | Tailwind CSS (CDN) + Alpine.js |\n| System metrics | psutil |\n| Data sources | `openclaw status` CLI, `openclaw security audit` CLI, `~/.openclaw/openclaw.json` |\n| Package manager | uv |\n\n## Architecture\n\n```mermaid\ngraph TD\n    Browser[\"Browser\\n(Alpine.js + Tailwind)\"] --\u003e FastAPI[\"app.py\\n(FastAPI / uvicorn\\n127.0.0.1:8501)\"]\n\n    FastAPI --\u003e Session[\"/api/session\\nparse_ascii_table()\"]\n    FastAPI --\u003e Security[\"/api/security\\nrun_command()\"]\n    FastAPI --\u003e Config[\"/api/config\\nredact_config()\"]\n    FastAPI --\u003e System[\"/api/system\\npsutil\"]\n    FastAPI --\u003e Memory[\"/api/memory\\nworkspace .md files\"]\n    FastAPI --\u003e Skills[\"/api/skills\\nSKILL.md frontmatter\"]\n    FastAPI --\u003e Workspace[\"/api/workspace\\nbuild_file_tree()\"]\n\n    Session --\u003e CLI[\"openclaw CLI\\n(status / security audit)\"]\n    Security --\u003e CLI\n    Config --\u003e ConfigFile[\"~/.openclaw/openclaw.json\"]\n    Memory --\u003e WorkspaceDir[\"~/.openclaw/workspace/\"]\n    Skills --\u003e SkillsDir[\"node_modules/openclaw/skills/\"]\n\n    style Browser fill:#0f3460,color:#fff\n    style FastAPI fill:#533483,color:#fff\n    style Session fill:#16213e,color:#fff\n    style Security fill:#16213e,color:#fff\n    style Config fill:#16213e,color:#fff\n    style System fill:#16213e,color:#fff\n    style Memory fill:#16213e,color:#fff\n    style Skills fill:#16213e,color:#fff\n    style Workspace fill:#16213e,color:#fff\n    style CLI fill:#0f3460,color:#fff\n    style ConfigFile fill:#0f3460,color:#fff\n    style WorkspaceDir fill:#0f3460,color:#fff\n    style SkillsDir fill:#0f3460,color:#fff\n```\n\n## Demo\n\n![Session Status - hero metrics and system overview](screenshots/session-status-top.png)\n\n![Session Status - runtime, maintenance, and active sessions](screenshots/session-status-bottom.png)\n\n![System Information - host metrics with CPU, memory, and disk usage](screenshots/system-info.png)\n\n## Getting Started\n\n### Prerequisites\n\n- Python 3.11+\n- [uv](https://docs.astral.sh/uv/) package manager\n- OpenClaw installed and available as `openclaw` in PATH\n- OpenClaw running (so `openclaw status` returns live data)\n\n### Installation\n\n1. Clone the repository:\n   ```bash\n   git clone https://github.com/adityonugrohoid/openclaw-dashboard.git\n   cd openclaw-dashboard\n   ```\n\n2. Install dependencies with uv:\n   ```bash\n   uv sync\n   ```\n\n3. Run the dashboard:\n   ```bash\n   uv run python app.py\n   ```\n\n   Open `http://localhost:8501` in your browser.\n\n### Configuration\n\nThe dashboard reads from fixed paths by default. If your OpenClaw installation is in a non-standard location, edit the constants at the top of `app.py`:\n\n```python\nOPENCLAW_BIN    = \"/path/to/openclaw\"\nOPENCLAW_CONFIG = \"/path/to/.openclaw/openclaw.json\"\nWORKSPACE_PATH  = \"/path/to/.openclaw/workspace\"\nSKILLS_PATH     = \"/path/to/openclaw/skills\"\n```\n\nNo `.env` file is required. The dashboard does not expose any user-configurable secrets of its own.\n\n## Usage\n\n```bash\n# Start the dashboard (binds to 127.0.0.1:8501)\nuv run python app.py\n```\n\nThe sidebar provides navigation to: Session Status, Configuration, Memory Files, Skills, Workspace, Channels, Security, and System Info.\n\nEach page polls the corresponding `/api/*` endpoint and renders the response live. There is no manual refresh button; use browser reload.\n\n## How It Works\n\n### ASCII table parsing\n\n`openclaw status` outputs box-drawing ASCII tables (Overview, Sessions, Channels). `parse_ascii_table()` locates each table by name, strips `┌ ├ └` separator lines, and zips column headers with cell values to produce a list of dicts. The parsed dicts feed the Session Status hero cards and the active sessions table.\n\n### Noise filtering\n\nThe raw `openclaw status` output includes conditional rows for Tailscale, Node Service, Probes, Events, and Agents that are irrelevant when those features are off. The frontend Alpine.js layer inspects each field and hides rows that match known empty-state strings (`no bootstraps`, `unavailable`, `skipped`), keeping the UI clean.\n\n### Secret redaction\n\n`redact_config()` walks `openclaw.json` recursively. Any key whose name contains `token`, `key`, `secret`, `password`, `auth`, or `api` has its string value truncated to `first4...last4` (or `***` for short values). The redacted object is returned by `/api/config`; the raw file is never served.\n\n### Security audit parsing\n\n`/api/security` runs `openclaw security audit` and walks the output line-by-line looking for `CRITICAL`, `WARN`, and `INFO` severity markers. Each marker triggers collection of the following indented block as finding ID, title, description, and `Fix:` recommendation.\n\n## API Reference\n\nAll endpoints return JSON. No authentication is required (localhost-only binding).\n\n| Method | Endpoint | Description |\n|--------|----------|-------------|\n| `GET` | `/` | Serve `static/index.html` (SPA entry point) |\n| `GET` | `/api/session` | Parsed `openclaw status`: overview, sessions, channels, security summary |\n| `GET` | `/api/config` | Redacted `openclaw.json` organized by section |\n| `GET` | `/api/memory` | Workspace `.md` files and daily log listing with content |\n| `GET` | `/api/skills` | Installed skills with `SKILL.md` frontmatter |\n| `GET` | `/api/workspace` | 4-level file tree of `~/.openclaw/workspace/` |\n| `GET` | `/api/channels` | Channel config from `openclaw.json` with DM scope |\n| `GET` | `/api/security` | Parsed `openclaw security audit` findings with severity counts |\n| `GET` | `/api/system` | CPU percent, memory, disk usage via psutil |\n\n### Example\n\n```bash\ncurl http://localhost:8501/api/session | jq '.config_info'\n```\n\n```json\n{\n  \"model\": \"claude-opus-4-5\",\n  \"thinking\": \"auto\",\n  \"reasoning\": \"On\",\n  \"dm_scope\": \"all\",\n  \"compaction\": \"auto\"\n}\n```\n\n## Architectural Decisions\n\n### 1. Single-file SPA with CDN assets\n\n**Decision:** All backend logic lives in `app.py`. Frontend uses Tailwind CSS from CDN and Alpine.js from CDN, served as a static `index.html`.\n\n**Reasoning:** Eliminates the npm build pipeline entirely. No `node_modules`, no bundler, no compile step. For a localhost-only personal tool, CDN latency is irrelevant and the reduced setup friction matters.\n\n### 2. Localhost-only binding (127.0.0.1)\n\n**Decision:** `uvicorn` is bound to `127.0.0.1:8501`, not `0.0.0.0`.\n\n**Reasoning:** Browser security extensions flag `0.0.0.0` as a potential SSRF surface. Localhost-only binding avoids that and is appropriate for a personal observability tool with no authentication layer.\n\n### 3. CLI invocation over IPC\n\n**Decision:** Session and security data are fetched by shelling out to `openclaw status` and `openclaw security audit` via `subprocess.run`, then parsing ASCII output.\n\n**Reasoning:** OpenClaw does not expose a stable programmatic API. Parsing the CLI output is the only integration point available without forking the framework. A 15-second timeout guards against stalled commands.\n\n### 4. Redact-on-read for config display\n\n**Decision:** Config secrets are redacted in the API layer (`redact_config()`), not in the frontend.\n\n**Reasoning:** Never serving raw secret values to the browser, even on localhost, means accidental browser history or DevTools captures cannot leak credentials.\n\n## Project Structure\n\n```\nopenclaw-dashboard/\n├── app.py                  # FastAPI server: all endpoints + parsing logic\n├── static/\n│   ├── index.html          # SPA entry point (Alpine.js + Tailwind CDN)\n│   └── favicon.ico\n├── screenshots/\n│   ├── session-status-top.png\n│   ├── session-status-bottom.png\n│   └── system-info.png\n├── pyproject.toml          # Project metadata + uv dependencies\n└── uv.lock                 # Locked dependency graph\n```\n\n## Security\n\n- **Secret redaction** - `openclaw.json` keys matching `token`, `key`, `secret`, `password`, `auth`, or `api` are masked before serving. Raw config is never returned.\n- **Localhost-only** - the server binds to `127.0.0.1`. No auth layer is implemented because no external network exposure is intended.\n- **No inbound user input** - all endpoints are read-only `GET` requests; no user-supplied data reaches the filesystem or the CLI.\n\n## License\n\nThis project is licensed under the [MIT License](LICENSE).\n\n## Author\n\n**Adityo Nugroho** ([@adityonugrohoid](https://github.com/adityonugrohoid))\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadityonugrohoid%2Fopenclaw-dashboard","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fadityonugrohoid%2Fopenclaw-dashboard","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadityonugrohoid%2Fopenclaw-dashboard/lists"}