## 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)

```bash
brew install doitintl/dci-cli/dci
```

### Windows (WinGet)

```bash
winget install DoiT.dci
```

### Windows (Scoop)

```bash
scoop bucket add doitintl https://github.com/doitintl/dci-cli
scoop install dci
```

### Linux (Debian/Ubuntu)

Download the `.deb` package from the [latest release](https://github.com/doitintl/dci-cli/releases/latest), then install:

```bash
sudo dpkg -i dci_*_linux_amd64.deb
```

### Linux (RHEL/Fedora)

Download the `.rpm` package from the [latest release](https://github.com/doitintl/dci-cli/releases/latest), then install:

```bash
sudo rpm -i dci_*_linux_amd64.rpm
```

### Direct download

Prebuilt binaries for all platforms are available on the [GitHub Releases page](https://github.com/doitintl/dci-cli/releases/latest).

### Validate the installation

```bash
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

```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

```bash
dci completion zsh > "${fpath[1]}/_dci"
```

Then restart your shell or run `exec zsh` to pick up the new completions.

### Fish

```bash
dci completion fish > ~/.config/fish/completions/dci.fish
```

### PowerShell

```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:

```bash
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:

```bash
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:

```bash

```

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                                              | <ol><li>Sign in to the DoiT console.</li><li>Select your avatar in the upper-right corner of the top navigation bar, and then select your name from the drop-down menu.</li><li>Select the **API** tab.</li><li>Select **Create API token**.</li></ol>                                                                                  |
| **Service account API token** | Shared automation (CI/CD, scheduled jobs) that should not depend on one person | <ol><li>Sign in to the DoiT console, select the gear icon () from the top navigation bar, and then select **Users and access**.</li><li>Select **Service accounts** from the left-hand menu.</li><li>Select a service account.</li><li>Select the **API tokens** tab.</li><li>Select **Create API token**.</li></ol> |

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.

:::note

New tokens may take up to one minute to work after creation.

:::

:::caution

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](https://developer.doit.com/docs/start), [Personal API tokens](https://help.doit.com/docs/general/profile/api-tokens), and [Service accounts](https://help.doit.com/docs/user-management/service-accounts).

### Verify authentication

Check your configuration, session state, and active customer context:

```bash
dci status
```

To confirm your identity and permissions against the API, run:

```bash
dci validate
```

---

## Getting started

After installing and authenticating, try a few commands:

```bash
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:

```bash
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:

```bash
dci <command> [arguments] [flags]
```

Examples:

```bash
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:

```bash
dci create-alert < alert.json
dci invite-user email: user@example.com, roleId: <role-id>
```

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):

```bash
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](#timestamps)). 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                                               |

```bash
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](#timestamps)), 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:

```bash
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:

```json
{
  "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](#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:

```bash
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:

```bash
dci commands --json
```

### Documentation for agents

Agents can discover and consume the CLI documentation without a browser:

- `dci docs` prints 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 `.md` to its URL — this page is [help.doit.com/docs/cli.md](https://help.doit.com/docs/cli.md)
- [help.doit.com/llms.txt](https://help.doit.com/llms.txt) is a machine-readable index of all Help Center pages (including the CLI command reference), and [llms-full.txt](https://help.doit.com/llms-full.txt) inlines the full content
- [help.doit.com/llms-cli.txt](https://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, and `dci <command> --help-full` includes 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](https://help.doit.com/docs/mcp/connections).

---

## 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/…`):

```bash
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`:

```bash
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](#timestamps)        |

---

## 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 json` for machine-readable output
- Set `DCI_API_KEY` to 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:

```bash

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 `--help` on any command for inline usage details
- Integrate the CLI into scripts and automation using `DCI_API_KEY` and an API token from the console
- Install the agent skill with `dci skill <agent>` if you drive the CLI from an AI coding assistant
