netbox-super-cli 1.0.3__tar.gz → 1.0.4__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.
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/CHANGELOG.md +15 -2
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/PKG-INFO +10 -4
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/README.md +9 -3
- netbox_super_cli-1.0.4/docs/architecture/caching.md +72 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/docs/architecture/command-generation.md +4 -4
- netbox_super_cli-1.0.4/docs/architecture/http-client.md +66 -0
- netbox_super_cli-1.0.4/docs/architecture/overview.md +48 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/docs/architecture/schema-loading.md +13 -10
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/docs/contributing/adding-bundled-schemas.md +11 -6
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/docs/contributing/development.md +1 -1
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/docs/contributing/release-process.md +6 -0
- netbox_super_cli-1.0.4/docs/getting-started/first-run.md +88 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/docs/guides/ci-and-automation.md +10 -3
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/docs/guides/managing-profiles.md +27 -2
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/docs/guides/output-formats.md +5 -2
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/docs/guides/using-with-ai-agents.md +18 -7
- netbox_super_cli-1.0.4/docs/guides/working-with-plugins.md +54 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/docs/guides/writes-and-safety.md +18 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/_version.py +1 -1
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/aliases/resolver.py +4 -7
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/builder/build.py +26 -53
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/cache/store.py +3 -23
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/cli/app.py +0 -5
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/cli/commands_dump.py +3 -8
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/cli/config_commands.py +2 -3
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/cli/globals.py +1 -11
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/cli/handlers.py +7 -4
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/cli/runtime.py +23 -29
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/cli/writes/apply.py +3 -5
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/cli/writes/bulk.py +3 -3
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/cli/writes/input.py +1 -5
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/cli/writes/preflight.py +0 -1
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/config/loader.py +1 -3
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/config/models.py +3 -3
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/config/settings.py +1 -5
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/config/writer.py +1 -1
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/http/audit.py +1 -1
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/http/client.py +3 -6
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/http/retry.py +1 -1
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/output/errors.py +0 -3
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/schema/loader.py +1 -1
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/schema/models.py +1 -2
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/schema/source.py +4 -13
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/pyproject.toml +1 -1
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/skills/netbox-super-cli/SKILL.md +50 -21
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/uv.lock +4 -4
- netbox_super_cli-1.0.3/docs/architecture/caching.md +0 -46
- netbox_super_cli-1.0.3/docs/architecture/http-client.md +0 -44
- netbox_super_cli-1.0.3/docs/architecture/overview.md +0 -44
- netbox_super_cli-1.0.3/docs/getting-started/first-run.md +0 -72
- netbox_super_cli-1.0.3/docs/guides/working-with-plugins.md +0 -46
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/.github/workflows/agents-md-sync.yml +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/.github/workflows/bench.yml +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/.github/workflows/claude.yml +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/.github/workflows/docs.yml +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/.github/workflows/e2e.yml +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/.github/workflows/lint.yml +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/.github/workflows/release.yml +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/.github/workflows/test.yml +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/.gitignore +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/.pre-commit-config.yaml +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/.python-version +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/AGENTS.md +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/CLAUDE.md +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/LICENSE +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/docs/contributing/branching.md +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/docs/getting-started/concepts.md +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/docs/getting-started/install.md +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/docs/index.md +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/docs/reference/cli.md +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/docs/reference/config.md +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/docs/reference/exit-codes.md +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/docs/reference/schemas.md +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/justfile +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/mkdocs.yml +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/__init__.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/__main__.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/aliases/__init__.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/auth/__init__.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/auth/verify.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/builder/__init__.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/cache/__init__.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/cli/__init__.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/cli/aliases_commands.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/cli/cache_commands.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/cli/init_commands.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/cli/login_commands.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/cli/profiles_commands.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/cli/registration.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/cli/skill_commands.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/cli/writes/__init__.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/cli/writes/coercion.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/cli/writes/confirmation.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/config/__init__.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/http/__init__.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/http/errors.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/model/__init__.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/model/command_model.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/output/__init__.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/output/csv_.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/output/explain.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/output/flatten.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/output/headers.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/output/json_.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/output/jsonl.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/output/render.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/output/table.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/output/yaml_.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/schema/__init__.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/schema/hashing.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/schemas/__init__.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/schemas/bundled/__init__.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/schemas/bundled/manifest.yaml +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/schemas/bundled/netbox-4.5.10.json.gz +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/schemas/bundled/netbox-4.6.0.json.gz +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/nsc/skill/__init__.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/scripts/gen_docs.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/scripts/sync_agents_md.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/__init__.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/aliases/__init__.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/aliases/test_resolver.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/auth/__init__.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/auth/test_verify.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/benchmarks/__init__.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/benchmarks/test_startup.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/builder/__init__.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/builder/test_build.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/builder/test_default_columns.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/builder/test_redaction_marking.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/builder/test_request_body_shape.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/cache/__init__.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/cache/test_prune.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/cache/test_store.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/cli/__init__.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/cli/test_aliases_commands.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/cli/test_app_smoke.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/cli/test_cache_commands.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/cli/test_commands_dump.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/cli/test_completion_smoke.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/cli/test_config_commands.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/cli/test_explain.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/cli/test_handlers.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/cli/test_init_commands.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/cli/test_login_commands.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/cli/test_meta_subcommands_under_broken_config.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/cli/test_ndjson_input.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/cli/test_profiles_commands.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/cli/test_registration.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/cli/test_respx_integration.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/cli/test_runtime.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/cli/test_skill_commands.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/cli/test_stdin_sniffer.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/cli/test_writes_respx.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/cli/writes/__init__.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/cli/writes/test_apply.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/cli/writes/test_bulk.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/cli/writes/test_confirmation.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/cli/writes/test_handler_helpers.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/cli/writes/test_handlers_audit.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/cli/writes/test_input.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/cli/writes/test_preflight.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/config/__init__.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/config/test_loader.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/config/test_models.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/config/test_writer_atomicity.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/config/test_writer_dotted_paths.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/config/test_writer_roundtrip.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/conftest.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/e2e/README.md +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/e2e/__init__.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/e2e/conftest.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/e2e/docker-compose.yml +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/e2e/test_audit_redaction.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/e2e/test_auth_error_envelope.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/e2e/test_bulk_create_with_loop_fallback.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/e2e/test_full_cycle.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/e2e/test_login.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/e2e/test_ndjson.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/e2e/test_preflight_blocks_apply.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/e2e/test_validation_error_envelope_from_netbox.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/e2e/wait_for_netbox.sh +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/fixtures/profiles/single_profile.yaml +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/fixtures/responses/auth_401.json +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/fixtures/responses/circuits_providers_list.json +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/fixtures/responses/dcim_devices_get.json +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/fixtures/responses/dcim_devices_list_p1.json +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/fixtures/responses/dcim_devices_list_p2.json +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/http/__init__.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/http/test_audit.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/http/test_audit_redaction.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/http/test_client.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/http/test_client_redaction_threading.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/http/test_errors.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/http/test_retry.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/model/__init__.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/model/test_command_model.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/model/test_request_body_shape.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/output/__init__.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/output/test_csv.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/output/test_errors.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/output/test_errors_aliases.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/output/test_explain.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/output/test_flatten.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/output/test_input_error_envelope.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/output/test_json.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/output/test_jsonl.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/output/test_render_dispatch.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/output/test_table.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/output/test_yaml.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/schema/__init__.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/schema/test_hashing.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/schema/test_loader.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/schema/test_models.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/schema/test_source.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/schema/test_source_ttl.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/scripts/__init__.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/scripts/test_gen_docs.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/skill/__init__.py +0 -0
- {netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/tests/skill/test_bundle.py +0 -0
|
@@ -2,14 +2,27 @@
|
|
|
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.0.4 — 2026-05-16
|
|
6
|
+
|
|
7
|
+
Maintenance release: a codebase-wide internal simplification pass (no behavioural change), a full documentation parity audit, and a dependency bump. There are no CLI, config, or output-contract changes — upgrading from v1.0.3 is transparent.
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- **Codebase-wide simplification pass** (PRs #61–#71). Every package was audited to remove dead code, tighten types, and drop unreachable branches: schema parsing (#61), cache store & schema source (#62), output (#63), command model / alias resolver / auth verify (#64), config (#65), http (#66), cli (#68), builder (#69), top-level package files (#70), and the cli writes pipeline (#71). These are internal-only changes — the public CLI surface, command tree, error envelope, and exit codes are unchanged and remain covered by the existing test suite.
|
|
12
|
+
- Bumped `urllib3` 2.6.3 → 2.7.0 (PR #46).
|
|
13
|
+
|
|
14
|
+
### Documentation
|
|
15
|
+
|
|
16
|
+
- **Full documentation parity audit** (PR #73). Every hand-written user-facing and contributor page, plus the bundled `SKILL.md`, was audited file-by-file against the current code and corrected. Notable fixes: removed references to non-existent `nsc describe` / `nsc refresh` commands; documented the real `replace` (PUT) verb; corrected the HTTP retry policy (writes are never retried on 5xx); corrected the schema-cache invalidation model to the TTL fast-path; documented `nsc skill export`, `nsc login --fetch-schema`, and the post-`login --new` schema-fetch prompt; and corrected exit-code semantics (a malformed single JSON/YAML input is a `client`/exit-6 error — only a bad NDJSON line is `input_error`/exit 4). Auto-generated reference pages were verified current.
|
|
17
|
+
|
|
5
18
|
## v1.0.3 — 2026-05-07
|
|
6
19
|
|
|
7
20
|
Third patch release. Headline changes: `nsc login --new` now prompts to fetch the live schema (issue #32), the schema TTL fast-path self-heals on hash-confirmed fetches (issue #39), and bundled schemas are updated to 4.5.10 and 4.6.0.
|
|
8
21
|
|
|
9
22
|
### Added
|
|
10
23
|
|
|
11
|
-
- **`nsc login --new` prompts to fetch the live schema** (issue #32, PR #44). After a new profile is created, `nsc login` asks
|
|
12
|
-
- **`nsc skill export <dir>`** (PR #37). Copies the bundled `SKILL.md`
|
|
24
|
+
- **`nsc login --new` prompts to fetch the live schema** (issue #32, PR #44). After a new profile is created, `nsc login` asks `Fetch and cache the live schema now?` (defaults `Y`) and fetches if accepted. A new `nsc login --fetch-schema` flag fetches unconditionally (no prompt) and also applies to the bare/`--profile` verify path. Either way the schema is fetched with a forced refresh, priming the cache so the next command skips the bootstrap fetch entirely. `--rotate` does not prompt for or fetch the schema.
|
|
25
|
+
- **`nsc skill export <dir>`** (PR #37). Copies the bundled `SKILL.md` into `<dir>/netbox-super-cli/SKILL.md` so it can be dropped into any agent harness without `nsc` on the `PATH`. Dry-run by default (prints the would-write path); `--apply` actually copies. `--output json` emits a structured envelope. Useful in CI or shared-skill repos where the package is not installed globally.
|
|
13
26
|
- **Bundled schemas updated** (PR #36). Ships 4.5.10 and 4.6.0; drops the 4.6.0-beta2 snapshot. Offline fallback is now available for both stable release lines.
|
|
14
27
|
|
|
15
28
|
### Fixed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: netbox-super-cli
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.4
|
|
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: Issues, https://github.com/thomaschristory/netbox-super-cli/issues
|
|
@@ -171,11 +171,17 @@ JSON output, error envelope, audit log).
|
|
|
171
171
|
```sh
|
|
172
172
|
nsc skill install --target claude-code # dry-run; prints the destination
|
|
173
173
|
nsc skill install --target claude-code --apply # actually copies
|
|
174
|
+
|
|
175
|
+
# Or export to an arbitrary directory (e.g. CI or a shared-skill repo).
|
|
176
|
+
nsc skill export ./skills # dry-run; prints the would-write path
|
|
177
|
+
nsc skill export ./skills --apply # writes ./skills/netbox-super-cli/SKILL.md
|
|
174
178
|
```
|
|
175
179
|
|
|
176
|
-
|
|
177
|
-
documented programmatic install path, the helper prints actionable
|
|
178
|
-
instructions instead of guessing.
|
|
180
|
+
`skill install` targets: `claude-code`, `codex`, `gemini`, `copilot`. Where a
|
|
181
|
+
target has no documented programmatic install path, the helper prints actionable
|
|
182
|
+
manual instructions instead of guessing. `skill export <dir>` always writes to
|
|
183
|
+
`<dir>/netbox-super-cli/SKILL.md` and, like `install`, is dry-run unless you
|
|
184
|
+
pass `--apply`.
|
|
179
185
|
|
|
180
186
|
## License
|
|
181
187
|
|
|
@@ -144,11 +144,17 @@ JSON output, error envelope, audit log).
|
|
|
144
144
|
```sh
|
|
145
145
|
nsc skill install --target claude-code # dry-run; prints the destination
|
|
146
146
|
nsc skill install --target claude-code --apply # actually copies
|
|
147
|
+
|
|
148
|
+
# Or export to an arbitrary directory (e.g. CI or a shared-skill repo).
|
|
149
|
+
nsc skill export ./skills # dry-run; prints the would-write path
|
|
150
|
+
nsc skill export ./skills --apply # writes ./skills/netbox-super-cli/SKILL.md
|
|
147
151
|
```
|
|
148
152
|
|
|
149
|
-
|
|
150
|
-
documented programmatic install path, the helper prints actionable
|
|
151
|
-
instructions instead of guessing.
|
|
153
|
+
`skill install` targets: `claude-code`, `codex`, `gemini`, `copilot`. Where a
|
|
154
|
+
target has no documented programmatic install path, the helper prints actionable
|
|
155
|
+
manual instructions instead of guessing. `skill export <dir>` always writes to
|
|
156
|
+
`<dir>/netbox-super-cli/SKILL.md` and, like `install`, is dry-run unless you
|
|
157
|
+
pass `--apply`.
|
|
152
158
|
|
|
153
159
|
## License
|
|
154
160
|
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Caching
|
|
2
|
+
|
|
3
|
+
`~/.nsc/` holds all on-disk state. Bundled schemas live inside the installed
|
|
4
|
+
wheel and are NOT copied into `~/.nsc/`.
|
|
5
|
+
|
|
6
|
+
## Layout
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
~/.nsc/
|
|
10
|
+
├── config.yaml
|
|
11
|
+
├── cache/
|
|
12
|
+
│ ├── prod/<schema-hash>.json # generated CommandModel
|
|
13
|
+
│ ├── prod/<schema-hash>.meta.json # sidecar: {"fetched_at": <epoch>}
|
|
14
|
+
│ ├── lab/<schema-hash>.json
|
|
15
|
+
│ └── adhoc/<schema-hash>.json # env-var-only invocations
|
|
16
|
+
└── logs/
|
|
17
|
+
├── last-request.json # most recent HTTP exchange (overwritten)
|
|
18
|
+
└── audit.jsonl # append-only mutation log
|
|
19
|
+
# (rotated to audit.jsonl.1 at 10 MB)
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
The location root is `~/.nsc/` unless `NSC_HOME` is set, in which case it is
|
|
23
|
+
`$NSC_HOME` (expanded and resolved).
|
|
24
|
+
|
|
25
|
+
## Invalidation
|
|
26
|
+
|
|
27
|
+
The cache is keyed by `sha256` of the canonicalized schema body. There are two
|
|
28
|
+
distinct caches: this **command-model disk cache** (`<hash>.json`), and the
|
|
29
|
+
**schema-source TTL fast-path** that decides whether to re-fetch the live
|
|
30
|
+
schema at all.
|
|
31
|
+
|
|
32
|
+
Invalidation is **TTL-gated**, not "every invocation". Under the default
|
|
33
|
+
`daily` policy (`Defaults.schema_refresh = SchemaRefresh.DAILY`) `nsc` trusts
|
|
34
|
+
the cached command-model — and skips the schema fetch entirely — as long as the
|
|
35
|
+
profile's newest `<hash>.meta.json` sidecar `fetched_at` is within the policy's
|
|
36
|
+
TTL. Only once the TTL has lapsed (or the policy forces it) does `nsc` re-fetch
|
|
37
|
+
the live schema; a changed schema then produces a new hash and a new
|
|
38
|
+
`<hash>.json`. Freshness is keyed off the sidecar's `fetched_at`, **not** the
|
|
39
|
+
cache file's mtime, so a `touch`, backup-restore, or `cp -p` cannot fake
|
|
40
|
+
freshness. A sidecar dated more than 60s in the future (clock skew or
|
|
41
|
+
tampering) is rejected.
|
|
42
|
+
|
|
43
|
+
When a live fetch returns a hash that is already cached, the sidecar's
|
|
44
|
+
`fetched_at` is bumped (`CacheStore.touch_fetched_at`) so the TTL fast-path
|
|
45
|
+
trusts the cache on the next invocation — this also self-heals legacy caches
|
|
46
|
+
written before sidecars existed.
|
|
47
|
+
|
|
48
|
+
Force a re-fetch sooner with the global `--refresh-schema` flag (bypasses the
|
|
49
|
+
TTL fast-path under any policy) or `nsc login --fetch-schema`. The full policy
|
|
50
|
+
table lives in [Schema loading](schema-loading.md#refresh-modes).
|
|
51
|
+
|
|
52
|
+
## Cleaning up
|
|
53
|
+
|
|
54
|
+
`nsc cache prune` handles three classes of orphan:
|
|
55
|
+
|
|
56
|
+
1. Profile directories not in `~/.nsc/config.yaml` (e.g., a removed profile).
|
|
57
|
+
2. `<schema_hash>.json` files inside an active profile whose hash no longer
|
|
58
|
+
matches the live schema. **Skipped per-profile when the profile is
|
|
59
|
+
offline** so a network blip never removes the offline fallback.
|
|
60
|
+
3. With `--max-age <days>`: cache files older than the threshold (excludes
|
|
61
|
+
files already covered by rule 1).
|
|
62
|
+
|
|
63
|
+
The `adhoc` cache is **never pruned automatically** — it represents valid
|
|
64
|
+
env-var-only usage. Applying a prune also removes each deleted file's
|
|
65
|
+
`<hash>.meta.json` sidecar.
|
|
66
|
+
|
|
67
|
+
```sh
|
|
68
|
+
nsc cache prune # dry-run
|
|
69
|
+
nsc cache prune --apply # actually delete
|
|
70
|
+
nsc cache prune --max-age 30 --apply
|
|
71
|
+
nsc cache prune --output json # structured envelope
|
|
72
|
+
```
|
|
@@ -5,13 +5,13 @@
|
|
|
5
5
|
## The shape
|
|
6
6
|
|
|
7
7
|
```python
|
|
8
|
-
CommandModel
|
|
8
|
+
CommandModel(info_title, info_version, schema_hash, tags: dict[str, Tag])
|
|
9
9
|
├── tags: dict[str, Tag]
|
|
10
|
-
│ └── Tag(name, resources: dict[str, Resource])
|
|
10
|
+
│ └── Tag(name, description?, resources: dict[str, Resource])
|
|
11
11
|
│ └── Resource(name, list_op?, get_op?, create_op?, update_op?, replace_op?,
|
|
12
12
|
│ delete_op?, custom_actions: list[Operation])
|
|
13
|
-
└── Operation(operation_id, http_method, path,
|
|
14
|
-
|
|
13
|
+
└── Operation(operation_id, http_method, path, summary?, description?,
|
|
14
|
+
parameters, request_body?, default_columns?)
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
Pure Pydantic. JSON-serializable. Cached to disk.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# HTTP client
|
|
2
|
+
|
|
3
|
+
`nsc/http/` is a thin wrapper around `httpx.Client`.
|
|
4
|
+
|
|
5
|
+
## What it adds
|
|
6
|
+
|
|
7
|
+
- Token auth: `Authorization: Token <token>` header (plus
|
|
8
|
+
`Accept: application/json`), set once per Client.
|
|
9
|
+
- Configurable `verify_ssl` and `timeout` (default 30s, from
|
|
10
|
+
`Defaults.timeout`).
|
|
11
|
+
- Method-aware retries, up to 3 attempts with exponential backoff
|
|
12
|
+
(`base_delay` 0.5s, ±25% jitter):
|
|
13
|
+
- **Reads** (GET/HEAD/OPTIONS) retry on 5xx **and** on connect
|
|
14
|
+
failures.
|
|
15
|
+
- **Writes** (POST/PATCH/PUT/DELETE) retry **only** on a provable
|
|
16
|
+
connect failure (request never left the client). They are
|
|
17
|
+
**never** retried on 5xx, read-timeout, or ambiguous transport
|
|
18
|
+
errors — a write that may have reached the server is not replayed.
|
|
19
|
+
Every attempt is recorded as its own audit entry with `attempt_n` and
|
|
20
|
+
`final_attempt`; redaction is applied on every write, so a failed
|
|
21
|
+
retry never unredacts.
|
|
22
|
+
- Pagination helper that follows `next` URLs (used by `--all`).
|
|
23
|
+
- Audit log appender at `~/.nsc/logs/audit.jsonl` — written for writes
|
|
24
|
+
always, and for any request when `--debug` is set.
|
|
25
|
+
- A "last request" snapshot at `~/.nsc/logs/last-request.json`
|
|
26
|
+
(overwritten every call, regardless of `--debug`) — handy for triage.
|
|
27
|
+
|
|
28
|
+
## Auth and the bootstrap path
|
|
29
|
+
|
|
30
|
+
A schema fetch may run before the first command request (only when the
|
|
31
|
+
TTL fast-path misses — see [Caching](caching.md)); it uses its own
|
|
32
|
+
short-lived `httpx.Client` in `nsc/schema/`, not this `NetBoxClient`.
|
|
33
|
+
Command requests then go through a single `NetBoxClient` whose
|
|
34
|
+
`httpx.Client` carries the auth header for the life of the process.
|
|
35
|
+
Token rotation via `nsc login --rotate` does NOT invalidate the cached
|
|
36
|
+
model (the schema hash is what keys the cache; the token never affected
|
|
37
|
+
it).
|
|
38
|
+
|
|
39
|
+
## Audit entry shape
|
|
40
|
+
|
|
41
|
+
Each line of `audit.jsonl` is a JSON object with:
|
|
42
|
+
|
|
43
|
+
- `schema_version`, `timestamp` (UTC ISO8601, `…Z`)
|
|
44
|
+
- `operation_id`, `method`, `url`
|
|
45
|
+
- `request.headers` (sensitive headers, incl. `Authorization`, rewritten
|
|
46
|
+
to `"<redacted>"` — the key stays, the value is masked)
|
|
47
|
+
- `request.query`, `request.body` (sensitive `sensitive_paths` fields
|
|
48
|
+
rewritten to `"<redacted>"`); bodies over 256 KB collapse to
|
|
49
|
+
`{"_truncated": true, "_size_bytes": N}` with `request.body_truncated`
|
|
50
|
+
- `response.status_code`, `response.headers`, `response.body` (same
|
|
51
|
+
256 KB truncation via `response.body_truncated`); `response` is `null`
|
|
52
|
+
on a transport failure
|
|
53
|
+
- `duration_ms`, `attempt_n`, `final_attempt`, `error_kind`
|
|
54
|
+
- `dry_run`, `preflight_blocked`, `record_indices`, `applied`, `explain`
|
|
55
|
+
|
|
56
|
+
The audit file is append-only and rotates to `audit.jsonl.1` at 10 MB;
|
|
57
|
+
failed writes do NOT unredact. See
|
|
58
|
+
[Writes and safety](../guides/writes-and-safety.md) for the full redaction
|
|
59
|
+
contract.
|
|
60
|
+
|
|
61
|
+
## What it deliberately does not do
|
|
62
|
+
|
|
63
|
+
- Async — sync only in v1, kept feasible by httpx if a future async path lands.
|
|
64
|
+
- Connection pooling across profiles — each profile gets its own `Client`.
|
|
65
|
+
- Caching responses — caching the command-model is enough; caching response
|
|
66
|
+
payloads would surprise users.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Architecture overview
|
|
2
|
+
|
|
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.
|
|
5
|
+
The CLI layer consumes the brain; a future TUI could too without changing the
|
|
6
|
+
brain.
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
nsc/
|
|
10
|
+
├── schema/ # OpenAPI fetching, hashing, parsing
|
|
11
|
+
├── model/ # Normalized command-model (data only, framework-free)
|
|
12
|
+
├── builder/ # Schema → CommandModel
|
|
13
|
+
├── cli/ # Typer application; walks the model, registers commands
|
|
14
|
+
├── http/ # Thin httpx wrapper: auth, retries, audit
|
|
15
|
+
├── output/ # Formatters (table/json/jsonl/yaml/csv) + error envelope
|
|
16
|
+
├── config/ # Pydantic config models + ruamel.yaml writer
|
|
17
|
+
├── cache/ # On-disk cache for generated CommandModels
|
|
18
|
+
├── auth/ # Login verification helpers (verify probe, token rotate)
|
|
19
|
+
├── aliases/ # Curated alias resolver (ls/get/rm/search)
|
|
20
|
+
├── skill/ # Bundle-path helper for the portable SKILL.md
|
|
21
|
+
└── schemas/bundled/ # Versioned NetBox OpenAPI snapshots (offline fallback)
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## The hard rule
|
|
25
|
+
|
|
26
|
+
`nsc/model/` imports nothing from `nsc/cli/`, `nsc/http/`, or any framework.
|
|
27
|
+
If you need to add a dependency to `model/`, you're solving the wrong problem.
|
|
28
|
+
|
|
29
|
+
## Data flow at runtime
|
|
30
|
+
|
|
31
|
+
1. `nsc` startup → resolve profile (CLI flags > env > config > adhoc).
|
|
32
|
+
2. Resolve schema source (`--schema` override > fresh cache within the
|
|
33
|
+
TTL policy > live fetch > stale cache > bundled fallback).
|
|
34
|
+
3. Hash + parse → build the command-model (or load cached).
|
|
35
|
+
4. Hand model to Typer; register commands dynamically.
|
|
36
|
+
5. Dispatch.
|
|
37
|
+
6. `http/` executes (or shows dry-run).
|
|
38
|
+
7. `output/` renders.
|
|
39
|
+
|
|
40
|
+
## Where to read next
|
|
41
|
+
|
|
42
|
+
- [Schema loading](schema-loading.md) — fetch, hash, fallback chain.
|
|
43
|
+
- [Command generation](command-generation.md) — how `operationId` becomes a verb.
|
|
44
|
+
- [HTTP client](http-client.md) — auth, retries, audit log.
|
|
45
|
+
- [Caching](caching.md) — disk layout, invalidation.
|
|
46
|
+
|
|
47
|
+
For the full design rationale, see the specs in `docs/superpowers/specs/` (in
|
|
48
|
+
the repo, not in this site — the planning artifacts are local-only).
|
|
@@ -18,10 +18,13 @@ and an optional `--refresh-schema` override:
|
|
|
18
18
|
`{profile.url}/api/schema/?format=json`. The fetched body is hashed;
|
|
19
19
|
if a cache file already exists at that hash it's loaded directly,
|
|
20
20
|
otherwise the command-model is rebuilt and saved.
|
|
21
|
-
4. On fetch failure:
|
|
22
|
-
stderr).
|
|
23
|
-
5. Bundled snapshot
|
|
24
|
-
(
|
|
21
|
+
4. On fetch failure: the newest valid cached entry for the profile
|
|
22
|
+
(warns once on stderr), sorted by mtime.
|
|
23
|
+
5. Bundled snapshot — the **last (newest) entry** in
|
|
24
|
+
`nsc/schemas/bundled/manifest.yaml` (currently
|
|
25
|
+
`netbox-4.6.0.json.gz`), shipped in the wheel. This is the
|
|
26
|
+
last-resort offline fallback; it is *not* version-matched to the
|
|
27
|
+
unreachable instance.
|
|
25
28
|
|
|
26
29
|
## Hashing
|
|
27
30
|
|
|
@@ -49,12 +52,12 @@ that's the upgrade path for caches written before sidecars existed.
|
|
|
49
52
|
|
|
50
53
|
## Offline behavior
|
|
51
54
|
|
|
52
|
-
- Live schema unreachable + cache present → use
|
|
53
|
-
stderr.
|
|
54
|
-
- Live schema unreachable + no cache → fall back to the
|
|
55
|
-
|
|
56
|
-
-
|
|
57
|
-
|
|
55
|
+
- Live schema unreachable + cache present → use the newest valid cached
|
|
56
|
+
entry, warn once on stderr.
|
|
57
|
+
- Live schema unreachable + no cache → fall back to the newest bundled
|
|
58
|
+
snapshot (last manifest entry), warn once on stderr.
|
|
59
|
+
- Neither cache nor bundled snapshot available → `SchemaSourceError`
|
|
60
|
+
(exit 3).
|
|
58
61
|
|
|
59
62
|
## Refresh modes
|
|
60
63
|
|
{netbox_super_cli-1.0.3 → netbox_super_cli-1.0.4}/docs/contributing/adding-bundled-schemas.md
RENAMED
|
@@ -9,14 +9,16 @@ the repo and shipped inside the wheel.
|
|
|
9
9
|
```
|
|
10
10
|
nsc/schemas/bundled/
|
|
11
11
|
├── manifest.yaml
|
|
12
|
-
├── netbox-4.
|
|
13
|
-
└── netbox
|
|
12
|
+
├── netbox-4.5.10.json.gz
|
|
13
|
+
└── netbox-4.6.0.json.gz
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
`manifest.yaml
|
|
16
|
+
`manifest.yaml` (newest entry last):
|
|
17
17
|
|
|
18
18
|
```yaml
|
|
19
19
|
schemas:
|
|
20
|
+
- version: "4.5.10"
|
|
21
|
+
file: "netbox-4.5.10.json.gz"
|
|
20
22
|
- version: "4.6.0"
|
|
21
23
|
file: "netbox-4.6.0.json.gz"
|
|
22
24
|
```
|
|
@@ -56,6 +58,9 @@ versions when they're no longer cited by any active deployment.
|
|
|
56
58
|
|
|
57
59
|
1. **First-run offline.** A new install with no cache, no network — the user
|
|
58
60
|
gets a usable command tree from the bundled schema.
|
|
59
|
-
2. **CI without a NetBox container.** `
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
2. **CI without a NetBox container.** Pointing `--schema` at a bundled
|
|
62
|
+
snapshot path (e.g. `nsc commands --schema
|
|
63
|
+
nsc/schemas/bundled/netbox-4.6.0.json.gz --output json`) produces a
|
|
64
|
+
deterministic command-model for tests that don't need a live NetBox.
|
|
65
|
+
`--schema` accepts an `http(s)://` URL or a local path; `.json.gz`
|
|
66
|
+
files are gunzipped automatically — there is no `bundled` keyword.
|
|
@@ -22,7 +22,7 @@ just lint # ruff + ruff format --check + mypy --strict
|
|
|
22
22
|
just fix # auto-fix ruff issues
|
|
23
23
|
just bench # cold-start benchmark (target <300ms median)
|
|
24
24
|
just nsc <args> # run the local CLI (e.g., just nsc dcim devices list)
|
|
25
|
-
just docs # serve the docs site at http://
|
|
25
|
+
just docs # serve the docs site at http://127.0.0.1:8000
|
|
26
26
|
just docs-build # build the site, fail on broken links / missing nav
|
|
27
27
|
```
|
|
28
28
|
|
|
@@ -10,6 +10,12 @@ process assumes. Release prep (CHANGELOG roll + version bumps) happens
|
|
|
10
10
|
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
|
+
The same `v*` tag push also publishes the documentation site.
|
|
14
|
+
`docs.yml` runs build-only (`mkdocs build --strict`) on docs-touching
|
|
15
|
+
pull requests, but the GitHub Pages **deploy** job only runs on a `v*`
|
|
16
|
+
tag push — the live docs site updates on release, not on merge to
|
|
17
|
+
`main`.
|
|
18
|
+
|
|
13
19
|
## Normal release checklist
|
|
14
20
|
|
|
15
21
|
1. Full unit suite green: `just test`.
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# First run
|
|
2
|
+
|
|
3
|
+
Two paths to your first command:
|
|
4
|
+
|
|
5
|
+
1. **Interactive wizard** — `nsc init` prompts for everything.
|
|
6
|
+
2. **Env vars** — `NSC_URL` + `NSC_TOKEN` and you're done; no config file needed.
|
|
7
|
+
|
|
8
|
+
## Interactive: `nsc init`
|
|
9
|
+
|
|
10
|
+
```sh
|
|
11
|
+
nsc init
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
The wizard prompts, in order, for:
|
|
15
|
+
|
|
16
|
+
- A **profile name** (default `default`; e.g., `prod`, `lab`).
|
|
17
|
+
- The NetBox URL.
|
|
18
|
+
- **Verify SSL certificates?** (default yes).
|
|
19
|
+
- **Token storage** — `plaintext` or `env` (default `plaintext`).
|
|
20
|
+
- Then either an **environment variable name** (if you chose `env` storage — written as
|
|
21
|
+
an `!env NAME` indirection) or the **token** itself (hidden input, stored verbatim in
|
|
22
|
+
`~/.nsc/config.yaml`). See [Managing profiles](../guides/managing-profiles.md).
|
|
23
|
+
|
|
24
|
+
`nsc init` is offline-safe: it does not contact NetBox. On success it writes
|
|
25
|
+
`~/.nsc/config.yaml` with the profile, prints the path, and suggests
|
|
26
|
+
`nsc login --profile <name>` as the next step. It does **not** fetch the
|
|
27
|
+
schema — run `nsc login` afterwards to verify the token and prime the schema
|
|
28
|
+
cache (see below).
|
|
29
|
+
|
|
30
|
+
`nsc init` refuses to overwrite an existing config — use
|
|
31
|
+
`nsc login --new --profile <name> --url <url>` to add more profiles.
|
|
32
|
+
|
|
33
|
+
## Env-var only
|
|
34
|
+
|
|
35
|
+
For one-off use, agents, or CI:
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
export NSC_URL=https://netbox.example.com
|
|
39
|
+
export NSC_TOKEN=$(cat ~/.netbox-token)
|
|
40
|
+
|
|
41
|
+
nsc dcim devices list
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
No `~/.nsc/config.yaml` required. The cache lives at `~/.nsc/cache/adhoc/`
|
|
45
|
+
when there's no profile.
|
|
46
|
+
|
|
47
|
+
## Authenticate / verify a profile
|
|
48
|
+
|
|
49
|
+
```sh
|
|
50
|
+
nsc login # verify the default profile
|
|
51
|
+
nsc login --profile lab # verify a specific profile
|
|
52
|
+
nsc login --new --profile staging --url https://netbox-staging.example.com
|
|
53
|
+
nsc login --rotate --profile prod # rotate the token
|
|
54
|
+
nsc login --fetch-schema # verify, then fetch & cache the live schema
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
`nsc login` probes `GET /api/status/` and `GET /api/users/tokens/?limit=1`
|
|
58
|
+
(both must succeed) and prints `✓ authenticated as <user>, NetBox <version>`
|
|
59
|
+
on success. On failure it emits the standard auth error envelope
|
|
60
|
+
(`type: auth`, exit 8).
|
|
61
|
+
|
|
62
|
+
`--new` requires both `--profile` and `--url`, prompts for the token
|
|
63
|
+
(hidden input), verifies it before writing, and persists the profile. After a
|
|
64
|
+
successful `--new` it also asks **"Fetch and cache the live schema now?"**
|
|
65
|
+
(default **yes**) — accepting primes the schema cache so your first real
|
|
66
|
+
command skips the bootstrap fetch. Pass `--fetch-schema` to any `nsc login`
|
|
67
|
+
(or `--new`) to fetch the schema unconditionally without the prompt;
|
|
68
|
+
`--rotate` neither prompts for nor fetches the schema.
|
|
69
|
+
|
|
70
|
+
## Your first read
|
|
71
|
+
|
|
72
|
+
```sh
|
|
73
|
+
nsc dcim devices list # default page (page_size=50)
|
|
74
|
+
nsc dcim devices list --all # paginate to completion
|
|
75
|
+
nsc dcim devices get 7 # get by id
|
|
76
|
+
nsc ls devices # alias — matches devices.list
|
|
77
|
+
nsc dcim devices list --output json --all # canonical machine-readable form
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Your first write
|
|
81
|
+
|
|
82
|
+
```sh
|
|
83
|
+
nsc dcim devices create --field name=test-1 --field site=2 --explain # dry-run + reasoning
|
|
84
|
+
nsc dcim devices create --field name=test-1 --field site=2 --apply # commit
|
|
85
|
+
nsc rm devices test-1 --apply # delete via alias
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Every write previews as a dry-run unless you pass `--apply`. See [Writes and safety](../guides/writes-and-safety.md) for the full discipline.
|
|
@@ -89,10 +89,17 @@ just means one extra fetch on the next run — never a wrong command tree.
|
|
|
89
89
|
|
|
90
90
|
```sh
|
|
91
91
|
# Verify connectivity + auth before doing anything mutating.
|
|
92
|
-
nsc login
|
|
92
|
+
nsc login || { echo "auth failed"; exit 1; }
|
|
93
93
|
```
|
|
94
94
|
|
|
95
|
+
`nsc login` verifies the active profile's token (exit **8** on auth failure,
|
|
96
|
+
**12** on a config/profile problem). It takes no `--output` flag; on failure it
|
|
97
|
+
prints the standard JSON error envelope.
|
|
98
|
+
|
|
95
99
|
## Cleaning up the cache
|
|
96
100
|
|
|
97
|
-
`nsc cache prune` removes orphan profile dirs and stale-hash files (
|
|
98
|
-
|
|
101
|
+
`nsc cache prune` removes orphan profile dirs and stale-hash files (it is
|
|
102
|
+
dry-run unless you pass `--apply`). The default prune never touches the
|
|
103
|
+
`adhoc` cache. Add `--max-age N` to also prune cache files older than N days
|
|
104
|
+
by mtime — note that age-based pruning is profile-agnostic and *will* remove
|
|
105
|
+
aged `adhoc` files too. Safe to run unattended (dry-run by default).
|
|
@@ -16,8 +16,8 @@ nsc profiles add lab --url https://netbox-lab.local --token "$LAB_TOKEN"
|
|
|
16
16
|
```
|
|
17
17
|
|
|
18
18
|
This is the scriptable equivalent of `nsc login --new --profile lab`. It runs
|
|
19
|
-
the same verification (`GET /api/users/tokens/?limit=1`)
|
|
20
|
-
Refuses if `lab` already exists.
|
|
19
|
+
the same verification (`GET /api/status/` plus `GET /api/users/tokens/?limit=1`)
|
|
20
|
+
before persisting. Refuses if `lab` already exists.
|
|
21
21
|
|
|
22
22
|
## Add a profile interactively
|
|
23
23
|
|
|
@@ -26,6 +26,31 @@ nsc init # first ti
|
|
|
26
26
|
nsc login --new --profile staging --url https://netbox-staging.local # subsequent profiles
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
+
`nsc login --new` requires both `--profile` and `--url`, then prompts for the
|
|
30
|
+
token (hidden input) and runs verification before persisting. Add `--store env
|
|
31
|
+
--env-var NAME` to store the token as an `!env NAME` reference instead of
|
|
32
|
+
plaintext. Refuses (exit 12) if the profile already exists.
|
|
33
|
+
|
|
34
|
+
After a successful `--new`, `nsc` interactively asks **"Fetch and cache the
|
|
35
|
+
live schema now?"** (default **yes**) — accept it to pre-warm the command-model
|
|
36
|
+
cache, or pass `--fetch-schema` to fetch unconditionally without the prompt.
|
|
37
|
+
|
|
38
|
+
## Verify, rotate, and fetch the schema
|
|
39
|
+
|
|
40
|
+
```sh
|
|
41
|
+
nsc login # verify the default profile's token
|
|
42
|
+
nsc login --profile lab # verify a specific profile
|
|
43
|
+
nsc login --profile lab --fetch-schema # verify, then refresh the cached schema
|
|
44
|
+
nsc login --rotate --profile lab # prompt for a new token, verify, then persist
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
`nsc login` (bare or with `--profile`) verifies the token by probing
|
|
48
|
+
`GET /api/status/` and `GET /api/users/tokens/?limit=1`; it writes no config.
|
|
49
|
+
`--fetch-schema` additionally force-refreshes the cached OpenAPI schema.
|
|
50
|
+
`--rotate` requires `--profile`, prompts for the new token, verifies it
|
|
51
|
+
*before* writing, and does **not** prompt for or fetch the schema. `--new` and
|
|
52
|
+
`--rotate` are mutually exclusive.
|
|
53
|
+
|
|
29
54
|
## Rename / set default / remove
|
|
30
55
|
|
|
31
56
|
```sh
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
# Output formats
|
|
2
2
|
|
|
3
|
-
`nsc` ships five output formats
|
|
4
|
-
stdout is piped
|
|
3
|
+
`nsc` ships five output formats: `table`, `json`, `jsonl`, `yaml`, `csv`.
|
|
4
|
+
Default is **table** on a TTY and **JSON** when stdout is piped — the piped
|
|
5
|
+
default is JSON even if your config sets a different `defaults.output`.
|
|
6
|
+
Selection precedence (highest first): `--output`/`-o` > `NSC_OUTPUT` env var >
|
|
7
|
+
non-TTY → JSON > `defaults.output` in config (default `table`).
|
|
5
8
|
|
|
6
9
|
## The five formats
|
|
7
10
|
|
|
@@ -9,7 +9,7 @@ correctly without trial-and-error.
|
|
|
9
9
|
| Feature | Mechanism |
|
|
10
10
|
|---|---|
|
|
11
11
|
| Predictable command shape | `nsc <tag> <resource> <verb>` — derived from the OpenAPI schema, no hand-curation |
|
|
12
|
-
| Self-describing | `nsc commands --output json` dumps the full command-model
|
|
12
|
+
| Self-describing | `nsc commands --schema <path-or-url> --output json` dumps the full command-model (tags → resources → operations) |
|
|
13
13
|
| Stable machine output | `--output json` everywhere; data on stdout, errors as JSON on stderr (or stdout when `--output json`), non-zero exit on failure |
|
|
14
14
|
| Stable error envelope | `{error, type, endpoint, method, status_code, operation_id, details}` — locked schema, see [Exit codes](../reference/exit-codes.md) |
|
|
15
15
|
| Safe by default | Writes preview as dry-runs; `--apply` is the only path to mutation |
|
|
@@ -18,15 +18,26 @@ correctly without trial-and-error.
|
|
|
18
18
|
## Bundled portable Skill
|
|
19
19
|
|
|
20
20
|
`nsc` ships a portable Skill bundle at `skills/netbox-super-cli/SKILL.md`
|
|
21
|
-
(installed inside the wheel). Install it into
|
|
21
|
+
(installed inside the wheel). Install it into a known agent harness with:
|
|
22
22
|
|
|
23
23
|
```sh
|
|
24
24
|
nsc skill install --target claude-code # dry-run; prints the destination
|
|
25
25
|
nsc skill install --target claude-code --apply # actually copies
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
+
Or export the bundled `SKILL.md` to an arbitrary directory:
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
nsc skill export ./my-skills # dry-run; prints the would-write path
|
|
32
|
+
nsc skill export ./my-skills --apply # actually copies
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
`nsc skill export <dir>` always writes to `<dir>/netbox-super-cli/SKILL.md` —
|
|
36
|
+
the `netbox-super-cli/` subdirectory is inserted for you. Both `skill install`
|
|
37
|
+
and `skill export` are **dry-run unless `--apply`** is passed.
|
|
38
|
+
|
|
28
39
|
Use `--output json` for programmatic consumers; the dry-run envelope contains
|
|
29
|
-
the resolved
|
|
40
|
+
the resolved destination path.
|
|
30
41
|
|
|
31
42
|
### Per-target resolved paths
|
|
32
43
|
|
|
@@ -54,9 +65,9 @@ When briefing an agent to use `nsc`, include:
|
|
|
54
65
|
read command.
|
|
55
66
|
2. **The output format.** "Use `--output json` for everything. Errors are JSON
|
|
56
67
|
envelopes — read `.type` for the category, the exit code for control flow."
|
|
57
|
-
3. **Discovery commands.** "Run `nsc commands --
|
|
58
|
-
|
|
59
|
-
|
|
68
|
+
3. **Discovery commands.** "Run `nsc commands --schema <path-or-url> --output
|
|
69
|
+
json` to see the whole surface (tags → resources → operations)." This
|
|
70
|
+
prevents the agent from guessing endpoints.
|
|
60
71
|
4. **The audit log.** "If a command fails unexpectedly, check
|
|
61
72
|
`~/.nsc/logs/audit.jsonl` — it has the exact request and response." This
|
|
62
73
|
replaces guesswork with evidence.
|
|
@@ -66,6 +77,6 @@ When briefing an agent to use `nsc`, include:
|
|
|
66
77
|
- **Asking the agent to skip dry-run.** Just don't. The dry-run is the agent's
|
|
67
78
|
one chance to surface an objection.
|
|
68
79
|
- **Hand-curated endpoint lists in the prompt.** They go stale on every NetBox
|
|
69
|
-
upgrade. Use `nsc commands --output json` instead.
|
|
80
|
+
upgrade. Use `nsc commands --schema <path-or-url> --output json` instead.
|
|
70
81
|
- **Authenticating per-command.** Configure a profile (or env vars) once at
|
|
71
82
|
session start.
|