Common workflows and usage patterns for Pup CLI.
# Login with default site (datadoghq.com)
pup auth login
# Login with specific site
pup --site=datadoghq.eu auth login
# Check authentication status
pup auth status
# Print the current OAuth access token for a command-backed integration
pup auth token
# Logout
pup auth logoutexport DD_API_KEY="your-api-key"
export DD_APP_KEY="your-app-key"
export DD_SITE="datadoghq.com"# List all metrics
pup metrics list
# Filter by pattern
pup metrics list --filter="system.*"
pup metrics list --filter="custom.app.*"# Classic query syntax
pup metrics search --query="avg:system.cpu.user{*}" --from="1h"
# Search with aggregation and grouping
pup metrics search --query="sum:app.requests{env:prod} by {service}" --from="4h"# Timeseries formula query
pup metrics query --query="avg:system.cpu.user{*}" --from="1h" --to="now"
# Query with aggregation
pup metrics query --query="sum:app.requests{env:prod} by {service}" --from="4h"# List all monitors
pup monitors list
# Filter by tag
pup monitors list --tag="env:production"
pup monitors list --tag="team:backend"
# Multiple tags
pup monitors list --tag="env:prod" --tag="service:api"# Get specific monitor by ID
pup monitors get 12345678# Delete monitor (prompts for confirmation)
pup monitors delete 12345678
# Skip confirmation
pup monitors delete 12345678 --yes# Compare a candidate JSON file against the live monitor
pup monitors diff 12345678 candidate.json
# Scope the diff to a specific field subtree
pup monitors diff 12345678 candidate.json --only options.thresholds
# Exclude noisy fields from the diff
pup monitors diff 12345678 candidate.json --ignore message
# Combine --only and --ignore; both accept comma-separated or repeated flags
pup monitors diff 12345678 candidate.json --only options.thresholds --ignore options.thresholds.warning"removed" entries:
pup monitors updateis a partial/merge update — fields absent from the candidate are left unchanged on the live monitor, not deleted."removed"entries in the diff show fields the candidate does not specify; they will not be deleted byupdate. Use--ignoreto hide specific live-only fields from the output. Example:pup monitors diff 12345678 candidate.json --ignore options
# Search for errors in last hour
pup logs search --query="status:error" --from="1h" --to="now"
# Search by service
pup logs search --query="service:web-app status:warn" --from="30m"
# Complex query with attributes
pup logs search --query="@user.id:12345 status:error" --limit=100
# Search with time range
pup logs search \
--query="service:api" \
--from="2024-02-04T10:00:00Z" \
--to="2024-02-04T11:00:00Z"
# Search specific indexes (comma-separated or repeated)
pup logs query --query="service:api" --index="main,security" --from="1h"
pup logs query --query="service:api" --index="main" --index="security" --from="1h"# Cluster similar message values instead of grouping exact values
pup logs patterns \
--query="status:error" \
--pattern-field="message" \
--from="1h"
# Analyze a specific index with larger sampling limits and grouping fields
pup logs patterns \
--query="service:api" \
--pattern-field="@request.path" \
--group-by="service,status" \
--index="main" \
--sample-limit=100 \
--event-limit=20000 \
--from="24h"Pattern clustering returns similar-value groups. Use logs aggregate --group-by when exact-value buckets are required.
# Count logs by status
pup logs aggregate \
--query="service:web-app" \
--from="1h" \
--compute="count" \
--group-by="status"
# Average duration by service
pup logs aggregate \
--query="service:web-app" \
--from="1h" \
--compute="avg(@duration)" \
--group-by="service"
# 99th percentile latency by service
pup logs aggregate \
--query="env:prod" \
--from="30m" \
--compute="percentile(@duration, 99)" \
--group-by="service"
# Multiple metrics in one query (comma-separated)
pup logs aggregate \
--query="service:web-app" \
--from="1h" \
--compute="count,avg(@duration),percentile(@duration, 95)" \
--group-by="service,status"
# Aggregate a specific index
pup logs aggregate \
--query="service:web-app" \
--index="main" \
--from="1h" \
--compute="count" \
--group-by="status"# Search Flex logs (cost-optimized storage tier)
pup logs search --query="service:api" --from="7d" --storage="flex"
# Search online archives (long-term storage)
pup logs search --query="status:error" --from="30d" --storage="online-archives"
# Search standard indexes (fastest tier)
pup logs search --query="service:web-app" --from="1h" --storage="indexes"
# Automatically try Flex, then fall back to indexed logs when Flex is unavailable
pup logs search --query="status:warn" --from="1h"
# Request automatic storage selection explicitly
pup logs search --query="status:warn" --from="1h" --storage="auto"# List all dashboards
pup dashboards list
# Output as table
pup dashboards list --output=table# Get dashboard details
pup dashboards get "abc-123-def"
# Get public URL for sharing
pup dashboards url "abc-123-def"
# Open with a live 1 week time window
pup dashboards url "abc-123-def" --from=now-1w --to=now --live=true# Compare a candidate JSON file against the live dashboard
pup dashboards diff "abc-123-def" dashboard.json
# Scope or suppress specific field paths
pup dashboards diff "abc-123-def" dashboard.json --only widgets
pup dashboards diff "abc-123-def" dashboard.json --ignore modified_atpup dashboards delete "abc-123-def" --yes# Search recent DBM activity samples
pup dbm samples search --query="dbm_type:activity service:orders env:prod" --from="1h" --limit=10
# Search a specific database host
pup dbm samples search --query="db.hostname:primary-db service:checkout" --from="30m" --sort="asc"
# Search an explicit time window
pup dbm samples search \
--query="service:payments @db.statement_type:select" \
--from="2024-02-04T10:00:00Z" \
--to="2024-02-04T11:00:00Z" \
--limit=25pup profiling wraps a small, pup-CLI-scoped Continuous Profiler API.
Reduced support guarantee:
pup profilingcommands call unstable (/api/unstable/profiling/pup/...) endpoints. These are supported for the latest pup release, with older pup versions kept working for 30 days after a newer release. Upgrade pup regularly if you depend on these commands.
pup profiling profiles list --query="service:my-service" --from="1h" --to="now" --limit=20# Download one file from a profile event
pup profiling profiles download --profile-id="prof-123" --event-id="AwAAAaB7..." --file-name="cpu.jfr" --output-file="cpu.jfr"
# Download a zip of all files for a profile event (omit --file-name)
pup profiling profiles download --profile-id="prof-123" --event-id="AwAAAaB7..." --output-file="profile.zip"pup profiling services list --query="env:prod" --from="1h" --to="now"pup profiling profile-types list --query="service:my-service" --from="1h" --to="now"
# Scoped to a specific trace
pup profiling profile-types list --trace-id="trace-abc" --span-id="span-123" --time-hint="1700000000" --from="1h" --to="now"pup profiling explore flamegraph \
--profile-type="cpu-time" \
--query="service:my-service" \
--from="1h" --to="now" \
-o json
# With full frame names instead of the default simplified string
pup profiling explore flamegraph \
--profile-type="alloc-space" \
--query="service:my-service" \
--from="1h" --to="now" \
--frame-format="full"
# Scoped to a specific profile event instead of --query (--profile-id and --event-id are required together)
pup profiling explore flamegraph \
--profile-type="cpu-time" \
--profile-id="prof-123" --event-id="AwAAAaB7..." \
--from="1h" --to="now"pup profiling explore callgraph \
--profile-type="cpu-time" \
--query="service:my-service" \
--from="1h" --to="now" \
-o json
# Filter to frames matching a glob pattern, scoped to a specific trace instead of --query
pup profiling explore callgraph \
--profile-type="cpu-time" \
--trace-id="trace-abc" --span-id="span-123" --time-hint="1700000000" \
--frame-filter="*MyService*" \
--from="1h" --to="now"# Summarize a single profile's timeline (top lane groups by activity)
pup profiling explore timeline \
--profile-id="prof-123" --event-id="AwAAAaB7..."
# Recent timeline of one process, drilling into one lane group
# (use a "groupName" returned by a previous call)
pup profiling explore timeline \
--runtime-id="0b1c2d3e-..." \
--query="service:my-service" \
--from="15m" --to="now" \
--focus-lane-group="<groupName>"
# Timeline around a span, restricted to its critical path (Go only)
pup profiling explore timeline \
--trace-id="trace-abc" --span-id="span-123" --time-hint="1700000000" \
--critical-path# All change events in the last hour (relative time)
pup change-stories list --service api-gateway --from 1h --to now
# All change events using an absolute window with unix timestamps
pup change-stories list --service api-gateway --from 1713132000 --to 1713135600
# Narrow to deployments in production using an absolute window
pup change-stories list \
--service api-gateway --env prod \
--from 2024-01-15T00:00:00Z --to 2024-01-15T01:00:00Z \
--story-types deployment
# Multiple story types
pup change-stories list \
--service api-gateway \
--from 2024-01-15T00:00:00Z --to 2024-01-15T01:00:00Z \
--story-types deployment --story-types kubernetes
# Region-scoped filter (--filter-tags is key:value)
pup change-stories list \
--service api-gateway \
--from 2024-01-15T00:00:00Z --to 2024-01-15T01:00:00Z \
--filter-tags datacenter:us1.prod.dog
# Trim response to ~4000 tokens (server default is 10000)
pup change-stories list \
--service api-gateway --from 30min --to now \
--token-limit 4000# List all SLOs
pup slos list
# Filter by name or API-supported query string
pup slos list --query="monitor-history-reader"
# Filter by a single SLO tag
pup slos list --tags-query="team:slo-app"
# Filter by metric query and paginate results
pup slos list --metrics-query="sum:requests.error{service:api}" --limit=25 --offset=50pup slos get "abc-123-def"# Compare a candidate JSON file against the live SLO
pup slos diff "abc-123-def" slo.json
# Scope or suppress specific field paths
pup slos diff "abc-123-def" slo.json --only thresholds
pup slos diff "abc-123-def" slo.json --ignore overall_statuspup slos create \
--name="API Availability" \
--type="metric" \
--target=99.9 \
--timeframe="30d"# List corrections for SLO
pup slos corrections list "abc-123-def"
# Create correction
pup slos corrections create "abc-123-def" \
--start="2024-02-04T10:00:00Z" \
--end="2024-02-04T11:00:00Z" \
--category="deployment"# List all incidents
pup incidents list
# Filter by status
pup incidents list --status="active"pup incidents get "abc-123"pup incidents create \
--title="High Error Rate in API" \
--severity="SEV-2" \
--customer-impacted=truepup incidents update "abc-123" --status="resolved"pup rum apps listpup rum apps get "abc-123"pup rum sessions search \
--query="@application.id:abc-123" \
--from="1h"pup security rules listpup security rules get "abc-123"pup security signals list --from="1h"pup security findings search \
--query="@severity:high"# Get service instance metadata (IDs, hostnames, config IDs)
pup apm service-config get --service-name my-service
# Filter by environment
pup apm service-config get --service-name my-service --env prod
# Filter by specific instance IDs
pup apm service-config get --service-name my-service --service-instance-ids "id-1,id-2"# Get tracer configuration for a service across all instances
pup apm service-library-config get --service-name my-service
# Filter by environment
pup apm service-library-config get --service-name my-service --env prod
# Filter by language
pup apm service-library-config get --service-name my-service --env prod --language python
# Only show configs where instances disagree (useful for finding config drift)
pup apm service-library-config get --service-name my-service --mixed# Show APM instrumentation errors for a specific host
pup apm troubleshooting list --hostname my-host
# Narrow results to a specific time window
pup apm troubleshooting list --hostname my-host --timeframe 4h# List all tracers (telemetry-derived service names, language, runtime IDs)
pup fleet tracers list
# Filter tracers by environment
pup fleet tracers list --filter "env:prod"
# Filter tracers by hostname
pup fleet tracers list --filter "hostname:my-host"
# Paginate results
pup fleet tracers list --filter "env:prod" --page-size 50 --page-number 0# Get tracers running on a specific agent
pup fleet agents tracers <agent-key>
# With pagination
pup fleet agents tracers <agent-key> --page-size 20# List pods instrumented by SSI in a cluster
pup fleet instrumented-pods list <cluster-name># List all clusters
pup fleet clusters list
# Filter by cluster name
pup fleet clusters list --filter "cluster_name:production"
# Paginate
pup fleet clusters list --filter "env:prod" --page-size 50 --page-number 0# Get full service context as JSON (environments, instances, probe support)
pup debugger context my-service
# Filter to a specific environment
pup debugger context my-service --env staging
# Select specific fields for compact output: service, language, envs, repo
pup debugger context my-service --fields service,language,envs# List all log probes
pup debugger probes list
# Filter by service
pup debugger probes list --service my-servicepup debugger probes get "probe-id"# Create a probe with capture expressions (recommended)
pup debugger probes create \
--service my-service \
--env staging \
--probe-location com.example.MyClass:myMethod \
--capture "request.id" --capture "user.name"
# Use a method signature from --view probe-locations output
pup debugger probes create \
--service my-service \
--env staging \
--probe-location "com.example.MyClass:myMethod(String, int)" \
--capture "request.id"
# Increase capture depth for nested objects (default: 1)
pup debugger probes create \
--service my-service \
--env staging \
--probe-location com.example.MyClass:myMethod \
--capture "response.body" --depth 3
# Create with full snapshot capture
pup debugger probes create \
--service my-service \
--env staging \
--probe-location com.example.MyClass:myMethod \
--capture
# Create with a custom template
pup debugger probes create \
--service my-service \
--env staging \
--probe-location com.example.MyClass:myMethod \
--capture "userId" \
--template "User {userId} called, took {@duration}ms"
# Create with a condition
pup debugger probes create \
--service my-service \
--env staging \
--probe-location com.example.MyClass:myMethod \
--capture "userId" \
--condition "userId != null"
# Create with custom budget and TTL
pup debugger probes create \
--service my-service \
--env staging \
--probe-location com.example.MyClass:myMethod \
--budget 500 --ttl 2hpup debugger probes delete "probe-id"# Stream probe events — compact output (message, captures, timestamp)
pup debugger probes watch "probe-id" --fields "message,captures,timestamp" --wait 10
# Template message only (one line per event)
pup debugger probes watch "probe-id" --fields "message" --limit 5
# Full debugger payload (default — trimmed to just the debugger field)
pup debugger probes watch "probe-id"
# Limit to 5 events
pup debugger probes watch "probe-id" --limit 5
# Custom timeout
pup debugger probes watch "probe-id" --timeout 300
# Start from a specific time
pup debugger probes watch "probe-id" --from 1h
# Wait for a newly created probe to become available (useful in pipelines)
pup debugger probes watch "probe-id" --wait 30# Search for a method, create a probe, and watch events
# Note: --view probe-locations may output signatures like TYPE:METHOD(args)
pup symdb search --service my-service --query MyController --view probe-locations \
| head -1 \
| xargs -I{} pup debugger probes create --service my-service --env staging --probe-location {} --capture --ttl 1h \
| jq -r .data.id \
| xargs -I{} pup debugger probes watch {} --fields "message,captures,timestamp" --wait 30 --limit 5# Search for classes/methods by name
pup symdb search --service my-service --query MyController
# List all scopes in a service
pup symdb search --service my-service
# Filter by service version
pup symdb search --service my-service --query MyController --version 1.2.3# Full JSON response (default)
pup symdb search --service my-service --query MyController --view full
# Scope names only
pup symdb search --service my-service --query MyController --view names
# Probe locations (type:method or type:method(args) format)
pup symdb search --service my-service --query MyController --view probe-locations# List all containers
pup containers list
# Filter by tags
pup containers list --filter-tags="env:production"
# Group by image
pup containers list --group-by="image_name"# List all container images
pup containers images list
# Filter images by tags
pup containers images list --filter-tags="env:production"# List all hosts
pup infrastructure hosts list
# Filter by tag
pup infrastructure hosts list --filter="env:production"# Filter agents by hostname
pup fleet agents list --filter "hostname:my-host"
# Filter by IP address
pup fleet agents list --filter "ip_address:1.2.3.4"
# Boolean filter expression
pup fleet agents list --filter "(hostname:host-a OR hostname:host-b) AND env:prod"pup infrastructure hosts get "host-name"# List all host tags
pup tags listpup tags get "host-name"pup tags add "host-name" \
--tag="env:production" \
--tag="team:backend"pup tags update "host-name" \
--tag="env:prod" \
--tag="service:api"pup users listpup users get "user-id"pup users roles list
# Paginate results (max page size 100)
pup users roles list --page-size=50 --page-number=1
# Sort by name descending and filter by a search string
pup users roles list --sort="-name" --filter="admin"
# Filter by specific role IDs
pup users roles list --filter-id="id1,id2"Sort accepts: name, -name, modified_at, -modified_at, user_count, -user_count (a leading - sorts descending).
pup organizations getpup api-keys listpup api-keys get "key-id"pup api-keys create --name="CI/CD Key"pup api-keys delete "key-id" --yespup synthetics tests listpup synthetics tests get "test-id"pup synthetics locations list# Compare a candidate JSON file against the live notebook
pup notebooks diff 12345 notebook.json
# Scope or suppress specific field paths
pup notebooks diff 12345 notebook.json --only data.attributes.cells
pup notebooks diff 12345 notebook.json --ignore data.attributes.modified# Compare a candidate JSON file against the live pipeline
pup obs-pipelines diff <pipeline-id> pipeline.json
# Scope or suppress specific field paths
pup obs-pipelines diff <pipeline-id> pipeline.json --only data.attributes.config
pup obs-pipelines diff <pipeline-id> pipeline.json --ignore data.attributes.updated_atpup workflows get <workflow-id>pup workflows create --file=workflow.jsonpup workflows update <workflow-id> --file=workflow.json# Compare a candidate JSON file against the live workflow
pup workflows diff <workflow-id> workflow.json
# Scope or suppress specific field paths
pup workflows diff <workflow-id> workflow.json --only data.attributes.spec
pup workflows diff <workflow-id> workflow.json --ignore data.attributes.updatedAtpup workflows delete <workflow-id># Run with inline payload (requires DD_API_KEY + DD_APP_KEY)
pup workflows run <workflow-id> --payload '{"key": "value"}'
# Run with payload from file
pup workflows run <workflow-id> --payload-file=params.json
# Run and wait for completion (default timeout: 5m)
pup workflows run <workflow-id> --wait
# Run with custom timeout
pup workflows run <workflow-id> --wait --timeout 2m# List recent executions
pup workflows instances list <workflow-id>
# List with pagination
pup workflows instances list <workflow-id> --limit=20 --page=2
# Get instance details
pup workflows instances get <workflow-id> <instance-id>
# Cancel a running instance
pup workflows instances cancel <workflow-id> <instance-id>Runbooks are YAML files stored in ~/.config/pup/runbooks/ that encode multi-step operational procedures. Each step runs a pup command, shell command, HTTP request, Datadog Workflow, or an interactive confirmation.
pup runbooks list
pup runbooks list --tag=type:deploymentpup runbooks describe deploy-service# Run with required variables via --arg flags
pup runbooks run deploy-service --arg SERVICE=payments --arg VERSION=1.2.3
# Dry-run (print steps without executing)
pup runbooks run incident-triage --dry-run# Copy a runbook YAML into ~/.config/pup/runbooks/
pup runbooks import ./my-runbook.yamlpup runbooks validate ./my-runbook.yamlname: restart-service
description: Safely restart a service after checking monitors
vars:
SERVICE:
description: Service name
required: true
steps:
- name: Check active monitors
kind: pup
run: monitors list --tags="service:{{SERVICE}}"
capture: MONITORS_JSON
- name: Confirm restart
kind: confirm
message: "Restart {{SERVICE}}? Review monitors above."
- name: Trigger restart workflow
kind: datadog-workflow
workflow_id: "abc-123"
inputs:
service: "{{SERVICE}}"
on_failure: fail
- name: Notify via webhook
kind: http
url: https://hooks.example.com/notify
method: POST
body: '{"text": "Restarted {{SERVICE}}"}'
content_type: application/json
on_failure: warnStore shared step logic in ~/.config/pup/runbooks/_templates/<name>.yaml:
# _templates/slack-notify.yaml
kind: http
url: "{{SLACK_WEBHOOK}}"
method: POST
body: '{"text": "{{MESSAGE}}"}'
content_type: application/json
on_failure: warnReference a template in any runbook step:
steps:
- name: Notify Slack
template: slack-notify
# Override any template field as neededSee docs/examples/runbooks/ for complete examples.
# Get owner, on-call, health, dependencies, and metadata gaps in one call
pup idp assist my-service
# Useful as a starting point for incident response or code review
pup idp assist payments-api# Search services by a literal name substring
pup idp find payments
# Bound the page and continue with the returned cursor
pup idp find payments --limit 5
pup idp find payments --limit 5 --cursor '<next-cursor>'
# Existing explicit queries remain compatible; prefer `idp entities query`
# for new non-service or advanced graph workflows
pup idp find "kind:team AND name:backend"# List one known kind without writing the kind predicate yourself
pup idp entities list --filter-kind=service --field=name,owner
# Search within the selected kind; OR expressions stay scoped to services
pup idp entities search \
--filter-kind=service \
--query='owner:idp OR team:idp' \
--field=name,owner,contacts
# Use full DSL control for concrete refs, relation expansion, or advanced queries
pup idp entities query 'kind:service AND name:*payments*' \
--include=owner_teams,systems# Show owning team and current on-call responders
pup idp owner my-service# List upstream (callers) and downstream (callees) services
pup idp deps my-service# Register v1-v3 Catalog entities from YAML or JSON
pup idp register service.datadog.yaml
# Multi-document YAML is accepted
pup idp register entities.datadog.yaml
# Verify after registration
pup --read-only software-catalog entities list --filter-ref service:default/my-service# Get full service context immediately
pup idp assist payments-api
# Investigate alerts for the service
pup monitors list --tag="service:payments-api"
# Check who is on-call
pup idp owner payments-api
# Review upstream services that may be affected
pup idp deps payments-api# Projected cost for current month
pup costs datadog projected
# Cost breakdown by org for a date range
pup costs datadog by-org --start-month="2024-01-01T00:00:00Z" --end-month="2024-03-01T00:00:00Z"
# Monthly cost attribution
pup costs datadog attribution --start="2024-01-01T00:00:00Z"
# AWS CUR config management
pup costs datadog aws-config list
pup costs datadog aws-config get 42
pup costs datadog aws-config create --file=aws-cur.json
pup costs datadog aws-config delete 42
# Azure UC config management
pup costs datadog azure-config list
# GCP usage cost config management
pup costs datadog gcp-config list# List uploaded custom cost files
pup costs ccm custom-costs list
# Filter by status or sort
pup costs ccm custom-costs list --status=SUCCESS --sort=created_at
# Get a specific custom cost file
pup costs ccm custom-costs get <file-id>
# Upload a custom cost CSV (multipart PUT)
pup costs ccm custom-costs upload --file=costs.csv
# Upload with a schema version
pup costs ccm custom-costs upload --file=costs.csv --version=2
# Delete a custom cost file
pup costs ccm custom-costs delete <file-id># List all tag descriptions
pup costs ccm tag-descriptions list
# Filter by cloud provider
pup costs ccm tag-descriptions list --cloud=aws
# Get description for a specific tag key
pup costs ccm tag-descriptions get --tag-key=env
# Generate an AI-suggested description for a tag
pup costs ccm tag-descriptions generate --tag-key=team
# Create or update a tag description
pup costs ccm tag-descriptions upsert --tag-key=env --description="Deployment environment"
# Delete a tag description
pup costs ccm tag-descriptions delete --tag-key=env# List all tag metadata for a month
pup costs ccm tag-metadata list --month=2024-01
# Filter by provider and metric
pup costs ccm tag-metadata list --month=2024-01 --provider=aws --metric=aws.cost
# List tag sources
pup costs ccm tag-metadata tag-sources --month=2024-01
# List available metrics
pup costs ccm tag-metadata metrics --month=2024-01
# List orchestrators
pup costs ccm tag-metadata orchestrators --month=2024-01
# List supported currencies
pup costs ccm tag-metadata currency --month=2024-01# List all CCM tags
pup costs ccm tags list
# Filter by metric
pup costs ccm tags list --metric=aws.cost
# List tag keys
pup costs ccm tag-keys list
# Get details for a specific tag key
pup costs ccm tag-keys get env# List all budgets
pup costs ccm budgets list
# Get a specific budget
pup costs ccm budgets get <budget-id>
# Get with actual and forecasted spend for a time range
pup costs ccm budgets get <budget-id> \
--start="2024-01-01T00:00:00Z" \
--end="2024-03-01T00:00:00Z" \
--actual --forecast
# Create or update a budget (upsert)
pup costs ccm budgets upsert --file=budget.json
# Delete a budget
pup costs ccm budgets delete <budget-id>
# Validate a budget payload without saving
pup costs ccm budgets validate --file=budget.json# Utilization of RIs over a time range
pup costs ccm commitments utilization \
--provider=aws --product=EC2 \
--from=2024-01-01T00:00:00Z --to=2024-02-01T00:00:00Z
# Coverage by Savings Plans
pup costs ccm commitments coverage \
--provider=aws --product=EC2 \
--from=2024-01-01T00:00:00Z --to=2024-02-01T00:00:00Z \
--commitment-type=SP
# Savings summary
pup costs ccm commitments savings \
--provider=aws --product=RDS \
--from=2024-01-01T00:00:00Z --to=2024-02-01T00:00:00Z
# On-demand hot spots (unreserved spend)
pup costs ccm commitments hotspots \
--provider=aws --product=EC2 \
--from=2024-01-01T00:00:00Z --to=2024-02-01T00:00:00Z
# Utilization time series
pup costs ccm commitments utilization-ts \
--provider=aws --product=EC2 \
--from=2024-01-01T00:00:00Z --to=2024-02-01T00:00:00Z
# Coverage time series
pup costs ccm commitments coverage-ts \
--provider=aws --product=EC2 \
--from=2024-01-01T00:00:00Z --to=2024-02-01T00:00:00Z
# Savings time series
pup costs ccm commitments savings-ts \
--provider=aws --product=EC2 \
--from=2024-01-01T00:00:00Z --to=2024-02-01T00:00:00Z
# List all commitment programs
pup costs ccm commitments list \
--provider=aws --product=EC2 \
--from=2024-01-01T00:00:00Z --to=2024-02-01T00:00:00Zpup monitors list --output=jsonpup monitors list --output=yamlpup monitors list --output=tableSingle-resource responses use field/value rows, while collections remain horizontal.
Scalar table results are rendered in a VALUE column instead of producing an empty table.
Table cells use compact previews for long strings, arrays, nested objects, and null values.
Commands that know their response shape provide concise, opinionated columns; generic API and formatter input keeps the priority-and-fallback selection.
JSON, YAML, and table output use best-effort color highlighting when stdout is an
interactive terminal. This is lightweight presentation logic, not a general syntax
parser. Set NO_COLOR or CLICOLOR=0 to keep interactive output plain.
HTTP(S) strings that occupy an entire table cell use OSC 8 terminal hyperlinks. The
link keeps its complete URL even when the displayed value is shortened. Set
PUP_HYPERLINKS=0 to disable links; NO_COLOR and CLICOLOR=0 disable them too.
pup monitors list --output=csv
pup monitors list --output=tsvpup monitors list --fields="id,name,type,status"pup --config=/path/to/config.yaml monitors listpup --site=datadoghq.eu monitors listpup --verbose monitors listpup --yes monitors delete 12345678# Block all write operations (create, update, delete)
pup --read-only monitors list
pup --read-only dashboards list
# Also available via env var or config file
DD_READ_ONLY=true pup monitors list# List monitors for a service
pup monitors list --tag="service:api" --output=table
# Check recent logs
pup logs search --query="service:api" --from="1h" --output=table
# Query metrics
pup metrics query --query="avg:api.latency{*}" --from="1h"# Create incident
pup incidents create --title="API Down" --severity="SEV-1"
# Search related logs
pup logs search --query="status:error service:api" --from="1h"
# Check monitors
pup monitors list --tag="service:api"
# Update incident status
pup incidents update "incident-id" --status="investigating"# List recent security signals
pup security signals list --from="24h"
# Check security rules
pup security rules list
# Search security findings
pup security findings search --query="@severity:critical"
# Review audit logs
pup audit-logs list --from="7d"# List all hosts
pup infrastructure hosts list --output=table
# Get host details
pup infrastructure hosts get "host-name"
# Review host tags
pup tags list --output=table--from="1h" # 1 hour ago
--from="30m" # 30 minutes ago
--from="7d" # 7 days ago
--from="now" # Current time--from="2024-02-04T10:00:00Z"
--to="2024-02-04T11:00:00Z"--from="1707048000" # Unix timestamp in seconds# Authentication
export DD_API_KEY="your-api-key"
export DD_APP_KEY="your-app-key"
export DD_SITE="datadoghq.com"
# Configuration
export PUP_CONFIG="/path/to/config.yaml"
export PUP_OUTPUT="json"
export PUP_LOG_LEVEL="debug"pup acp serve starts a local HTTP server that lets AI coding assistants and agents
talk directly to Datadog Bits AI. It speaks two protocols:
- ACP (Agent Communication Protocol) — for ACP-native clients
- OpenAI-compatible — for tools like opencode, Cursor, or any
@ai-sdk/openai-compatibleclient
# Authenticate first (notebooks_read + notebooks_write scopes required)
pup auth login
# Start the server (auto-discovers your first Datadog Bits AI agent)
pup acp serve
# Specify a particular agent
pup acp serve --agent-id <uuid>
# Custom port or bind address
pup acp serve --port 8080
pup acp serve --host 0.0.0.0 --port 9099| Method | Path | Protocol | Description |
|---|---|---|---|
| GET | /agent.json |
ACP | Agent card / capability discovery |
| POST | /runs |
ACP | Synchronous run — returns full response |
| POST | /runs/stream |
ACP | Streaming run — SSE events |
| GET | /models or /v1/models |
OpenAI | Model list |
| POST | /chat/completions or /v1/chat/completions |
OpenAI | Chat completions (streaming or sync) |
# ACP sync
curl -s -X POST http://127.0.0.1:9099/runs \
-H "Content-Type: application/json" \
-d '{"input": [{"role": "user", "content": [{"type": "text", "text": "list my monitors with status alert"}]}]}' \
| jq .output[0].content[0].text
# ACP streaming
curl -X POST http://127.0.0.1:9099/runs/stream \
-H "Content-Type: application/json" \
-d '{"input": [{"role": "user", "content": [{"type": "text", "text": "what services have errors in the last hour?"}]}]}'
# OpenAI-compatible
curl -s -X POST http://127.0.0.1:9099/chat/completions \
-H "Content-Type: application/json" \
-d '{"model": "datadog-ai", "messages": [{"role": "user", "content": "how many monitors are currently alerting?"}]}' \
| jq .choices[0].message.contentAdd to ~/Library/Application Support/opencode/opencode.jsonc (macOS) or
~/.config/opencode/opencode.jsonc (Linux):
Then start the server (pup acp serve) and select the Datadog AI provider in opencode.
Create ~/.config/pup/config.yaml:
site: datadoghq.com
output: json
verbose: false
# Default time ranges
default_from: 1h
default_to: now
# Output preferences
output_format: json
table_max_width: 120
{ "$schema": "https://opencode.ai/config.json", "provider": { "datadog": { "name": "Datadog AI", "npm": "@ai-sdk/openai-compatible", "models": { "datadog-ai": { "name": "Datadog AI Agent" } }, "options": { "baseURL": "http://127.0.0.1:9099" } } } }