Skip to content

Releases: lance0/nbox

v0.7.0

21 Jun 22:47

Choose a tag to compare

Added

  • First-run orientation on the home screen. A fresh launch (or any time there
    are no recent items yet) now lands on an oriented getting-started panel — /
    search, j/k ↵ browse a kind from the rail, D dashboard, T prefix tree, ?
    help — instead of a bare "Press / to search". Returning users with recents are
    unaffected.
  • Connection status at launch, and a recoverable connection banner. A
    successful start shows a connected to NetBox vX.Y confirmation in the footer. A
    connection or auth failure (bad token, unreachable host) no longer hard-exits
    before the TUI opens — it launches with an actionable banner ("Press S to edit
    the profile or set NBOX_TOKEN"), so you fix the profile in-app and reconnect
    without re-running the binary. A server below the supported NetBox floor stays a
    hard, explicit error.
  • Edit the active connection from the Settings modal. The Config modal's
    Settings section gains a Connection category for the active profile's
    page_size, timeout_secs, exclude_config_context, and the per-surface
    [api] vrf / route_target backends (rest/graphql). Saving a change
    persists it to the profile (format-preserving) and reconnects so it takes effect
    live. The profile editor still manages every profile; Settings is the quick-tweak
    surface for the active one.

Performance

  • Prefix detail loads its child prefixes and contained IPs concurrently — one
    combined fetch after the prefix header instead of two sequential round-trips.
  • Search resolves the --scope and --vrf references concurrently before the
    multi-endpoint fan-out, so a scoped + VRF-filtered search pays one resolution
    tail instead of two.

Internal

  • Deepened machine-facing contract tests: strict response-shape pins for the MCP
    nbox_next_ip / nbox_next_prefix / nbox_cache_clear / nbox_journal /
    nbox_list_tags tools, and CSV RFC-4180 quoting verified through the compiled
    binary.
  • Refactors with no behavior change: bundled the profile-edit-form arguments
    (ProfileFormData), shared one HTTP 429 retry policy across the REST and GraphQL
    paths, and slimmed persist_profile's signature.
  • Dependency maintenance: sha2 0.11, several GitHub Actions bumps, and the Rust
    toolchain pinned to the project MSRV (1.88) so CI keeps a low support floor.

What's Changed

  • chore(deps): bump docker/build-push-action from 6 to 7 by @dependabot[bot] in #44
  • chore(deps): bump actions/download-artifact from 4 to 8 by @dependabot[bot] in #42
  • chore(deps): bump actions/checkout from 6 to 7 by @dependabot[bot] in #43
  • chore(deps): bump docker/metadata-action from 5 to 6 by @dependabot[bot] in #40
  • perf(detail): fetch prefix children and IPs concurrently by @lance0 in #48
  • chore(deps): ignore dtolnay/rust-toolchain bumps (deliberate MSRV floor) by @lance0 in #49
  • feat(tui): orient the empty home screen for first-run users by @lance0 in #50
  • chore(deps): bump sha2 from 0.10.9 to 0.11.0 in the rust-dependencies group across 1 directory by @dependabot[bot] in #45
  • refactor: bundle profile-edit-form args; share the 429-retry policy by @lance0 in #51
  • feat(tui): recoverable connect banner + connected cue at startup by @lance0 in #52
  • test: deepen CSV + MCP response-shape contracts by @lance0 in #53
  • feat(tui): connection knobs in the Settings modal with hot-apply by @lance0 in #54
  • refactor: persist_profile takes ProfileFormData; pin journal author key by @lance0 in #55
  • feat(tui): api backends in the Settings Connection category by @lance0 in #56
  • perf(search): resolve scope and VRF concurrently by @lance0 in #57

Full Changelog: v0.6.0...v0.7.0

v0.6.0

21 Jun 17:52

Choose a tag to compare

Added

  • nbox_get (MCP) accepts ip_address as an alias for ip. A nbox_search
    result's kind is ip_address (the one kind whose spelling differs from
    nbox_get's ip; all others already match), so a search → get chain — and the
    nbox://ip_address/<ref> resource URI — now works without translating the kind.
  • Edit more profile knobs from the in-app Config modal. The profile add/edit
    form now sets the settings that used to need hand-editing config.toml:
    timeout_secs and page_size (numeric fields; empty = default),
    exclude_config_context (Ctrl+E), and the per-surface API backends
    [profiles.<name>.api] vrf (Ctrl+B) / route_target (Ctrl+R), each cycling
    rest/graphql. REST backends and default/empty values leave the file clean
    (no [api] table, no redundant keys), and writes stay format-preserving. The
    API token is still never written to config.toml.
  • Drill into a prefix's children and contained IPs from the TUI. The prefix
    detail's child-prefix and IP-address lists are now navigable tabs (c children,
    a addresses): select a row and press Enter to open that prefix or IP, with
    b/Esc walking back through the drill path. The nbox prefix CLI/JSON output
    is unchanged.
  • Drill into a device's IPs and VLANs from the TUI. The device detail's
    IP-address (p) and VLAN (v) tabs are now navigable — Enter opens that IP or
    VLAN, b/Esc walks back. (Interfaces, cables, and services stay plain text;
    they aren't standalone objects.) The nbox device CLI/JSON output is unchanged.
  • Drill into a VLAN's prefixes from the TUI. The VLAN detail's prefix list is
    now a navigable p tab — Enter opens that prefix, b/Esc walks back. The
    nbox vlan CLI/JSON output is unchanged.
  • Drill into a site's / rack's devices from the TUI. The site detail gains
    navigable devices (d) and racks (r) tabs, and the rack detail gains a
    navigable devices (d) tab alongside its elevation — Enter opens that device
    or rack, b/Esc walks back. These lists are fetched best-effort (a fetch error
    shows in the tab; the summary still loads).
  • The detail screen advertises its tabs and the drill action. The tab bar now
    has a leading tabs: label with the active tab bolded, and the footer shows
    Tab tabs · Enter open — kind-agnostic (replacing the old device-only
    i/p/c/v/s hint), with Enter open shown only when the active tab actually has
    navigable rows (so it never lies on a summary/text tab). Makes the navigable
    detail lists discoverable instead of hidden behind an unmarked tab switch.

What's Changed

  • ci(release): build the GitHub Release body from the CHANGELOG section by @lance0 in #27
  • feat(tui): navigable prefix children + contained IPs by @lance0 in #28
  • feat(tui): navigable device IPs + VLANs by @lance0 in #29
  • feat(tui): navigable VLAN prefixes by @lance0 in #30
  • feat(tui): navigable site/rack devices by @lance0 in #31
  • chore(deps): bump ratatui 0.30.1 -> 0.30.2 by @lance0 in #32
  • perf(tui): fetch site/rack detail sections concurrently by @lance0 in #34
  • feat(tui): advertise detail tabs + guard the Enter-open hint by @lance0 in #35
  • test(config): lock token precedence, onboarding, and format-preserving edits by @lance0 in #36
  • feat(tui): editable per-surface backends + timeout/page_size/exclude in the profile editor by @lance0 in #37
  • fix(tui): onboarding persists the timeout_secs/page_size it shows by @lance0 in #38
  • ci(deps): ignore rand minor/major so it stops blocking the Dependabot group by @lance0 in #39
  • feat(mcp): nbox_get accepts ip_address as an alias for ip by @lance0 in #46
  • chore(release): add scripts/smoke.sh — the full pre-tag gate in one shot by @lance0 in #47

Full Changelog: v0.5.0...v0.6.0

v0.5.0

21 Jun 00:25

Choose a tag to compare

Added

  • Route-target view can use GraphQL. Set [profiles.<name>.api] route_target = "graphql" to fetch a route target's importing + exporting VRFs in one /graphql/
    query instead of two REST vrfs list calls. Identity resolution stays REST (so
    not-found/ambiguous exit codes are unchanged) and the result is byte-identical to
    the REST path; an instance whose schema can't support it transparently falls back
    to REST, with the reason in nbox status. The surface joins the per-surface api
    block and the capabilities report. (Also fixes the GraphQL filter probe to
    introspect RouteTargetFilter, so the id filter is shaped correctly.)

Changed

  • Browsing one kind shows kind-aware list columns. Opening a kind from the Nav
    rail now drops the redundant per-row KIND tag — the pane title already names the
    kind — and labels the second column with the attribute that kind actually carries:
    STATUS for prefixes/IPs, VID for VLANs, RD/TENANT for VRFs, TENANT for
    route targets, SITE for devices/racks, SLUG for sites. The column sizes to its
    content. This replaces the fixed, often-empty SITE column, so a site-less kind no
    longer reads as a ragged, empty row. Mixed search results and Recent keep the
    KIND / DISPLAY / SITE layout.

v0.4.0

20 Jun 04:00

Choose a tag to compare

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

v0.3.0

19 Jun 18:00

Choose a tag to compare

What's Changed

  • feat(netbox): add opt-in GraphQL search backend by @lance0 in #11
  • test(netbox): add GraphQL backend confidence coverage by @lance0 in #13
  • feat(tui): cycle profiles in config-file order by @lance0 in #14
  • fix(tui): refine footer navigation states by @lance0 in #12

New Contributors

Full Changelog: v0.2.0...v0.3.0

v0.2.0

18 Jun 17:59

Choose a tag to compare

What's Changed

  • chore(deps): bump actions/checkout from 4 to 6 by @dependabot[bot] in #2
  • chore(deps): bump clap_mangen from 0.2.33 to 0.3.0 in the rust-dependencies group across 1 directory by @dependabot[bot] in #3

New Contributors

Full Changelog: v0.1.1...v0.2.0

v0.1.1

17 Jun 17:44

Choose a tag to compare