CLI
Background
dci is the command-line interface for Cloud Intelligence™: work with your reports, budgets, anomalies, allocations, and the rest of the platform directly from your terminal — and hand the same tool to your AI agents. It is a standalone binary that generates its commands from the Cloud Intelligence™ API, handles authentication, and renders results for humans (pivoted, readable tables) or machines (JSON, CSV, and the token-efficient TOON format).
This documentation covers:
- Installing the CLI on macOS, Windows, and Linux
- Shell completion setup
- Authentication via OAuth or API token
- Command discovery and usage patterns
- Output formats and scripting
- A full, generated command reference (available via the sidebar)
Download and install
Install the dci binary using one of the methods below.
macOS (Homebrew)
brew install doitintl/dci-cli/dci
Windows (WinGet)
winget install DoiT.dci
Windows (Scoop)
scoop bucket add doitintl https://github.com/doitintl/dci-cli
scoop install dci
Linux (Debian/Ubuntu)
Download the .deb package from the latest release, then install:
sudo dpkg -i dci_*_linux_amd64.deb
Linux (RHEL/Fedora)
Download the .rpm package from the latest release, then install:
sudo rpm -i dci_*_linux_amd64.rpm
Direct download
Prebuilt binaries for all platforms are available on the GitHub Releases page.
Validate the installation
dci --version
Shell completion
Since v2.1, Homebrew and the Linux .deb/.rpm packages install shell completion automatically, and Scoop prints the one PowerShell profile line to add after install. For other setups, generate the script for your shell below.
Bash
# System-wide (requires sudo):
dci completion bash > /etc/bash_completion.d/dci
# Per-user:
mkdir -p ~/.bash_completions
dci completion bash > ~/.bash_completions/dci
echo 'source ~/.bash_completions/dci' >> ~/.bashrc
Zsh
dci completion zsh > "${fpath[1]}/_dci"
Then restart your shell or run exec zsh to pick up the new completions.
Fish
dci completion fish > ~/.config/fish/completions/dci.fish
PowerShell
dci completion powershell > dci.ps1
# Then add `. /path/to/dci.ps1` to your PowerShell profile.
Completion covers all API commands (list-budgets, list-reports, query, etc.) with descriptions, flag completion for each command, and — since v2.1 — your resource names: dci get-report Mon<TAB> offers matching report names, served from a local cache that refreshes in the background. Type names bare when completing (the shell escapes spaces for you); completing inside an open quote is not supported by shell completion frameworks. API command and name completion require an active auth session (dci login or DCI_API_KEY); the first Tab on a cold cache prints a short notice while names load (suppress notices with DCI_ACTIVE_HELP=0).
Authentication
The CLI supports two authentication methods.
Interactive (OAuth)
Run dci login to authenticate via the console in your browser:
dci login
This opens a browser window, prompts you to log in, completes an OAuth flow, and caches credentials locally. In an interactive terminal, the first command you run triggers this flow automatically; non-interactive sessions (CI, pipes, agents) never wait for a browser — without credentials they fail fast with AUTHENTICATION_REQUIRED and a pointer to DCI_API_KEY.
To clear cached credentials:
dci logout
API token (CI/automation)
For non-interactive environments such as CI/CD pipelines, cron jobs, and shell scripts, set the DCI_API_KEY environment variable to a DoiT API token:
export DCI_API_KEY=<YOUR_API_TOKEN>
When DCI_API_KEY is set, the CLI uses it instead of OAuth.
Choose a token type
DoiT supports two API token types for programmatic access. For CLI automation, choose based on whether the job runs as you or as shared organizational automation:
| Token type | Best for | Where to create it |
|---|---|---|
| Personal API token | Scripts or jobs tied to your user |
|
| Service account API token | Shared automation (CI/CD, scheduled jobs) that should not depend on one person |
|
Use a personal API token for local scripts or one-off automation you run yourself. Use a service account API token for pipelines and scheduled jobs that must keep working if you change roles or leave the organization.
When you create a personal API token, choose a permission scope that matches what the CLI commands need:
| Scope | Use when |
|---|---|
| Read only | The job only reads data (for example, dci list-reports) |
| Full access | The job needs every permission your user role grants |
| Custom scope | The job needs a specific subset of permissions |
Service account tokens inherit the permissions assigned to the service account. Grant only the permissions each workload needs.
New tokens may take up to one minute to work after creation.
Treat API tokens like passwords. Store DCI_API_KEY in your secrets manager or CI/CD secret store. Do not commit tokens to source control.
For more on creating tokens and permission behavior, see DoiT Developer Hub: Get started, Personal API tokens, and Service accounts.
Verify authentication
Check your configuration, session state, and active customer context:
dci status
To confirm your identity and permissions against the API, run:
dci validate
Getting started
After installing and authenticating, try a few commands:
dci list-budgets
dci list-reports
dci get-report <report-id>
Use --help on any command for inline usage details; help is terse by default, and --help-full adds the complete request/response schemas:
dci --help
dci list-budgets --help
dci query --help-full
If you mistype a command name, the CLI exits with a non-zero code and suggests the closest match. To jump from the terminal into the console, dci open (or dci open report <id>, budget, allocation) opens the deep link in your browser — or prints it in agent and non-interactive modes.
Command structure
Commands are generated directly from the Cloud Intelligence™ API. The general structure is:
dci <command> [arguments] [flags]
Examples:
dci list-alerts
dci get-alert <id>
dci list-budgets
dci list-reports
For commands that accept a request body, pipe a JSON file via stdin or pass fields as inline shorthand arguments:
dci create-alert < alert.json
The CLI validates request bodies against the API schema: unknown top-level fields are rejected with a usage error listing the valid fields, instead of being silently ignored by the API.
Running queries
dci query runs a Cloud Analytics report query without persisting it. The request body is a JSON object with a config key describing metrics, grouping, time ranges, and filters (there is no SQL input mode):
dci query < query.json
Always include a group limit in query configs — an unlimited grouped query over a long time range can return thousands of rows. Run dci query --help-full to see the full request schema and a complete example payload.
Report results
Report and query results (result.rows) are positional arrays zipped with result.schema. The following flags shape them:
In the interactive table view, report results render as a pivot by default — groups as rows, time periods as columns, with totals, a first→last trend column, and heatmap shading by magnitude — matching how the console presents a report. Machine formats (json, yaml, csv, toon), agent mode, and explicit -C column selections keep the flat row layout. Timestamps follow the report's time resolution (hourly results keep the hour on every row; daily and coarser show bare dates) and period columns are always UTC — they label billing buckets, not moments (see Timestamps and timezones). Ranges with too many periods to scan default to flat rows — pass --pivot to force the matrix.
Monetary amounts are currency-aware when the query config specifies a currency or a response row carries one (such as a budget). Human tables render those amounts with the currency sign rounded to whole units ($239,927, €205,956), and machine-formatted report results include the explicit currency. The CLI does not assume a currency when the API response and request omit it. --raw-numbers restores exact unformatted values. The following flags shape results further:
| Flag | Description |
|---|---|
--flat | Render report results as flat rows instead of the default pivot view |
--pivot | Force the pivot view in any mode or output format |
--heatmap | Shade pivot cells by magnitude in interactive terminals (default on; respects NO_COLOR; --heatmap=false disables) |
--rows keyed | Return rows as objects keyed by schema column names instead of positional arrays |
--max-rows <n> | Cap the number of result rows (0 = unlimited). Agent mode defaults to 500; when rows are omitted the result carries rowsOmitted and rowsTotal markers |
--include-empty-rows | Keep rows with a null group and zero metrics (dropped by default; emptyRowsDropped marks how many were removed) |
--raw-numbers | Print numbers unformatted in table output |
get-report also accepts --time-range (e.g. P30D), or --start-date and --end-date (yyyy-mm-dd, must be provided together) to override the report's time settings.
Output formats
Commands support multiple output formats via the --output flag:
| Format | Description |
|---|---|
table | Human-readable tabular display (default in interactive terminals) |
json | Machine-readable JSON — recommended for scripting |
yaml | YAML structured output |
csv | Comma-separated values for spreadsheet import (list and report results) |
toon | Compact, token-efficient encoding for LLM agents (default in agent mode) |
auto | Alias for the mode default |
dci list-budgets --output json
dci list-budgets --output table
dci list-reports --output csv > reports.csv
Use --fields id,name to project responses to specific fields before output, and --exclude description to remove fields.
Table output options
Tables are rendered for reading: text aligns left and numbers right, timestamps display as human-readable dates (bare dates at report grain, minute precision for event times — shown in your local timezone), integral numbers group without decimals, and when a response has more columns than fit the terminal, the table keeps the ones that render readably — identity (id, name) and date columns first — and lists the hidden rest with a hint (-C to choose, -M wrap to wrap, -W to widen). --raw-numbers restores exact unformatted values.
The following flags control how the table is rendered:
| Flag | Short | Default | Description |
|---|---|---|---|
--table-mode | -M | fit | fit truncates long cell values to fit the terminal width. wrap wraps them across multiple lines. |
--table-columns | -C | all columns | Comma-separated list of columns to include, in the order listed. |
--table-width | -W | auto-detect | Table width in columns. Defaults to terminal width, falls back to the COLUMNS env var, then 120. |
--table-max-col-width | -X | 0 (auto) | Maximum width per column when fitting or wrapping. 0 lets the CLI decide automatically. |
Example combining multiple options:
dci list-budgets --table-mode wrap --table-columns id,name,amount --table-max-col-width 40
Timestamps and timezones
Interactive tables show event timestamps — created, updated, acknowledged, and similar moments — in your local timezone. Columns carrying such values are titled with a (local) suffix (for example updated (local)), and a one-line note on stderr names the zone in use:
note: times shown in local time (UTC+03:00); pass --utc for UTC
Everything else stays in UTC by design:
- Report period columns (daily and hourly cost buckets) and anomaly usage windows (
started (UTC)) label UTC billing buckets — shifting them would move costs onto the wrong day. - Calendar dates — contract terms, invoice dates, budget periods — render as plain dates.
- Machine formats (
json,yaml,csv,toon) and agent mode always emit UTC or raw epoch values, so scripted output is identical on every machine.
| Control | Effect |
|---|---|
--utc | Keep table timestamps in UTC (time columns are titled (UTC)) |
DCI_TZ=<IANA name> | Display in a specific timezone instead of the system one, e.g. DCI_TZ=Europe/Berlin |
Agent mode
The CLI auto-detects when it is driven by an AI agent (via common agent environment variables) and switches to agent mode: output defaults to compact TOON, colors and decorations are disabled, and informational messages are routed to stderr so stdout stays parseable. Force it on with --agent or DCI_AGENT_MODE=1, or off with --no-agent; dci status shows the current mode.
In agent mode, failures are written to stderr as a JSON envelope with a stable code, message, and retryable flag, plus optional hint, http_status, request_id, and retry_after fields:
{
"error": {
"code": "RESOURCE_NOT_FOUND",
"message": "Not Found",
"retryable": false,
"http_status": 404,
"request_id": "..."
}
}
Agent mode also caps report results at 500 rows by default (see Report results) and fails fast with AUTHENTICATION_REQUIRED when no credentials are available, instead of starting a browser login flow.
To install the CLI's agent skill (usage guidance embedded in the binary) into a coding agent's configuration directory:
dci skill claude # also: codex, cursor, gemini, kiro, opencode
dci skill list # inspect embedded files and token estimates
For machine-readable command metadata — arguments, flags, output shapes, and destructive-operation classification — use:
dci commands --json
Documentation for agents
Agents can discover and consume the CLI documentation without a browser:
dci docsprints this page's URL and the other documentation entry points from the terminal- Every page of this Help Center is available as plain Markdown by appending
.mdto its URL — this page is help.doit.com/docs/cli.md - help.doit.com/llms.txt is a machine-readable index of all Help Center pages (including the CLI command reference), and llms-full.txt inlines the full content
- help.doit.com/llms-cli.txt is a compact CLI-only index — the guides plus every command, each linked to its Markdown page — for agents that only need to drive
dci dci skill <agent>installs task-oriented usage guidance directly into the agent's configuration, anddci <command> --help-fullincludes the full request/response schema for every command
For agents working with DoiT data through tool calls rather than a CLI, see the MCP server.
Customer context
DoiT employees and multi-tenant users must select which customer their commands operate on. Set it temporarily with the DCI_CUSTOMER_CONTEXT environment variable or the -D/--customer-context flag, or persist a default. The value can be a customer domain (acme.com), a customer ID, or the customer's URL display name as it appears in DoiT Console URLs (console.doit.com/customers/acme/…):
DCI_CUSTOMER_CONTEXT=acme.com dci list-budgets # this command only
dci list-budgets -D acme.com # this command only
dci customer-context set acme.com # persistent default
dci customer-context set acme # URL display name works too
dci customer-context show
dci customer-context clear
A wrong persisted context makes every command fail with PERMISSION_DENIED; the error hint names the active context. Verify access after switching with dci validate.
Destructive commands
Commands classified as destructive (deletes and similar) refuse to run without confirmation and exit with code 30:
dci delete-report <id> # refuses: requires confirmation
dci delete-report <id> --dry-run # prints a local preview without executing
dci delete-report <id> --yes # executes
Set DCI_CONFIRM_DESTRUCTIVE=1 to confirm globally in automation that has been reviewed — do not set it as a blanket default.
Environment variables
| Variable | Description |
|---|---|
DCI_API_KEY | API token for non-interactive authentication (personal or service account) |
DCI_CUSTOMER_CONTEXT | Override the customer context for commands |
DCI_AGENT_MODE | Force agent mode on (1) or off (0) |
DCI_CONFIRM_DESTRUCTIVE | Confirm destructive commands without --yes (use with care) |
DCI_SKIP_BODY_VALIDATION | Bypass client-side request-body validation (e.g. when a brand-new API field is rejected against a stale cached spec) |
NO_COLOR | Disable colored output, including the pivot heatmap |
DCI_TZ | Timezone (IANA name, e.g. Europe/Berlin) for table timestamps — see Timestamps and timezones |
Configuration
Configuration is stored in the OS-specific config directory and is created automatically on first run.
| OS | Path |
|---|---|
| macOS | ~/Library/Application Support/dci/apis.json |
| Linux | ~/.config/dci/apis.json |
| Windows | %APPDATA%\dci\apis.json |
To reset configuration, delete the file at the path above and re-run dci login.
Using the CLI in scripts
The CLI is suitable for shell scripts, cron jobs, and CI/CD pipelines.
Recommendations:
- Use
--output jsonfor machine-readable output - Set
DCI_API_KEYto a personal or service account API token for non-interactive authentication; without credentials, non-interactive invocations fail fast instead of waiting for a browser login - Branch on exit codes rather than parsing error text
Example:
export DCI_API_KEY=<YOUR_API_TOKEN>
budgets=$(dci list-budgets --output json)
Exit codes
Exit codes are stable across interactive, script, and agent usage:
| Code | Meaning |
|---|---|
0 | Success |
1 | Generic failure |
2 | Usage error (unknown command, flag, or request body field) |
10 | Authentication required or failed |
11 | Permission denied (check the customer context) |
20 | Resource not found |
21 | Conflict |
30 | Validation error, or a destructive command run without confirmation |
40 | Server or upstream error |
41 | Network error |
50 | Rate limited |
Next steps
- Browse the CLI command reference in the sidebar
- Use
--helpon any command for inline usage details - Integrate the CLI into scripts and automation using
DCI_API_KEYand an API token from the console - Install the agent skill with
dci skill <agent>if you drive the CLI from an AI coding assistant