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 hints

On 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. step auto-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. value is a dict {label: number}. Repeated calls with the same name overwrite the prior value.

nb.log_pie(name, value)

Log a pie-chart snapshot. value is 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. value is 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. step auto-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). Default False (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. value is 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. Default False (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.

  • pointsnb.labels.Points instance or list of them.

  • boxesnb.labels.Boxes instance or list of them (xyxy format).

  • circlesnb.labels.Circles instance or list of them.

  • polygonsnb.labels.Polygons instance or list of them. Polygons takes an extra fill: bool = True flag — set fill=False to stroke the outline only.

  • bitmasksnb.labels.Bitmasks instance 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 a TypeError pointing at the matching nb.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 params dict 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 TrackedIterable that yields items and reports progress.

Workflow Description

nb.md(description: str) None

Set or append to the workflow-level Markdown description. Distinct from node docstrings — this describes the overall workflow.

Parameters:

description – Markdown description text.

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:

    • None or a path-like string (default: ".nebo/") — file mode. The SDK writes <uri>/<timestamp>_<run_id>.nebo directly via FileTransport. 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 via NetworkTransport.

    Overridable via the NEBO_URI environment 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-Token header. Defaults to env var NEBO_API_TOKEN.

  • webhook_url – Slack-compatible webhook URL for nb.alert().

  • webhook_min_level – Minimum AlertLevel that fires the webhook.

Note

You rarely need to call init() explicitly. The SDK auto-initializes on the first @fn execution or nb.log* call. Set NEBO_URI and NEBO_API_TOKEN in 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.

  • metricstr shows a single metric by name; True shows the metrics gallery (filtered by node if set).

  • image – Same shape as metric for images.

  • audio – Same shape as metric for audio recordings.

  • logsTrue shows the logs panel (filtered by node if set).

  • dagTrue shows 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

?run=X

Full run dashboard (DAG + timeline)

?run=X&dag

DAG only

?run=X&node=Y

Single node detail

?run=X&logs

Logs panel

?run=X&metrics

Metrics gallery

?run=X&metric=loss

Single metric

?run=X&images

Image gallery

?run=X&image=hero.png

Single image

?run=X&audios

Audio gallery

?run=X&audio=bell.wav

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

nb.get_state() SessionState

Get the global session state singleton. Advanced usage — most users won’t need this.

Returns:

The SessionState instance containing all nodes, edges, and configuration.

CLI Reference: nebo

nebo <command> [options]

Commands

serve

Start 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]
--host

Host to bind (default: localhost).

--port

Port to bind (default: 7861).

-d, --daemon

Run in background (daemon mode).

--no-store

Disable .nebo file storage globally.

--store-dir DIR

Directory for .nebo files (default: ./.nebo). Sets NEBO_STORE_DIR. Useful when hosting on Hugging Face Spaces where the persistent volume mounts at /data.

--api-token TOKEN

Require this token on API requests. Sets NEBO_API_TOKEN. See --read / --write for the modes that activate when the token is set.

--read public|private

Read-access mode (default: public). Only matters when --api-token is set.

--write public|private

Write-access mode (default: private). Only matters when --api-token is set.

status

Show daemon status and recent runs.

$ nebo status [--port PORT]
stop

Stop the daemon.

$ nebo stop [--port PORT]
logs

View logs from runs.

$ nebo logs [--run RUN_ID] [--node NODE] [--limit N] [--port PORT]
errors

View errors from runs.

$ nebo errors [--run RUN_ID] [--port PORT]
load

Load a .nebo file into the daemon for viewing and Q&A. With --url (or NEBO_URL env), 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 URL

Remote daemon URL (e.g. an HF Space). Defaults to NEBO_URL.

--api-token TOKEN

Token for the remote daemon. Defaults to NEBO_API_TOKEN.

mcp

Print MCP connection config for Claude Code / Claude Desktop.

$ nebo mcp
mcp-stdio

Run the MCP stdio bridge (used internally).

$ nebo mcp-stdio [--port PORT]
deploy

Deploy the nebo daemon to a Hugging Face Space. Creates (or reuses) a Docker-SDK Space, sets NEBO_API_TOKEN as a Space secret, sets the read/write mode variables, and uploads a Dockerfile and a Spaces-flavored README.

Requires the optional deploy extra:

$ 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-source

Build a wheel from the current checkout and ship it instead of installing from PyPI. Use this to deploy un-released code.

--api-token TOKEN

Token clients must send via X-Nebo-Token / ?token=. Random if omitted; printed once after the deploy completes.

--hf-token TOKEN

Hugging Face write token. Defaults to the HF_TOKEN env or a cached login (huggingface-cli login).

--private

Create the Space as HF-private (visible only to your account).

--read public|private (default public)

Read-access mode for the deployed daemon.

--write public|private (default private)

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_graph

Get 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_status

Get 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_logs

Get 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_metrics

Get metric time series for a loggable.

param loggable_id:

The loggable ID (required).

param name:

Optional specific metric name.

nebo_get_errors

Get all errors with full tracebacks, node context, and parameter values.

param run_id:

Optional run ID.

nebo_get_description

Get the workflow-level description and all node docstrings.

Run & Alert Tools

nebo_get_run_status

Get the summary of a run: timestamps, node/edge counts, run_config, metric_series_count, latest_step, and metrics_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_history

List all runs with timestamps, counts, and metric indexes.

nebo_wait_for_alert

Block until an alert at or above min_level fires for the run, or the timeout elapses. Alerts come from nb.alert(...) calls in pipeline code or from alert rules created via nebo_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_alerts

List 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_alert

Create 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_alert

Delete an alert rule by id.

param rule_id:

Alert rule id (required).

nebo_load_file

Load a .nebo log file into the daemon for viewing.

param filepath:

Absolute path to the .nebo file (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_metric

Log 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?}. Default type is "line".

param run_id:

Default run ID for entries that don’t specify one.

nebo_log_image

Log one or more images. Mirrors nb.log_image. Each entry supplies either url (fetched server-side, persisted) or data (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_audio

Log one or more audio recordings. Same shape as nebo_log_image plus an optional per-entry sr (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_text

Log one or more text entries. Mirrors nb.log. loggable_id defaults 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_URI

Destination for events. A path (file mode, default ".nebo/") or an HTTP URL / host:port (network mode). Overrides the uri= arg.

NEBO_RUN_ID

The current run identifier.

NEBO_FLUSH_INTERVAL

Override the event flush interval (seconds).

NEBO_QUIET

When set, suppresses the one-line startup banner.

NEBO_NO_STORE

In file mode, opens no .nebo file — events are dropped. Used by the test suite. No effect in network mode.

NEBO_API_TOKEN

Token sent on every network-mode request as the X-Nebo-Token header. Required when the target daemon enforces auth.

Daemon-side (read by nebo serve):

NEBO_LOGDIR

Directory the watcher tails for .nebo files written by SDK file-mode runs. Set automatically by nebo serve --logdir.

NEBO_SAVE_FILES

Directory the daemon persists network-mode events into. Off by default. Set automatically by nebo serve --save-files.

NEBO_NO_LOCAL

When set, the daemon’s directory watcher is disabled. Set automatically by nebo serve --no-local.

NEBO_DAEMON_PORT

Used internally by the daemon process itself.

Daemon-side (read by nebo serve / the deployed Space):

NEBO_API_TOKEN

When set, gates the API per the read/write modes below. Routes accept the token via X-Nebo-Token header or ?token=… query parameter (the query form is for browser/iframe flows that can’t set custom WebSocket headers). /health and the static UI bundle stay open in every mode.

NEBO_READ_MODE

public (default) or private. Gates GET requests when NEBO_API_TOKEN is set. The WebSocket handshake follows this mode.

NEBO_WRITE_MODE

public or private (default). Gates non-GET requests when NEBO_API_TOKEN is set. Inbound WebSocket events follow this mode (unauthed events are silently dropped while the subscription stays open).

NEBO_STORE_DIR

Directory the daemon writes .nebo files into (default: ./.nebo). Set to a persistent path (e.g. /data on 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.