# OpenClaw Dashboard: gateway health, cron outcomes, and where the money went

> A single Go binary that answers the six questions you would otherwise assemble from log files, a status command, and a version control history. The interesting parts are the places it refuses to guess: a container status is never read from a host loopback probe, an unpriced model stays visibly unpriced, and a public bind requires an awkward opt-in.

**mudrii/openclaw-dashboard** — A beautiful, zero-dependency command center for OpenClaw AI agents

- Repository: https://github.com/mudrii/openclaw-dashboard
- Stars: 457 · Forks: 80
- Language: Go
- License: MIT
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/mudrii-openclaw-dashboard

## It is an overview layer, and the documentation says it is not a replacement

The scope statement comes early and it is worth reading before the feature list, because the feature list reads like an operations console.

The tool is not trying to replace the command line or the chat interface. It is the at-a-glance overview that tells you whether everything is healthy and where the money and compute went, so you can decide without hunting for data. Nothing in the dashboard changes state.

The problem statement is the best part of the documentation because it is written as a list of questions a person actually asks. Is the gateway running right now. How much has it cost today and which model is responsible. Which scheduled jobs ran, which failed, and when the next one fires. Which sessions are active and how much context they are consuming. Whether the sub-agents are doing useful work or spinning. And what the cost trend has done over the last week.

The stated cause of needing a tool is that the answer previously required digging through log files, running commands, and mentally stitching a picture together from five sources. The design target is a single local page that collects all of it, refreshed automatically, with no login, no cloud, and no external dependencies.

There are fourteen views behind that, from an always-on metrics bar at the top through cost cards, scheduled jobs, active sessions, per-model token usage, sub-agent activity, charts, a log feed, runtime diagnostics, configuration, and an optional natural language query box.

## Runtime state is probed three ways, and a loopback guess is explicitly banned

The system endpoint carries live gateway state, and the description of where it comes from is the part that shows the care taken.

Liveness, readiness, failing dependencies, uptime, the process identifier, and memory are sourced from the CLI's own health and readiness endpoints and from its machine-readable status output, so a native install is probed natively. Container status is handled separately and uses the selected gateway's own health call, and the documentation is emphatic that it never uses a host loopback guess.

That last clause is a bug report in advance. In a container, a loopback probe from inside the container tells you about the container, not about the gateway on the host, so a healthy-looking status would be a lie. Refusing to guess means the field can be empty, and empty is honest.

The same principle appears in three more places. Channel health for migrated runtimes reports account configuration, connection state, and probe state as three separate things, and unknown fields stay unknown rather than being filled with a default. Log collection uses the platform's user journal on older installations and the gateway's own bounded log tail on migrated ones, rather than assuming one shape. And the model catalog is read from the CLI's model list output, so a model released after this binary was built still shows a real name and a real context limit instead of an identifier.

Readiness also surfaces as an alert rather than only as a field: a banner naming the failing dependency, which clears itself on recovery.

## A five-level chain decides which model a session actually used

One line in the feature list is more interesting than the rest of the observability section: there is a five-level resolution chain that ensures every session and every sub-agent shows its real model rather than the default.

That is a specific problem. A default configuration usually names one model, so anything that reports the configured model instead of the model actually used will show every session as identical and every cost breakdown as a single line. On a machine with ten or more models and sub-agents, that is the difference between a useful cost view and a decorative one.

Five levels means the tool has five sources to consult before it gives up, and the model catalog feature explains part of it: a curated set of display names wins, and the live catalog fills in identifiers the curated set does not know. So a known model gets a proper name from the curated list, and an unknown one still gets a name from the running system rather than a raw identifier.

The cost side has a matching discipline. The dashboard labels known subtotals when pricing is incomplete rather than showing a confident total that is wrong, unpriced records stay explicit in the per-model breakdown, and the charts state when pricing is unavailable instead of drawing a flat line. For a tool whose main job is telling you where the money went, a number that silently omits a model is worse than a gap.

Sub-agent activity is read from the gateway's own durable task store rather than inferred from logs, which is why it can be tabbed by day, week, month, and all time with a duration per run.

## The container refuses a public bind unless you opt in, and the opt-in is meant to annoy

The default bind is loopback and the container image is where the reasoning is spelled out in full.

The image header carries two documented ways to run it. One publishes a port and sets an environment variable to opt out of the loopback restriction, which is for running on a local network. The other uses host networking, which preserves the loopback-only design, is Linux only, and passes an explicit bind address and port. And the comment underneath explains the rule: the dashboard rejects a bind to all interfaces unless the opt-in variable is set.

The stated reason is the best sentence in the file. The opt-in is described as intentionally awkward, because containers expose the chat rate limit map's unbounded growth as a denial of service surface on a hostile network.

That is a specific and correct concern. The chat endpoint is rate limited per address, and a rate limit map that never evicts is a memory leak an attacker can aim at deliberately. Putting it on a network is exactly the case where that matters, and making the opt-in a named environment variable rather than a flag means a container started with a casual port mapping does not silently become public.

The build itself is a two-stage image with both stages pinned by digest, cgo disabled, paths trimmed, and the version string injected from a version file at build time so the binary reports what it is. The runtime stage adds a small set of system packages, each with a stated reason.

The install is one command, and the formula does the setup for you:

```bash
brew install mudrii/tap/openclaw-dashboard
```

It installs the binary and seeds a writable runtime directory on first run, so there is no directory to create by hand before the first run.

## Cron rows answer whether output arrived, not just whether the job ran

The scheduled job view is where a dashboard earns its place, because the default question about a cron job is the wrong one.

Each row shows status, the schedule, the last and next run, the duration, and the model that ran it. Two additions are what make the view useful. There is a delivery outcome dot, which answers whether the job actually delivered its output rather than merely executing. And there is a badge for unstable jobs, derived from the count of consecutive errors, so a job that fails and recovers quietly is visible as a pattern rather than as a series of green rows.

An agent platform's scheduled work is usually a prompt sent to a model, and a prompt that runs without error can still deliver nothing useful, or deliver to a channel that is down, or fail on a model that no longer exists. A status column that only reflects process exit would show all of those as success.

The rest of the cost and usage surface follows the same logic. Context consumption is shown per session as a percentage alongside the token count, with type badges for direct, group, scheduled, and sub-agent sessions, so you can tell a human conversation from an automated one when deciding whether a large context number matters.

Charts are described as pure vector markup with a week or month toggle, which matters for a page that is meant to work without any external assets.

## One binary, cgo off, and a separate debug build that keeps its symbols

The build configuration is a good place to read how seriously the project takes the release artefact.

The production build strips debug information to keep the binary small, and the debug build keeps it with a different version suffix, with a comment saying to use it locally when investigating crashes and not to ship it. The same flag set is reused by the container build, the release tooling, and the Nix build, and there is a target that rehearses all four archive formats without publishing or needing signing credentials.

The module declares a language version and pins a toolchain version, so a contributor building from source gets the same compiler the release was made with rather than whatever their machine defaults to.

Two static analysis tools are pinned to exact versions with an explicit reason: the vulnerability scanner has to match the version continuous integration uses so local and remote scans agree, and the static analyser is pinned to a release that understands the current language version's export data. That is a small detail that saves a confusing CI failure, and the comment says so.

The test target is the interesting one. The race detector is enabled explicitly with cgo turned back on, with a comment that this is the one case where the shipped configuration has to be overridden, because race builds need cgo and the shipped binary does not.

There are also two non-Go test targets that run node scripts, one for a frontend regression check and one for a workflow regression check, plus a workflow linter pinned to a version. So the repository tests the workflow definitions and the interface, not only the server.

## Every source file at the root has a test file beside it

The repository root is flat in a way that tells you about the project. The server, the chat handler, the configuration, the OpenClaw integration, the refresh logic, the token refresh, the system service, and the entry point are all root-level Go files, and most have a matching test file sitting next to them with the same base name.

The test names are more informative than the file names. There is a test for the CLI entry point, one for shutdown behaviour, one named as a contract test, one for the release gate, and one for the service command. A contract test and a release gate test in the same directory is a project that has been burned by something at least once.

Alongside the code are the documents a long-running project accumulates: a changelog, an architecture note, a technical note, a benchmark note, a plan, a to-do list, a loop state file, and separate agent instruction files for three assistants. There are also hidden configuration directories for those agents, a contributor guide, a linter configuration, a release tool configuration, a Nix flake, an install script, a container file, and a version file read by the build.

The examples directory holds two configuration files, one minimal and one fully populated, which is the fastest way to see every option the tool has rather than reading the configuration parser.

## Conclusion

This suits someone running several agents on one machine who has stopped being able to tell from logs whether the gateway is up and which job is burning tokens. It is a poor fit if you want to control anything, since the documentation is explicit that it is an overview layer and not a replacement for the command line or the chat interface, and a poor fit if you need remote access without putting a gateway in front of it, because the bind is loopback by design. Before you install, check three things: that the version you are reading about is the one you are running, since the page warns that the working tree has runtime changes that are not a published release and that screenshots may show an older layout; how you will reach it from another machine, because there is no login and the default bind is local; and whether you need a container at all, since the Homebrew formula seeds a writable runtime directory for you. The newest release is v2026.9.7 from 2026-09-07 and the last push was 2026-09-23.

## FAQ

### What is the URL for the OpenClaw dashboard?

It is a local page served by a single Go binary that binds to loopback by default, with no login and no cloud. The documented container invocation passes a bind address and port of 127.0.0.1 and 8080, and the dashboard rejects a bind to all interfaces unless an opt-in environment variable is set.

### How do I install the OpenClaw dashboard?

On macOS and Linux through Homebrew, which installs the binary and seeds a writable runtime directory on first run. There is also a container image built in two stages with both stages pinned by digest, and a production build that strips debug symbols.

### Does the OpenClaw dashboard let me control anything?

No. The documentation says explicitly that it is not trying to replace the OpenClaw CLI or the chat interface, and that it is the at-a-glance overview layer telling you whether everything is healthy and where compute and money are going. The views are read-only.

### How does the OpenClaw dashboard handle costs it cannot price?

It labels known subtotals when pricing is incomplete rather than showing a total that is wrong, keeps unpriced records explicit in the per-model breakdown, and states on the charts when pricing is unavailable. Sub-agent activity is read from the gateway's durable task store so runs can be broken down by period.

## Sources

- [Issues](https://github.com/mudrii/openclaw-dashboard/issues)
- [License: MIT](https://github.com/mudrii/openclaw-dashboard/blob/main/LICENSE)
- [mudrii/openclaw-dashboard on GitHub](https://github.com/mudrii/openclaw-dashboard)
- [README](https://github.com/mudrii/openclaw-dashboard/blob/main/README.md)
- [Releases](https://github.com/mudrii/openclaw-dashboard/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/mudrii-openclaw-dashboard
