Skip to content

Latest commit

 

History

9 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Datadog CLI

ddcli is a Datadog CLI designed for scripts and LLM agents. It keeps the interface narrow and discoverable while returning stable JSON on stdout. Most commands are read-only; write commands are explicit and idempotent.

Auth

Use a scoped API key and application key:

export DD_SITE=datadoghq.com
export DD_API_KEY=...
export DD_APP_KEY=...

DD_APPLICATION_KEY is also accepted. Flags can override env vars:

ddcli --site us3.datadoghq.com --api-key "$DD_API_KEY" --app-key "$DD_APP_KEY" dashboards list

For temporary OAuth-style credentials, DD_ACCESS_TOKEN or --access-token is accepted and sent as bearer auth through the Datadog Go client. A full auth login flow is not implemented yet because it needs OAuth client registration and secure refresh-token storage.

Output

Every command writes JSON to stdout. Diagnostics and errors go to stderr.

Default output is wrapped:

{
  "query": {
    "command": "logs search",
    "filter": "service:web error"
  },
  "meta": {
    "site": "datadoghq.com",
    "from": "now-15m",
    "to": "now",
    "limit": 50
  },
  "data": {}
}

Use --pretty for indented JSON and --raw to print the Datadog response without the query and meta wrapper.

Commands

ddcli logs search --query 'service:web error' --from now-15m --to now --limit 50
ddcli logs indexes order
ddcli logs indexes list --query production
ddcli logs indexes get bandzoogle-production
ddcli logs indexes patch-exclusions patch.json --dry-run
ddcli logs indexes patch-exclusions patch.json
ddcli logs pipelines order
ddcli logs pipelines list --query openresty
ddcli logs pipelines get PIPELINE_ID
ddcli logs pipelines apply pipeline.json --dry-run
ddcli logs pipelines apply pipeline.json
ddcli synthetics list --query checkout --limit 25
ddcli synthetics get abc-def-ghi
ddcli synthetics validate test.json
ddcli synthetics apply test.json --dry-run
ddcli synthetics apply test.json
ddcli metrics list --query system.cpu
ddcli metrics metadata system.cpu.user
ddcli metrics query --query 'avg:system.cpu.user{*}' --from now-1h --to now
ddcli hosts list --filter 'env:prod' --limit 25
ddcli hosts totals
ddcli dashboards list --query app --limit 100
ddcli dashboards get abc-def-ghi
ddcli dashboards apply dashboard.json --dry-run
ddcli dashboards apply dashboard.json
ddcli monitors list --name 'Kamal edge'
ddcli monitors get 12345678
ddcli monitors validate monitor.json
ddcli monitors apply monitor.json --dry-run --require-non-notifying
ddcli apm spans --query 'service:api @http.status_code:500' --from now-15m --to now --limit 25
ddcli appsec blocked-rules summary --from now-7d --limit 200 --pretty
ddcli appsec custom-rules list
ddcli appsec exclusion-filters list
ddcli errors search --query 'service:api' --track trace --from now-1h --to now
ddcli errors get ISSUE_ID
ddcli security signals search --query 'team:bandzoogle' --from now-1h --to now
ddcli security signals get SIGNAL_ID
ddcli cost analyze --group-by service --from now-30d --to now-2d --limit 25
ddcli cost analyze --metric aws.cost.amortized --filter 'env:prod' --group-by region
ddcli cost accounts list --provider all
ddcli cost budgets list
ddcli cost allocation-rules list
ddcli cost tag-pipelines list
ddcli scopes
ddcli scopes --command cost

Time flags accept now, relative values like now-15m, RFC3339 timestamps, Unix seconds, or Unix milliseconds. Logs and spans pass time strings through to Datadog; metrics and Error Tracking convert them to the epoch formats required by their APIs.

Log configuration audit

logs indexes list|get|order and logs pipelines list|get|order are read-only. Index responses include routing filters, daily quotas, Standard/Flex retention, and ordered exclusion filters with sample rates. Pipeline responses preserve the API's processor order and include filters, parser rules, remappers, and nested processors. Write access exists for both — logs indexes patch-exclusions and logs pipelines apply — and is covered in its own section below.

Use the explicit order commands when routing order matters:

ddcli logs indexes order --pretty
ddcli logs indexes get bandzoogle-production --pretty
ddcli logs pipelines order --pretty
ddcli logs pipelines list --query openresty --pretty

These commands require logs_read_config. Datadog also requires an administrator-owned application key for pipeline configuration reads.

Log pipeline apply

logs pipelines apply validates canonical pipeline JSON and creates or updates a custom pipeline, the same way dashboards apply and monitors apply do. If the definition contains an id, that pipeline is updated. Otherwise, the command matches by exact name: no match creates a pipeline, one match updates it, and multiple matches fail without writing.

Apply refuses to write to a pipeline that is read-only on either side of the match: a submitted definition with "is_read_only": true, or a live pipeline Datadog already marks read-only, such as its bundled Varnish or Rails integration pipelines. Those pipelines can never be created or edited through this API, so if you need to change what they emit, add your own pipeline after them instead — see insert_after_pipeline_id below.

ddcli logs pipelines apply pipeline.json --dry-run
ddcli logs pipelines apply pipeline.json

An optional top-level insert_after_pipeline_id places the pipeline immediately after a named pipeline in the evaluation order, and is stripped before the body is sent to Datadog. This is how you make a pipeline run after a read-only integration pipeline to re-map something it produced — for example, re-deriving a saner log-level status after Datadog's own Varnish pipeline maps every HTTP 4xx to warning:

{
  "name": "Varnish severity override",
  "filter": { "query": "source:varnish" },
  "insert_after_pipeline_id": "4DOu6dYaR46nARsjyjShbg",
  "processors": [
    {
      "type": "category-processor",
      "target": "http.varnish_severity",
      "categories": [
        { "filter": { "query": "@http.status_code:[500 TO 599]" }, "name": "error" },
        { "filter": { "query": "@http.status_code:[200 TO 499]" }, "name": "info" }
      ]
    },
    {
      "type": "status-remapper",
      "sources": ["http.varnish_severity"]
    }
  ]
}

Order placement is idempotent: apply fetches the live pipeline order first and only issues an order update when the pipeline is not already positioned immediately after insert_after_pipeline_id; a rerun with no drift reports order_changed: false and makes no order write. --dry-run performs the same lookups and reports the intended action and order diff without writing anything, and needs no write permission — only logs_read_config.

The application key or access token needs logs_write_pipelines (Datadog UI: Logs Write Pipelines) for the write itself; name-based matching and the read-only check also need logs_read_config. Pipeline configuration endpoints require an administrator-owned application key. The exact logs_write_pipelines permission name has not been confirmed against a live 403 from this tool — if apply is rejected on authorization, the error detail will name whatever permission Datadog actually requires.

Preconditioned exclusion patch

logs indexes patch-exclusions is one of two log-configuration write commands (the other is logs pipelines apply above). It fetches the named index, requires every named exclusion to occur exactly once with the exact expected query, replaces only those query strings, and sends one index update request containing all current updateable properties. Missing, duplicate, stale, unknown, empty, and no-op patch entries fail without writing.

Patch files are non-secret JSON:

{
  "index_name": "example-index",
  "replacements": [
    {
      "name": "Example exclusion",
      "expected_query": "service:example status:info",
      "replacement_query": "service:example status:(info OR ok)"
    }
  ]
}

Always run --dry-run first. It performs the read and all precondition checks, then prints the exact before/after queries and preserved invariants without an update. The guarded read requires the logs_read_config RBAC permission. Applying through the V1 UpdateLogsIndex endpoint requires logs_modify_indexes, shown as Logs Modify Indexes in the Datadog UI. These are role or scoped application-key permissions; Datadog does not offer them as OAuth client scopes.

Dashboard apply

dashboards apply validates a canonical Datadog dashboard JSON file and creates or updates it. If the definition contains an id, that dashboard is updated. Otherwise, the command matches by exact title: no match creates a dashboard, one match updates it, and multiple matches fail without writing.

Use --dry-run to validate the JSON locally without credentials or a write:

ddcli dashboards apply dashboards/review-edge-overview.json --dry-run --pretty
ddcli dashboards apply dashboards/review-edge-overview.json --pretty

The application key or access token needs dashboards_write; title-based matching also needs dashboards_read.

Monitor apply

monitors apply validates canonical monitor JSON and creates or updates it. If the definition contains an id, that monitor is updated. Otherwise, the command matches by exact name: no match creates a monitor, one match updates it, and multiple matches fail without writing.

Use --dry-run before writes and monitors validate to ask Datadog to validate the query and options without creating the monitor. For unattended preparation, pass --require-non-notifying; the command then accepts only draft monitors or monitors globally silenced indefinitely with no notification mentions in their message. Draft monitors require Datadog's draft-monitor preview to be enabled for the organization.

The application key or access token needs monitors_write for validation and apply; name-based matching and inventory also need monitors_read.

Required Permissions

Use ddcli scopes to print the Datadog RBAC permissions and, where available, separate OAuth scopes needed by each command group. Commands marked with no OAuth scope require application-key authentication. This command does not require Datadog credentials.

Datadog API keys identify the organization. Access is controlled by the application key owner's role permissions, scoped application key permissions, or OAuth access token scopes.

Unlike most commands, ddcli scopes prints a compact human-readable permissions list by default because it is primarily a setup reference. Use --raw if you need the underlying JSON data object.

Synthetic Tests as Code

ddcli synthetics apply manages a Synthetic API test from a canonical JSON definition, the same way dashboards apply and monitors apply do, so a test can live in version control next to the monitors it backs up.

ddcli synthetics validate systems/production/datadog/synthetics/asset-delivery.json
ddcli synthetics apply systems/production/datadog/synthetics/asset-delivery.json --dry-run
ddcli synthetics apply systems/production/datadog/synthetics/asset-delivery.json

Matching works like the other apply commands:

  • A public_id in the JSON names the test to update.
  • Otherwise apply matches an existing test by exact name.
  • Two tests with the same name is a refusal, not a guess, so an ambiguous match can never overwrite the wrong test. A name belonging to a browser or mobile test is refused for the same reason.
  • --dry-run resolves the match read-only and prints what would be written.

public_id and monitor_id are assigned by Datadog. Apply strips both from the request body and takes the public ID from the match instead, so a file produced by ddcli synthetics get can be edited and applied back.

Both single-request API tests ("subtype": "http") and multistep API tests ("subtype": "multi") are supported. Browser and mobile tests are not: they use different endpoints and schemas.

Validation is strict about unrecognized keys, at any depth. The Datadog client keeps unknown JSON keys instead of rejecting them, so {"tick_evry": 300} would otherwise round-trip to Datadog and be ignored, leaving a test that does not do what the file says. Apply and validate both report the dotted path instead:

Synthetic test JSON contains unsupported fields: config.steps[0].extracedValues, options.tick_evry

synthetics validate runs entirely locally and needs no credentials — Datadog publishes no Synthetics validate endpoint, unlike monitors. Use apply --dry-run when you also want to see which test would be written.

A multistep test that checks end-to-end asset delivery — fetch a page, extract a digest-stamped asset URL from the body, then assert the asset itself is served — looks like this:

{
  "name": "Production asset delivery end-to-end",
  "type": "api",
  "subtype": "multi",
  "message": "Asset delivery failed while pages still returned 200.",
  "tags": ["env:production", "service:openresty"],
  "locations": ["aws:us-east-1", "aws:eu-west-1"],
  "config": {
    "steps": [
      {
        "name": "Fetch a member page",
        "subtype": "http",
        "request": { "method": "GET", "url": "https://www.example.com/", "timeout": 30 },
        "assertions": [{ "type": "statusCode", "operator": "is", "target": 200 }],
        "extractedValues": [
          {
            "name": "ASSET_URL",
            "type": "http_body",
            "parser": { "type": "regex", "value": "https://[^\"]+/assets/application-[0-9a-f]+\\.css" }
          }
        ]
      },
      {
        "name": "Fetch the digest asset",
        "subtype": "http",
        "request": { "method": "GET", "url": "{{ ASSET_URL }}", "timeout": 30 },
        "assertions": [
          { "type": "statusCode", "operator": "is", "target": 200 },
          { "type": "header", "property": "content-type", "operator": "contains", "target": "text/css" }
        ]
      }
    ]
  },
  "options": { "tick_every": 300, "min_location_failed": 1, "retry": { "count": 1, "interval": 300 } },
  "status": "live"
}

Apply needs synthetics_write in addition to synthetics_read; see ddcli scopes --command synthetics.

Cost Analysis

ddcli cost analyze queries Datadog's Cloud Cost data source through the metrics API. Its default query is sum:all.cost{*} by {service} over the last 30 days, ending at now-2d to avoid incomplete recent cost data.

For cost-cutting work, start broad and then pivot:

ddcli cost analyze --group-by service
ddcli cost analyze --group-by team
ddcli cost analyze --group-by subaccountname
ddcli cost analyze --group-by region
ddcli cost analyze --metric aws.cost.amortized --group-by instance_type

The Cloud Cost Management inventory commands expose setup and governance context, such as connected accounts, budgets, custom allocation rules, tag pipelines, and custom cost files.

MCP Tradeoff

This CLI is meant to complement MCP rather than replace it everywhere. MCP is useful for integrated auth and rich tool discovery, but it also adds server and tool context to conversations. A CLI gives agents a smaller contract: --help, explicit commands, JSON stdout, stderr diagnostics, and replayable invocations outside Cursor.

Binary releases

Pushes to main that pass CI and change Go sources or go.mod / go.sum trigger a patch semver GitHub release (for example v0.1.1). Builds are published for Linux and macOS on amd64 and arm64.

Stable download URLs (always point at the latest release’s asset names):

  • Linux x86_64: https://github.com/bandzoogle/datadog-cli/releases/latest/download/ddcli_linux_amd64.tar.gz
  • Linux arm64: https://github.com/bandzoogle/datadog-cli/releases/latest/download/ddcli_linux_arm64.tar.gz
  • macOS x86_64: https://github.com/bandzoogle/datadog-cli/releases/latest/download/ddcli_darwin_amd64.tar.gz
  • macOS arm64: https://github.com/bandzoogle/datadog-cli/releases/latest/download/ddcli_darwin_arm64.tar.gz

Each archive contains a single ddcli binary. Run ddcli --version to see the release tag baked into the binary. Versioned archives (ddcli_<tag>_linux_amd64.tar.gz, etc.) are attached for pinning.

Development

bin/build

bin/build runs unit tests, builds dist/ddcli, and smoke-tests the help output for the main command groups. Live Datadog smoke tests require credentials and are intentionally manual for now.

About

Read-only Datadog CLI for scripts and LLM agents

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages