BitBake Dashboard (bbdash)
Passive monitor for concurrent BitBake builds: reports which builds are
running across independent project directories — their state, targets,
workers, and tasks — using only /proc and read-only build-directory
artifacts. It never connects to bitbake.sock and never interferes with a
build.
Status: milestones 1–5 done (local CLI, MCP server, remote SSH hosts, web
dashboard, tinfoil recipe inspection); M6 (attach to a live build's event
stream) was researched and concluded not recommended — see
specs/spike-m6-event-stream.md. See specs/ for the
requirements, design, and task plan.
Install
$ uv tool install . # from a checkout
$ bbdash --version
Or run in place during development: uv run bbdash ....
Usage
$ bbdash list # one line per discovered build
$ bbdash status # detailed view of the build enclosing $PWD
$ bbdash status DIR # detailed view of a specific build dir
$ bbdash status DIR --fast # L1 overview only (skip worker/task detail)
$ bbdash watch DIR # live-refreshing view, Ctrl-C to quit
$ bbdash history DIR # past buildstats runs, most recent first
$ bbdash --json list # machine-readable Snapshot JSON (see below)
Global options (before the subcommand): --root PATH (repeatable — build
roots to scan; defaults to ~/.config/bbdash/config.toml, then $PWD),
--json, --no-procfs (skip the /proc scan; artifact-only, deterministic),
--host NAME (repeatable) / --all-hosts (also query configured remote
hosts — list only, see below).
Exit codes: 0 ok, 1 error (e.g. status given an ambiguous directory
containing multiple builds), 2 no builds found — scriptable.
Remote hosts (bbdash --all-hosts list)
Agentless: bbdash ships its collector as a single stdlib-only file and
runs it on each configured host via plain ssh — nothing needs to be
installed there beyond Python 3.10+.
$ bbdash --all-hosts list # local builds + every configured host
$ bbdash --host buildbox list # local + just "buildbox" (repeatable)
A host that fails to respond (unreachable, times out, bad output) is
reported as a warning on stderr and simply left out — it never fails the
command or blocks the other hosts' results. This currently only applies to
list; status/watch/history resolve "which build" from a local
directory, a semantic that doesn't generalize to a remote host without more
design (see specs/design.md).
Config file
~/.config/bbdash/config.toml:
roots = ["/home/you/yocto/builds"]
interval = 2.0 # bbdash watch default refresh, seconds
ssh_timeout = 10.0 # per-host SSH timeout, seconds
[[hosts]]
name = "buildbox" # optional; defaults to `host`
host = "buildbox.internal"
user = "ci" # optional
roots = ["/srv/yocto/builds"]
ssh_opts = ["-p", "2222"] # optional, passed straight to `ssh`
JSON schema (--json)
Every command's --json output is a Snapshot (schema_version: 1,
src/bbdash/collector/model.py):
{
"schema_version": 1,
"host": "hostname",
"collected_at": "2026-07-26T09:49:00+00:00",
"builds": [{
"build_dir": "/…/sample-yocto-sitl/build",
"root": "sample-yocto-sitl",
"host": null, // set only when merged from --host/--all-hosts (M3)
"state": "running", // running|parsing|idle-server|finished|failed|stale-lock|unknown
"state_evidence": ["server-pid-alive", "…"],
"server": {"pid": 292830, "started_at": "…", "cpu_pct": 12.0, "rss_kb": 524288},
"targets": ["mc:machine-a:sample-firmware"],
"config": {"machine": null, "sstate_dir": "/…/.sstate-cache", "dl_dir": "/…", "...": "…"},
"sources": {"procfs": "ok", "cookerdaemon_log": "ok", "buildstats": "absent"},
"progress": {"current": 512, "total": 2041},
"workers": [{"pid": 293001, "cpu_pct": 95.0, "tasks": [{"recipe": "…", "task": "do_compile"}]}],
"recent_tasks": [{"recipe": "…", "task": "…", "outcome": "ok", "duration_s": 12.3}],
"errors": [],
"buildstats_dir": "tmp/buildstats/20260726134405"
}],
"shared": [{"kind": "sstate", "path": "/…/.sstate-cache", "builds": ["…", "…"]}]
}
Fields fed by an optional source (buildstats, console logs, conf vars) are
nullable; sources says why a value is missing (absent = not enabled/not
yet created, unreadable = permission/I-O error) rather than leaving you to
guess whether "null" means "disabled" or "broken". A sources key only
appears once its source was actually consulted at the requested detail level
— list (L1) omits buildstats entirely rather than reporting it absent.
schema_version gates compatibility: additive fields don't bump it, breaking
changes do.
Web dashboard
$ uv sync --extra web # or: pip install bbdash[web]
$ bbdash serve # http://127.0.0.1:8765, Ctrl-C to stop
$ bbdash serve DIR # serve a specific build or root dir instead of cwd
$ bbdash --all-hosts serve # include configured remote hosts too
A single auto-refreshing page (plain HTML/CSS/JS, no build step, no CDN
dependencies — reads fine offline) listing every discovered build; click a
row to drill into its config, live workers, recent tasks, errors, and data
gaps, same detail bbdash status shows. GET /api/snapshot (same query
params as the params above: root, level, host, all_hosts,
no_procfs) serves the identical Snapshot JSON directly, for scripting
against the running dashboard. Binds to 127.0.0.1 by default — this is a
passive local viewer, not meant to be exposed on a network; override with
--bind/--port if you know what you're doing.
Recipe inspection (bbdash inspect)
$ bbdash inspect DIR --recipe busybox
The one command that isn't purely passive: it runs the build's own
bitbake/tinfoil (in a subprocess, cwd=the build dir) to print a recipe's
metadata (file, PV, PR, summary, license) and its DEPENDS/RDEPENDS.
Refuses outright — before touching bitbake at all — if the build shows any
sign of being active: a live process, or even just a bitbake.lock file
that might be stale. Never used by any other command or by polling; it only
runs when you explicitly ask. If bbdash can't find the build's bitbake
checkout automatically (it tries the bitbake-setup convention and the
poky-style poky/bitbake layout), point it there with --bitbake-dir.
MCP server (for LLM clients)
$ uv sync --extra mcp # or: pip install bbdash[mcp]
$ claude mcp add bbdash -- uv run --extra mcp bbdash mcp
Exposes 5 read-only tools over stdio — list_builds, build_status,
list_tasks, build_history, tail_log — each a thin wrapper over the same
collector the CLI uses, every one annotated readOnlyHint=True,
destructiveHint=False. list_builds also takes an optional hosts list
(configured host names, or ["all"]) to merge in remote builds the same way
bbdash --all-hosts list does. See src/bbdash/mcp_server.py for full tool
docstrings (units, enums, and what each field means) and
specs/acceptance-m2.md for a verified example transcript.
Development
$ uv sync
$ uv run pytest
$ uv run ruff check
Spec-driven: specs/tasks.md is the work queue; specs/design.md has the
architecture and the environment facts it's built on; CLAUDE.md documents
the hard rules (non-interference with live builds, stdlib-only collector,
fixture-only tests). scripts/record-fixture.py captures a real build
directory's small artifacts into tests/fixtures/ for scenario tests.
Releasing
The published version comes entirely from the git tag (hatch-vcs,
pyproject.toml's [tool.hatch.version]) — nothing to bump by hand.
$ git tag v0.2.0
$ git push origin v0.2.0
That triggers .github/workflows/publish.yml: run tests → build sdist +
wheel → wait for approval in the pypi GitHub Environment → publish to
PyPI via Trusted Publishing (OIDC, no stored token). Approve the run at
github.com/robwoolley/bbdash/actions once it's waiting. See
specs/publishing.md for the full setup (PyPI Trusted Publisher
configuration, required one-time steps).
Metadata
Release files for bbdash 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| bbdash-0.2.0.tar.gz | 214.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| bbdash-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 264.7 kB
Release files / bbdash-0.2.0.tar.gz
| Download URL | bbdash-0.2.0.tar.gz |
|---|---|
| Size | 214.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ef43c3b8d3299f9c12cb082e09d0dc4c860f27b37c0bb33cc23b5c168d34c4df
|
|
BLAKE2b-256 checksum How to use checksums |
29fcef1886c6773d567e8987ffa8058bc826c5096085c918bca8d543de5fb04c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 28, 2026.
Transparency logRelease files / bbdash-0.2.0-py3-none-any.whl
| Download URL | bbdash-0.2.0-py3-none-any.whl |
|---|---|
| Size | 50.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2f02b0afc829385e1aea04a7e20f82ee790d3e030fb5b9659aaa154590acb246
|
|
BLAKE2b-256 checksum How to use checksums |
b90f25c199ce66ecd37ce43190ffe951c00a2c67478a9e4416751b81483b0a66
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 28, 2026.
Transparency log