Summary
Today, TUI "saved searches" are a purely local nsc feature: filter sets are stored in the user's config.yaml under saved_searches.<tag>.<resource>.<name> and never touch the server. The --saved CLI option help even spells this out: "Unrelated to NetBox server-side saved filters."
This proposes transforming (or augmenting) them to use NetBox's native saved filters API — extras.SavedFilter / GET|POST|PATCH|DELETE /api/extras/saved-filters/ — so saved searches become server-side, shareable across users/machines, and consistent with what the NetBox web UI shows.
Current behavior
nsc/config/saved_searches.py — framework-free read/validate helpers over the saved_searches config map.
nsc/cli/tui_commands.py — _save_search / _delete_search callbacks do atomic round-trip writes to config.yaml.
nsc/tui/app.py — in-memory mirror + persistence delegation (save_search / saved_searches_for / delete_search).
nsc/tui/screens/filter.py — ctrl+w save, ctrl+o load.
nsc/tui/screens/saved_search_picker.py — the save-name prompt and load/delete picker.
nsc/cli/registration.py — the --saved <name> option that applies a local set (and explicitly notes it is unrelated to server-side saved filters).
Desired behavior
Saved searches resolve against NetBox's extras.SavedFilter objects:
- name →
SavedFilter.name (+ slug)
- filter params →
SavedFilter.parameters (JSON dict)
- resource scope →
SavedFilter.content_types (e.g. dcim.device) instead of the local <tag>.<resource> key
- plus native fields:
shared, enabled, weight, user
So a search saved from the TUI shows up in the NetBox web UI (and vice-versa), and is available from any machine.
Design considerations / open questions
- Replace vs. augment — fully replace local
config.yaml saved searches, or keep local as a fallback/offline mode and add native as a second source? (Recommend: native primary, with the local store kept for offline / unauthenticated use.)
- content_types mapping — map nsc's
<tag>.<resource> to NetBox app_label.model (note: NetBox content types are singular, e.g. dcim.device, not devices). Need a reliable mapping from the command model.
- parameters shape — confirm
SavedFilter.parameters accepts the same query-param dict nsc already stores (state.as_params()); some NetBox filter forms expect list values.
- shared vs. private — expose a toggle in the save prompt? Default to private (
shared=false, owned by current user).
- Permissions / offline — handle 403 (no perms on
extras.savedfilter) and offline gracefully; this is why keeping a local fallback may be wise.
- CLI
--saved — update to resolve native filters; update the help text that currently says "Unrelated to NetBox server-side saved filters."
- Schema availability —
extras/saved-filters exists in the OpenAPI schema we already parse, so the dynamic command tree should already cover the CRUD; the work is wiring the TUI/CLI saved-search surfaces to it rather than to config.yaml.
Out of scope (for now)
- Migrating existing local
config.yaml saved searches into NetBox (could be a follow-up nsc migration command).
Acceptance criteria
Summary
Today, TUI "saved searches" are a purely local
nscfeature: filter sets are stored in the user'sconfig.yamlundersaved_searches.<tag>.<resource>.<name>and never touch the server. The--savedCLI option help even spells this out: "Unrelated to NetBox server-side saved filters."This proposes transforming (or augmenting) them to use NetBox's native saved filters API —
extras.SavedFilter/GET|POST|PATCH|DELETE /api/extras/saved-filters/— so saved searches become server-side, shareable across users/machines, and consistent with what the NetBox web UI shows.Current behavior
nsc/config/saved_searches.py— framework-free read/validate helpers over thesaved_searchesconfig map.nsc/cli/tui_commands.py—_save_search/_delete_searchcallbacks do atomic round-trip writes toconfig.yaml.nsc/tui/app.py— in-memory mirror + persistence delegation (save_search/saved_searches_for/delete_search).nsc/tui/screens/filter.py—ctrl+wsave,ctrl+oload.nsc/tui/screens/saved_search_picker.py— the save-name prompt and load/delete picker.nsc/cli/registration.py— the--saved <name>option that applies a local set (and explicitly notes it is unrelated to server-side saved filters).Desired behavior
Saved searches resolve against NetBox's
extras.SavedFilterobjects:SavedFilter.name(+slug)SavedFilter.parameters(JSON dict)SavedFilter.content_types(e.g.dcim.device) instead of the local<tag>.<resource>keyshared,enabled,weight,userSo a search saved from the TUI shows up in the NetBox web UI (and vice-versa), and is available from any machine.
Design considerations / open questions
config.yamlsaved searches, or keep local as a fallback/offline mode and add native as a second source? (Recommend: native primary, with the local store kept for offline / unauthenticated use.)<tag>.<resource>to NetBoxapp_label.model(note: NetBox content types are singular, e.g.dcim.device, notdevices). Need a reliable mapping from the command model.SavedFilter.parametersaccepts the same query-param dict nsc already stores (state.as_params()); some NetBox filter forms expect list values.shared=false, owned by current user).extras.savedfilter) and offline gracefully; this is why keeping a local fallback may be wise.--saved— update to resolve native filters; update the help text that currently says "Unrelated to NetBox server-side saved filters."extras/saved-filtersexists in the OpenAPI schema we already parse, so the dynamic command tree should already cover the CRUD; the work is wiring the TUI/CLI saved-search surfaces to it rather than to config.yaml.Out of scope (for now)
config.yamlsaved searches into NetBox (could be a follow-upnscmigration command).Acceptance criteria
ctrl+w) creates a NetBoxSavedFilterand is visible in the NetBox web UI.ctrl+o) lists native saved filters scoped to the current resource's content type.--saved <name>applies a native saved filter; help text updated.extras.savedfilterpermissions.tests/config/test_saved_searches.pyandtests/tui/test_filter_screen.py.