CLI v2.0: before and after
Every entry below shows the same command on dci v1.x and on v2.0. Examples are representative (names and figures anonymized); the behavior is exactly what ships. For the narrative summary, see What's new in v2.0; for flags and reference, the CLI guide.
For humans
Reports pivot by default
Report results used to print as a flat database dump — one row per group × time period, raw floats, epoch timestamps in scientific notation.
║ cost │ month │ service_description │ timestamp │ year ║ ║ 239927.13841529994 │ 05 │ analytics │ 1.7462e+09 │ 2026 ║ ║ 291018.65484701947 │ 06 │ analytics │ 1.7488e+09 │ 2026 ║ ║ 345927.05937314965 │ 07 │ analytics │ 1.7514e+09 │ 2026 ║ ║ 48875.47185098996 │ 05 │ pipelines │ 1.7462e+09 │ 2026 ║ ║ 70157.24905170000 │ 06 │ pipelines │ 1.7488e+09 │ 2026 ║
║ service_description │ 2026-05 │ 2026-06 │ 2026-07 │ total │ trend ║ ║ analytics │ $239,927 │ $291,019 │ $345,927 │ $876,873 │ +44% ║ ║ pipelines │ $48,875 │ $70,157 │ $95,806 │ $214,839 │ +96% ║ ║ storage │ $83,219 │ $70,721 │ $53,925 │ $207,865 │ -35% ║ ║ TOTAL │ $521,554 │ $567,513 │ $638,837 │ $1,727,905 │ +22% ║
Groups × time with currency-signed totals, ranked by spend, heatmap-shaded by magnitude, with a trend column — no flag needed. --flat restores flat rows; NO_COLOR or --heatmap=false disables shading.
Readable numbers, dates, and alignment
The flat view (--flat) keeps every readability improvement: text aligns left and numbers right, amounts carry the currency and group digits, and timestamps render at the report's resolution — hourly results keep the hour on every row (2026-08-09 01:00), daily and coarser show bare dates. --raw-numbers restores exact values.
║ cost │ month │ service_description │ timestamp │ year ║ ║ 291018.6548470196 │ 06 │ analytics │ 1.780272e+09 │ 2026 ║ ║ 143178.912223 │ 07 │ pipelines │ 1.782864e+09 │ 2026 ║
║ cost │ month │ service_description │ timestamp │ year ║ ║ $291,019 │ 06 │ analytics │ 2026-06-01 │ 2026 ║ ║ $143,179 │ 07 │ pipelines │ 2026-07-01 │ 2026 ║
Currency awareness
A report run in EUR used to be indistinguishable from one in USD — the same bare floats, an easy way to misreport by 8%. The currency now comes from an explicit query config or the row itself, and machine formats carry that context without assuming a currency when none is supplied.
║ 205956.13841529994 │ 05 │ analytics ║ ║ 254993.65484701947 │ 06 │ analytics ║
║ service_description │ 2026-05 │ 2026-06 │ 2026-07 │ total │ trend ║ ║ analytics │ €205,956 │ €254,993 │ €299,851 │ €760,800 │ +46% ║
Listings: curated columns instead of crushed ones
Anomalies return sixteen columns; squeezing them all in left every cell as a truncated stub, nulls printed as a literal <nil>, and the anomaly's date invisible.
║ ackno… │ actua… │ attri… │ billi… │ costO… │ endTi… │ expec… │ id │ notif… │ … ║ ║ false │ 59.74 │ All I… │ examp… │ 30.82 │ <nil> │ 28.92 │ b0f3c… │ │ … ║ ║ false │ 55 │ All I… │ examp… │ 12.32 │ <nil> │ 42.68 │ bcdac… │ │ … ║
║ acknowledged │ actualCost │ attribution │ costOfAnomaly │ id │ startTime ║ ║ false │ 59.74 │ All Resources │ 30.82 │ b0f3c260-3df3-42… │ 2026-08-07 ║ ║ false │ 55 │ All Resources │ 12.32 │ bcdac84e-07ac-44… │ 2026-08-06 ║ Hidden columns (nested objects, or too many to fit): resourceData, top3SKUs, endTime, … Use -C to choose columns, -M wrap to wrap, or -W to widen
Identity and date columns always survive the fit; nulls are empty cells; hidden columns are named, with the flags to get them back.
An empty listing now prints No results instead of a one-row budgets: <nil> wrapper table, and budget amounts show their row's currency ($4,900).
Mistakes fail fast, with help
Command-line interface for the DoiT Cloud Intelligence API. Usage: dci [flags] dci [command]
Error: unknown command "list-bugets" (did you mean "list-budgets"?)
One plain-text line with the closest match, and a non-zero exit your scripts can trust. Interactive errors print exactly once (previously three times, with a usage dump).
Setting an invalid customer context is rejected when you set it — instead of silently breaking every later command with 403s:
Error: customerContext "foo" does not look like a customer domain (e.g. acme.com) or customer ID
From terminal to console, and spreadsheets
https://console.doit.com/customers/<customer-id>/analyze/reports/AbCdEfGhIjKlMnOpQrSt
dci open (also budget, allocation) opens the console deep link in your browser; agents and pipes get the URL printed. dci query --output csv > results.csv exports for spreadsheets, and dci docs prints every documentation entry point.
For AI agents
The silent query trap is closed
Unknown request-body fields were silently ignored — this command returned default report data unrelated to the SQL, which an agent would confidently present as the answer.
result:
rows[7]{cost,day,month,timestamp,year}:
20881.45,"04","08",1785801600,"2026"
21385.90,"05","08",1785888000,"2026"{"error":{"code":"USAGE_ERROR","message":"unknown request body field(s): body",
"hint":"Valid top-level fields: config. Run the command with --help-full to inspect
the request schema…","retryable":false}}Successful deletes are no longer "failures"
The delete succeeded server-side, but the CLI reported a retryable error — note the http_status: 200 inside the envelope — sending agents into a retry-the-delete loop.
{"error":{"code":"UPSTREAM_NON_JSON_RESPONSE","message":"The DoiT API returned
a non-JSON response","hint":"Retry the request…","retryable":true,"http_status":200}}(no output — success)
Clean success. Client errors (4xx) are never marked retryable either.
No hangs without credentials
Open your browser to log in using the URL: https://console.doit.com/sign-in/oauth?client_id=cli&code_challenge=…
{"error":{"code":"AUTHENTICATION_REQUIRED","message":"no credentials available and
this session cannot open a browser to log in","hint":"Set DCI_API_KEY to a DoiT API
token (recommended for CI/agents), or run: dci login from an interactive terminal"}}Structured failure in ~10 ms instead of an indefinite hang.
Bounded output protects the context window
A 30-day query grouped by service returned 7,500+ rows — roughly 120,000 tokens — in one response.
result:
rows[7507]{cost,day,month,service_description,timestamp,year}:
…result:
rows[500]{cost,day,month,service_description,timestamp,year}:
…
rowsOmitted: 7007
rowsTotal: 7507
note: 7007 of 7507 rows omitted; narrow the query (group limit, metricFilter)
or pass --max-rows to adjust~9,500 tokens (−92%), with the truncation explicit instead of silent. --max-rows 0 restores everything.
Results carry their context
--rows keyed returns schema-named objects instead of positional arrays, results include an explicit currency field when the query config specifies one, and identical queries return identical row order.
{ "result": { "rows": [
["analytics", "2026", "06", 291018.65, 1780272000] ] } }{ "result": { "currency": "USD", "rows": [
{ "service_description": "analytics", "month": "06", "cost": 291018.65, … } ] } }Terse help — schemas one flag away
Runs a report query with the specified configuration without persisting it.
## Input Example
```json
{
"config": {
"aggregation": "total",
…Runs a report query with the specified configuration without persisting it. Schemas and examples: add --help-full Usage: query [flags]
2,532 bytes (−84%). The full request/response schemas are one flag away: --help-full.
One exit-code taxonomy
agent mode: exit 20 pipe/human: exit 4
agent mode: exit 20 pipe/human: exit 20
The same failure maps to the same code everywhere — see the exit-code table in the CLI guide.
Try it
dci upgrade # check your version
dci skill update <agent> # refresh the installed agent skill after upgrading
dci query --help-full # the schemas are still there when you need them