Using the CLI Binary for Scripts and Agents#

Overview#

Scripts and agents call the CLI binary directly instead of the nvwb shell wrapper.

The binary is found at ~/.nvwb/bin/nvwb-cli on macOS and Linux, as well as in the WSL distribution on Windows.

The shell wrapper is a bash function that is only available in interactive shells that have sourced .bashrc. A script or agent’s execution environment does not guarantee that.

The binary does not use activate, deactivate, open or close.

Those commands manage shell session state for interactive use through the nvwb wrapper. Script and agent commands run in their own process, so they don’t inhereit session state.

Instead, you need to pass the location and project to the command explicitly using the -c and -p flags, as well as setting the output flag like -o json.

Not all commands require the contect and project flag.

Not every command needs all three flags.

For example the list contexts command doesn’t require any flags, nor do the integration commands.

Others, for example list projects and list bases require a location flag with -c but not a project with -p.

The CLI does not change its output format when piped.

The default table output is identical whether stdout is a terminal or a pipe. -o json is required for any command whose output you want to parse.

Key Concepts#

Calling convention

Projects: ~/.nvwb/bin/nvwb-cli -c <context> -p <project-path> <command> [args] -o json.

Location but no project: ~/.nvwb/bin/nvwb-cli -c <context> <command> [args] -o json.

Targeting AI Workbench itself ~/.nvwb/bin/nvwb-cli <command> [args] -o json.

Context flag -c

Replaces activate when calling the binary. Does not start the service on the location, and the location must already be running

Not needed for commands that do not target a specific location, such as list contexts or integration commands.

Project flag -p

Replaces open when calling the binary and takes the absolute path to the project directory on the location.

Not needed for commands that do not target a specific project, such as list projects or create project.

JSON output -o json

Returns structured JSON instead of styled table output. Required for parsing command results.

Calling Convention#

Pass -c and -p where relevant, and -o json when you need to parse the output.
#!/bin/bash
# Define the binary path and context once
NVWB="$HOME/.nvwb/bin/nvwb-cli"
CONTEXT="local"
PROJECT="/home/workbench/nvidia-workbench/my-project"

# Commands that target AI Workbench itself (no -c or -p)
$NVWB list contexts -o json
$NVWB list integrations -o json
$NVWB connect integration Github

# Commands that target a location (-c only)
$NVWB list projects -c "$CONTEXT" -o json
$NVWB list bases -c "$CONTEXT" -o json

# Commands that target a project (-c and -p)
$NVWB status -c "$CONTEXT" -p "$PROJECT" -o json
$NVWB build -c "$CONTEXT" -p "$PROJECT"

On Windows you can use a WSL command to call the CLI or you can do it in the WSL distribution.

If you are scripting or using an agent from the Windows side, you can wrap them in a call to the proper WSL distribution.

Example: wsl -d NVIDIA-Workbench -u workbench -- /home/workbench/.nvwb/bin/nvwb-cli <arguments>

JSON Response Shapes#

Every JSON response from the CLI is one of four shapes.

List and query commands return {"result": [...]}.

The result is always an array, even for a single item. Access items with .result[] in jq.

# Extract all project paths
$NVWB list projects -c local -o json | jq -r '.result[].Path'
The status command returns {"result": {...}}.

The result is a single object, not an array. Access fields directly with .result.FieldName.

# Get build state
$NVWB status -c local -p "$PROJECT" -o json | jq -r '.result.Environment.BuildState'
The create project and clone project commands return {"messages": [...]}.

Each message has message and detail fields. The project path is embedded in the message string, not a dedicated field. Use the --projectPath you passed to the command rather than parsing the message.

All errors return {"error": "...", "detail": "..."}.

This shape is consistent across every command. Exit code 1 accompanies every error response.

#!/bin/bash
# Check for errors in the response
RESPONSE=$($NVWB status -c local -p "$PROJECT" -o json)

ERROR=$(echo "$RESPONSE" | jq -r '.error // empty')
if [ -n "$ERROR" ]; then
  DETAIL=$(echo "$RESPONSE" | jq -r '.detail // empty')
  echo "Error: $ERROR$DETAIL"
  exit 1
fi

Project State Machine#

Many commands require the project to be in a specific state before they succeed.

Check the project state with status before running commands that have preconditions.

Build states:
  • NO_BUILD — Build has never run or was reset.

  • BUILDING — Build is in progress.

  • BUILD_COMPLETE — Built and the project container is available.

  • BUILD_ERROR — Last build failed.

Run states:
  • CONTAINER_NOT_CREATED — The project container does not exist.

  • RUNNING — The project container is running.

  • STOPPED — The project container exists but is stopped.

Preconditions by operation:
  • build — Any build state. Re-runs if already built.

  • start <app> — Build state must be BUILD_COMPLETE. All sensitive environment variables must be configured.

  • stop <app> — Run state must be RUNNING.

  • add/remove environment variables, mounts, or secrets — Run state must be CONTAINER_NOT_CREATED or STOPPED.

  • delete project — Run state must be CONTAINER_NOT_CREATED or STOPPED.

Check state before acting.
#!/bin/bash
# Only build if the project has not been built
NVWB="$HOME/.nvwb/bin/nvwb-cli"
PROJECT="/home/workbench/nvidia-workbench/my-project"

STATE=$($NVWB status -c local -p "$PROJECT" -o json \
  | jq -r '.result.Environment.BuildState')

if [ "$STATE" = "NO_BUILD" ] || [ "$STATE" = "BUILD_ERROR" ]; then
  $NVWB build -c local -p "$PROJECT"
fi

Useful Status Fields#

The status command returns detailed project information.

Use jq to extract the fields you need.

result.Path                           Absolute path (use with -p)
result.Name                           Registered name (from spec.yaml)
result.Environment.BuildState         See build states above
result.Environment.RunState           See run states above
result.Applications[].name            Application name for start/stop
result.Applications[].info.runState   NOT_RUNNING or RUNNING
result.Applications[].info.url        null when stopped, URL when running
result.RepoState.CommitsAhead         Integer
result.RepoState.CommitsBehind        Integer
result.CurrentGitBranch.Name          Current branch name
result.Resources.GPUsRequested        Integer

Use the Project Path, Not the Name#

Always identify projects by absolute path, not by name.

The registered project name comes from spec.yaml inside the repository, not from the directory name. Cloning a project into --projectPath .../my-dir may register it under a completely different name. The absolute path is stable and unambiguous.

#!/bin/bash
# Correct: use the path you specified
$NVWB clone project https://github.com/org/repo \
  --projectPath /home/workbench/nvidia-workbench/my-project \
  -c local

# Subsequent commands use the same path
$NVWB build -c local -p /home/workbench/nvidia-workbench/my-project

Patterns#

Check state, build, and start an application.
#!/bin/bash
NVWB="$HOME/.nvwb/bin/nvwb-cli"
CONTEXT="local"
PROJECT="/home/workbench/nvidia-workbench/my-project"

# Check current build state
BUILD_STATE=$($NVWB status -c "$CONTEXT" -p "$PROJECT" -o json \
  | jq -r '.result.Environment.BuildState')

# Build if needed
if [ "$BUILD_STATE" = "NO_BUILD" ] || [ "$BUILD_STATE" = "BUILD_ERROR" ]; then
  $NVWB build -c "$CONTEXT" -p "$PROJECT"
fi

# Check run state before starting
RUN_STATE=$($NVWB status -c "$CONTEXT" -p "$PROJECT" -o json \
  | jq -r '.result.Environment.RunState')

if [ "$RUN_STATE" != "RUNNING" ]; then
  APP_NAME=$($NVWB status -c "$CONTEXT" -p "$PROJECT" -o json \
    | jq -r '.result.Applications[0].name')

  $NVWB start "$APP_NAME" -c "$CONTEXT" -p "$PROJECT" --no-browser
fi
Iterate over all projects in a location.
#!/bin/bash
# Get status for every project in a location
NVWB="$HOME/.nvwb/bin/nvwb-cli"

$NVWB list projects -c local -o json \
  | jq -r '.result[].Path' \
  | while read path; do
      $NVWB status -c local -p "$path" -o json \
        | jq '{name: .result.Name, build: .result.Environment.BuildState, run: .result.Environment.RunState}'
    done
Set a sensitive variable from stdin.
#!/bin/bash
# Pipe a value from a vault or environment into a sensitive env var
echo "$SECRET_VALUE" | $NVWB create environment-variable API_KEY - \
  --is-sensitive -c local -p "$PROJECT" -o json
Create a project with a specific base environment.
#!/bin/bash
NVWB="$HOME/.nvwb/bin/nvwb-cli"

# Look up the base environment ID
BASE_ID=$($NVWB list bases -c local -o json \
  | jq -r '.result[] | select(.Name == "Python Basic") | .Id')

# Create the project
$NVWB create project my-project \
  --base-environment-id "$BASE_ID" \
  --projectPath /home/workbench/nvidia-workbench/my-project \
  -c local

# Build using the known path
$NVWB build -c local -p /home/workbench/nvidia-workbench/my-project