Skip to content

thomaschristory/netbox-super-cli

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

268 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

netbox-super-cliΒ Β·Β nsc

A Python CLI for NetBox that builds its entire command tree from your install's live OpenAPI schema.

One binary, any NetBox version, every plugin endpoint β€” the schema, not hand-written code, defines the surface.


PyPI version Python Downloads License Tests Docs Stars

πŸ“š Documentation Β Β·Β  πŸš€ Install Β Β·Β  πŸ–₯️ Interactive TUI Β Β·Β  πŸ€– AI Skill


Docs: thomaschristory.github.io/netbox-super-cli β€” the full guide, including install, first-run, guides, and the auto-generated CLI/config/exit-code reference.

Why

  • Plugins just work. If your install has plugins, their endpoints appear as commands automatically.
  • Multi-instance. Named profiles per NetBox instance, plus env-var overrides.
  • Safe by default. POST/PATCH/PUT/DELETE preview as dry-runs unless you pass --apply.
  • Agent-friendly. Deterministic command shape, machine-readable JSON output, stable error envelope with documented exit codes.
  • Interactive TUI. nsc tui opens a keyboard-driven terminal UI β€” see below.

Install

uv tool install netbox-super-cli
# or, with pipx:
pipx install netbox-super-cli

Or from source:

git clone https://github.com/thomaschristory/netbox-super-cli
cd netbox-super-cli
uv sync
uv run nsc --version

Interactive TUI

nsc tui (aliases nsc interactive, nsc i) opens a full-screen, keyboard-driven UI over your NetBox β€” browse, filter, edit, bulk-edit and search across object types without writing a command. Like the CLI it is generated from the live schema, so it works for every resource and plugin.

The nsc interactive TUI

nsc tui            # land on the resource picker
nsc tui devices    # jump straight into the devices list

Highlights: a collapsible resource picker, a web-UI-style filter builder (/), inline record editing with a confirm-diff save, schema-derived relationship drill-down, bulk edit with a per-record preview, a persisted column chooser (f) that lists each custom field individually, and global search (Ctrl+F). The same dotted paths work on the CLI: nsc ls devices --columns id,name,custom_fields.rack_role. Full walkthrough in the Interactive TUI guide.

Reading

export NSC_URL=https://netbox.example.com
export NSC_TOKEN=$(cat ~/.netbox-token)

uv run nsc dcim devices list
uv run nsc dcim devices list --site-id 42 --status active --all --output json
uv run nsc dcim devices get 7
uv run nsc circuits providers list --output csv
uv run nsc ipam prefixes list --filter created__gte=2026-01-01 --output yaml

Saved searches

Filter sets you save from the TUI (Ctrl+W in the filter builder) are stored as NetBox native saved filters (extras.saved-filters), scoped to the resource's object type. A search you save in nsc shows up in the NetBox web UI's filter dropdown for that object β€” and a filter saved in the web UI loads in the TUI (Ctrl+O) β€” so the two are fully interchangeable. Re-apply one on the CLI with --saved:

uv run nsc dcim devices list --saved active-switches
# explicit --filter / typed options override the saved values:
uv run nsc dcim devices list --saved active-switches --status offline

When NetBox is unreachable (offline, or missing permission on extras.savedfilter), nsc transparently falls back to a local store under saved_searches in ~/.nsc/config.yaml, keyed by tag/resource, and tells you it did so.

Object colors

NetBox assigns colors to roles, tags, and similar fields. In table output nsc renders those values in their NetBox-defined colors:

uv run nsc dcim devices list                      # colored when stdout is a TTY
uv run nsc dcim devices list --no-object-colors   # plain text

Toggle it independently of --color with the object_colors setting (auto/on/off) or the --object-colors/--no-object-colors flag. off, NO_COLOR, and non-TTY output are always respected, so piped or redirected output stays uncolored.

Writing

# Dry-run by default β€” shows the resolved request without sending it.
uv run nsc dcim devices create -f device.yaml --explain

# Commit with --apply.
uv run nsc dcim devices create -f device.yaml --apply

# Bulk create: one HTTP call when the schema supports it, sequential loop otherwise.
uv run nsc dcim devices create -f devices.yaml --apply
uv run nsc dcim devices create -f devices.yaml --no-bulk --on-error continue --apply

# Speed up a loop-mode bulk write with concurrent requests (default 1, max 32).
# Per-record --on-error semantics hold; the audit log stays one line per record.
uv run nsc dcim devices create -f devices.ndjson --workers 8 --apply

# NDJSON / JSONL β€” one record per line; parse failures abort the whole batch
# before any wire request fires (`type: input_error`, exit 4, `details.bad_lines`).
uv run nsc dcim devices create -f devices.ndjson --apply
cat devices.ndjson | uv run nsc dcim devices create -f - --apply

# Per-field overrides (CLI wins over file on overlap).
uv run nsc dcim devices update 42 --field status=active --apply

# Delete; default is exit-0 if already gone, --strict turns missing-id into exit 9.
uv run nsc dcim devices delete 42 --apply
uv run nsc dcim devices delete 42 --apply --strict

Every write attempt β€” dry-run included β€” appends one line to ~/.nsc/logs/audit.jsonl; the most recent exchange is also mirrored to ~/.nsc/logs/last-request.json.

Bulk input formats

Form File extension or stdin shape Routing
YAML mapping .yaml / .yml Single record.
YAML list .yaml / .yml Bulk: one record per list item.
JSON object .json or {...}EOF on stdin Single record.
JSON array .json or [...] on stdin Bulk: one record per array item.
NDJSON .ndjson / .jsonl or {...}\n{...} on stdin Bulk: one record per line.

Stdin is sniffed from the first 512 bytes (first non-whitespace byte plus a one-object lookahead for newline-then-{). NDJSON parse failures collect up to 20 bad_lines and abort before any wire request; --no-bulk still forces a loop fallback for any bulk shape.

Audit log sensitivity

audit.jsonl is confidential (not secret). It records what was sent β€” record-level data your account had write access to. The CLI redacts:

  • HTTP headers in the SENSITIVE_HEADERS set (e.g. Authorization, X-API-Key) β€” replaced with "<redacted>".
  • Request-body fields whose OpenAPI definition has format: password OR whose name (case-insensitive) is one of: password, secret, token, api_key, apikey, private_key, passphrase, client_secret. Nested fields and arrays of objects are walked recursively.

The wire body sent to NetBox is not redacted β€” only the audit log. A failed write still records the redacted body; redaction is irreversible. Treat audit.jsonl like a verbose application log: gate it behind your home-directory permissions and rotate / archive accordingly.

For a stricter posture, set audit_redaction: full in ~/.nsc/config.yaml (the default is safe, the field-level redaction described above). In full mode every audit line keeps only {method, url, status_code, timestamp, profile} β€” all request and response bodies are dropped, and the url is sanitized (query string and any user:pass@ credentials stripped).

Curated aliases

nsc ls, nsc get, nsc rm, and nsc search are short verbs over the dynamic command tree.

nsc ls devices                 # list a resource by plural name
nsc ls device                  # singular also works (curated set, see below)
nsc get devices 7              # one record by id or name
nsc rm devices 7 --apply       # delete (dry-run by default)
nsc search "rack-42"           # /api/search/ on NetBox 4.5+

Singular forms resolve for a curated set of nine resources: device, prefix, tenant, vlan, site, rack, interface, cable, and tag. Any other singular that does not resolve suggests its plural ("Did you mean devices?").

Output and errors

  • --output {table,json,yaml,csv,jsonl}. Table is the default on a TTY; JSON is the default when stdout is piped.
  • On --output json, the records array is emitted directly (no NetBox-style count/results wrapper); single-record writes emit the resulting record dict.
  • Failures emit a stable ErrorEnvelope (JSON to stdout on --output json, Rich panel to stderr otherwise) with type ∈ {auth, not_found, validation, conflict, rate_limited, server, transport, schema, config, client, internal, ambiguous_alias, unknown_alias, input_error} and a documented exit code per type. See CHANGELOG.md and the spec for the full table.

Schema introspection

# Dump every endpoint in the bundled NetBox schema as JSON.
uv run nsc commands --schema nsc/schemas/bundled/netbox-4.6.0.json.gz --output json | head

# Or against a live install.
uv run nsc commands --schema https://netbox.example.com/api/schema/?format=json --output json

Cache management

The on-disk command-model cache lives at ~/.nsc/cache/<profile>/<schema-hash>.json and is regenerated automatically when the live NetBox schema changes. Over time, removed profiles or upgraded NetBox versions can leave orphan entries behind.

nsc cache prune                          # show what would be deleted (dry-run)
nsc cache prune --apply                  # actually delete
nsc cache prune --max-age 30 --apply     # also delete cache files older than 30 days
nsc cache prune --output json            # structured envelope for scripts

What gets pruned:

  1. Cache directories for profiles that are no longer in your config.
  2. Cache files whose schema-hash differs from the live NetBox schema (skipped per-profile when offline).
  3. With --max-age <days>: cache files older than the threshold (excludes files already covered by rule 1).

The adhoc cache directory (used by env-var-only invocations like NSC_URL=… nsc dcim devices list) is never pruned automatically.

Shell completion

nsc ships static completion stubs that complete subcommands and option names.

nsc --install-completion         # auto-detects $SHELL
nsc --show-completion            # prints the script instead of installing

Typer supports bash, zsh, fish, and pwsh.

Completion of dynamic values reads the cached schema and complements the static stubs above:

nsc ls dev<TAB>                               # devices device-roles device-types
nsc --profile <TAB>                           # configured profile names
nsc dcim devices list --status <TAB>          # enum values for the field

Bundled Skill for AI agents

nsc ships a portable Skill bundle at skills/netbox-super-cli/SKILL.md that briefs an AI agent on how to drive nsc correctly (dry-run discipline, JSON output, error envelope, audit log).

nsc skill install --target claude-code            # dry-run; prints the destination
nsc skill install --target claude-code --apply    # actually copies

# Or export to an arbitrary directory (e.g. CI or a shared-skill repo).
nsc skill export ./skills                          # dry-run; prints the would-write path
nsc skill export ./skills --apply                  # writes ./skills/netbox-super-cli/SKILL.md

skill install targets: claude-code, codex, gemini, copilot. Where a target has no documented programmatic install path, the helper prints actionable manual instructions instead of guessing. skill export <dir> always writes to <dir>/netbox-super-cli/SKILL.md and, like install, is dry-run unless you pass --apply.

License

Apache 2.0.

About

Dynamic NetBox CLI generated from the live OpenAPI schema.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages