Output, errors & exit codes¶
vsc is built to be scriptable and agent-friendly: stdout is data, stderr is
diagnostics, and exit codes are a stable contract.
Output formats¶
JSON is the default; --output/-o table renders a Rich table for humans.
vsc --profile prod vsphere vm list # JSON (default)
vsc --profile prod vsphere vm list -o table # table
Only json and table are accepted; anything else is rejected with exit code 2.
Shell completion¶
Install completion for your shell once:
vsc --install-completion # bash, zsh, fish, PowerShell
vsc --show-completion # print the script instead of installing
Completion is fully offline — it never opens a connection. It suggests:
- enum option choices (e.g.
--power-states <TAB>→POWERED_ON,POWERED_OFF), - output formats (
-o <TAB>→json,table), - configured profile names (
--profile <TAB>), - and per-field
listfilter enum choices.
Live resource-id completion (opt-in)¶
Completing a real id (e.g. <vm> from the live inventory) does require a network
call, so it is opt-in and off by default:
export VSC_COMPLETE_DYNAMIC=1
vsc vsphere vm get <TAB> # → vm-101 vm-102 … (real ids, names as help)
When enabled, pressing <TAB> on an id-typed argument or option suggests live
ids for that resource type (VMs, hosts, clusters, datacenters, datastores,
resource pools), showing each resource's name as completion help.
It is built to never get in your way:
- Off by default. Without
VSC_COMPLETE_DYNAMIC,<TAB>stays fully offline (the suggestions above are all you get). - Cached. Results are cached per profile/backend/resource-type under the
platform cache dir with a short TTL (default 60s; override with
VSC_COMPLETE_TTL=<seconds>), so repeated presses don't re-hit the API. - Bounded and fail-soft. The fetch is abandoned after a short timeout
(
VSC_COMPLETE_TIMEOUT, default 2s); any error, missing auth, or timeout yields no suggestions —<TAB>never hangs or prints a traceback. --helpis always offline. Only the shell-completion subprocess ever fetches;--helpand command execution are unaffected.
This is a convenience only. The agent contract is unchanged: don't rely on completion for correctness — list commands remain the source of truth for ids.
Error envelope¶
Errors are written to stderr as a stable JSON object:
{
"error": {
"code": 4,
"kind": "NOT_FOUND",
"message": "...",
"details": { }
}
}
kind is the vAPI error type (or the exception class for transport/config errors).
Branch on code/kind, never on message text.
Exit codes¶
| Code | Name | Meaning |
|---|---|---|
| 0 | OK | Success |
| 1 | ERROR | Generic / unexpected failure |
| 2 | USAGE | Invalid arguments or usage |
| 3 | AUTH | Authentication / authorization failure |
| 4 | NOT_FOUND | Requested resource does not exist |
| 5 | CONNECTION | Could not reach or negotiate with the target (incl. TLS) |
| 6 | CONFIG | Missing or invalid configuration/profile |
| 7 | CONFLICT | Already exists / in use / wrong state / concurrent change |
| 8 | UNAVAILABLE | Target busy, timed out, or temporarily unavailable |
Writes are dry-run by default¶
Write commands (create, delete, set, patch, power actions, …) preview the
request and change nothing unless --apply is passed — a dry-run never opens a
connection. See Writes for the full model and the request/response
envelope. Write failures use the same error envelope and exit codes above (notably
7 CONFLICT and 8 UNAVAILABLE).