API Reference
This is the complete API reference for the nebo package.
Module: nebo
The top-level module provides all the public functions you need. Import it as:
import nebo as nb
Decorators
- nb.fn(func=None, depends_on=None, ui=None)
Register a function or class for observability. When applied to a function, it sets up scope tracking — the node materializes (becomes visible in the DAG) as soon as the decorated function is executed, regardless of whether it calls a log function. When applied to a class, all methods are wrapped with scope tracking and the class becomes a visual grouping container in the DAG.
- Parameters:
func – The function or class to decorate (when used without parentheses).
depends_on – Optional list of decorated functions or node ID strings that this node depends on.
ui – Optional dict of per-node UI display hints (e.g.,
{"color": "#34d399", "default_tab": "metrics"}).
- Returns:
The decorated function or class (unchanged behavior, with observability added).
Usage forms:
@nb.fn # bare decorator @nb.fn() # with empty parentheses @nb.fn(depends_on=[setup]) # with explicit dependencies @nb.fn(ui={"color": "#34d399"}) # with per-node UI hintsOn functions: The node ID is derived from the function’s
__qualname__. The function’s docstring becomes the node’s description. The node materializes (becomes visible) on the first call to the decorated function, so even silent functions that never log appear in the DAG and act as real links in dependency chains.On classes: All methods are wrapped. The class itself is never a node — it is a transparent bounding box in the DAG. Every method that runs materializes as a node inside that bounding box, including methods that never call a log function.
Logging Functions
- nb.log(message: str | Any, *, name: str = 'text', step: int | None = None) None
Log a text message to the current node as a named stream. Tensor-like objects (NumPy arrays, PyTorch tensors) are auto-formatted with shape, dtype, and statistics.
- Parameters:
message – The message string or tensor-like object.
name – Stream name for this log entry. Defaults to
"text". Multiple names create distinct streams that appear separately in the Tracker tree.step – Optional step counter.
- nb.log_line(name, value, *, step=None, tags=None)
Log a scalar line-chart datapoint. Line accumulates — repeated calls with the same name append another point to the series.
stepauto-increments per(loggable, name)when omitted.- Parameters:
name – Metric name.
value – A scalar
int | float(NumPy/PyTorch scalars are accepted).step – Optional step counter.
tags – List of strings attached to this emission for UI filtering.
- nb.log_bar(name, value)
Log a bar-chart snapshot.
valueis a dict{label: number}. Repeated calls with the same name overwrite the prior value.
- nb.log_pie(name, value)
Log a pie-chart snapshot.
valueis a dict{label: number}. Repeated calls with the same name overwrite the prior value.
- nb.log_scatter(name, value, *, step=None, tags=None, colors=False)
Log a labeled scatter emission.
valueis a dict{label: list[(x, y)]}— every label becomes its own series on the same chart and is toggleable via the UI chip row. Scatter accumulates: repeated calls with the same name append more points to the same plot.stepauto-increments per(loggable, name)when omitted, so each emission can be correlated to a moment in the run (e.g. clicking a point in the UI filters logs/images/audio to that step).- Parameters:
step – Optional step counter for this emission.
tags – List of strings attached to this emission for UI filtering.
colors – When
True, distinguish labels by palette color (in addition to the per-label shape). DefaultFalse(every label uses the run color, distinguished by shape only). Not recommended in comparison views where color is reserved for run identity.
- nb.log_histogram(name, value, *, colors=False)
Log a labeled histogram snapshot.
valueis a dict{label: list[number]}— every label is a distribution; the UI bins all labels against a shared range so overlapping distributions line up. Repeated calls with the same name overwrite the prior value. To log a single histogram, wrap in a single-key dict, e.g.{"all": samples}.- Parameters:
colors – When
True, give each label a distinct palette color so overlapping distributions can be picked apart. DefaultFalse(every label uses the run color; the overlap reads as a single mass via alpha compositing). Not recommended in comparison views where color is reserved for run identity.
The chart type locks on first emission per (loggable, name) pair —
mixing log_line and log_bar for the same metric name raises
ValueError.
Steps and tags apply to the accumulating helpers (log_line and
log_scatter) only. The snapshot helpers ignore them; passing
step= or tags= to log_bar / log_pie / log_histogram
is a TypeError.
Clicking any point on a line or scatter chart in the web UI sets a
global step filter: the Tracker (bottom panel) switches to step mode,
the clicked step is highlighted on every line/scatter chart (vertical
guideline + value bubble for line, dimmed non-matching points for
scatter), and the per-node logs/images/audio panels filter to entries
whose step matches. Use the Tracker’s Clear all filters button to
clear the step filter (the Reset zoom button only resets the timeline
zoom). You can also step through with the prev/next arrows or
Ctrl/⌘+Left/Right.
Example:
nb.log_line("loss", 0.5)
nb.log_bar("counts", {"cat": 3, "dog": 5})
# Accumulating scatter — call once per emission; step auto-advances.
for x, y in points:
nb.log_scatter("embed_2d", {"inliers": [(x, y)]})
nb.log_histogram(
"latencies",
{"p50": [...], "p95": [...], "p99": [...]},
colors=True,
)
nb.log_line("lr", 3e-4, tags=["main"])
- nb.log_image(image, *, name=None, step=None, points=None, boxes=None, circles=None, polygons=None, bitmasks=None)
Log an image with optional geometric labels overlaid.
- Parameters:
image – PIL.Image, numpy ndarray, or torch.Tensor.
name – Display label for the image.
step – Optional step counter.
points –
nb.labels.Pointsinstance or list of them.boxes –
nb.labels.Boxesinstance or list of them (xyxy format).circles –
nb.labels.Circlesinstance or list of them.polygons –
nb.labels.Polygonsinstance or list of them.Polygonstakes an extrafill: bool = Trueflag — setfill=Falseto stroke the outline only.bitmasks –
nb.labels.Bitmasksinstance or list of them.
Each label dataclass pairs the raw geometry (list / ndarray / tensor) with a color string (“#hex” or any CSS color name). Pass a list to draw multiple groups of the same kind in different colors —
boxes=[Boxes(preds, color="#22d3ee"), Boxes(gt, color="#22c55e")]. Raw lists / tensors are rejected with aTypeErrorpointing at the matchingnb.labels.*class.Tensors and ndarrays are normalized to plain Python lists; bitmasks are PNG-encoded and transmitted inline. The UI’s Settings pane > “Image labels” section exposes per-(loggable, image, key) visibility and opacity controls.
Example:
nb.log_image( img, name="pred", boxes=nb.labels.Boxes([[10, 10, 50, 50]], color="#22d3ee"), points=nb.labels.Points([[30, 30]], color="red"), )
- nb.log_audio(audio: Any, sr: int = 16000, *, name: str | None = None, step: int | None = None) None
Log audio data.
- Parameters:
audio – Audio data as a NumPy array.
sr – Sample rate (default: 16000).
name – Optional audio clip name.
step – Optional step counter.
- nb.log_cfg(cfg: dict[str, Any]) None
Log configuration for the current node. Merges cfg into the node’s
paramsdict so the Info tab displays all configuration in one place.- Parameters:
cfg – A flat or nested dictionary of configuration values. Only JSON-serializable values are retained.
Multiple calls within the same node merge dictionaries (later calls win on key conflicts).
Progress Tracking
- nb.track(iterable: Iterable[T], name: str | None = None, total: int | None = None) TrackedIterable[T]
Wrap an iterable for tqdm-like progress tracking. The progress is reported to the terminal dashboard, daemon, and web UI.
- Parameters:
iterable – The iterable to wrap.
name – Display name for the progress bar.
total – Total number of items. Auto-detected from
__len__if available.
- Returns:
A
TrackedIterablethat yields items and reports progress.
Workflow Description
UI Configuration
- nb.ui(layout: str | None = None, view: str | None = None, minimap: bool | None = None, theme: str | None = None) None
Set run-level UI defaults. These are sent to the daemon and web UI as defaults that the user can override.
- Parameters:
layout – DAG layout direction:
"horizontal"or"vertical".view – Default view mode:
"dag"or"flat".minimap – Whether to show the minimap.
theme – Color theme:
"dark"or"light".
Calling
nb.ui()again overwrites the previous defaults.
Initialization
- nb.init(uri: str | None = None, *, dag_strategy: str = 'object', flush_interval: float = 0.1, api_token: str | None = None, webhook_url: str | None = None, webhook_min_level: int | None = None) None
Explicitly initialize nebo.
- Parameters:
uri –
Destination for events. Selects the transport by shape:
Noneor a path-like string (default:".nebo/") — file mode. The SDK writes<uri>/<timestamp>_<run_id>.nebodirectly viaFileTransport. No daemon required.An HTTP URL (
"http://localhost:7861","https://my-space.hf.space") or bare"host:port"— network mode. Events are POSTed to the daemon viaNetworkTransport.
Overridable via the
NEBO_URIenvironment variable.dag_strategy – How DAG edges are inferred:
"object"(default),"stack","both","linear", or"none"."linear"chains nodes in first-execution order.flush_interval – Seconds between event flushes (default: 0.1).
api_token – Token for daemons that require auth (network mode only). Sent as the
X-Nebo-Tokenheader. Defaults to env varNEBO_API_TOKEN.webhook_url – Slack-compatible webhook URL for
nb.alert().webhook_min_level – Minimum
AlertLevelthat fires the webhook.
Note
You rarely need to call
init()explicitly. The SDK auto-initializes on the first@fnexecution ornb.log*call. SetNEBO_URIandNEBO_API_TOKENin the environment so the same code works in file mode locally and against a remote daemon without a change.
Notebook Embedding
- nb.show(*, run=None, node=None, metric=None, image=None, audio=None, logs=False, dag=False, width='100%', height=600)
Return a Jupyter-renderable iframe of the daemon UI scoped to one slice of a run. The slice is determined by which kwargs are set — pass nothing to embed the full run dashboard. At most one slice kwarg may be set; passing more than one raises
ValueError.- Parameters:
run – Run ID to embed. Defaults to the active run.
node – Node ID or function name. With no slice kwarg, shows the node detail; combined with a slice it filters that slice.
metric –
strshows a single metric by name;Trueshows the metrics gallery (filtered bynodeif set).image – Same shape as
metricfor images.audio – Same shape as
metricfor audio recordings.logs –
Trueshows the logs panel (filtered bynodeif set).dag –
Trueshows the DAG-only view.height (width,) – iframe dimensions. Strings (
"100%") or ints (px).
- Returns:
A handle whose
_repr_html_emits the<iframe>.
Example:
nb.show(metric="loss") # one metric chart nb.show(node="train", metric=True) # gallery of train's metrics nb.show(image="hero.png") # one image nb.show(logs=True, node="train") # logs panel filtered to train
Iframe URL scheme
The dashboard switches into embedded mode whenever a ?run=… query
param is present. The slice is inferred from the other params — there
is no view= discriminator:
URL |
Renders |
|---|---|
|
Full run dashboard (DAG + timeline) |
|
DAG only |
|
Single node detail |
|
Logs panel |
|
Metrics gallery |
|
Single metric |
|
Image gallery |
|
Single image |
|
Audio gallery |
|
Single audio recording |
Add &node=Y to any of the slice forms to filter to one node.
Append &token=… to authenticate with a token-protected daemon —
the dashboard captures it once, persists it in localStorage, and
strips it from the visible URL.
State Access
CLI Reference: nebo
nebo <command> [options]
Commands
serveStart the persistent daemon server.
$ nebo serve [--host HOST] [--port PORT] [-d] [--no-store] [--store-dir DIR] [--api-token TOKEN] [--read public|private] [--write public|private]--hostHost to bind (default:
localhost).--portPort to bind (default:
7861).-d,--daemonRun in background (daemon mode).
--no-storeDisable
.nebofile storage globally.--store-dir DIRDirectory for
.nebofiles (default:./.nebo). SetsNEBO_STORE_DIR. Useful when hosting on Hugging Face Spaces where the persistent volume mounts at/data.--api-token TOKENRequire this token on API requests. Sets
NEBO_API_TOKEN. See--read/--writefor the modes that activate when the token is set.--read public|privateRead-access mode (default:
public). Only matters when--api-tokenis set.--write public|privateWrite-access mode (default:
private). Only matters when--api-tokenis set.
statusShow daemon status and recent runs.
$ nebo status [--port PORT]stopStop the daemon.
$ nebo stop [--port PORT]logsView logs from runs.
$ nebo logs [--run RUN_ID] [--node NODE] [--limit N] [--port PORT]errorsView errors from runs.
$ nebo errors [--run RUN_ID] [--port PORT]loadLoad a
.nebofile into the daemon for viewing and Q&A. With--url(orNEBO_URLenv), the file is read locally and its events are replayed to the remote daemon — useful when the daemon is on a Hugging Face Space and can’t see the user’s filesystem.$ nebo load <file> [--port PORT] $ nebo load <file> --url URL [--api-token TOKEN]--url URLRemote daemon URL (e.g. an HF Space). Defaults to
NEBO_URL.--api-token TOKENToken for the remote daemon. Defaults to
NEBO_API_TOKEN.
mcpPrint MCP connection config for Claude Code / Claude Desktop.
$ nebo mcpmcp-stdioRun the MCP stdio bridge (used internally).
$ nebo mcp-stdio [--port PORT]deployDeploy the nebo daemon to a Hugging Face Space. Creates (or reuses) a Docker-SDK Space, sets
NEBO_API_TOKENas a Space secret, sets the read/write mode variables, and uploads a Dockerfile and a Spaces-flavored README.Requires the optional
deployextra:$ pip install 'nebo[deploy]'$ nebo deploy --space-id <user>/<space> [--from-source] [--api-token TOKEN] [--hf-token TOKEN] [--private] [--read public|private] [--write public|private]--space-id <user>/<space>Hugging Face Space identifier (required).
--from-sourceBuild a wheel from the current checkout and ship it instead of installing from PyPI. Use this to deploy un-released code.
--api-token TOKENToken clients must send via
X-Nebo-Token/?token=. Random if omitted; printed once after the deploy completes.--hf-token TOKENHugging Face write token. Defaults to the
HF_TOKENenv or a cached login (huggingface-cli login).--privateCreate the Space as HF-private (visible only to your account).
--read public|private(defaultpublic)Read-access mode for the deployed daemon.
--write public|private(defaultprivate)Write-access mode for the deployed daemon.
MCP Tools Reference
The daemon exposes 21 MCP tools split across observation, action, and write categories.
Observation Tools
nebo_get_graphGet the full DAG structure: nodes (with docstrings, execution counts, group membership), edges, and workflow description.
- param run_id:
Optional run ID. Uses the latest run if omitted.
nebo_get_loggable_statusGet detailed status for a specific loggable (node or global): execution count, params, docstring, recent logs, errors, and progress.
- param loggable_id:
The loggable ID (required).
- param run_id:
Optional run ID.
nebo_get_logsGet recent log entries, optionally filtered by loggable and run.
- param loggable_id:
Optional loggable ID filter.
- param run_id:
Optional run ID.
- param limit:
Maximum entries (default: 100).
nebo_get_metricsGet metric time series for a loggable.
- param loggable_id:
The loggable ID (required).
- param name:
Optional specific metric name.
nebo_get_errorsGet all errors with full tracebacks, node context, and parameter values.
- param run_id:
Optional run ID.
nebo_get_descriptionGet the workflow-level description and all node docstrings.
Run & Alert Tools
nebo_get_run_statusGet the summary of a run: timestamps, node/edge counts,
run_config,metric_series_count,latest_step, andmetrics_index({loggable_id: [name, ...]}) so callers can discover available metric names without iterating every loggable card.- param run_id:
The run ID (required).
nebo_get_run_historyList all runs with timestamps, counts, and metric indexes.
nebo_wait_for_alertBlock until an alert at or above
min_levelfires for the run, or the timeout elapses. Alerts come fromnb.alert(...)calls in pipeline code or from alert rules created vianebo_set_alert.- param run_id:
Run ID to monitor (required).
- param timeout:
Max seconds to wait (default: 300).
- param min_level:
Minimum alert level to trigger on (default: 20).
nebo_list_alertsList alert rules (
triggered_by: "cli", with condition and fired history) and code-fired alerts (triggered_by: "code").- param run_id:
Optional run ID to scope the listing.
nebo_set_alertCreate an alert rule on a metric condition — no code changes needed. The rule fires at most once per run.
- param title:
Alert headline (required).
- param condition:
Condition string, e.g.
"train/loss > 5"(ops:> >= < <= == !=) (required).- param text:
Optional body.
- param level:
10/20/30/40 for DEBUG/INFO/WARN/ERROR (default: 20).
- param loggable_id:
Only match the metric on this loggable.
- param run_id:
Only apply to this run (default: all runs).
nebo_delete_alertDelete an alert rule by id.
- param rule_id:
Alert rule id (required).
nebo_load_fileLoad a
.nebolog file into the daemon for viewing.- param filepath:
Absolute path to the
.nebofile (required).
Write Tools
These mirror the SDK’s nb.log_* helpers as MCP tools so an
external agent can push data into a run without owning the SDK
process. Each tool accepts a single entry or a list of entries;
entries are auto-registered as loggables so unknown loggable_id
values aren’t silently dropped.
nebo_log_metricLog one or more metric points. Mirrors
nb.log_line/log_bar/log_pie/log_scatter/log_histogram.- param entries:
Single dict or list. Each:
{run_id?, loggable_id, name, value, type?, step?, tags?}. Defaulttypeis"line".- param run_id:
Default run ID for entries that don’t specify one.
nebo_log_imageLog one or more images. Mirrors
nb.log_image. Each entry supplies eitherurl(fetched server-side, persisted) ordata(already-base64 bytes). Bytes are stored on the daemon so the run survives the source URL going stale.- param entries:
Single dict or list. Each:
{run_id?, loggable_id, name, url? | data?, step?, labels?}.- param run_id:
Default run ID.
nebo_log_audioLog one or more audio recordings. Same shape as
nebo_log_imageplus an optional per-entrysr(sample rate, default 16000).- param entries:
Single dict or list. Each:
{run_id?, loggable_id, name, url? | data?, sr?, step?}.- param run_id:
Default run ID.
nebo_log_textLog one or more text entries. Mirrors
nb.log.loggable_iddefaults to"__global__"when omitted.- param entries:
Single dict or list. Each:
{run_id?, loggable_id?, message, level?, step?}.- param run_id:
Default run ID.
Environment Variables
SDK-side (read by nb.init()):
NEBO_URIDestination for events. A path (file mode, default
".nebo/") or an HTTP URL /host:port(network mode). Overrides theuri=arg.NEBO_RUN_IDThe current run identifier.
NEBO_FLUSH_INTERVALOverride the event flush interval (seconds).
NEBO_QUIETWhen set, suppresses the one-line startup banner.
NEBO_NO_STOREIn file mode, opens no
.nebofile — events are dropped. Used by the test suite. No effect in network mode.NEBO_API_TOKENToken sent on every network-mode request as the
X-Nebo-Tokenheader. Required when the target daemon enforces auth.
Daemon-side (read by nebo serve):
NEBO_LOGDIRDirectory the watcher tails for
.nebofiles written by SDK file-mode runs. Set automatically bynebo serve --logdir.NEBO_SAVE_FILESDirectory the daemon persists network-mode events into. Off by default. Set automatically by
nebo serve --save-files.NEBO_NO_LOCALWhen set, the daemon’s directory watcher is disabled. Set automatically by
nebo serve --no-local.NEBO_DAEMON_PORTUsed internally by the daemon process itself.
Daemon-side (read by nebo serve / the deployed Space):
NEBO_API_TOKENWhen set, gates the API per the read/write modes below. Routes accept the token via
X-Nebo-Tokenheader or?token=…query parameter (the query form is for browser/iframe flows that can’t set custom WebSocket headers)./healthand the static UI bundle stay open in every mode.NEBO_READ_MODEpublic(default) orprivate. Gates GET requests whenNEBO_API_TOKENis set. The WebSocket handshake follows this mode.NEBO_WRITE_MODEpublicorprivate(default). Gates non-GET requests whenNEBO_API_TOKENis set. Inbound WebSocket events follow this mode (unauthed events are silently dropped while the subscription stays open).NEBO_STORE_DIRDirectory the daemon writes
.nebofiles into (default:./.nebo). Set to a persistent path (e.g./dataon Hugging Face Spaces) so runs survive container restarts.
.nebo File Format
Nebo persists runs as append-only binary files using MessagePack.
[Header]
magic: "nebo" (4 bytes)
version: u16 big-endian (currently 1)
metadata_size: u32 big-endian
metadata: msgpack map {run_id, script_path, started_at, nebo_version, args}
[Entry]*
type: u8 (entry type index)
size: u32 big-endian (payload size in bytes)
payload: msgpack map (entry-specific data)
Entry types: log (0), metric (1), image (2), audio (3), node_register (4), edge (5), error (6), ui_config (8), text (9), progress (10), config (11), description (12), node_executed (13), run_start (15), run_completed (16), run_config (18), loggable_register (19). Codes 7, 14, and 17 are reserved (formerly ask, ask_response, pause_state — removed).
Media assets (images, audio) are embedded as raw bytes inside the msgpack payload, avoiding base64 overhead.