メインコンテンツへスキップ

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.

Before — dci v1.x
$ dci query < monthly.json
║ 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 ║
…12 interleaved rows for a 4-service × 3-month report
exit code: 0
After — v2.0
$ dci query < monthly.json
║ 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%  ║
exit code: 0

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.

Before — dci v1.x
$ dci query < query.json
║ cost               │ month │ service_description      │ timestamp    │ year ║
║ 291018.6548470196  │    06 │              analytics   │ 1.780272e+09 │ 2026 ║
║ 143178.912223      │    07 │              pipelines   │ 1.782864e+09 │ 2026 ║
exit code: 0
After — v2.0
$ dci query --flat < query.json
║ cost     │ month │ service_description │ timestamp  │ year ║
║ $291,019 │ 06    │ analytics           │ 2026-06-01 │ 2026 ║
║ $143,179 │ 07    │ pipelines           │ 2026-07-01 │ 2026 ║
exit code: 0

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.

Before — dci v1.x
$ dci query < query-eur.json # config.currency: EUR
║ 205956.13841529994 │ 05 │ analytics ║
║ 254993.65484701947 │ 06 │ analytics ║
nothing reveals these are euros
exit code: 0
After — v2.0
$ dci query < query-eur.json # config.currency: EUR
║ service_description │ 2026-05  │ 2026-06  │ 2026-07  │ total    │ trend ║
║ analytics           │ €205,956 │ €254,993 │ €299,851 │ €760,800 │ +46%  ║
exit code: 0

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.

Before — dci v1.x
$ dci list-anomalies --max-results 2
║ 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… │        │ … ║
exit code: 0
After — v2.0
$ dci list-anomalies --max-results 2
║ 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
exit code: 0

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

Before — dci v1.x
$ dci list-bugets
Command-line interface for the DoiT Cloud Intelligence API.

Usage:
dci [flags]
dci [command]
…the full command list follows: ~258 lines of help, and the script keeps running
exit code: 0
After — v2.0
$ dci list-bugets
Error: unknown command "list-bugets" (did you mean "list-budgets"?)
exit code: 2

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:

v2.0
$ dci customer-context set foo
Error: customerContext "foo" does not look like a customer domain (e.g. acme.com) or customer ID
exit code: 1

From terminal to console, and spreadsheets

New in v2.0
$ dci open report AbCdEfGhIjKlMnOpQrSt
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.

Before — dci v1.x
$ dci query body.query:"SELECT * FROM billing LIMIT 10"
result:
rows[7]{cost,day,month,timestamp,year}:
  20881.45,"04","08",1785801600,"2026"
  21385.90,"05","08",1785888000,"2026"
exit 0 — with data that has nothing to do with the SQL
exit code: 0
After — v2.0
$ dci query body.query:"SELECT * FROM billing LIMIT 10"
{"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}}
exit code: 2

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.

Before — dci v1.x
$ dci delete-report <id> --yes
{"error":{"code":"UPSTREAM_NON_JSON_RESPONSE","message":"The DoiT API returned
a non-JSON response","hint":"Retry the request…","retryable":true,"http_status":200}}
exit code: 40
After — v2.0
$ dci delete-report <id> --yes
(no output — success)
exit code: 0

Clean success. Client errors (4xx) are never marked retryable either.

No hangs without credentials

Before — dci v1.x
$ dci list-budgets # no DCI_API_KEY, no terminal
Open your browser to log in using the URL:
https://console.doit.com/sign-in/oauth?client_id=cli&code_challenge=…
blocks forever — there is no browser in CI
After — v2.0
$ dci list-budgets # no DCI_API_KEY, no terminal
{"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"}}
exit code: 10

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.

Before — dci v1.x
$ dci query < query-30d-by-service.json
result:
rows[7507]{cost,day,month,service_description,timestamp,year}:
  …
~480 KB / ~120,000 tokens, straight into the agent's context
exit code: 0
After — v2.0
$ dci query < query-30d-by-service.json
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
exit code: 0

~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.

Before — dci v1.x
$ dci query --output json < query.json
{ "result": { "rows": [
  ["analytics", "2026", "06", 291018.65, 1780272000] ] } }
which cell is the cost? Consult result.schema and count
After — v2.0
$ dci query --rows keyed --output json < query.json
{ "result": { "currency": "USD", "rows": [
  { "service_description": "analytics", "month": "06", "cost": 291018.65, … } ] } }

Terse help — schemas one flag away

Before — dci v1.x
$ dci query --help
Runs a report query with the specified configuration without persisting it.
## Input Example
```json
{
"config": {
  "aggregation": "total",
…
15,434 bytes / ~3,900 tokens — mostly schema markdown, paid on every exploratory --help
After — v2.0
$ dci query --help
Runs a report query with the specified configuration without persisting it.

Schemas and examples: add --help-full

Usage:
query [flags]
exit code: 0

2,532 bytes (−84%). The full request/response schemas are one flag away: --help-full.

One exit-code taxonomy

Before — dci v1.x
$ dci get-report doesnotexist # agent mode vs a pipe
agent mode:  exit 20
pipe/human:  exit 4
After — v2.0
$ dci get-report doesnotexist # any mode
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