v0.4.0
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, anddocs/TROUBLESHOOTING.md.
Documented the in-memory read cache ([cache]) and thenbox_cache_clearMCP
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. ExpandedSECURITY.md
(thenbox servenetwork surface, supported-versions) andCONTRIBUTING.md
(module map, an "adding a feature" recipe), and added GitHub issue/PR templates.
Changed
- BREAKING: per-surface API backends replace the coarse
backendkey. The
profile-levelbackend = "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:A missing table/key means REST; unknown surfaces (e.g.[profiles.work.api] vrf = "graphql" # rest | graphql
detail) and invalid
values are config errors. REST stays canonical; agraphqlsurface is honored
only when the live schema probe supports it, otherwise it falls back to REST.
nbox status(CLI + MCP) drops the singlebackendfield for a per-surface
apiblock (configured/effective/reason), andcapabilities.graphqlis
now surface-aware (surfaces.{search,vrf}.{supported,recommended,missing}). - Search is always REST. NetBox's GraphQL API has no equivalent to REST's
full-textqquick-search (filtering moved to per-field Strawberry lookups in
4.3), so GraphQL can't reproduce canonical NetBox search.nbox searchnow
always runs over REST; asearch = "graphql"preference is accepted but
transparently falls back to REST, with the reason innbox 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, sonbox 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 — noEnter
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, andEnter
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_browsedon 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}(sovrf --jsongains the id) andEnteropens 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-identicalVrfDetail.nbox vrfnow prints the
full routing context (summary + prefix tree + addresses), and MCPnbox_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// MCPnbox_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 bynbox 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,
withaddressesandtargetstabs. The prefix and address rows are navigable —
j/kmove a cursor andEnteropens that prefix/IP (b/Escreturns), 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 withEnterto 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.Enterlists a kind into Results (search stays on/); the
Results title names the kind.Tab/Shift-Tabcycle 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 viaeor 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