Skip to content

v0.4.0

Choose a tag to compare

@github-actions github-actions released this 20 Jun 04:00
· 65 commits to master since this release

Documentation

  • Docs overhauled to the project standard. Restructured the README (a "vs the
    NetBox web UI / raw API" comparison table, a complete keybindings table, a
    troubleshooting section, a full documentation index) and added
    docs/COMPARISON.md, docs/SCRIPTING.md, and docs/TROUBLESHOOTING.md.
    Documented the in-memory read cache ([cache]) and the nbox_cache_clear MCP
    tool. Corrected the MSRV (1.88), the MCP tool count (nine), the searchable-kind
    lists (racks, VRFs, route targets), and the GraphQL/REST split (search is always
    REST; GraphQL backs the VRF view only) across every doc. Expanded SECURITY.md
    (the nbox serve network surface, supported-versions) and CONTRIBUTING.md
    (module map, an "adding a feature" recipe), and added GitHub issue/PR templates.

Changed

  • BREAKING: per-surface API backends replace the coarse backend key. The
    profile-level backend = "rest"|"graphql" setting is removed; a config that
    still sets it is rejected with a pointer to the new shape. Configure the backend
    per read surface under [profiles.<name>.api] instead:
    [profiles.work.api]
    vrf = "graphql"   # rest | graphql
    A missing table/key means REST; unknown surfaces (e.g. detail) and invalid
    values are config errors. REST stays canonical; a graphql surface is honored
    only when the live schema probe supports it, otherwise it falls back to REST.
    nbox status (CLI + MCP) drops the single backend field for a per-surface
    api block (configured/effective/reason), and capabilities.graphql is
    now surface-aware (surfaces.{search,vrf}.{supported,recommended,missing}).
  • Search is always REST. NetBox's GraphQL API has no equivalent to REST's
    full-text q quick-search (filtering moved to per-field Strawberry lookups in
    4.3), so GraphQL can't reproduce canonical NetBox search. nbox search now
    always runs over REST; a search = "graphql" preference is accepted but
    transparently falls back to REST, with the reason in nbox status. The VRF view
    is currently the only GraphQL-capable surface. (The per-kind GraphQL search
    fan-out — which silently returned unfiltered results on 4.3+ — was removed.)

Fixed

  • Search no longer randomly times out one endpoint. NetBox is commonly served
    by gunicorn sync workers, which close the connection after each response;
    reqwest could reuse such a half-closed keep-alive connection from its pool and
    hang that request to the full timeout, so nbox search's ~17-way fan-out would
    intermittently report one endpoint as failed (operation timed out) even though
    the server was healthy. nbox now disables idle-connection reuse (a fresh
    connection per request, like curl) and sets a 10s connect timeout.

Performance

  • VRF detail (REST) fetches its prefixes and addresses concurrently via
    tokio::try_join! instead of sequentially, roughly halving the REST VRF view's
    latency on a high-RTT link.

Added

  • Live-browse the Nav rail. Moving the Nav-rail cursor with j/k (or
    g/G) now auto-browses the highlighted kind into the results pane — no Enter
    needed — so scrolling the rail previews each kind's list (and its first item)
    beside it. It's debounced until the cursor settles, so a fast scroll doesn't
    flash the list of every section it passes; focus stays on the rail, and Enter
    still commits and jumps into the results. The footer reflects the rail's
    controls when it's focused (j/k browse · Enter results).
  • TUI remembers the last-browsed kind. The Nav rail's browsed kind is
    persisted to [ui].last_browsed on exit and restored on the next launch — the
    cursor lands on it and its list preloads (focus stays on the Nav rail). First
    run (nothing remembered) still opens on Recent. Also: a Route Targets Nav
    section, right-aligned Nav counts, and a count on the Recent row.
  • Route targets are now a first-class object. A route target (BGP extended
    community, e.g. 65000:100) can be looked up (nbox route-target <name|id>),
    found in search, opened (nbox open route-target/<ref>), journalled, and
    fetched over MCP (nbox_get route_target / nbox://route-target/<ref>). Its
    detail is the relation graph — the VRFs that import and export it — built by
    resolving both directions over REST concurrently; each VRF row is navigable.
    The VRF view's targets tab is now navigable: import/export route targets
    are structured {id, name} (so vrf --json gains the id) and Enter opens the
    route target's detail, like the prefix/address sections.
  • VRF GraphQL bundle. With [profiles.<name>.api] vrf = "graphql", the VRF
    view fetches its prefixes + addresses in a single GraphQL query (the VRF
    identity is still resolved over REST, preserving not-found/ambiguous exit codes).
    REST and GraphQL produce a byte-identical VrfDetail. nbox vrf now prints the
    full routing context (summary + prefix tree + addresses), and MCP nbox_get vrf
    returns the same bundle.
  • VRFs are now a first-class object. A VRF can be looked up (nbox vrf <name|rd|id>),
    found in search (nbox search / TUI / / MCP nbox_search, REST and GraphQL —
    subtitle = its RD, falling back to the tenant), browsed from the TUI Nav rail
    (a VRFs section with a live count), opened from the palette (vrf <ref>),
    resolved by nbox open vrf/<ref>, journalled (nbox journal vrf/<ref>), and
    fetched over MCP (nbox_get / nbox://vrf/<ref>). The VRF view normalizes RD,
    tenant, enforce-unique, import/export route targets, and the prefix/address
    counts. In the TUI the detail opens as a routing context: a fixed header card
    (RD · tenant · route-target counts · enforce-unique) over the VRF's prefix tree,
    with addresses and targets tabs. The prefix and address rows are navigable —
    j/k move a cursor and Enter opens that prefix/IP (b/Esc returns), the
    same drill the related-objects (R) jump performs. Previously VRF was only a
    search filter (--vrf) and an exact-by-RD lookup, never a navigable object.
  • Navigable detail sections. Detail tabs can now be interactive lists (a row
    cursor with Enter to open), not just scrollable text — the foundation the VRF
    view's prefix tree and address list are built on. Sections without navigable rows
    scroll exactly as before.
  • Three-pane home (Navigation rail). The home screen is now Nav │ Results │
    Detail. The left Nav rail browses by kind — Devices / Prefixes / IPs / VLANs /
    Sites / Racks — each with a domain-colored bullet and a live object count,
    plus a Recent entry. Enter lists a kind into Results (search stays on /); the
    Results title names the kind. Tab / Shift-Tab cycle the three panes.
  • Rack elevation. A rack's detail now has an e (elevation) tab: a framed,
    U-by-U front view (from NetBox's /dcim/racks/{id}/elevation/ endpoint) where
    each device fills its U span with the name on the top row, and any devices
    assigned to the rack without a mounted position are listed below as "not racked".
    Reachable via e or by cycling detail tabs with Tab.

Install: cargo install nbox · brew install lance0/tap/nbox · pre-built binaries · GHCR image ghcr.io/lance0/nbox (tags 0.4.0, latest)

Full changelog: CHANGELOG.md · compare v0.3.0...v0.4.0