-
Notifications
You must be signed in to change notification settings - Fork 4
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.
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:
- An explicit
--output/-oflag wins. - Otherwise a
default-outputvalue from the config file. - Otherwise auto:
tablewhen stdout is a terminal,jsonwhen stdout is piped or redirected.
jamf-cli pro computers list # terminal -> table
jamf-cli pro computers list | jq '.[].name' # piped -> jsonTo 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.
--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-fileand reads stdout reads nothing, because the payload goes to the file it asked for. - A job that passes
--selector--compactand 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.
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
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.
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:
-
id,name(always first) - Status-like columns (
isManaged,supervised,enrolled, etc.) - Key identifiers (
serialNumber,osVersion,model) - Date columns (
lastContactDate,lastReportDate)
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.
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
|
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.
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'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.
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,commandThe 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).
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,2-space indented YAML output:
jamf-cli pro computers list -o yamlTab-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-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.
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 backupandprotect backupare the exceptions to every-oinstruction on this page. Both take--outputas a destination directory, and cobra drops an inherited persistent flag whose name the command already declares, the shorthand with it, so-odoes not exist on those two commands:$ jamf-cli pro backup -o json --output ./backup unknown shorthand flag: 'o' in -o # exit 2Use
--format yaml|json, their own switch for the files they write. This bites hardest throughJAMF_CLI_ARGS, which the CLI prepends to every invocation, soexport JAMF_CLI_ARGS='-o json'breaks the backup step of an otherwise working pipeline. See CI/CD & Scripting#JAMF_CLI_ARGS.
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.
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.
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 jsonTo 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.
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 jsonDot-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.
--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.
$ 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.
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 tableNote: XML output is available on Classic API commands. Modern API commands (
computers,scripts,buildings, etc.) return JSON by default.
-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.
During API requests, the CLI displays a braille spinner animation (⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏) on stderr. The spinner:
- Only appears when stderr is a TTY
- Is suppressed by
--quietor--verbose - Is suppressed by the
NO_COLORenvironment variable or--no-colorflag - Does not interfere with stdout output
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_HINTSand--quietall 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 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
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
-vvvare redacted for credentials: a field whose name containspassword,passphrase,secret,client_secret,api-key,private-key,encryption-key,recovery-key,signing-keyorservice-tokenhas 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-vvvwith care: a body can carry sensitive data in fields named nothing like a credential.
Repository · Issues · Releases
jamf-cli Wiki
- Home
- Community
- Getting Started
- CLI Reference
- Product Commands
- Workflows
- Configuration
- Reference
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