netbox-super-cli 1.6.3__tar.gz → 1.8.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 (372) hide show
  1. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/.github/workflows/bench.yml +2 -2
  2. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/.github/workflows/claude.yml +2 -2
  3. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/.github/workflows/docs.yml +5 -5
  4. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/.github/workflows/e2e.yml +37 -2
  5. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/.github/workflows/lint.yml +6 -6
  6. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/.github/workflows/release.yml +3 -3
  7. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/.github/workflows/test.yml +2 -2
  8. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/.gitignore +1 -1
  9. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/.pre-commit-config.yaml +2 -1
  10. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/AGENTS.md +2 -1
  11. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/CHANGELOG.md +123 -0
  12. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/CLAUDE.md +2 -1
  13. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/PKG-INFO +24 -3
  14. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/README.md +20 -0
  15. netbox_super_cli-1.8.0/SECURITY.md +12 -0
  16. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/architecture/http-client.md +14 -5
  17. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/architecture/overview.md +3 -2
  18. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/contributing/release-process.md +1 -1
  19. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/getting-started/concepts.md +16 -0
  20. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/getting-started/first-run.md +6 -2
  21. netbox_super_cli-1.8.0/docs/guides/branching.md +135 -0
  22. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/guides/ci-and-automation.md +17 -0
  23. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/guides/interactive-tui.md +16 -0
  24. netbox_super_cli-1.8.0/docs/guides/keyring.md +86 -0
  25. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/guides/managing-profiles.md +29 -6
  26. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/guides/output-formats.md +5 -0
  27. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/guides/using-with-ai-agents.md +1 -0
  28. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/guides/working-with-plugins.md +11 -0
  29. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/guides/writes-and-safety.md +17 -0
  30. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/index.md +3 -0
  31. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/reference/config.md +2 -1
  32. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/justfile +14 -4
  33. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/mkdocs.yml +2 -0
  34. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/_version.py +1 -1
  35. netbox_super_cli-1.8.0/nsc/auth/keyring_store.py +77 -0
  36. netbox_super_cli-1.8.0/nsc/auth/verify.py +199 -0
  37. netbox_super_cli-1.8.0/nsc/branching/__init__.py +5 -0
  38. netbox_super_cli-1.8.0/nsc/branching/api.py +100 -0
  39. netbox_super_cli-1.8.0/nsc/branching/errors.py +82 -0
  40. netbox_super_cli-1.8.0/nsc/branching/jobs.py +57 -0
  41. netbox_super_cli-1.8.0/nsc/branching/models.py +42 -0
  42. netbox_super_cli-1.8.0/nsc/branching/resolve.py +46 -0
  43. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/aliases_commands.py +4 -3
  44. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/app.py +38 -1
  45. netbox_super_cli-1.8.0/nsc/cli/branch_commands.py +460 -0
  46. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/cache_commands.py +7 -4
  47. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/globals.py +15 -0
  48. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/handlers.py +23 -9
  49. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/login_commands.py +153 -25
  50. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/profiles_commands.py +2 -2
  51. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/registration.py +1 -1
  52. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/runtime.py +106 -9
  53. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/tui_commands.py +19 -1
  54. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/writes/bulk.py +3 -3
  55. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/completion/cache_probe.py +1 -1
  56. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/completion/callbacks.py +1 -1
  57. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/config/loader.py +11 -1
  58. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/config/models.py +31 -2
  59. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/config/writer.py +6 -1
  60. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/http/audit.py +1 -1
  61. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/http/client.py +66 -41
  62. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/http/errors.py +4 -0
  63. netbox_super_cli-1.8.0/nsc/http/pagination.py +78 -0
  64. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/http/retry.py +5 -4
  65. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/schema/loader.py +4 -4
  66. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/schema/source.py +6 -3
  67. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/__init__.py +2 -0
  68. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/app.py +6 -0
  69. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/keymap.py +1 -0
  70. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/screens/list.py +104 -7
  71. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/styles.tcss +6 -0
  72. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/view.py +11 -0
  73. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/pyproject.toml +11 -5
  74. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/scripts/gen_docs.py +1 -1
  75. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/skills/netbox-super-cli/SKILL.md +31 -1
  76. netbox_super_cli-1.8.0/tests/auth/test_keyring_store.py +58 -0
  77. netbox_super_cli-1.8.0/tests/auth/test_verify.py +283 -0
  78. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/benchmarks/test_startup.py +7 -2
  79. netbox_super_cli-1.8.0/tests/branching/_fixtures.py +54 -0
  80. netbox_super_cli-1.8.0/tests/branching/test_api.py +159 -0
  81. netbox_super_cli-1.8.0/tests/branching/test_jobs.py +70 -0
  82. netbox_super_cli-1.8.0/tests/branching/test_resolve.py +106 -0
  83. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_aliases_commands.py +106 -129
  84. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_app_smoke.py +23 -27
  85. netbox_super_cli-1.8.0/tests/cli/test_branch_commands.py +275 -0
  86. netbox_super_cli-1.8.0/tests/cli/test_branch_lifecycle.py +179 -0
  87. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_cache_commands.py +31 -0
  88. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_commands_dump.py +10 -7
  89. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_handlers.py +72 -0
  90. netbox_super_cli-1.8.0/tests/cli/test_lazy_httpx2_import.py +52 -0
  91. netbox_super_cli-1.8.0/tests/cli/test_lazy_keyring_import.py +27 -0
  92. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_login_commands.py +57 -43
  93. netbox_super_cli-1.8.0/tests/cli/test_login_keyring.py +528 -0
  94. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_ndjson_input.py +14 -15
  95. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_profiles_commands.py +6 -10
  96. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_respx_integration.py +39 -37
  97. netbox_super_cli-1.8.0/tests/cli/test_runtime_branch.py +135 -0
  98. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_tui_command.py +2 -0
  99. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_writes_respx.py +108 -120
  100. netbox_super_cli-1.8.0/tests/config/test_keyring_tag.py +67 -0
  101. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/config/test_models.py +6 -0
  102. netbox_super_cli-1.8.0/tests/conftest.py +85 -0
  103. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/e2e/README.md +12 -0
  104. netbox_super_cli-1.8.0/tests/e2e/branching/Dockerfile +5 -0
  105. netbox_super_cli-1.8.0/tests/e2e/branching/plugins.py +21 -0
  106. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/e2e/conftest.py +13 -5
  107. netbox_super_cli-1.8.0/tests/e2e/docker-compose.branching.yml +45 -0
  108. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/e2e/test_audit_redaction.py +2 -2
  109. netbox_super_cli-1.8.0/tests/e2e/test_branching.py +137 -0
  110. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/e2e/test_bulk_create_with_loop_fallback.py +3 -3
  111. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/e2e/test_full_cycle.py +2 -2
  112. netbox_super_cli-1.8.0/tests/e2e/test_keyring_roundtrip.py +79 -0
  113. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/e2e/test_login.py +55 -4
  114. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/e2e/test_ndjson.py +3 -3
  115. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/e2e/test_preflight_blocks_apply.py +2 -2
  116. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/e2e/test_validation_error_envelope_from_netbox.py +2 -2
  117. netbox_super_cli-1.8.0/tests/http/test_client.py +412 -0
  118. netbox_super_cli-1.8.0/tests/http/test_client_branch.py +112 -0
  119. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/http/test_client_redaction_threading.py +10 -10
  120. netbox_super_cli-1.8.0/tests/http/test_pagination.py +127 -0
  121. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/http/test_retry.py +7 -7
  122. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/schema/test_loader.py +14 -24
  123. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/schema/test_source.py +29 -35
  124. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/schema/test_source_ttl.py +46 -50
  125. netbox_super_cli-1.8.0/tests/tui/__init__.py +0 -0
  126. netbox_super_cli-1.8.0/tests/tui/test_branch_indicator.py +24 -0
  127. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_list_screen.py +298 -0
  128. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_view.py +17 -1
  129. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/uv.lock +365 -285
  130. netbox_super_cli-1.6.3/nsc/auth/verify.py +0 -143
  131. netbox_super_cli-1.6.3/tests/auth/test_verify.py +0 -84
  132. netbox_super_cli-1.6.3/tests/conftest.py +0 -41
  133. netbox_super_cli-1.6.3/tests/http/test_client.py +0 -384
  134. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  135. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  136. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/.github/ISSUE_TEMPLATE/docs.yml +0 -0
  137. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  138. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/.github/dependabot.yml +0 -0
  139. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/.github/pull_request_template.md +0 -0
  140. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/.github/workflows/skill-convention-review.yml +0 -0
  141. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/.python-version +0 -0
  142. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/LICENSE +0 -0
  143. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/architecture/caching.md +0 -0
  144. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/architecture/command-generation.md +0 -0
  145. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/architecture/schema-loading.md +0 -0
  146. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/assets/tui/detail.svg +0 -0
  147. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/assets/tui/filter.svg +0 -0
  148. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/assets/tui/list.svg +0 -0
  149. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/assets/tui/picker.svg +0 -0
  150. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/assets/tui/search.svg +0 -0
  151. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/contributing/adding-bundled-schemas.md +0 -0
  152. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/contributing/branching.md +0 -0
  153. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/contributing/development.md +0 -0
  154. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/getting-started/install.md +0 -0
  155. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/guides/audit-log.md +0 -0
  156. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/reference/cli.md +0 -0
  157. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/reference/exit-codes.md +0 -0
  158. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/reference/schemas.md +0 -0
  159. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/__init__.py +0 -0
  160. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/__main__.py +0 -0
  161. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/aliases/__init__.py +0 -0
  162. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/aliases/resolver.py +0 -0
  163. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/auth/__init__.py +0 -0
  164. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/builder/__init__.py +0 -0
  165. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/builder/build.py +0 -0
  166. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cache/__init__.py +0 -0
  167. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cache/store.py +0 -0
  168. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/__init__.py +0 -0
  169. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/commands_dump.py +0 -0
  170. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/config_commands.py +0 -0
  171. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/init_commands.py +0 -0
  172. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/skill_commands.py +0 -0
  173. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/writes/__init__.py +0 -0
  174. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/writes/apply.py +0 -0
  175. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/writes/coercion.py +0 -0
  176. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/writes/confirmation.py +0 -0
  177. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/writes/input.py +0 -0
  178. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/writes/preflight.py +0 -0
  179. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/completion/__init__.py +0 -0
  180. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/completion/providers.py +0 -0
  181. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/config/__init__.py +0 -0
  182. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/config/saved_searches.py +0 -0
  183. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/config/settings.py +0 -0
  184. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/http/__init__.py +0 -0
  185. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/model/__init__.py +0 -0
  186. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/model/command_model.py +0 -0
  187. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/output/__init__.py +0 -0
  188. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/output/_console.py +0 -0
  189. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/output/colors.py +0 -0
  190. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/output/csv_.py +0 -0
  191. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/output/errors.py +0 -0
  192. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/output/explain.py +0 -0
  193. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/output/flatten.py +0 -0
  194. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/output/headers.py +0 -0
  195. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/output/json_.py +0 -0
  196. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/output/jsonl.py +0 -0
  197. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/output/render.py +0 -0
  198. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/output/table.py +0 -0
  199. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/output/yaml_.py +0 -0
  200. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/savedfilters/__init__.py +0 -0
  201. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/savedfilters/custom_fields.py +0 -0
  202. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/savedfilters/objecttypes.py +0 -0
  203. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/savedfilters/params.py +0 -0
  204. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/savedfilters/store.py +0 -0
  205. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/savedfilters/tags.py +0 -0
  206. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/schema/__init__.py +0 -0
  207. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/schema/hashing.py +0 -0
  208. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/schema/models.py +0 -0
  209. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/schemas/__init__.py +0 -0
  210. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/schemas/bundled/__init__.py +0 -0
  211. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/schemas/bundled/manifest.yaml +0 -0
  212. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/schemas/bundled/netbox-4.5.10.json.gz +0 -0
  213. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/schemas/bundled/netbox-4.6.0.json.gz +0 -0
  214. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/skill/__init__.py +0 -0
  215. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/_bindings.py +0 -0
  216. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/bulk.py +0 -0
  217. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/catalog.py +0 -0
  218. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/columns.py +0 -0
  219. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/errors.py +0 -0
  220. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/filters.py +0 -0
  221. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/fk.py +0 -0
  222. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/forms.py +0 -0
  223. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/nav.py +0 -0
  224. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/relations.py +0 -0
  225. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/screens/__init__.py +0 -0
  226. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/screens/bulk_edit_form.py +0 -0
  227. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/screens/columns.py +0 -0
  228. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/screens/detail.py +0 -0
  229. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/screens/edit_form.py +0 -0
  230. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/screens/filter.py +0 -0
  231. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/screens/global_search.py +0 -0
  232. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/screens/picker.py +0 -0
  233. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/screens/record_picker.py +0 -0
  234. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/screens/saved_search_picker.py +0 -0
  235. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/search.py +0 -0
  236. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/selection.py +0 -0
  237. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/widgets/__init__.py +0 -0
  238. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/widgets/_modal.py +0 -0
  239. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/widgets/bulk_diff.py +0 -0
  240. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/widgets/bulk_summary.py +0 -0
  241. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/widgets/confirm.py +0 -0
  242. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/widgets/diff.py +0 -0
  243. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/widgets/help.py +0 -0
  244. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/widgets/nav_tree.py +0 -0
  245. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/scripts/sync_agents_md.py +0 -0
  246. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/__init__.py +0 -0
  247. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/aliases/__init__.py +0 -0
  248. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/aliases/test_resolver.py +0 -0
  249. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/audit/__init__.py +0 -0
  250. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/audit/test_redaction_full.py +0 -0
  251. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/auth/__init__.py +0 -0
  252. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/benchmarks/__init__.py +0 -0
  253. {netbox_super_cli-1.6.3/tests/builder → netbox_super_cli-1.8.0/tests/branching}/__init__.py +0 -0
  254. {netbox_super_cli-1.6.3/tests/cache → netbox_super_cli-1.8.0/tests/builder}/__init__.py +0 -0
  255. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/builder/test_build.py +0 -0
  256. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/builder/test_default_columns.py +0 -0
  257. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/builder/test_fk_metadata.py +0 -0
  258. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/builder/test_redaction_marking.py +0 -0
  259. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/builder/test_request_body_shape.py +0 -0
  260. {netbox_super_cli-1.6.3/tests/cli → netbox_super_cli-1.8.0/tests/cache}/__init__.py +0 -0
  261. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cache/test_prune.py +0 -0
  262. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cache/test_store.py +0 -0
  263. {netbox_super_cli-1.6.3/tests/cli/writes → netbox_super_cli-1.8.0/tests/cli}/__init__.py +0 -0
  264. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_completion_protocol_smoke.py +0 -0
  265. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_completion_smoke.py +0 -0
  266. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_config_commands.py +0 -0
  267. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_dynamic_completion.py +0 -0
  268. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_explain.py +0 -0
  269. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_globals_color.py +0 -0
  270. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_init_commands.py +0 -0
  271. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_lazy_textual_import.py +0 -0
  272. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_meta_subcommands_under_broken_config.py +0 -0
  273. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_registration.py +0 -0
  274. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_runtime.py +0 -0
  275. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_runtime_color.py +0 -0
  276. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_skill_commands.py +0 -0
  277. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_stdin_sniffer.py +0 -0
  278. {netbox_super_cli-1.6.3/tests/config → netbox_super_cli-1.8.0/tests/cli/writes}/__init__.py +0 -0
  279. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/writes/test_apply.py +0 -0
  280. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/writes/test_bulk.py +0 -0
  281. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/writes/test_confirmation.py +0 -0
  282. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/writes/test_handler_helpers.py +0 -0
  283. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/writes/test_handlers_audit.py +0 -0
  284. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/writes/test_input.py +0 -0
  285. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/writes/test_preflight.py +0 -0
  286. {netbox_super_cli-1.6.3/tests/http → netbox_super_cli-1.8.0/tests/config}/__init__.py +0 -0
  287. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/config/test_loader.py +0 -0
  288. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/config/test_saved_search_fallback.py +0 -0
  289. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/config/test_saved_searches.py +0 -0
  290. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/config/test_settings_private_dir.py +0 -0
  291. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/config/test_writer_atomicity.py +0 -0
  292. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/config/test_writer_dotted_paths.py +0 -0
  293. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/config/test_writer_roundtrip.py +0 -0
  294. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/e2e/__init__.py +0 -0
  295. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/e2e/docker-compose.yml +0 -0
  296. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/e2e/test_auth_error_envelope.py +0 -0
  297. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/e2e/wait_for_netbox.sh +0 -0
  298. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/fixtures/profiles/single_profile.yaml +0 -0
  299. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/fixtures/responses/auth_401.json +0 -0
  300. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/fixtures/responses/circuits_providers_list.json +0 -0
  301. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/fixtures/responses/dcim_devices_get.json +0 -0
  302. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/fixtures/responses/dcim_devices_list_p1.json +0 -0
  303. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/fixtures/responses/dcim_devices_list_p2.json +0 -0
  304. {netbox_super_cli-1.6.3/tests/model → netbox_super_cli-1.8.0/tests/http}/__init__.py +0 -0
  305. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/http/test_audit.py +0 -0
  306. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/http/test_audit_permissions.py +0 -0
  307. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/http/test_audit_redaction.py +0 -0
  308. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/http/test_errors.py +0 -0
  309. {netbox_super_cli-1.6.3/tests/output → netbox_super_cli-1.8.0/tests/model}/__init__.py +0 -0
  310. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/model/test_command_model.py +0 -0
  311. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/model/test_request_body_shape.py +0 -0
  312. {netbox_super_cli-1.6.3/tests/savedfilters → netbox_super_cli-1.8.0/tests/output}/__init__.py +0 -0
  313. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/output/test_colors.py +0 -0
  314. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/output/test_console.py +0 -0
  315. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/output/test_csv.py +0 -0
  316. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/output/test_errors.py +0 -0
  317. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/output/test_errors_aliases.py +0 -0
  318. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/output/test_errors_color.py +0 -0
  319. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/output/test_explain.py +0 -0
  320. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/output/test_explain_color.py +0 -0
  321. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/output/test_flatten.py +0 -0
  322. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/output/test_input_error_envelope.py +0 -0
  323. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/output/test_json.py +0 -0
  324. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/output/test_jsonl.py +0 -0
  325. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/output/test_render_dispatch.py +0 -0
  326. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/output/test_table.py +0 -0
  327. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/output/test_table_color.py +0 -0
  328. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/output/test_yaml.py +0 -0
  329. {netbox_super_cli-1.6.3/tests/schema → netbox_super_cli-1.8.0/tests/savedfilters}/__init__.py +0 -0
  330. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/savedfilters/test_custom_fields.py +0 -0
  331. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/savedfilters/test_objecttypes.py +0 -0
  332. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/savedfilters/test_params.py +0 -0
  333. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/savedfilters/test_store.py +0 -0
  334. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/savedfilters/test_tags.py +0 -0
  335. {netbox_super_cli-1.6.3/tests/scripts → netbox_super_cli-1.8.0/tests/schema}/__init__.py +0 -0
  336. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/schema/test_hashing.py +0 -0
  337. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/schema/test_models.py +0 -0
  338. {netbox_super_cli-1.6.3/tests/skill → netbox_super_cli-1.8.0/tests/scripts}/__init__.py +0 -0
  339. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/scripts/test_gen_docs.py +0 -0
  340. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/scripts/test_sync_agents_md.py +0 -0
  341. {netbox_super_cli-1.6.3/tests/tui → netbox_super_cli-1.8.0/tests/skill}/__init__.py +0 -0
  342. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/skill/test_bundle.py +0 -0
  343. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/test_packaging.py +0 -0
  344. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_app.py +0 -0
  345. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_bindings.py +0 -0
  346. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_bulk_apply.py +0 -0
  347. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_bulk_diff.py +0 -0
  348. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_bulk_diff_modal.py +0 -0
  349. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_bulk_edit_form.py +0 -0
  350. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_bulk_import_isolation.py +0 -0
  351. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_bulk_summary.py +0 -0
  352. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_catalog.py +0 -0
  353. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_column_chooser.py +0 -0
  354. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_columns.py +0 -0
  355. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_detail_screen.py +0 -0
  356. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_diff.py +0 -0
  357. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_diff_modal.py +0 -0
  358. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_edit_form.py +0 -0
  359. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_errors.py +0 -0
  360. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_filter_screen.py +0 -0
  361. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_filters.py +0 -0
  362. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_fk_resolve.py +0 -0
  363. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_forms.py +0 -0
  364. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_global_search.py +0 -0
  365. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_help_overlay.py +0 -0
  366. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_keymap.py +0 -0
  367. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_picker.py +0 -0
  368. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_record_picker.py +0 -0
  369. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_relations.py +0 -0
  370. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_saved_filter_integration.py +0 -0
  371. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_search.py +0 -0
  372. {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_selection.py +0 -0
@@ -13,8 +13,8 @@ jobs:
13
13
  startup-time:
14
14
  runs-on: ubuntu-latest
15
15
  steps:
16
- - uses: actions/checkout@v7
17
- - uses: astral-sh/setup-uv@v7
16
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
17
+ - uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
18
18
  - name: Install
19
19
  run: uv sync --all-extras --dev
20
20
  - name: Benchmark
@@ -41,13 +41,13 @@ jobs:
41
41
  actions: read # Required for Claude to read CI results on PRs
42
42
  steps:
43
43
  - name: Checkout repository
44
- uses: actions/checkout@v7
44
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
45
45
  with:
46
46
  fetch-depth: 1
47
47
 
48
48
  - name: Run Claude Code
49
49
  id: claude
50
- uses: anthropics/claude-code-action@v1
50
+ uses: anthropics/claude-code-action@db77d4d3c98f3f6380e7cd45ffba2342a3dbde3c # v1
51
51
  with:
52
52
  claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
53
53
 
@@ -26,9 +26,9 @@ jobs:
26
26
  build:
27
27
  runs-on: ubuntu-latest
28
28
  steps:
29
- - uses: actions/checkout@v7
29
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
30
30
  - name: Install uv
31
- uses: astral-sh/setup-uv@v7
31
+ uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
32
32
  with:
33
33
  enable-cache: true
34
34
  - name: Install Python
@@ -36,10 +36,10 @@ jobs:
36
36
  - name: Sync deps (runtime + docs)
37
37
  run: uv sync --frozen --group docs
38
38
  - name: Build site (strict)
39
- run: uv run mkdocs build --strict
39
+ run: uv run zensical build --strict
40
40
  - name: Upload Pages artifact
41
41
  if: github.ref_type == 'tag'
42
- uses: actions/upload-pages-artifact@v5
42
+ uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5
43
43
  with:
44
44
  path: site
45
45
 
@@ -52,4 +52,4 @@ jobs:
52
52
  url: ${{ steps.deployment.outputs.page_url }}
53
53
  steps:
54
54
  - id: deployment
55
- uses: actions/deploy-pages@v5
55
+ uses: actions/deploy-pages@368f82528645a54fb793d4d04e342629a3f51346 # v5
@@ -6,6 +6,11 @@ on:
6
6
  pull_request:
7
7
  paths:
8
8
  - 'nsc/http/**'
9
+ - 'nsc/branching/**'
10
+ - 'nsc/cli/branch_commands.py'
11
+ - 'nsc/auth/**'
12
+ - 'nsc/cli/login_commands.py'
13
+ - 'nsc/cli/profiles_commands.py'
9
14
  - 'nsc/cli/handlers.py'
10
15
  - 'nsc/cli/registration.py'
11
16
  - 'nsc/cli/writes/**'
@@ -34,8 +39,8 @@ jobs:
34
39
  env:
35
40
  NETBOX_IMAGE: netboxcommunity/netbox:${{ matrix.netbox-version }}
36
41
  steps:
37
- - uses: actions/checkout@v7
38
- - uses: astral-sh/setup-uv@v7
42
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
43
+ - uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
39
44
  - name: Sync deps
40
45
  run: uv sync --frozen
41
46
  - name: Start NetBox
@@ -54,3 +59,33 @@ jobs:
54
59
  - name: Stop NetBox
55
60
  if: always()
56
61
  run: docker compose -f tests/e2e/docker-compose.yml down -v
62
+
63
+ e2e-branching:
64
+ name: e2e-branching (v4.7.3 + branching 1.2.2)
65
+ runs-on: ubuntu-latest
66
+ timeout-minutes: 20
67
+ env:
68
+ NETBOX_IMAGE: netboxcommunity/netbox:v4.7.3
69
+ COMPOSE: -f tests/e2e/docker-compose.yml -f tests/e2e/docker-compose.branching.yml
70
+ steps:
71
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
72
+ - uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
73
+ - name: Sync deps
74
+ run: uv sync --frozen
75
+ - name: Build and start NetBox with Branching
76
+ run: docker compose $COMPOSE up -d --build
77
+ - name: Wait for NetBox
78
+ run: tests/e2e/wait_for_netbox.sh
79
+ - name: Run branching e2e tests
80
+ env:
81
+ NSC_E2E: '1'
82
+ NSC_E2E_BRANCHING: '1'
83
+ NSC_URL: http://127.0.0.1:8080
84
+ NSC_TOKEN: '0123456789abcdef0123456789abcdef01234567'
85
+ run: uv run pytest tests/e2e/test_branching.py -v
86
+ - name: Dump container logs on failure
87
+ if: failure()
88
+ run: docker compose $COMPOSE logs
89
+ - name: Stop NetBox
90
+ if: always()
91
+ run: docker compose $COMPOSE down -v
@@ -12,9 +12,9 @@ jobs:
12
12
  lint:
13
13
  runs-on: ubuntu-latest
14
14
  steps:
15
- - uses: actions/checkout@v7
15
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
16
16
  - name: Install uv
17
- uses: astral-sh/setup-uv@v7
17
+ uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
18
18
  with:
19
19
  enable-cache: true
20
20
  - name: Install Python
@@ -31,9 +31,9 @@ jobs:
31
31
  docs-reference-fresh:
32
32
  runs-on: ubuntu-latest
33
33
  steps:
34
- - uses: actions/checkout@v7
34
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
35
35
  - name: Install uv
36
- uses: astral-sh/setup-uv@v7
36
+ uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
37
37
  with:
38
38
  enable-cache: true
39
39
  - name: Install Python
@@ -46,9 +46,9 @@ jobs:
46
46
  agents-md-fresh:
47
47
  runs-on: ubuntu-latest
48
48
  steps:
49
- - uses: actions/checkout@v7
49
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
50
50
  - name: Install uv
51
- uses: astral-sh/setup-uv@v7
51
+ uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
52
52
  with:
53
53
  enable-cache: true
54
54
  - name: Install Python
@@ -39,7 +39,7 @@ jobs:
39
39
  # prerequisites).
40
40
  steps:
41
41
  - name: Checkout (full history for changelog notes)
42
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
42
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
43
43
  with:
44
44
  fetch-depth: 0
45
45
 
@@ -62,7 +62,7 @@ jobs:
62
62
  echo "Tag $GITHUB_REF_NAME ($GITHUB_SHA) is on main."
63
63
 
64
64
  - name: Install uv
65
- uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0
65
+ uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
66
66
  with:
67
67
  enable-cache: true
68
68
 
@@ -110,7 +110,7 @@ jobs:
110
110
  fi
111
111
 
112
112
  - name: Publish to PyPI (trusted publishing)
113
- uses: pypa/gh-action-pypi-publish@release/v1
113
+ uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1
114
114
  with:
115
115
  # No `password:` — trusted publishing uses the OIDC token bound
116
116
  # to id-token: write above. PyPI must have a Trusted Publisher
@@ -16,9 +16,9 @@ jobs:
16
16
  matrix:
17
17
  python: ["3.12", "3.13", "3.14"]
18
18
  steps:
19
- - uses: actions/checkout@v7
19
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
20
20
  - name: Install uv
21
- uses: astral-sh/setup-uv@v7
21
+ uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
22
22
  with:
23
23
  enable-cache: true
24
24
  - name: Install Python
@@ -33,7 +33,7 @@ venv/
33
33
  # Local-only design notes (kept out of git history)
34
34
  docs/superpowers/
35
35
 
36
- # mkdocs
36
+ # docs build output
37
37
  site/
38
38
 
39
39
  # git worktrees
@@ -27,11 +27,12 @@ repos:
27
27
  - click>=8.1
28
28
  - typer>=0.12
29
29
  - rich>=13.7
30
- - httpx>=0.27
30
+ - httpx2>=2.5
31
31
  - "ruamel.yaml>=0.18"
32
32
  - structlog>=24.1
33
33
  - platformdirs>=4.2
34
34
  - textual>=0.50
35
+ - keyring>=25.0
35
36
  - types-PyYAML>=6.0
36
37
  args: [--strict]
37
38
  files: ^(nsc|scripts)/
@@ -15,11 +15,12 @@ This is the contributor guide for AI agents (and humans!) modifying this repo. T
15
15
  - `nsc/model/` — the normalized command tree (data only, framework-free). The "brain".
16
16
  - `nsc/builder/` — converts a parsed schema into a `CommandModel`.
17
17
  - `nsc/cli/` — the Typer app; consumes a `CommandModel`.
18
- - `nsc/http/` — thin httpx wrapper: auth, retries, audit log.
18
+ - `nsc/http/` — thin httpx2 wrapper: auth, retries, audit log.
19
19
  - `nsc/output/` — formatters (table/json/jsonl/yaml/csv) + error envelope.
20
20
  - `nsc/config/` — config loader + Pydantic models + ruamel.yaml round-trip writer.
21
21
  - `nsc/cache/` — disk cache for generated command-models.
22
22
  - `nsc/auth/` — login verification helpers (pre-flight probes, token rotate).
23
+ - `nsc/branching/` — NetBox Branching: branch name→schema_id resolution, lifecycle API calls, job polling. Framework-free; `nsc/http` must not import it (the client takes a resolver callable).
23
24
  - `nsc/aliases/` — curated alias resolver (`ls`, `get`, `rm`, `search`). Framework-free.
24
25
  - `nsc/completion/` — dynamic shell-completion: framework-free providers + cheap on-disk cache probe + Typer `shell_complete` callbacks.
25
26
  - `nsc/skill/` — bundle-path helper for the portable `SKILL.md` shipped in the wheel.
@@ -2,6 +2,129 @@
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
+ ## Unreleased
6
+
7
+ ## v1.8.0 — 2026-10-22
8
+
9
+ Minor release. Adds NetBox Branching support (`--branch`, `NSC_BRANCH`,
10
+ `nsc branch …`), so changes can be staged in a branch, reviewed and merged.
11
+ Also adds OS keyring token storage, lazy TUI pagination with CLI truncation
12
+ notices, and a fix for `nsc login` reporting the wrong user.
13
+
14
+ ### Added
15
+
16
+ - **NetBox Branching support** ([#166]). Run any command inside a
17
+ [NetBox Branching](https://netboxlabs.com/docs/extensions/branching/) branch
18
+ with `--branch NAME`, `NSC_BRANCH`, or a sticky per-profile branch set by
19
+ `nsc branch use NAME` (`--branch main` forces main). nsc resolves the name
20
+ to the plugin's `schema_id` and sends `X-NetBox-Branch` on every request.
21
+ Each command run in a branch prints `⎇ branch: <name>` on stderr, and the
22
+ TUI header shows it. A missing or non-`ready` branch fails loudly (exit
23
+ 9/12) and never falls back to main. New `nsc branch` group: `list`, `show`,
24
+ `current`, `create` (waits until ready, `--use`), `use` / `use --main`,
25
+ `diff`, and `sync` / `merge` / `revert` / `archive` / `delete`. Like every
26
+ nsc write, these are dry-run unless you pass `--apply`. Conflicts exit 10
27
+ with `details.conflicts`, and `--acknowledge-conflicts` proceeds anyway.
28
+ Targets NetBox 4.7 with `netboxlabs-netbox-branching` 1.2.x; a new
29
+ `e2e-branching` CI job runs it live. See the
30
+ [branching guide](docs/guides/branching.md).
31
+ - **OS keyring token storage** ([#1]). A new `token: !keyring NAME` config tag
32
+ resolves the token from the OS keyring (macOS Keychain, Secret Service,
33
+ Windows Credential Manager) under service `nsc`, username `NAME`.
34
+ `nsc login --new|--rotate --store keyring [--keyring-name NAME]` verifies the
35
+ token, writes it to the keyring, and stores only the `!keyring` reference in
36
+ `~/.nsc/config.yaml`, so the plaintext token never touches disk. Any
37
+ invocation that builds the dynamic command tree reads the keyring, including
38
+ bare `nsc` and `nsc --help`; shell completion and the meta commands
39
+ (`config`, `profiles`, `cache`, `init`, `commands`, `skill`) do not. A missing
40
+ entry or an unavailable backend yields a `config` error envelope (exit 12),
41
+ except that `--help` on a static command still prints usage. `nsc login`
42
+ refuses to overwrite a keyring entry that another profile still references
43
+ (for example after `nsc profiles rename`) and asks for a distinct
44
+ `--keyring-name`. `keyring`
45
+ is a new core dependency, imported lazily so it adds no startup cost. See
46
+ the new [OS keyring storage guide](docs/guides/keyring.md).
47
+ `--keyring-name` is stripped of surrounding whitespace, and a blank name is
48
+ rejected as a usage error before the token prompt.
49
+
50
+ ### Fixed
51
+
52
+ - **`nsc login` / `nsc profiles add` no longer report a random user** ([#150]).
53
+ The identity probe used to take the owner of the first row of
54
+ `/api/users/tokens/`, which for admins is often another user's token. The
55
+ caller is now identified from the token they presented: v2 (`nbt_…`) tokens
56
+ are looked up by their non-secret key id; v1 tokens are matched client-side
57
+ against the retrievable plaintext when NetBox exposes it
58
+ (`ALLOW_TOKEN_RETRIEVAL`; the plaintext is never sent in a query string), or
59
+ by every visible token sharing one owner. When the user cannot be determined reliably, nsc prints
60
+ `authenticated (user unknown)` instead of guessing.
61
+ - **`nsc tui` lists are no longer capped at the first page** ([#151]). The list
62
+ screen loads 100 rows at a time and fetches the next chunk (following NetBox
63
+ `next` links) when the cursor reaches the last row or you press <kbd>m</kbd>.
64
+ The header shows `N of M` (rows loaded vs. the server's `count`). Loading stops
65
+ at 10,000 rows with a hint to filter instead. A page that fails mid-chunk
66
+ keeps the rows already received (retry with <kbd>m</kbd>), and a refresh no
67
+ longer drops selections made beyond the first chunk.
68
+ - **A negative `--limit` is now a usage error** instead of a Python traceback,
69
+ and `defaults.page_size` must be at least 1.
70
+ - **CLI `list` / `ls` / `search` now report truncation** ([#151]). When the
71
+ default page size hides records the server still has, a one-line
72
+ `nsc: showing 50 of 1234 results; pass --all ...` notice is printed on stderr
73
+ (stdout is unchanged). The default page also no longer fetches one extra page
74
+ from the server just to discard it.
75
+ - **Pages after the first keep multi-value filters** ([#151]). Following a
76
+ NetBox `next` link no longer drops repeated query keys, so
77
+ `--site a --site b --all` returns both sites on every page.
78
+ - **Pagination works when NetBox is served under a sub-path** (`BASE_PATH`,
79
+ e.g. `https://host/netbox`). The second and later pages no longer 404 from a
80
+ doubled path prefix.
81
+
82
+ ### Changed
83
+
84
+ - `NetBoxClient.paginate` now returns a lazy, resumable `Pager`
85
+ (`nsc/http/pagination.py`) exposing the server `total` and `has_more`, shared
86
+ by the CLI and the TUI.
87
+ - `nsc login --store` now rejects unknown values. Previously any value other
88
+ than `env` silently fell back to plaintext, so a typo could write the token
89
+ to disk. `nsc login --rotate` with no `--store` keeps an existing
90
+ `!keyring` reference instead of replacing it with plaintext.
91
+
92
+ [#1]: https://github.com/thomaschristory/netbox-super-cli/issues/1
93
+ [#166]: https://github.com/thomaschristory/netbox-super-cli/issues/166
94
+ [#150]: https://github.com/thomaschristory/netbox-super-cli/issues/150
95
+ [#151]: https://github.com/thomaschristory/netbox-super-cli/issues/151
96
+
97
+ ## v1.7.0 — 2026-09-10
98
+
99
+ Minor release. Migrates the HTTP stack from `httpx` to Pydantic's maintained
100
+ `httpx2` fork, and keeps `httpx2` off the `nsc --help` cold-start path. No
101
+ user-facing CLI or behavior changes.
102
+
103
+ ### Changed
104
+
105
+ - **Migrated the HTTP stack from `httpx` to `httpx2`** ([#146]). `httpx2` is
106
+ Pydantic's stewardship continuation of httpx (same author, API-identical) —
107
+ httpx itself has seen limited activity, and httpx2 is the reliably-maintained
108
+ path forward with timely security updates. The dependency floor is now
109
+ `httpx2>=2.5`; the source layer is a mechanical rename (`import httpx2`,
110
+ `httpx2.Client`/`httpx2.Response`/…). Test mocking moves from global `respx`
111
+ to the `pytest-httpx2` plugin's `httpx2_mock` fixture (a `respx.Router`, by
112
+ respx's own author), which targets httpx2's `httpcore2` transport. No
113
+ user-facing behavior or CLI surface changes.
114
+ - **httpx2 is now kept off the `nsc --help` / cold-start path** ([#13]). httpx2 is
115
+ the single heaviest import in the tree (~65ms cold), and nothing on the startup
116
+ path needs an HTTP client. It was being pulled in eagerly through the
117
+ runtime → client → retry chain (plus `cache`, `schema`, and `login`
118
+ command modules). All of these now import httpx2 lazily, at first request. Cold
119
+ startup drops by roughly httpx2's import cost, bringing the median back under the
120
+ 300ms project target. A new guard test (`test_lazy_httpx2_import.py`) asserts
121
+ httpx2 never loads on `nsc --help`, and the startup benchmark's threshold is
122
+ re-baselined to 300ms so an over-threshold skip once again signals a real
123
+ regression instead of firing on every run.
124
+
125
+ [#13]: https://github.com/thomaschristory/netbox-super-cli/issues/13
126
+ [#146]: https://github.com/thomaschristory/netbox-super-cli/issues/146
127
+
5
128
  ## v1.6.3 — 2026-07-03
6
129
 
7
130
  Patch release. Stops an offline instance from rebuilding the command model from
@@ -8,11 +8,12 @@ This is the contributor guide for AI agents (and humans!) modifying this repo. T
8
8
  - `nsc/model/` — the normalized command tree (data only, framework-free). The "brain".
9
9
  - `nsc/builder/` — converts a parsed schema into a `CommandModel`.
10
10
  - `nsc/cli/` — the Typer app; consumes a `CommandModel`.
11
- - `nsc/http/` — thin httpx wrapper: auth, retries, audit log.
11
+ - `nsc/http/` — thin httpx2 wrapper: auth, retries, audit log.
12
12
  - `nsc/output/` — formatters (table/json/jsonl/yaml/csv) + error envelope.
13
13
  - `nsc/config/` — config loader + Pydantic models + ruamel.yaml round-trip writer.
14
14
  - `nsc/cache/` — disk cache for generated command-models.
15
15
  - `nsc/auth/` — login verification helpers (pre-flight probes, token rotate).
16
+ - `nsc/branching/` — NetBox Branching: branch name→schema_id resolution, lifecycle API calls, job polling. Framework-free; `nsc/http` must not import it (the client takes a resolver callable).
16
17
  - `nsc/aliases/` — curated alias resolver (`ls`, `get`, `rm`, `search`). Framework-free.
17
18
  - `nsc/completion/` — dynamic shell-completion: framework-free providers + cheap on-disk cache probe + Typer `shell_complete` callbacks.
18
19
  - `nsc/skill/` — bundle-path helper for the portable `SKILL.md` shipped in the wheel.
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: netbox-super-cli
3
- Version: 1.6.3
3
+ Version: 1.8.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
6
  Project-URL: Documentation, https://thomaschristory.github.io/netbox-super-cli/
@@ -23,7 +23,8 @@ Classifier: Programming Language :: Python :: 3.14
23
23
  Classifier: Topic :: System :: Networking
24
24
  Requires-Python: >=3.12
25
25
  Requires-Dist: click>=8.1
26
- Requires-Dist: httpx>=0.27
26
+ Requires-Dist: httpx2>=2.5
27
+ Requires-Dist: keyring>=25.0
27
28
  Requires-Dist: platformdirs>=4.2
28
29
  Requires-Dist: pydantic>=2.7
29
30
  Requires-Dist: rich>=13.7
@@ -64,6 +65,7 @@ One binary, any NetBox version, every plugin endpoint — the schema, not hand-w
64
65
  - **Plugins just work.** If your install has plugins, their endpoints appear as commands automatically.
65
66
  - **Multi-instance.** Named profiles per NetBox instance, plus env-var overrides.
66
67
  - **Safe by default.** POST/PATCH/PUT/DELETE preview as dry-runs unless you pass `--apply`.
68
+ - **NetBox Branching.** Stage changes in a branch (`--branch`, `NSC_BRANCH`, `nsc branch use`), review with `nsc branch diff`, merge with `nsc branch merge --apply`. See [the guide](docs/guides/branching.md).
67
69
  - **Agent-friendly.** Deterministic command shape, machine-readable JSON output, stable error envelope with documented exit codes.
68
70
  - **Interactive TUI.** `nsc tui` opens a keyboard-driven terminal UI — see below.
69
71
 
@@ -208,6 +210,25 @@ The wire body sent to NetBox is **not** redacted — only the audit log. A faile
208
210
 
209
211
  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).
210
212
 
213
+ ## NetBox Branching
214
+
215
+ If your NetBox runs the [Branching plugin](https://netboxlabs.com/docs/extensions/branching/),
216
+ any command can stage its changes in a branch for review:
217
+
218
+ ```sh
219
+ nsc branch create add-london --use # create, wait until ready, make it sticky
220
+ nsc dcim sites create -f london.yaml --apply # lands in the branch; stderr shows "⎇ branch: add-london"
221
+ nsc branch diff # review the staged changes
222
+ nsc branch merge # dry-run, validated server-side
223
+ nsc branch merge --apply # merge into main
224
+ nsc branch use --main # back to main
225
+ ```
226
+
227
+ `--branch NAME` and `NSC_BRANCH` select a branch for a single command or a
228
+ whole shell, and agents should use these. A merged, missing or not-ready branch
229
+ fails loudly and never falls back to main. See the
230
+ [branching guide](docs/guides/branching.md).
231
+
211
232
  ## Curated aliases
212
233
 
213
234
  `nsc ls`, `nsc get`, `nsc rm`, and `nsc search` are short verbs over the dynamic
@@ -29,6 +29,7 @@ One binary, any NetBox version, every plugin endpoint — the schema, not hand-w
29
29
  - **Plugins just work.** If your install has plugins, their endpoints appear as commands automatically.
30
30
  - **Multi-instance.** Named profiles per NetBox instance, plus env-var overrides.
31
31
  - **Safe by default.** POST/PATCH/PUT/DELETE preview as dry-runs unless you pass `--apply`.
32
+ - **NetBox Branching.** Stage changes in a branch (`--branch`, `NSC_BRANCH`, `nsc branch use`), review with `nsc branch diff`, merge with `nsc branch merge --apply`. See [the guide](docs/guides/branching.md).
32
33
  - **Agent-friendly.** Deterministic command shape, machine-readable JSON output, stable error envelope with documented exit codes.
33
34
  - **Interactive TUI.** `nsc tui` opens a keyboard-driven terminal UI — see below.
34
35
 
@@ -173,6 +174,25 @@ The wire body sent to NetBox is **not** redacted — only the audit log. A faile
173
174
 
174
175
  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).
175
176
 
177
+ ## NetBox Branching
178
+
179
+ If your NetBox runs the [Branching plugin](https://netboxlabs.com/docs/extensions/branching/),
180
+ any command can stage its changes in a branch for review:
181
+
182
+ ```sh
183
+ nsc branch create add-london --use # create, wait until ready, make it sticky
184
+ nsc dcim sites create -f london.yaml --apply # lands in the branch; stderr shows "⎇ branch: add-london"
185
+ nsc branch diff # review the staged changes
186
+ nsc branch merge # dry-run, validated server-side
187
+ nsc branch merge --apply # merge into main
188
+ nsc branch use --main # back to main
189
+ ```
190
+
191
+ `--branch NAME` and `NSC_BRANCH` select a branch for a single command or a
192
+ whole shell, and agents should use these. A merged, missing or not-ready branch
193
+ fails loudly and never falls back to main. See the
194
+ [branching guide](docs/guides/branching.md).
195
+
176
196
  ## Curated aliases
177
197
 
178
198
  `nsc ls`, `nsc get`, `nsc rm`, and `nsc search` are short verbs over the dynamic
@@ -0,0 +1,12 @@
1
+ # Security policy
2
+
3
+ ## Supported versions
4
+
5
+ Only the latest release gets security fixes.
6
+
7
+ ## Reporting a vulnerability
8
+
9
+ Do not open a public issue. Use the private vulnerability reporting of GitHub:
10
+ [Report a vulnerability](https://github.com/thomaschristory/netbox-super-cli/security/advisories/new)
11
+ (**Security > Report a vulnerability** on the repository). Only the maintainer sees the report.
12
+ The maintainer replies, fixes the problem, and publishes an advisory with the fix.
@@ -1,6 +1,6 @@
1
1
  # HTTP client
2
2
 
3
- `nsc/http/` is a thin wrapper around `httpx.Client`.
3
+ `nsc/http/` is a thin wrapper around `httpx2.Client`.
4
4
 
5
5
  ## What it adds
6
6
 
@@ -20,6 +20,15 @@
20
20
  `final_attempt`; redaction is applied on every write, so a failed
21
21
  retry never unredacts.
22
22
  - Pagination helper that follows `next` URLs (used by `--all`).
23
+ - Optional NetBox Branching context. Given a `branch_resolver`, the client
24
+ resolves the branch lazily on its first request: the resolver's own lookups
25
+ go out unbranched, and every later request carries
26
+ `X-NetBox-Branch: <schema_id>`. Resolution is serialized under a lock, so
27
+ concurrent `--workers` threads wait instead of racing ahead without the
28
+ header. A failed resolution is stored and raised again on every later call,
29
+ so once a branch is selected no request can reach main. The resolver
30
+ itself lives in `nsc/branching/` (`nsc/http` does not import it), and
31
+ `nsc branch …` commands build a client without one.
23
32
  - Audit log appender at `~/.nsc/logs/audit.jsonl` — written for writes
24
33
  always, and for any request when `--debug` is set.
25
34
 
@@ -27,7 +36,7 @@
27
36
 
28
37
  Bulk write commands accept `--workers N` (default 1, max 32) to keep up to N
29
38
  requests in flight. Concurrency is **thread-based**: a `ThreadPoolExecutor`
30
- fans the per-record loop out over the single sync `httpx.Client` — there is no
39
+ fans the per-record loop out over the single sync `httpx2.Client` — there is no
31
40
  async path. Per-record `--on-error` semantics are preserved regardless of
32
41
  worker count. Audit appends are serialized by a module-level lock
33
42
  (`_APPEND_LOCK` in `nsc/http/audit.py`) wrapped around the whole
@@ -40,9 +49,9 @@ each record is one well-formed JSON line.
40
49
 
41
50
  A schema fetch may run before the first command request (only when the
42
51
  TTL fast-path misses — see [Caching](caching.md)); it uses its own
43
- short-lived `httpx.Client` in `nsc/schema/`, not this `NetBoxClient`.
52
+ short-lived `httpx2.Client` in `nsc/schema/`, not this `NetBoxClient`.
44
53
  Command requests then go through a single `NetBoxClient` whose
45
- `httpx.Client` carries the auth header for the life of the process.
54
+ `httpx2.Client` carries the auth header for the life of the process.
46
55
  Token rotation via `nsc login --rotate` does NOT invalidate the cached
47
56
  model (the schema hash is what keys the cache; the token never affected
48
57
  it).
@@ -91,7 +100,7 @@ contract.
91
100
 
92
101
  ## What it deliberately does not do
93
102
 
94
- - Async — sync only in v1, kept feasible by httpx if a future async path lands.
103
+ - Async — sync only in v1, kept feasible by httpx2 if a future async path lands.
95
104
  - Connection pooling across profiles — each profile gets its own `Client`.
96
105
  - Caching responses — caching the command-model is enough; caching response
97
106
  payloads would surprise users.
@@ -1,7 +1,7 @@
1
1
  # Architecture overview
2
2
 
3
3
  `nsc` is layered around a framework-free "brain". The brain — schema parsing
4
- and the normalized command-model — knows nothing about Typer, Rich, or httpx.
4
+ and the normalized command-model — knows nothing about Typer, Rich, or httpx2.
5
5
  The CLI layer consumes the brain; a future TUI could too without changing the
6
6
  brain.
7
7
 
@@ -11,11 +11,12 @@ nsc/
11
11
  ├── model/ # Normalized command-model (data only, framework-free)
12
12
  ├── builder/ # Schema → CommandModel
13
13
  ├── cli/ # Typer application; walks the model, registers commands
14
- ├── http/ # Thin httpx wrapper: auth, retries, audit
14
+ ├── http/ # Thin httpx2 wrapper: auth, retries, audit
15
15
  ├── output/ # Formatters (table/json/jsonl/yaml/csv) + error envelope
16
16
  ├── config/ # Pydantic config models + ruamel.yaml writer
17
17
  ├── cache/ # On-disk cache for generated CommandModels
18
18
  ├── auth/ # Login verification helpers (verify probe, token rotate)
19
+ ├── branching/ # NetBox Branching: branch lookup, lifecycle calls, job polling
19
20
  ├── aliases/ # Curated alias resolver (ls/get/rm/search)
20
21
  ├── completion/ # Dynamic shell-completion: providers + cache probe + Typer callbacks
21
22
  ├── skill/ # Bundle-path helper for the portable SKILL.md
@@ -11,7 +11,7 @@ on a `chore/release-X.Y.Z` feature branch, gets PR-merged into `main`,
11
11
  and only then is `vX.Y.Z` tagged on the resulting merge commit.
12
12
 
13
13
  The same `v*` tag push also publishes the documentation site.
14
- `docs.yml` runs build-only (`mkdocs build --strict`) on docs-touching
14
+ `docs.yml` runs build-only (`zensical build --strict`) on docs-touching
15
15
  pull requests, but the GitHub Pages **deploy** job only runs on a `v*`
16
16
  tag push — the live docs site updates on release, not on merge to
17
17
  `main`.
@@ -70,6 +70,22 @@ nsc dcim devices create --field name=foo --field site=1 --apply
70
70
  Add `--explain` to a dry-run to see the schema reasoning ("PATCH because of
71
71
  operationId `dcim_devices_partial_update`").
72
72
 
73
+ ## Branches (NetBox Branching)
74
+
75
+ If your server runs the NetBox Branching plugin, any command can run inside a
76
+ branch instead of main. Pick one with `--branch NAME`, `NSC_BRANCH=NAME`, or
77
+ make it sticky on the profile with `nsc branch use NAME`. While a branch is
78
+ active, every command prints `⎇ branch: NAME` on stderr. If the branch can't be
79
+ used (merged, missing, not ready), the command fails without sending anything.
80
+ It never quietly falls back to main. See [NetBox Branching](../guides/branching.md).
81
+
82
+ ```sh
83
+ nsc branch create add-london --use
84
+ nsc dcim sites create --field name=London --field slug=london --apply # staged in the branch
85
+ nsc branch diff
86
+ nsc branch merge --apply
87
+ ```
88
+
73
89
  ## Audit log
74
90
 
75
91
  Every wire request and its response are appended to
@@ -54,9 +54,13 @@ nsc login --rotate --profile prod # rotate the token
54
54
  nsc login --fetch-schema # verify, then fetch & cache the live schema
55
55
  ```
56
56
 
57
- `nsc login` probes `GET /api/status/` and `GET /api/users/tokens/?limit=1`
57
+ `nsc login` probes `GET /api/status/` and `GET /api/users/tokens/`
58
58
  (both must succeed) and prints `✓ authenticated as <user>, NetBox <version>`
59
- on success. On failure it emits the standard auth error envelope
59
+ on success. NetBox has no "current user" endpoint, so the user is derived from
60
+ the token you presented; when that can't be done reliably (e.g. a v1 token
61
+ held by an admin who can see other users' tokens) it prints
62
+ `✓ authenticated (user unknown), NetBox <version>` rather than guessing.
63
+ On failure it emits the standard auth error envelope
60
64
  (`type: auth`, exit 8).
61
65
 
62
66
  `--new` requires both `--profile` and `--url`, prompts for the token