CLI tool
crabwise-ai/crabwalk avatar
crabwise-ai/crabwalk

Crabwalk: a node-graph monitor that reads your agent's own token file

🦀 Crabwalk 🦀 Real-time companion monitor for OpenClaw agents.

874 stars95 forksTypeScriptMIT

At a glance

What is it?
Crabwalk is a real-time visualisation of an OpenClaw agent's sessions, drawn as a node graph of thinking states, tool calls and response chains across four messaging platforms. What the documentation makes plain is its operational posture: the dashboard binds every interface by default, the gateway token is read out of the agent's configuration file, and the documented fix for a loopback-bound gateway is to hand the container host networking.
Who is it for?
Crabwalk fits someone running an agent locally who wants to see what it is actually doing rather than infer it from a transcript, and who is comfortable with a second process reading the agent's configuration. Four things to do before the first run.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 75 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 5, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Every shipped artifact comes from a personal namespace, not the project

The repository lives under a project organisation, but not one download instruction points at it. The skill file for the agent-assisted install is fetched from a raw path under a different account. The CLI install script resolves the latest tag against a third path and downloads the release archive from it. The Docker image is pulled from a registry namespace matching that same third path, and the compose file is downloaded by curling a raw URL under it too. The from-source clone instruction uses it. So the repository you read is not the repository the tooling fetches, which means the two can diverge without it being visible from either side. The author is credited by handle in the introduction, which suggests the third path is the personal namespace the project started from, and that the organisation repository is the distribution point for reading rather than for installing.

The dashboard binds every interface by default while the gateway binds loopback

The option list is short and one default is worth arguing with.

bash
-p, --port <port>      Server port (default: 3000)
-H, --host <host>      Bind address (default: 0.0.0.0)
-g, --gateway <url>    Gateway WebSocket URL (default: ws://127.0.0.1:18789)
-t, --token <token>    Gateway auth token
-d, --daemon           Run in background
-v, --version          Show version

The monitor binds all interfaces while the thing it monitors is loopback-only. That asymmetry means the upstream is protected and the view of it is not. What the view contains is the point: the graph nodes expand to show tool arguments and payloads, so a node-graph dashboard on a shared network is a rendering of everything your agent was told and everything it fetched. There is a coherent reason for the default, because on startup the program displays a QR code for opening the monitor on a phone, which needs a reachable address. That is a legitimate design, but it means the safe invocation passes an explicit host and the QR code is then the mechanism for reaching it deliberately rather than the exposure being incidental.

The token is read out of the agent's own configuration file

Authentication is where this tool reaches into the system it observes. The CLI detects the gateway token automatically from a file in the agent's own configuration directory, and the configuration section states that no manual setup is needed for local setups. The value lives at a specific path inside that file, and the documentation even gives you the command to read it yourself.

bash
jq '.gateway.auth.token' ~/.openclaw/openclaw.json

You can override it in two ways, as a flag or as an environment variable, and the environment variable is what the Docker instructions use. The auto-detection is convenient in the common case where both programs run as the same user on the same machine, and it is worth understanding precisely because the file it opens is the agent's full configuration rather than a dedicated credential store. Nothing in the documentation suggests the token is cached, scoped or redacted once read, so if the monitor is a long-lived background process, its privilege is the privilege of that file.

The documented fix for a loopback gateway is host networking

The container instructions describe the awkward case honestly. When the monitor runs in a container and the gateway runs on the host, the address has to be the host's special hostname for reaching the host from a container. Then there is a harder case. If the gateway is configured to bind to loopback only and exposed on a private network through a serving proxy for secure access, the container cannot reach it at all, because the container's loopback is its own. The recommended fix is to run the container with host networking instead of publishing a port, and the stated reason is that it lets the container reach the loopback address while keeping the benefit of loopback-only binding. That reasoning is sound for the gateway. The side effect is that the container now shares the host's network namespace, so its own listener is also on every host interface, and the port publication that was supposed to scope it is gone.

The workspace mount works because the image sets HOME to root

The workspace explorer reads local files, and by default it looks for them at a path inside the agent's home directory. In a container that path has to be created and mounted at the same location, which the instructions do.

bash
-v ~/.openclaw/workspace:/root/.openclaw/workspace

The reason a tilde in the host path becomes a root-owned path in the container is in the image build. It sets the home directory environment variable to the root user's home, and it creates the workspace directory explicitly with a comment saying the reason is to allow volume mounting. That is a tidy trick, but it depends on the container running as root, because there is no unprivileged user created anywhere in the build file. So the bind mount is read-write into a directory owned by root inside the container, and the process reading your agent's files is root inside its own namespace. It is a display-only read path by design, but it is a read path.

The project has three names and the environment variables kept the oldest

Follow the identifiers across the documentation and the renaming is only partly finished. The product is called Crabwalk. What it monitors is referred to as one thing in the title and links to a repository under a third name, so the monitored agent has two names as well. Every environment variable uses the older of those two, with the API token and the gateway URL both carrying that prefix. The configuration example confirms it, with a comment naming the gateway auth token and an empty value beside it. The description on the repository itself carries the same two names joined by a parenthetical. None of this breaks anything, since the variable names are internally consistent, but it means searching for the current name of the monitored agent will not find the configuration documentation.

The installer parses the GitHub API response with grep and cut

The CLI install path is four lines of shell and one of them is the interesting one.

bash
VERSION=$(curl -s https://api.github.com/repos/luccast/crabwalk/releases/latest | grep '"tag_name"' | cut -d'"' -f4)

The latest version is discovered by calling the releases API unauthenticated and scraping the tag name out of the JSON with a text filter and a field splitter. It works, and it is the sort of thing that breaks the day the API adds a field containing the same key, or returns a rate-limit message instead of a release object, in which case the pipeline silently produces an empty version and the download URL becomes malformed. The remaining three lines create two directories, stream the release archive through a tar extractor into the first, copy the binary into the second, and make it executable. Nothing verifies a checksum or a signature at any point, and the install is a curl piped into a tar extractor.

A nightly server framework, two lockfiles, and three npm scripts

The package manifest has some choices worth naming. The server framework is a nightly build, aliased from its package registry to a dated version string with a commit hash appended, listed among the development dependencies. That is a fast-moving dependency pinned to a specific nightly rather than a released version, and it is the kind of choice that makes a build unreproducible six months later. The component library the interface is drawn with has also been renamed, appearing under its new scoped package name rather than the one the documentation refers to. The dependency list includes an optional native buffer package, which is the standard way to get a WebSocket implementation to use a faster extension when one is available. At the repository root there are two lockfiles for two package managers, plus a workspace file for one of them, while the container build installs with the other. And the script list has three entries: development, build, and start. There is no test script, no lint script and no type check. One more small inconsistency lives in the environment file: the tracked example says in its first comment that you should copy it to a differently named local file before filling in values, so the example is not the file you are meant to end up with and the name it tells you to use appears nowhere else in the repository. Its content is one variable and one comment, which is appropriate for a tool whose only required setting is the gateway token, and the development instructions set that same variable inline before sending you to a specific route on the local server.

Editorial conclusion

Crabwalk fits someone running an agent locally who wants to see what it is actually doing rather than infer it from a transcript, and who is comfortable with a second process reading the agent's configuration. Four things to do before the first run. Pass an explicit bind address so the dashboard is not on every interface, since what it renders includes tool arguments and payload contents. Decide how the container reaches the gateway, because host networking removes the isolation the rest of the compose file is built around. Read the token handling, because auto-detection means the monitor opens a file it was not explicitly pointed at. And note the release gap, since the newest tag is from February while commits have continued through the summer.

Frequently asked questions

How do I install Crabwalk?

Four ways. Paste the skill file URL to your OpenClaw agent and ask it to install or update Crabwalk; use the CLI install block, which resolves the latest release tag and extracts the tarball; run the published container image, which the documentation recommends; or clone the repository, run `npm install`, and start the dev server with the gateway token set inline.

What address and port does Crabwalk listen on?

The server binds 0.0.0.0 on port 3000 by default, changeable with `-p`/`--port` and `-H`/`--host`. The gateway it connects to defaults to the loopback WebSocket address `ws://127.0.0.1:18789`, changeable with `-g`/`--gateway`. Note the asymmetry: the upstream defaults to loopback while the dashboard defaults to every interface.

How does Crabwalk get the OpenClaw gateway token?

Automatically, from the agent's own configuration file at `~/.openclaw/openclaw.json`, reading the value at `gateway.auth.token`. You can read it yourself with `jq '.gateway.auth.token' ~/.openclaw/openclaw.json`, or supply it explicitly with `-t` or by exporting `CLAWDBOT_API_TOKEN`, which is what the container instructions use.

How do I reach a loopback-bound OpenClaw gateway from the Crabwalk container?

If the gateway is bound to loopback and exposed privately through a serving proxy, the container cannot reach it and must run with host networking instead. For `docker run`, replace the port publication with `--network host`. For compose, edit the file to add `network_mode: host`. That keeps the gateway loopback-only but also puts the container on the host's network interface.

How do I give the Crabwalk container access to my workspace files?

The workspace explorer looks at `~/.openclaw/workspace` by default, so bind-mount the host workspace to `/root/.openclaw/workspace` inside the container. With `docker run` pass the volume flag directly. With the compose file, set `WORKSPACE_HOST_PATH` to the host path and the default mounts from there.

Official sources

  1. crabwise-ai/crabwalk on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/crabwise-ai-crabwalk.svg)](https://hysenlabs.com/projects/crabwise-ai-crabwalk)