Skip to content

Output Formats

Neil Martin edited this page Sep 11, 2026 · 18 revisions

Output Formats

Set the output format with --output / -o or configure a default in the config file with default-output.

Available formats: table, json, csv, yaml, plain, xml, raw, ndjson.

Default Format (TTY-aware)

Since v1.19.0 the CLI auto-resolves the default format from where output is going, so interactive use is readable and piped use is machine-parseable with no extra flags. Resolution order:

  1. An explicit --output / -o flag wins.
  2. Otherwise a default-output value from the config file.
  3. Otherwise auto: table when stdout is a terminal, json when stdout is piped or redirected.
jamf-cli pro computers list                 # terminal -> table
jamf-cli pro computers list | jq '.[].name' # piped     -> json

To force one format whatever the TTY, set default-output in your config (e.g. default-output: table) or pass -o. Classic API commands (classic-*) default to xml with no -o flag set.

Color is gated on the terminal too: the CLI disables ANSI color whenever stdout is not a terminal, so it stays out of a pipe or file.

The global output flags apply to one formatter

--out-file, --select, --compact, --field, --quiet and --no-hints apply to every command, including the pro report family, pro audit, pro overview, protect overview, school overview, pro group-tools, pro classic app-usage, multi and commands. Two consequences for a script:

  • A job that passes --out-file and reads stdout reads nothing, because the payload goes to the file it asked for.
  • A job that passes --select or --compact and parses whole rows receives narrowed rows.

Two previews are exempt. The --yes confirmation tables on pro bulk and on the bulk-targeting device actions stay a table whatever -o says, and stay out of the --out-file data file: their contract is a preview on stdout with the mutation log on stderr, so a format switch meant for the payload leaves the thing you are confirming alone.

pro group-tools export renders through its own --format (yaml or json), and a multi aggregation captures each profile's output and re-renders it one section per merged key. Both sit outside the global -o and both honour the projection flags, multi applying --field per section as a pro report section does.

Table

Best for interactive use: curated column selection, status indicators, and relative timestamps.

$ jamf-cli pro computers list -o table
RESULTS (4 total)

 ID   NAME              ISMANAGED   SERIALNUMBER   LASTCONTACTDATE
──────────────────────────────────────────────────────────────────
 36   MacBook Pro 16    ● true      C02X1234       just now
 42   iMac Office       ● true      C02Y5678       5h ago
 71   MacBook Air       ○ false     C02Z9012       3d ago
 99   Mac mini Server   ● true      C02W3456       Sep 15, 2025 2:30 PM

Protect commands produce the same table format:

$ jamf-cli protect plans list -o table
RESULTS (3 total)

 NAME             LOGLEVEL   AUTOUPDATE   ACTIONCONFIG      TELEMETRY
───────────────────────────────────────────────────────────────────────
 Default Plan     warn       ● true       Standard Alerts   Standard
 Test Plan        info       ○ false      Verbose Alerts    Full
 Minimal Plan     error      ● true       Standard Alerts   Minimal

Detail view for single objects

Since v1.19.0, a single-object response (e.g. a get) rendered in table mode comes out as a vertical FIELD / VALUE layout:

$ jamf-cli pro buildings get 12
FIELD          VALUE
─────────────────────────────
 id            12
 name          HQ London
 streetAddress 1 Finsbury Avenue
 city          London

Arrays render as tables even when they hold a single element. The detail view applies to a single object response.

Smart columns

By default, the table shows a curated set of columns: id, name, status fields (isManaged, enrolled, etc.), serialNumber, and date columns. Use --wide / -w to show all columns.

Column display priority:

  1. id, name (always first)
  2. Status-like columns (isManaged, supervised, enrolled, etc.)
  3. Key identifiers (serialNumber, osVersion, model)
  4. Date columns (lastContactDate, lastReportDate)

Relative timestamps

Date columns within 30 days show as relative times:

Age Display
< 1 minute just now
< 1 hour 5m ago
< 1 day 3h ago
< 1 week 2d ago
< 30 days 1w ago
≥ 30 days Sep 15, 2025 2:30 PM

In --wide mode, dates show as absolute timestamps.

Status indicators

The table renders boolean and status-like fields with colored symbols:

Symbol Color Meaning Example values
green Active/positive true, managed, enrolled, active, enabled, healthy
dim Inactive/negative false, unmanaged, unenrolled, inactive, disabled
yellow Pending/warning pending, unknown, warning
red Error/critical error, failed, critical, unhealthy

Color control

Disable colors with --no-color, by setting the NO_COLOR environment variable (any value; see no-color.org), or by redirecting stdout (colors are auto-disabled for non-TTY output). The --out-file flag also disables colors.

JSON

Pretty-printed with 2-space indentation, for scripting and piping to jq:

# Get all computer names
jamf-cli pro computers list -o json | jq '.[].name'

# Find computers with old OS versions
jamf-cli pro computers list -o json | jq '.[] | select(.operatingSystemVersion < "15")'

# Count managed devices
jamf-cli pro computers list -o json | jq '[.[] | select(.isManaged == true)] | length'

An empty list prints []

A collection with nothing in it renders as an empty JSON array, so a jq pipeline behaves the same whether the tenant holds objects or not:

$ jamf-cli security ztna-gateways list -o json
[]

-o ndjson differs by design: an empty list prints nothing at all, no empty array and no null line.

Table columns come from the first row

A table's (and CSV's, and plain's) column set is the keys of its first row. The formatter does not union keys across rows, so a field that only some rows carry is a column only when the first row carries it. --wide reads the first row too.

Parse -o json when you are after a field that is optional on the resource. One concrete case: config list sorts profiles by name, and its table / csv / plain forms therefore carry environment-id and default on every row and leave out tenant-id, environment being the scope level to prefer. -o json and -o yaml carry tenant-id.

With --select or --compact active, the column set is the union across rows. Both flags leave rows heterogeneous (a row keeps a key only where it carried a match), so a first-row-decides column set would drop a key the first row lacked from every row:

$ jamf-cli commands -o csv --select command,api | head -1
api,command

The union is scoped to that case; with no projector the first row decides.

With -o json active, errors are also emitted as JSON on stdout (see Error Handling & Exit Codes).

CSV

Headers on the first row, spreadsheet-ready:

# Export to file
jamf-cli pro computers list -o csv --out-file fleet-report.csv

# Pipe to other tools
jamf-cli pro computers list -o csv | column -t -s,

YAML

2-space indented YAML output:

jamf-cli pro computers list -o yaml

Plain

Tab-separated values, no headers. Built for Unix pipelines:

# Get just the IDs
jamf-cli pro computers list -o plain | cut -f1

# Count managed devices
jamf-cli pro computers list -o plain | awk -F'\t' '$5=="true"' | wc -l

# Feed IDs into another command
jamf-cli pro computers list -o plain | cut -f1 | while read id; do
  jamf-cli pro computers get "$id" -o json
done

NDJSON (v1.22.0+)

-o ndjson prints one compact, newline-terminated JSON object per line, with no enclosing []. A list is never buffered into a single array, so a consumer can process records as they arrive:

# Stream computers one JSON object per line
jamf-cli pro computers list --all -o ndjson

# Pipe straight into jq without waiting for the whole array
jamf-cli pro computers list --all -o ndjson | jq -c 'select(.isManaged == true)'

A get (single object) prints one line. An empty list prints nothing at all, no null line. List commands unwrap the API's {"results": [...]} envelope, so -o ndjson emits records and never the wrapper.

Output to File

Use --out-file to write output to a file in place of stdout. The CLI disables colors.

jamf-cli pro computers list -o csv --out-file inventory.csv

pro backup and protect backup are the exceptions to every -o instruction on this page. Both take --output as a destination directory, and cobra drops an inherited persistent flag whose name the command already declares, the shorthand with it, so -o does not exist on those two commands:

$ jamf-cli pro backup -o json --output ./backup
unknown shorthand flag: 'o' in -o        # exit 2

Use --format yaml|json, their own switch for the files they write. This bites hardest through JAMF_CLI_ARGS, which the CLI prepends to every invocation, so export JAMF_CLI_ARGS='-o json' breaks the backup step of an otherwise working pipeline. See CI/CD & Scripting#JAMF_CLI_ARGS.

Field Extraction

Use --field to extract a single field from every object in the JSON response. Output is one value per line, for piping.

# Get just the IDs
jamf-cli pro buildings list --field id

# Get just the names
jamf-cli pro computers list --field name

# Pipe IDs into another command
jamf-cli pro scripts list --field id | while read id; do
  jamf-cli pro scripts get "$id" -o yaml
done

# Count buildings
jamf-cli pro buildings list --field id | wc -l

--field works with both array responses ([{"id":1}, ...]) and single objects ({"id":1, "name":"HQ"}). The CLI skips an object that lacks the field, and returns an error on a non-JSON response.

Field Projection

Two flags narrow output beyond --field, for AI agents, token-efficient pipelines, or pulling a few specific paths out of a large response. Both are global flags available on all list and get commands.

--compact

Keeps only high-signal scalar fields and drops rare noise. As of v1.19.0 it is semantic in place of a blunt drop-all-nested filter:

  • In a list, it keeps an identity/allowlist of leaf fields (id, name, etc.) plus any scalar present in ≥ 80% of rows; fields carried by a handful of objects are dropped as noise.
  • For a single object, it keeps scalars except a verbose blocklist.
# High-signal scalars only, a smaller payload for agents
jamf-cli pro computers list --all --compact -o json

# Single object, minus verbose fields
jamf-cli pro computers get --serial C02X1234 --compact -o json

To keep a rare field that --compact drops, name it with --select. --compact is ignored when --field is also set, since --field reduces to one value per object.

--select

Projects output to a specific set of dot-path fields. Multiple fields are comma-separated.

# ID and name only
jamf-cli pro computers list --all --select id,general.name -o json

# ID, serial, and OS version
jamf-cli pro computers list --all --select id,hardware.serialNumber,operatingSystemVersion -o json

# Works on any resource
jamf-cli pro scripts list --select id,name,categoryId -o json

Dot-path notation follows JSON key nesting (general.name{"general": {"name": "..."} }). The CLI skips fields absent from an object. --select is ignored when --field is also set. A blank or whitespace-only path is dropped, so --select "$FIELDS" with FIELDS unset leaves the output unprojected.

The two flags across formats

--select and --compact keep the value's own structure under json, yaml, ndjson, xml and raw, and project it into columns for the rest. The CLI takes the --output value verbatim without normalising case, so -o Table is a value the renderer does not recognise and renders as a table, with the column shape that any unrecognised format gets.

A projection that matches nothing says so

$ jamf-cli commands -o table --select nosuchfield
--select nosuchfield matched no field in 1757 row(s)

$ jamf-cli commands --field nosuchfield
--field nosuchfield matched no field in 1757 row(s)

Neither --quiet nor --no-hints silences those lines, since a miss produces no output at all under table, csv, plain and the single-object detail view, and nothing else separates a wrong field name from an empty result. A projection matching nothing in any row renders nothing.

The large-result hint is withheld while either flag is active. And --select bypasses the table's default-column heuristic, so a named field renders without --wide.

XML

Classic API commands (classic-*) return pretty-printed XML by default, the native wire format for these endpoints. You can also ask for XML by name:

# Default for Classic API, pretty-printed XML
jamf-cli pro classic-policies get 100

# Equivalent explicit form
jamf-cli pro classic-policies get 100 -o xml

# Convert to JSON instead
jamf-cli pro classic-policies get 100 -o json

# Table view
jamf-cli pro classic-policies list -o table

Note: XML output is available on Classic API commands. Modern API commands (computers, scripts, buildings, etc.) return JSON by default.

Raw

-o raw outputs exact bytes from the API: no pretty-printing, no conversion. Useful when you need the wire response verbatim:

# Write exact API response to file
jamf-cli pro classic-policies get 100 -o raw > policy.xml

# Pipe to xmllint or another tool
jamf-cli pro classic-policies get 100 -o raw | xmllint --format -

-o xml reformats; raw output keeps the indentation and line breaks the server returned.

Spinner Animation

During API requests, the CLI displays a braille spinner animation (⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏) on stderr. The spinner:

  • Only appears when stderr is a TTY
  • Is suppressed by --quiet or --verbose
  • Is suppressed by the NO_COLOR environment variable or --no-color flag
  • Does not interfere with stdout output

Advisory Hints (v1.18.0+)

A list returning 50 or more results picks up a one-line advisory hint on stderr, suggesting how to narrow the output:

hint: 137 results returned. Narrow with --select=<fields>, --compact, or command-specific filter flags.

The hint is informational: it goes to stderr and leaves stdout alone, so it is safe alongside machine-parseable output. It fires for json, csv and yaml output, and is skipped for table (which already shows a row count) and below the 50-result threshold.

Suppress it with the --no-hints flag or the JAMF_CLI_NO_HINTS environment variable:

jamf-cli pro computers list --no-hints
export JAMF_CLI_NO_HINTS=1        # suppress for the whole session

--no-hints is narrower than --quiet: it silences the advisory hint and keeps the spinner and progress output. --quiet suppresses the hint too, along with all other non-error output.

Since v1.26.0: the once-a-day "new jamf-cli release" notice counts as an advisory hint, so --no-hints, JAMF_CLI_NO_HINTS and --quiet all suppress it as well. It fires only when both stdout and stderr are terminals. See Configuration & Profiles#Release Update Notice (v1.26.0+) for its own opt-outs.

Verbose Mode

Verbose is a count flag: repeat to add detail. Three levels (added in v1.14.0):

Flag Shows
-v Request/response lines (--> / <--)
-vv -v + request and response headers
-vvv -vv + request and response bodies
--> GET https://jamf.company.com/api/preview/computers
<-- 200 200 OK

Retries are labelled

A retried request carries the attempt number and how long the CLI waited, which separates a slow call from a retry sequence:

--> GET https://eu.api.jamfcloud.com/sso/v1/connections
<-- 502 502 Bad Gateway
--> GET https://eu.api.jamfcloud.com/sso/v1/connections (retry 1, waited 1.4s)
<-- 502 502 Bad Gateway
--> GET https://eu.api.jamfcloud.com/sso/v1/connections (retry 2, waited 2.5s)

A repeat carries the label when the previous attempt failed, so a command that re-issues one request (a poll, or a --name lookup followed by a list of the same collection) reads as what it is. This covers requests through the Platform gateway: Platform API commands and the gateway-served Jamf Security Cloud commands.

Note: Verbose output goes to stderr so it stays clear of machine-parseable stdout. Bodies at -vvv are redacted for credentials: a field whose name contains password, passphrase, secret, client_secret, api-key, private-key, encryption-key, recovery-key, signing-key or service-token has its value replaced with [REDACTED], across all three encodings the CLI logs (JSON, form-encoded and Classic XML), on requests and responses alike, so the OAuth token exchange and a Classic read of a distribution point or SMTP server are both safe to log. Redaction matches on the field name, so reach for -vvv with care: a body can carry sensitive data in fields named nothing like a credential.

jamf-cli Wiki


Products

  • Jamf Pro: jamf-cli pro
  • Jamf Platform API: jamf-cli pro (blueprints, benchmarks, DDM reports)
  • Jamf Platform: jamf-cli platform (AI Governance, Jamf Account, audit)
  • Jamf Protect: jamf-cli protect
  • Jamf School: jamf-cli school
  • Jamf Security Cloud: jamf-cli security

Clone this wiki locally