Skip to content
Back to skills

Npa Cli Conventions

ASecurity

Use when writing or modifying npa CLI commands or SDK functions — registration, option naming, path contract, output format, error handling, exit codes, the decorators that are easy to forget, and config/credential access.

  • 33 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added September 8, 2026
toolspythonrustgoshellbashrailsterraformgit

Works with

  • cli

Security analysis

A100/100

Scanned September 27, 2026

npx -y skills add nebius/nebius-physical-ai --skill npa-cli-conventions --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Npa Cli Conventions?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Npa Cli Conventions
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/nebius-npa-cli-conventions/badge)](https://www.skillsdirectory.com/skills/nebius-npa-cli-conventions)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: npa-cli-conventions
description: Use when writing or modifying npa CLI commands or SDK functions — registration, option naming, path contract, output format, error handling, exit codes, the decorators that are easy to forget, and config/credential access.
---

# npa CLI And SDK Conventions

Conventions for changing the `npa` package itself. For the full path of adding a
new tool, use `skills/workflows/add-workbench-tool/SKILL.md`.

The codebase is mixed: some modules predate the current pattern. Where this
skill and an existing module disagree, follow this skill and leave the old module
alone unless you are deliberately migrating it.

## Where Code Goes

Behavior belongs in `npa/src/npa/workbench/<tool_snake>/`. The CLI and SDK are
clients of it, not second implementations. Three integration patterns exist:

- **Workbench module first** — the SDK builds a Pydantic request and calls the
  shared implementation, or HTTP when `service=True`. This is the pattern for
  new work. See `npa/src/npa/sdk/workbench/dataset.py`.
- **CLI wrapper** — `make_cli_wrapper` in `npa/src/npa/_sdk.py` exposes an
  existing CLI callback as an SDK function. Used by older orchestration-heavy
  tools such as LeRobot. Do not choose it for new tools.
- **Direct module import** — for platform code with no service, such as
  `npa/src/npa/sdk/provisioning.py`.

## Registration

Register workload command groups under `npa workbench` in
`npa/src/npa/cli/workbench/__init__.py`. Do not add top-level groups: the
platform utilities registered in `npa/src/npa/cli/main.py` predate the solution
namespace model and are marked as legacy in that file.

The operator desktop is explicitly registered under `npa tools desktop`, with
shared implementation in `npa/src/npa/tools/desktop` and CLI wiring in
`npa/src/npa/cli/tools`.
Use that namespace for its setup, display, HTTPS access, status, and open
commands. It is a development environment rather than a Workbench workload;
its Python surface calls the platform module directly and has no container or
workflow toolRef requirement.

## Options

The cross-tool handoff flags are `--input-path` (reads an `s3://` URI) and
`--output-path` (writes one). Validate them with the shared contract in
`npa/src/npa/cli/path_contract.py`. Public handoff paths must not require
VM-local paths, `file://` URIs, or plain HTTP URLs. A few legacy tools use
`--input-uri` / `--output-uri`; keep them working with aliases rather than
spreading the older spelling.

Conventional flags: `-p/--project` for the config alias, `-n/--name` for the
workbench instance, `--endpoint` to override a saved endpoint, `--service` to
call the deployed service instead of running in-process, and `--token-env` for
the env var holding a bearer token. Not every tool has all of them; check the
sibling module rather than assuming.

## Output

There is no shared output-format module. Each CLI package defines its own
`OutputFormat` enum and an `emit()` helper — copy the one next to you rather
than inventing a third shape. `npa/src/npa/cli/workbench/lancedb/helpers.py` is
a compact reference.

JSON flag spellings differ by area: `--output-format json` and `--json` on
workflow and platform commands, `--output json` on several workbench tools. For
anything an agent or script will parse, prefer `--output-format` plus
`@json_stdout_contract` from `npa/src/npa/lifecycle_intent.py`, which guarantees
exactly one JSON document on stdout.

## Errors And Exit Codes

Raise a domain error from the workbench module, map it to `HTTPException` in the
service, and let the CLI turn it into a message. `npa/src/npa/errors.py` holds
the shared base (`NpaError`); most tools define their own subclasses locally.
`npa/src/npa/cli/_error_formatting.py` renders serverless errors for humans or
as JSON.

The top-level handler is `app_entry()` in `npa/src/npa/cli/main.py`:

| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Serverless/client errors, and most command-local `typer.Exit(1)` |
| 2 | Unexpected exception |
| 130 | SIGINT |

On exit code 2 the CLI prints a hint instead of a traceback; `NPA_DEBUG=1`
restores the traceback. Never swallow an exception silently — a bare
`except Exception: pass` is rejected by
`npa/tests/guardrails/test_hygiene_guards.py`.

## Three Decorators That Are Easy To Forget

- `@resolve_typer_defaults` (`npa/src/npa/cli/_typer_defaults.py`) — required
  when one Typer command calls another as a plain Python function. Without it an
  unresolved `OptionInfo` object leaks into downstream code such as Terraform
  variables or shell commands. Enforced by
  `npa/tests/guardrails/test_typer_command_calls.py`.
- `@json_stdout_contract` (`npa/src/npa/lifecycle_intent.py`) — on any command
  exposing a JSON flag.
- `@intent_boundary` (`npa/src/npa/lifecycle_intent.py`) — on entrypoints that
  provision or destroy, so the lifecycle intent is inherited by child processes.

## Config And Credentials

Never hardcode project, tenant, registry, or bucket identifiers. Read them
through `npa/src/npa/clients/config.py` and
`npa/src/npa/clients/credentials.py`:

```python
from npa.clients.config import resolve_config, resolve_environment
from npa.clients.credentials import load_credentials

cfg = resolve_config(project=project, name=name)
env = resolve_environment(project=project)
creds = load_credentials()
```

Precedence is CLI flags, then environment variables, then
`~/.npa/credentials.yaml`, then `~/.npa/config.yaml`. Other accessors worth
knowing: `resolve_ssh_config`, `resolve_project_storage`,
`resolve_container_registry`, and the deep-merging `write_config` /
`write_credentials_file`.

Committed examples use placeholders such as `<your-project-id>` and
`<your-bucket>`. Concrete values are caught by gitleaks and the confidentiality
scan — see `skills/atomic/protect-nebius-infra-details/SKILL.md`.

## Subprocesses

To re-invoke the CLI internally, use `internal_cli_argv()` from
`npa/src/npa/cli/invocation.py`. It runs `python -m npa` on the active
interpreter rather than trusting an `npa` binary on `PATH`.

## Before You Push

Changing CLI options invalidates generated docs and can break catalog argv.
Regenerate with `bash scripts/build_docs.sh` and re-check the catalog contract
in `skills/atomic/toolref-argv-contract/SKILL.md`. Full gate order is in
`skills/atomic/pre-pr-validation/SKILL.md`.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.