netbox-super-cli 1.4.0__tar.gz → 1.6.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (336) hide show
  1. netbox_super_cli-1.6.0/.github/ISSUE_TEMPLATE/bug_report.yml +127 -0
  2. netbox_super_cli-1.6.0/.github/ISSUE_TEMPLATE/config.yml +11 -0
  3. netbox_super_cli-1.6.0/.github/ISSUE_TEMPLATE/docs.yml +35 -0
  4. netbox_super_cli-1.6.0/.github/ISSUE_TEMPLATE/feature_request.yml +68 -0
  5. netbox_super_cli-1.6.0/.github/pull_request_template.md +17 -0
  6. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/.github/workflows/test.yml +2 -3
  7. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/CHANGELOG.md +54 -0
  8. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/PKG-INFO +19 -9
  9. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/README.md +10 -6
  10. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/docs/guides/interactive-tui.md +16 -0
  11. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/_version.py +1 -1
  12. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/cli/handlers.py +36 -3
  13. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/cli/registration.py +22 -10
  14. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/cli/tui_commands.py +7 -47
  15. netbox_super_cli-1.6.0/nsc/config/saved_searches.py +112 -0
  16. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/output/csv_.py +7 -1
  17. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/output/render.py +10 -2
  18. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/output/table.py +2 -1
  19. netbox_super_cli-1.6.0/nsc/savedfilters/__init__.py +4 -0
  20. netbox_super_cli-1.6.0/nsc/savedfilters/custom_fields.py +151 -0
  21. netbox_super_cli-1.6.0/nsc/savedfilters/objecttypes.py +103 -0
  22. netbox_super_cli-1.6.0/nsc/savedfilters/params.py +55 -0
  23. netbox_super_cli-1.6.0/nsc/savedfilters/store.py +140 -0
  24. netbox_super_cli-1.6.0/nsc/savedfilters/tags.py +62 -0
  25. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/tui/__init__.py +2 -0
  26. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/tui/app.py +47 -1
  27. netbox_super_cli-1.6.0/nsc/tui/forms.py +261 -0
  28. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/tui/screens/bulk_edit_form.py +92 -20
  29. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/tui/screens/columns.py +9 -2
  30. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/tui/screens/detail.py +40 -19
  31. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/tui/screens/edit_form.py +73 -12
  32. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/tui/screens/filter.py +27 -9
  33. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/tui/screens/list.py +37 -2
  34. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/tui/styles.tcss +33 -0
  35. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/tui/view.py +8 -2
  36. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/pyproject.toml +9 -3
  37. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/cli/test_handlers.py +48 -0
  38. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/cli/test_registration.py +20 -6
  39. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/cli/test_tui_command.py +13 -31
  40. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/cli/writes/test_bulk.py +19 -14
  41. netbox_super_cli-1.6.0/tests/config/test_saved_search_fallback.py +55 -0
  42. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/output/test_csv.py +13 -0
  43. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/output/test_table.py +14 -0
  44. netbox_super_cli-1.6.0/tests/savedfilters/test_custom_fields.py +157 -0
  45. netbox_super_cli-1.6.0/tests/savedfilters/test_objecttypes.py +123 -0
  46. netbox_super_cli-1.6.0/tests/savedfilters/test_params.py +64 -0
  47. netbox_super_cli-1.6.0/tests/savedfilters/test_store.py +190 -0
  48. netbox_super_cli-1.6.0/tests/savedfilters/test_tags.py +54 -0
  49. netbox_super_cli-1.6.0/tests/tui/__init__.py +0 -0
  50. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/tui/test_bulk_edit_form.py +153 -2
  51. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/tui/test_column_chooser.py +30 -3
  52. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/tui/test_detail_screen.py +90 -0
  53. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/tui/test_edit_form.py +181 -2
  54. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/tui/test_filter_screen.py +6 -0
  55. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/tui/test_forms.py +85 -0
  56. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/tui/test_list_screen.py +65 -0
  57. netbox_super_cli-1.6.0/tests/tui/test_saved_filter_integration.py +98 -0
  58. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/uv.lock +1 -1
  59. netbox_super_cli-1.4.0/nsc/config/saved_searches.py +0 -54
  60. netbox_super_cli-1.4.0/nsc/tui/forms.py +0 -129
  61. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/.github/dependabot.yml +0 -0
  62. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/.github/workflows/bench.yml +0 -0
  63. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/.github/workflows/claude.yml +0 -0
  64. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/.github/workflows/docs.yml +0 -0
  65. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/.github/workflows/e2e.yml +0 -0
  66. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/.github/workflows/lint.yml +0 -0
  67. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/.github/workflows/release.yml +0 -0
  68. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/.github/workflows/skill-convention-review.yml +0 -0
  69. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/.gitignore +0 -0
  70. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/.pre-commit-config.yaml +0 -0
  71. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/.python-version +0 -0
  72. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/AGENTS.md +0 -0
  73. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/CLAUDE.md +0 -0
  74. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/LICENSE +0 -0
  75. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/docs/architecture/caching.md +0 -0
  76. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/docs/architecture/command-generation.md +0 -0
  77. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/docs/architecture/http-client.md +0 -0
  78. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/docs/architecture/overview.md +0 -0
  79. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/docs/architecture/schema-loading.md +0 -0
  80. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/docs/assets/tui/detail.svg +0 -0
  81. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/docs/assets/tui/filter.svg +0 -0
  82. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/docs/assets/tui/list.svg +0 -0
  83. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/docs/assets/tui/picker.svg +0 -0
  84. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/docs/assets/tui/search.svg +0 -0
  85. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/docs/contributing/adding-bundled-schemas.md +0 -0
  86. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/docs/contributing/branching.md +0 -0
  87. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/docs/contributing/development.md +0 -0
  88. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/docs/contributing/release-process.md +0 -0
  89. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/docs/getting-started/concepts.md +0 -0
  90. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/docs/getting-started/first-run.md +0 -0
  91. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/docs/getting-started/install.md +0 -0
  92. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/docs/guides/audit-log.md +0 -0
  93. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/docs/guides/ci-and-automation.md +0 -0
  94. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/docs/guides/managing-profiles.md +0 -0
  95. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/docs/guides/output-formats.md +0 -0
  96. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/docs/guides/using-with-ai-agents.md +0 -0
  97. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/docs/guides/working-with-plugins.md +0 -0
  98. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/docs/guides/writes-and-safety.md +0 -0
  99. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/docs/index.md +0 -0
  100. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/docs/reference/cli.md +0 -0
  101. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/docs/reference/config.md +0 -0
  102. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/docs/reference/exit-codes.md +0 -0
  103. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/docs/reference/schemas.md +0 -0
  104. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/justfile +0 -0
  105. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/mkdocs.yml +0 -0
  106. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/__init__.py +0 -0
  107. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/__main__.py +0 -0
  108. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/aliases/__init__.py +0 -0
  109. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/aliases/resolver.py +0 -0
  110. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/auth/__init__.py +0 -0
  111. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/auth/verify.py +0 -0
  112. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/builder/__init__.py +0 -0
  113. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/builder/build.py +0 -0
  114. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/cache/__init__.py +0 -0
  115. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/cache/store.py +0 -0
  116. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/cli/__init__.py +0 -0
  117. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/cli/aliases_commands.py +0 -0
  118. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/cli/app.py +0 -0
  119. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/cli/cache_commands.py +0 -0
  120. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/cli/commands_dump.py +0 -0
  121. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/cli/config_commands.py +0 -0
  122. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/cli/globals.py +0 -0
  123. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/cli/init_commands.py +0 -0
  124. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/cli/login_commands.py +0 -0
  125. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/cli/profiles_commands.py +0 -0
  126. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/cli/runtime.py +0 -0
  127. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/cli/skill_commands.py +0 -0
  128. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/cli/writes/__init__.py +0 -0
  129. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/cli/writes/apply.py +0 -0
  130. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/cli/writes/bulk.py +0 -0
  131. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/cli/writes/coercion.py +0 -0
  132. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/cli/writes/confirmation.py +0 -0
  133. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/cli/writes/input.py +0 -0
  134. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/cli/writes/preflight.py +0 -0
  135. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/completion/__init__.py +0 -0
  136. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/completion/cache_probe.py +0 -0
  137. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/completion/callbacks.py +0 -0
  138. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/completion/providers.py +0 -0
  139. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/config/__init__.py +0 -0
  140. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/config/loader.py +0 -0
  141. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/config/models.py +0 -0
  142. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/config/settings.py +0 -0
  143. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/config/writer.py +0 -0
  144. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/http/__init__.py +0 -0
  145. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/http/audit.py +0 -0
  146. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/http/client.py +0 -0
  147. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/http/errors.py +0 -0
  148. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/http/retry.py +0 -0
  149. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/model/__init__.py +0 -0
  150. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/model/command_model.py +0 -0
  151. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/output/__init__.py +0 -0
  152. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/output/_console.py +0 -0
  153. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/output/colors.py +0 -0
  154. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/output/errors.py +0 -0
  155. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/output/explain.py +0 -0
  156. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/output/flatten.py +0 -0
  157. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/output/headers.py +0 -0
  158. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/output/json_.py +0 -0
  159. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/output/jsonl.py +0 -0
  160. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/output/yaml_.py +0 -0
  161. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/schema/__init__.py +0 -0
  162. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/schema/hashing.py +0 -0
  163. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/schema/loader.py +0 -0
  164. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/schema/models.py +0 -0
  165. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/schema/source.py +0 -0
  166. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/schemas/__init__.py +0 -0
  167. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/schemas/bundled/__init__.py +0 -0
  168. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/schemas/bundled/manifest.yaml +0 -0
  169. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/schemas/bundled/netbox-4.5.10.json.gz +0 -0
  170. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/schemas/bundled/netbox-4.6.0.json.gz +0 -0
  171. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/skill/__init__.py +0 -0
  172. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/tui/_bindings.py +0 -0
  173. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/tui/bulk.py +0 -0
  174. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/tui/catalog.py +0 -0
  175. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/tui/columns.py +0 -0
  176. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/tui/errors.py +0 -0
  177. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/tui/filters.py +0 -0
  178. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/tui/fk.py +0 -0
  179. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/tui/keymap.py +0 -0
  180. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/tui/nav.py +0 -0
  181. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/tui/relations.py +0 -0
  182. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/tui/screens/__init__.py +0 -0
  183. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/tui/screens/global_search.py +0 -0
  184. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/tui/screens/picker.py +0 -0
  185. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/tui/screens/record_picker.py +0 -0
  186. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/tui/screens/saved_search_picker.py +0 -0
  187. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/tui/search.py +0 -0
  188. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/tui/selection.py +0 -0
  189. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/tui/widgets/__init__.py +0 -0
  190. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/tui/widgets/_modal.py +0 -0
  191. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/tui/widgets/bulk_diff.py +0 -0
  192. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/tui/widgets/bulk_summary.py +0 -0
  193. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/tui/widgets/confirm.py +0 -0
  194. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/tui/widgets/diff.py +0 -0
  195. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/tui/widgets/help.py +0 -0
  196. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/nsc/tui/widgets/nav_tree.py +0 -0
  197. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/scripts/gen_docs.py +0 -0
  198. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/scripts/sync_agents_md.py +0 -0
  199. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/skills/netbox-super-cli/SKILL.md +0 -0
  200. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/__init__.py +0 -0
  201. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/aliases/__init__.py +0 -0
  202. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/aliases/test_resolver.py +0 -0
  203. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/audit/__init__.py +0 -0
  204. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/audit/test_redaction_full.py +0 -0
  205. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/auth/__init__.py +0 -0
  206. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/auth/test_verify.py +0 -0
  207. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/benchmarks/__init__.py +0 -0
  208. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/benchmarks/test_startup.py +0 -0
  209. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/builder/__init__.py +0 -0
  210. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/builder/test_build.py +0 -0
  211. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/builder/test_default_columns.py +0 -0
  212. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/builder/test_redaction_marking.py +0 -0
  213. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/builder/test_request_body_shape.py +0 -0
  214. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/cache/__init__.py +0 -0
  215. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/cache/test_prune.py +0 -0
  216. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/cache/test_store.py +0 -0
  217. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/cli/__init__.py +0 -0
  218. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/cli/test_aliases_commands.py +0 -0
  219. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/cli/test_app_smoke.py +0 -0
  220. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/cli/test_cache_commands.py +0 -0
  221. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/cli/test_commands_dump.py +0 -0
  222. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/cli/test_completion_protocol_smoke.py +0 -0
  223. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/cli/test_completion_smoke.py +0 -0
  224. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/cli/test_config_commands.py +0 -0
  225. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/cli/test_dynamic_completion.py +0 -0
  226. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/cli/test_explain.py +0 -0
  227. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/cli/test_globals_color.py +0 -0
  228. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/cli/test_init_commands.py +0 -0
  229. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/cli/test_lazy_textual_import.py +0 -0
  230. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/cli/test_login_commands.py +0 -0
  231. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/cli/test_meta_subcommands_under_broken_config.py +0 -0
  232. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/cli/test_ndjson_input.py +0 -0
  233. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/cli/test_profiles_commands.py +0 -0
  234. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/cli/test_respx_integration.py +0 -0
  235. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/cli/test_runtime.py +0 -0
  236. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/cli/test_runtime_color.py +0 -0
  237. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/cli/test_skill_commands.py +0 -0
  238. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/cli/test_stdin_sniffer.py +0 -0
  239. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/cli/test_writes_respx.py +0 -0
  240. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/cli/writes/__init__.py +0 -0
  241. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/cli/writes/test_apply.py +0 -0
  242. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/cli/writes/test_confirmation.py +0 -0
  243. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/cli/writes/test_handler_helpers.py +0 -0
  244. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/cli/writes/test_handlers_audit.py +0 -0
  245. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/cli/writes/test_input.py +0 -0
  246. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/cli/writes/test_preflight.py +0 -0
  247. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/config/__init__.py +0 -0
  248. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/config/test_loader.py +0 -0
  249. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/config/test_models.py +0 -0
  250. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/config/test_saved_searches.py +0 -0
  251. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/config/test_settings_private_dir.py +0 -0
  252. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/config/test_writer_atomicity.py +0 -0
  253. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/config/test_writer_dotted_paths.py +0 -0
  254. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/config/test_writer_roundtrip.py +0 -0
  255. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/conftest.py +0 -0
  256. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/e2e/README.md +0 -0
  257. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/e2e/__init__.py +0 -0
  258. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/e2e/conftest.py +0 -0
  259. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/e2e/docker-compose.yml +0 -0
  260. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/e2e/test_audit_redaction.py +0 -0
  261. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/e2e/test_auth_error_envelope.py +0 -0
  262. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/e2e/test_bulk_create_with_loop_fallback.py +0 -0
  263. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/e2e/test_full_cycle.py +0 -0
  264. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/e2e/test_login.py +0 -0
  265. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/e2e/test_ndjson.py +0 -0
  266. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/e2e/test_preflight_blocks_apply.py +0 -0
  267. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/e2e/test_validation_error_envelope_from_netbox.py +0 -0
  268. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/e2e/wait_for_netbox.sh +0 -0
  269. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/fixtures/profiles/single_profile.yaml +0 -0
  270. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/fixtures/responses/auth_401.json +0 -0
  271. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/fixtures/responses/circuits_providers_list.json +0 -0
  272. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/fixtures/responses/dcim_devices_get.json +0 -0
  273. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/fixtures/responses/dcim_devices_list_p1.json +0 -0
  274. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/fixtures/responses/dcim_devices_list_p2.json +0 -0
  275. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/http/__init__.py +0 -0
  276. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/http/test_audit.py +0 -0
  277. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/http/test_audit_permissions.py +0 -0
  278. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/http/test_audit_redaction.py +0 -0
  279. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/http/test_client.py +0 -0
  280. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/http/test_client_redaction_threading.py +0 -0
  281. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/http/test_errors.py +0 -0
  282. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/http/test_retry.py +0 -0
  283. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/model/__init__.py +0 -0
  284. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/model/test_command_model.py +0 -0
  285. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/model/test_request_body_shape.py +0 -0
  286. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/output/__init__.py +0 -0
  287. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/output/test_colors.py +0 -0
  288. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/output/test_console.py +0 -0
  289. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/output/test_errors.py +0 -0
  290. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/output/test_errors_aliases.py +0 -0
  291. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/output/test_errors_color.py +0 -0
  292. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/output/test_explain.py +0 -0
  293. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/output/test_explain_color.py +0 -0
  294. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/output/test_flatten.py +0 -0
  295. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/output/test_input_error_envelope.py +0 -0
  296. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/output/test_json.py +0 -0
  297. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/output/test_jsonl.py +0 -0
  298. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/output/test_render_dispatch.py +0 -0
  299. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/output/test_table_color.py +0 -0
  300. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/output/test_yaml.py +0 -0
  301. {netbox_super_cli-1.4.0/tests/schema → netbox_super_cli-1.6.0/tests/savedfilters}/__init__.py +0 -0
  302. {netbox_super_cli-1.4.0/tests/scripts → netbox_super_cli-1.6.0/tests/schema}/__init__.py +0 -0
  303. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/schema/test_hashing.py +0 -0
  304. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/schema/test_loader.py +0 -0
  305. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/schema/test_models.py +0 -0
  306. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/schema/test_source.py +0 -0
  307. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/schema/test_source_ttl.py +0 -0
  308. {netbox_super_cli-1.4.0/tests/skill → netbox_super_cli-1.6.0/tests/scripts}/__init__.py +0 -0
  309. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/scripts/test_gen_docs.py +0 -0
  310. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/scripts/test_sync_agents_md.py +0 -0
  311. {netbox_super_cli-1.4.0/tests/tui → netbox_super_cli-1.6.0/tests/skill}/__init__.py +0 -0
  312. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/skill/test_bundle.py +0 -0
  313. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/test_packaging.py +0 -0
  314. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/tui/test_app.py +0 -0
  315. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/tui/test_bindings.py +0 -0
  316. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/tui/test_bulk_apply.py +0 -0
  317. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/tui/test_bulk_diff.py +0 -0
  318. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/tui/test_bulk_diff_modal.py +0 -0
  319. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/tui/test_bulk_import_isolation.py +0 -0
  320. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/tui/test_bulk_summary.py +0 -0
  321. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/tui/test_catalog.py +0 -0
  322. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/tui/test_columns.py +0 -0
  323. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/tui/test_diff.py +0 -0
  324. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/tui/test_diff_modal.py +0 -0
  325. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/tui/test_errors.py +0 -0
  326. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/tui/test_filters.py +0 -0
  327. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/tui/test_fk_resolve.py +0 -0
  328. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/tui/test_global_search.py +0 -0
  329. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/tui/test_help_overlay.py +0 -0
  330. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/tui/test_keymap.py +0 -0
  331. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/tui/test_picker.py +0 -0
  332. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/tui/test_record_picker.py +0 -0
  333. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/tui/test_relations.py +0 -0
  334. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/tui/test_search.py +0 -0
  335. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/tui/test_selection.py +0 -0
  336. {netbox_super_cli-1.4.0 → netbox_super_cli-1.6.0}/tests/tui/test_view.py +0 -0
@@ -0,0 +1,127 @@
1
+ name: 🐞 Bug report
2
+ description: Something in nsc (the CLI or TUI) behaves incorrectly or crashes.
3
+ title: "[Bug]: "
4
+ labels: ["bug"]
5
+ body:
6
+ - type: markdown
7
+ attributes:
8
+ value: |
9
+ Thanks for filing a bug! The version numbers and the **exact command** make
10
+ most issues reproducible — please fill in as much as you can.
11
+
12
+ > [!WARNING]
13
+ > **Redact secrets.** Never paste your `NSC_TOKEN`, API tokens, or any
14
+ > credential. Replace them with `***`.
15
+
16
+ - type: input
17
+ id: nsc-version
18
+ attributes:
19
+ label: nsc version
20
+ description: Output of `nsc --version`.
21
+ placeholder: "nsc 1.4.0"
22
+ validations:
23
+ required: true
24
+
25
+ - type: dropdown
26
+ id: install-method
27
+ attributes:
28
+ label: How did you install nsc?
29
+ options:
30
+ - uv tool install
31
+ - pipx
32
+ - pip
33
+ - uvx (ephemeral)
34
+ - from source / git checkout
35
+ - other
36
+ validations:
37
+ required: true
38
+
39
+ - type: input
40
+ id: python-version
41
+ attributes:
42
+ label: Python version
43
+ description: Output of `python --version` for the interpreter nsc runs under.
44
+ placeholder: "3.12.x"
45
+ validations:
46
+ required: true
47
+
48
+ - type: dropdown
49
+ id: os
50
+ attributes:
51
+ label: Operating system
52
+ options:
53
+ - Linux
54
+ - macOS
55
+ - Windows
56
+ - Other
57
+ validations:
58
+ required: true
59
+
60
+ - type: input
61
+ id: netbox-version
62
+ attributes:
63
+ label: NetBox version
64
+ description: The NetBox server version nsc talks to (NetBox UI footer, or `/api/status/`).
65
+ placeholder: "v4.6.3"
66
+ validations:
67
+ required: false
68
+
69
+ - type: dropdown
70
+ id: schema-source
71
+ attributes:
72
+ label: Which schema was nsc using?
73
+ description: nsc generates commands from the OpenAPI schema — a live fetch, the on-disk cache, or the bundled offline snapshot.
74
+ options:
75
+ - Live NetBox API
76
+ - Cached schema
77
+ - Bundled offline snapshot
78
+ - Not sure
79
+ validations:
80
+ required: false
81
+
82
+ - type: textarea
83
+ id: command
84
+ attributes:
85
+ label: Command you ran
86
+ description: The exact `nsc ...` invocation. Redact tokens.
87
+ render: shell
88
+ placeholder: nsc dcim devices list --site-id 42 --output json
89
+ validations:
90
+ required: true
91
+
92
+ - type: textarea
93
+ id: what-happened
94
+ attributes:
95
+ label: What happened?
96
+ description: The actual behavior, including any error message or traceback.
97
+ render: shell
98
+ validations:
99
+ required: true
100
+
101
+ - type: textarea
102
+ id: expected
103
+ attributes:
104
+ label: What did you expect to happen?
105
+ validations:
106
+ required: true
107
+
108
+ - type: textarea
109
+ id: logs
110
+ attributes:
111
+ label: Relevant logs / audit output
112
+ description: Optional. Anything else that helps — re-run with extra output if useful. Redact secrets first.
113
+ render: shell
114
+ validations:
115
+ required: false
116
+
117
+ - type: checkboxes
118
+ id: checks
119
+ attributes:
120
+ label: Before submitting
121
+ options:
122
+ - label: I searched existing issues and this isn't a duplicate.
123
+ required: true
124
+ - label: I'm on the latest release of nsc, or I noted my version above.
125
+ required: true
126
+ - label: I removed any tokens / credentials from the command and logs above.
127
+ required: true
@@ -0,0 +1,11 @@
1
+ blank_issues_enabled: false
2
+ contact_links:
3
+ - name: 📖 Documentation
4
+ url: https://thomaschristory.github.io/netbox-super-cli/
5
+ about: Guides, the CLI/TUI reference, and configuration docs — please check here first.
6
+ - name: 💬 Questions & usage help
7
+ url: https://github.com/thomaschristory/netbox-super-cli/discussions
8
+ about: Ask how-to questions, share setups, or propose ideas before filing a feature request.
9
+ - name: 🔐 Security vulnerability
10
+ url: https://github.com/thomaschristory/netbox-super-cli/security/advisories/new
11
+ about: Report a security issue privately. Please do NOT open a public issue for vulnerabilities.
@@ -0,0 +1,35 @@
1
+ name: 📖 Documentation issue
2
+ description: A gap, error, or confusing part of the docs, README, or bundled SKILL.
3
+ title: "[Docs]: "
4
+ labels: ["documentation"]
5
+ body:
6
+ - type: textarea
7
+ id: where
8
+ attributes:
9
+ label: Where is the problem?
10
+ description: A page URL, a file path (e.g. `README.md`, `docs/...`), or a command's `--help` output.
11
+ validations:
12
+ required: true
13
+
14
+ - type: textarea
15
+ id: problem
16
+ attributes:
17
+ label: What's wrong or missing?
18
+ validations:
19
+ required: true
20
+
21
+ - type: textarea
22
+ id: suggestion
23
+ attributes:
24
+ label: Suggested fix
25
+ description: Optional — a sentence, a corrected snippet, or a link to the right info.
26
+ validations:
27
+ required: false
28
+
29
+ - type: checkboxes
30
+ id: checks
31
+ attributes:
32
+ label: Before submitting
33
+ options:
34
+ - label: I searched existing issues and this isn't a duplicate.
35
+ required: true
@@ -0,0 +1,68 @@
1
+ name: ✨ Feature request
2
+ description: Suggest a new capability or improvement for the CLI, TUI, or output.
3
+ title: "[Feature]: "
4
+ labels: ["enhancement"]
5
+ body:
6
+ - type: markdown
7
+ attributes:
8
+ value: |
9
+ Thanks for the idea! Describing the **problem** first (not just the
10
+ solution) helps us find the best fit. nsc is generated from NetBox's
11
+ OpenAPI schema, so features usually apply across every resource.
12
+
13
+ - type: dropdown
14
+ id: area
15
+ attributes:
16
+ label: Which area?
17
+ options:
18
+ - CLI (commands, flags, output)
19
+ - TUI (interactive browser)
20
+ - Output / formatting (table, json, jsonl, yaml, csv)
21
+ - Config / auth / profiles
22
+ - Shell completion
23
+ - Schema / code generation
24
+ - Documentation
25
+ - Other / not sure
26
+ validations:
27
+ required: true
28
+
29
+ - type: textarea
30
+ id: problem
31
+ attributes:
32
+ label: What problem are you trying to solve?
33
+ description: What are you trying to do, and where does nsc get in the way today?
34
+ validations:
35
+ required: true
36
+
37
+ - type: textarea
38
+ id: proposal
39
+ attributes:
40
+ label: Proposed solution
41
+ description: What would you like nsc to do? A sketch of the command, flag, or UX is great.
42
+ validations:
43
+ required: false
44
+
45
+ - type: textarea
46
+ id: example
47
+ attributes:
48
+ label: Example usage
49
+ description: How would it look on the command line (or in the TUI)?
50
+ render: shell
51
+ placeholder: nsc dcim devices list --some-new-flag
52
+ validations:
53
+ required: false
54
+
55
+ - type: textarea
56
+ id: alternatives
57
+ attributes:
58
+ label: Alternatives considered
59
+ validations:
60
+ required: false
61
+
62
+ - type: checkboxes
63
+ id: checks
64
+ attributes:
65
+ label: Before submitting
66
+ options:
67
+ - label: I searched existing issues and this isn't a duplicate.
68
+ required: true
@@ -0,0 +1,17 @@
1
+ <!--
2
+ Thanks for contributing to netbox-super-cli! Keep this short — a couple of
3
+ sentences plus the checklist is plenty. See CLAUDE.md / docs/contributing for
4
+ conventions.
5
+ -->
6
+
7
+ ## What & why
8
+
9
+ <!-- What does this change, and why? Link the issue: Closes #123 -->
10
+
11
+ ## Checklist
12
+
13
+ - [ ] PR title follows [Conventional Commits](https://www.conventionalcommits.org/) (`feat:`, `fix:`, `docs:`, `chore:`, `refactor:`, …)
14
+ - [ ] Tests added or updated, and `just test` passes
15
+ - [ ] `just lint` passes (ruff + `mypy --strict`)
16
+ - [ ] Docs / `CHANGELOG.md` updated if this is user-facing
17
+ - [ ] Linked the related issue (e.g. `Closes #…`)
@@ -10,12 +10,11 @@ permissions:
10
10
 
11
11
  jobs:
12
12
  test:
13
- runs-on: ${{ matrix.os }}
13
+ runs-on: ubuntu-latest
14
14
  strategy:
15
15
  fail-fast: false
16
16
  matrix:
17
- os: [ubuntu-latest, macos-latest]
18
- python: ["3.12", "3.13"]
17
+ python: ["3.12", "3.13", "3.14"]
19
18
  steps:
20
19
  - uses: actions/checkout@v7
21
20
  - name: Install uv
@@ -2,6 +2,60 @@
2
2
 
3
3
  All notable changes to netbox-super-cli are tracked here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) loosely. From v1.0.0 onward, releases follow [Semantic Versioning](https://semver.org/) and the version in `pyproject.toml` matches the git tag. Pre-1.0 milestones (Phase 1-5) were pinned by tag while `pyproject.toml` stayed at `0.0.1`.
4
4
 
5
+ ## v1.6.0 — 2026-06-29
6
+
7
+ Minor release. The interactive TUI gets human-readable custom-field columns,
8
+ clean rendering of list/M2M fields, and a far richer bulk-edit form.
9
+
10
+ ### Added
11
+
12
+ - **Custom-field column labels** ([#132]). Custom-field columns now show the
13
+ field's human label (e.g. "Site Contact") instead of the raw
14
+ `custom_fields.<name>` key — in the TUI list headers and column chooser, and in
15
+ CLI `table`/`csv` output for `list`, `get`, and create/update responses. The
16
+ raw `custom_fields.<name>` key stays the selector, so `--columns` and saved
17
+ column prefs are unchanged. Labels come from the custom-field definitions
18
+ (`/api/extras/custom-fields/`, scoped to the resource's object type) and fall
19
+ back to a humanized name or the raw key when unavailable or ambiguous; JSON/YAML
20
+ output is untouched.
21
+ - **Bulk-edit: per-field custom fields and a tags dropdown** ([#134]). The TUI
22
+ bulk-edit form now expands `custom_fields` into one typed widget per field
23
+ (text/number/switch/select/multi-select), each with its own include toggle, and
24
+ renders `tags` as a multi-select populated from `/api/extras/tags/` (submitting
25
+ the NetBox-native `{name, slug}` list). The same per-field custom fields and
26
+ tag picker apply to single-record editing, and the bulk form's layout is
27
+ aligned with the single-edit experience. Falls back to plain inputs when the
28
+ definitions can't be fetched.
29
+
30
+ ### Fixed
31
+
32
+ - **Detail view rendered list fields as raw dicts** ([#133]). Tags and other
33
+ list-of-object fields in the record detail view showed a raw
34
+ `[{'id': …, 'display': …}]` repr; they now render as a clean comma-joined list
35
+ (colored when object colors are on), matching the list table.
36
+
37
+ [#132]: https://github.com/thomaschristory/netbox-super-cli/issues/132
38
+ [#133]: https://github.com/thomaschristory/netbox-super-cli/issues/133
39
+ [#134]: https://github.com/thomaschristory/netbox-super-cli/issues/134
40
+
41
+ ## v1.5.0 — 2026-06-29
42
+
43
+ Minor release. Saved searches become interchangeable with the NetBox web UI.
44
+
45
+ ### Changed
46
+
47
+ - **Saved searches are now NetBox-native** ([#129]). Filter sets saved from the
48
+ TUI (`Ctrl+W`) and applied via `--saved` are stored as NetBox saved filters
49
+ (`extras.saved-filters`), scoped to the resource's object type, so they are
50
+ fully interchangeable with the web UI's filter dropdown — a search saved in
51
+ `nsc` appears in the web UI and vice versa. The object type is resolved from
52
+ NetBox's own object-type registry (`/api/core/object-types/`), so the mapping
53
+ is exact rather than guessed. When NetBox is unreachable or the user lacks
54
+ permission on `extras.savedfilter`, saves/loads transparently fall back to the
55
+ previous local `config.yaml` store and surface a notice instead of failing.
56
+
57
+ [#129]: https://github.com/thomaschristory/netbox-super-cli/issues/129
58
+
5
59
  ## v1.4.0 — 2026-06-26
6
60
 
7
61
  Minor release. Three user-facing features for the interactive TUI and table
@@ -1,19 +1,25 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: netbox-super-cli
3
- Version: 1.4.0
3
+ Version: 1.6.0
4
4
  Summary: Dynamic NetBox CLI generated from the live OpenAPI schema.
5
5
  Project-URL: Homepage, https://github.com/thomaschristory/netbox-super-cli
6
+ Project-URL: Documentation, https://thomaschristory.github.io/netbox-super-cli/
7
+ Project-URL: Source, https://github.com/thomaschristory/netbox-super-cli
6
8
  Project-URL: Issues, https://github.com/thomaschristory/netbox-super-cli/issues
7
- Author-email: Thomas <mick27@gmail.com>
9
+ Project-URL: Changelog, https://github.com/thomaschristory/netbox-super-cli/blob/main/CHANGELOG.md
10
+ Author: Thomas Christory
8
11
  License-Expression: Apache-2.0
9
12
  License-File: LICENSE
10
13
  Keywords: automation,cli,netbox,openapi
11
- Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Development Status :: 5 - Production/Stable
12
15
  Classifier: Environment :: Console
16
+ Classifier: Intended Audience :: Information Technology
13
17
  Classifier: Intended Audience :: System Administrators
18
+ Classifier: Intended Audience :: Telecommunications Industry
14
19
  Classifier: License :: OSI Approved :: Apache Software License
15
20
  Classifier: Programming Language :: Python :: 3.12
16
21
  Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Programming Language :: Python :: 3.14
17
23
  Classifier: Topic :: System :: Networking
18
24
  Requires-Python: >=3.12
19
25
  Requires-Dist: click>=8.1
@@ -114,9 +120,12 @@ uv run nsc ipam prefixes list --filter created__gte=2026-01-01 --output yaml
114
120
 
115
121
  ### Saved searches
116
122
 
117
- Filter sets you save from the TUI (Ctrl+W in the filter builder) are stored
118
- locally under `saved_searches` in `~/.nsc/config.yaml`, keyed by tag/resource.
119
- Re-apply one on the CLI with `--saved`:
123
+ Filter sets you save from the TUI (Ctrl+W in the filter builder) are stored as
124
+ **NetBox native saved filters** (`extras.saved-filters`), scoped to the resource's
125
+ object type. A search you save in `nsc` shows up in the NetBox web UI's filter
126
+ dropdown for that object — and a filter saved in the web UI loads in the TUI
127
+ (Ctrl+O) — so the two are fully interchangeable. Re-apply one on the CLI with
128
+ `--saved`:
120
129
 
121
130
  ```sh
122
131
  uv run nsc dcim devices list --saved active-switches
@@ -124,9 +133,10 @@ uv run nsc dcim devices list --saved active-switches
124
133
  uv run nsc dcim devices list --saved active-switches --status offline
125
134
  ```
126
135
 
127
- This is a local, per-config convenience and is unrelated to NetBox's
128
- server-side saved filters (`extras saved-filters`), which store web-UI query
129
- strings.
136
+ When NetBox is unreachable (offline, or missing permission on
137
+ `extras.savedfilter`), `nsc` transparently falls back to a local store under
138
+ `saved_searches` in `~/.nsc/config.yaml`, keyed by tag/resource, and tells you it
139
+ did so.
130
140
 
131
141
  ### Object colors
132
142
 
@@ -85,9 +85,12 @@ uv run nsc ipam prefixes list --filter created__gte=2026-01-01 --output yaml
85
85
 
86
86
  ### Saved searches
87
87
 
88
- Filter sets you save from the TUI (Ctrl+W in the filter builder) are stored
89
- locally under `saved_searches` in `~/.nsc/config.yaml`, keyed by tag/resource.
90
- Re-apply one on the CLI with `--saved`:
88
+ Filter sets you save from the TUI (Ctrl+W in the filter builder) are stored as
89
+ **NetBox native saved filters** (`extras.saved-filters`), scoped to the resource's
90
+ object type. A search you save in `nsc` shows up in the NetBox web UI's filter
91
+ dropdown for that object — and a filter saved in the web UI loads in the TUI
92
+ (Ctrl+O) — so the two are fully interchangeable. Re-apply one on the CLI with
93
+ `--saved`:
91
94
 
92
95
  ```sh
93
96
  uv run nsc dcim devices list --saved active-switches
@@ -95,9 +98,10 @@ uv run nsc dcim devices list --saved active-switches
95
98
  uv run nsc dcim devices list --saved active-switches --status offline
96
99
  ```
97
100
 
98
- This is a local, per-config convenience and is unrelated to NetBox's
99
- server-side saved filters (`extras saved-filters`), which store web-UI query
100
- strings.
101
+ When NetBox is unreachable (offline, or missing permission on
102
+ `extras.savedfilter`), `nsc` transparently falls back to a local store under
103
+ `saved_searches` in `~/.nsc/config.yaml`, keyed by tag/resource, and tells you it
104
+ did so.
101
105
 
102
106
  ### Object colors
103
107
 
@@ -81,11 +81,27 @@ NetBox list endpoint exposes hundreds of query parameters.
81
81
  | <kbd>↓</kbd> | Move to the next field (from a text field) |
82
82
  | <kbd>Tab</kbd> / <kbd>Shift</kbd>+<kbd>Tab</kbd> | Move between fields |
83
83
  | <kbd>Ctrl</kbd>+<kbd>S</kbd> | Apply |
84
+ | <kbd>Ctrl</kbd>+<kbd>W</kbd> | Save the current filters as a named search |
85
+ | <kbd>Ctrl</kbd>+<kbd>O</kbd> | Load (or delete) a saved search |
84
86
  | <kbd>Esc</kbd> | Cancel |
85
87
 
86
88
  Applying re-queries the list. Reopening the builder shows your current filters
87
89
  so you can refine them.
88
90
 
91
+ ### Saved searches
92
+
93
+ <kbd>Ctrl</kbd>+<kbd>W</kbd> stores the current filter set as a NetBox **native
94
+ saved filter** (`extras.saved-filters`), scoped to the current resource's object
95
+ type. It then appears in the NetBox web UI's filter dropdown for that object, and
96
+ filters created in the web UI load here with <kbd>Ctrl</kbd>+<kbd>O</kbd> — the two
97
+ surfaces are interchangeable. In the load picker, <kbd>Enter</kbd> applies the
98
+ highlighted search and <kbd>d</kbd> deletes it. Re-apply one non-interactively
99
+ with `nsc <app> <resource> list --saved <name>`.
100
+
101
+ If NetBox is unreachable (offline, or you lack permission on
102
+ `extras.savedfilter`), saves and loads transparently fall back to a local store in
103
+ `~/.nsc/config.yaml` and a toast tells you the fallback was used.
104
+
89
105
  ## Viewing and editing a record
90
106
 
91
107
  The detail view **is** the edit surface — there is no separate "edit window".
@@ -1,3 +1,3 @@
1
1
  """Single source of truth for the package version."""
2
2
 
3
- __version__ = "1.4.0"
3
+ __version__ = "1.6.0"
@@ -66,6 +66,33 @@ def _out(stream: TextIO | None) -> TextIO:
66
66
  return stream if stream is not None else sys.stdout
67
67
 
68
68
 
69
+ def _custom_field_header_labels(
70
+ ctx: RuntimeContext, operation: Operation, columns: list[str] | None
71
+ ) -> dict[str, str] | None:
72
+ """Map ``custom_fields.<name>`` columns to their NetBox labels, or None.
73
+
74
+ Only fetches definitions when a custom-field column is actually selected, so
75
+ ordinary lists incur no extra request. Display-only: the raw key stays the
76
+ selector everywhere else.
77
+ """
78
+ if not columns or not any(c.startswith("custom_fields.") for c in columns):
79
+ return None
80
+ from nsc.savedfilters.custom_fields import ( # noqa: PLC0415
81
+ CustomFieldResolver,
82
+ custom_field_labels,
83
+ )
84
+
85
+ # Custom-field definitions are keyed by the collection (list) endpoint, so a
86
+ # detail path like /api/dcim/devices/{id}/ must reduce to /api/dcim/devices/.
87
+ list_path = operation.path
88
+ if list_path.endswith("{id}/"):
89
+ list_path = list_path[: -len("{id}/")]
90
+ defs = CustomFieldResolver(ctx.client).resolve(list_path)
91
+ if defs is None:
92
+ return None
93
+ return custom_field_labels(columns, defs)
94
+
95
+
69
96
  def parse_filters(raw: list[str]) -> dict[str, str]:
70
97
  out: dict[str, str] = {}
71
98
  for item in raw:
@@ -97,10 +124,12 @@ def handle_list(
97
124
  page_size=ctx.page_size,
98
125
  )
99
126
  )
127
+ columns = ctx.resolve_columns(op_tag, op_resource, operation)
100
128
  render(
101
129
  rows,
102
130
  format=ctx.output_format,
103
- columns=ctx.resolve_columns(op_tag, op_resource, operation),
131
+ columns=columns,
132
+ header_labels=_custom_field_header_labels(ctx, operation, columns),
104
133
  stream=_out(stream),
105
134
  compact=ctx.compact,
106
135
  color=ctx.color,
@@ -124,10 +153,12 @@ def handle_get(
124
153
  try:
125
154
  params, path_vars = _split_params(operation, kwargs)
126
155
  obj = ctx.client.get(operation.path.format(**path_vars), params)
156
+ columns = ctx.resolve_columns(op_tag, op_resource, operation)
127
157
  render(
128
158
  obj,
129
159
  format=ctx.output_format,
130
- columns=ctx.resolve_columns(op_tag, op_resource, operation),
160
+ columns=columns,
161
+ header_labels=_custom_field_header_labels(ctx, operation, columns),
131
162
  stream=_out(stream),
132
163
  compact=ctx.compact,
133
164
  color=ctx.color,
@@ -611,10 +642,12 @@ def _render_response(
611
642
  if is_delete:
612
643
  _render_delete_ok(ctx, stream=stream)
613
644
  return
645
+ columns = ctx.resolve_columns(op_tag, op_resource, operation)
614
646
  render(
615
647
  response,
616
648
  format=ctx.output_format,
617
- columns=ctx.resolve_columns(op_tag, op_resource, operation),
649
+ columns=columns,
650
+ header_labels=_custom_field_header_labels(ctx, operation, columns),
618
651
  stream=stream,
619
652
  compact=ctx.compact,
620
653
  color=ctx.color,
@@ -128,22 +128,33 @@ def _resolve_saved_filters(
128
128
  ctx: RuntimeContext,
129
129
  tag_name: str,
130
130
  resource_name: str,
131
+ list_path: str,
131
132
  saved_name: str | None,
132
133
  explicit_filters: list[tuple[str, str]],
133
134
  typed_kwargs: dict[str, Any],
134
135
  ) -> list[tuple[str, str]]:
135
136
  """Layer a `--saved` filter set under explicit `--filter` and typed options.
136
137
 
137
- Saved params are the base; explicit `--filter` pairs and any non-None typed
138
- query option (already in ``typed_kwargs``) win. Order matters: ``handle_list``
139
- overlays ``ctx.filters`` onto the typed-option params, so saved keys that the
140
- user also set via a typed flag must be dropped here to let the flag win.
138
+ The set is resolved against NetBox's native saved filters (interchangeable
139
+ with the web UI), falling back to the local `config.yaml` map when the API is
140
+ unavailable. Saved params are the base; explicit `--filter` pairs and any
141
+ non-None typed query option (already in ``typed_kwargs``) win. Order matters:
142
+ ``handle_list`` overlays ``ctx.filters`` onto the typed-option params, so
143
+ saved keys that the user also set via a typed flag must be dropped here to let
144
+ the flag win.
141
145
  """
142
146
  if saved_name is None:
143
147
  return explicit_filters
144
- from nsc.config.saved_searches import get_saved_search # noqa: PLC0415
148
+ from nsc.config.saved_searches import ConfigFileSavedSearchStore # noqa: PLC0415
149
+ from nsc.savedfilters.store import NativeSavedFilterStore # noqa: PLC0415
145
150
 
146
- saved = get_saved_search(ctx.config, tag_name, resource_name, saved_name)
151
+ store = NativeSavedFilterStore(
152
+ ctx.client,
153
+ ConfigFileSavedSearchStore(ctx.config),
154
+ on_error=lambda message: typer.echo(f"Warning: {message}", err=True),
155
+ )
156
+ available = store.list(list_path, tag_name, resource_name)
157
+ saved = available.get(saved_name)
147
158
  if saved is None:
148
159
  raise typer.BadParameter(
149
160
  f"no saved search named {saved_name!r} for {tag_name}/{resource_name}"
@@ -191,7 +202,7 @@ def _build_read_closure(
191
202
  "limit": limit,
192
203
  "fetch_all": fetch_all,
193
204
  "filters": _resolve_saved_filters(
194
- ctx, tag_name, resource_name, saved_name, explicit_filters, kwargs
205
+ ctx, tag_name, resource_name, operation.path, saved_name, explicit_filters, kwargs
195
206
  ),
196
207
  }
197
208
  if output:
@@ -350,9 +361,10 @@ def _build_global_flag_params() -> tuple[inspect.Parameter, ...]:
350
361
  None,
351
362
  "--saved",
352
363
  help=(
353
- "Apply a LOCAL named filter set saved from the TUI (config "
354
- "`saved_searches`). Explicit --filter/typed options override it. "
355
- "Unrelated to NetBox server-side saved filters."
364
+ "Apply a named saved filter for this resource. Resolves against "
365
+ "NetBox's native saved filters (interchangeable with the web UI), "
366
+ "falling back to the local config `saved_searches` when the API is "
367
+ "unavailable. Explicit --filter/typed options override it."
356
368
  ),
357
369
  ),
358
370
  ),