Pup CLI

repository·main·Indexed 21 days ago

https://github.com/datadog/pup

A Rust-based CLI tool providing an AI-agent-friendly interface to the Datadog observability platform. Pup enables developers and autonomous agents to query metrics, search logs, and manage monitors, dashboards, and SLOs using structured JSON/YAML outputs. It supports OAuth2, API keys, and bearer token authentication, and can be compiled to WebAssembly (wasm32-wasip2).

Tokens
86.3K
Snippets
251
Records
365
Agent score
75%

What's inside pup

  1. What is Pup CLI?

    main
    Pup is a comprehensive, AI-agent-ready CLI designed to provide autonomous agents and developers with access to Datadog's observability platform. It exposes Datadog's API surface across multiple domains—including monitors, logs, metrics, RUM, and security—using structured formats that are easy for agents to navigate and parse.
  2. Manage multiple Datadog orgs using named sessions

    main

    Pup allows you to work with multiple Datadog organizations side-by-side using named sessions. A session is a (site, org) pair.

    To avoid ambiguity, it is recommended to always use the --org <name> flag (or DD_ORG=<name> environment variable) for every command rather than relying on the default unnamed session.

    Logging into orgs

    • Standard login: pup auth login --org <name>
    • Cross-site login: pup auth login --site <site> --org <name>
    • SAML/SSO with vanity host: Use the full host via --site (e.g., acme.datadoghq.com).
    • Pre-targeting with UUID: Use --org-uuid <uuid> to skip the org switcher and pre-route SAML/SSO.
    • Non-Datadog hosts: Use --site <host> --trust-site for API gateways or proxies.

    Using named sessions

    Once logged in, you can recall the site and credentials by specifying the org name in any subcommand:

    pup monitors list --org prod-child
    DD_ORG=prod-child pup metrics query --query "avg:system.cpu.user{*}"
    # Login to multiple orgs
    pup auth login --org prod-child
    pup auth login --org staging-child
    
    # Login to a specific site and org
    pup auth login --site ap2.datadoghq.com --org ap2-prod
    
    # Use a named session for commands
    pup logs query --org ap2-prod --query "service:web-store" --limit 10
  3. Choose between Pup CLI and Code Generation

    main

    The Datadog integration provides two distinct ways to interact with Datadog data:

    Use Pup CLI When:

    • You need immediate results.
    • You are exploring or experimenting with Datadog data.
    • You are performing one-off queries or operations.
    • You are troubleshooting quickly.
    • You want to test a query before implementing it in code.

    Generate Code When:

    • You need to integrate Datadog functionality into an application.
    • You are automating recurring operations.
    • You are building custom tools or dashboards.
    • You have specified a programming language (TypeScript, Python, Java, Go, or Rust).
  4. How pup extensions work

    main

    Pup extensions are standalone executables that add new subcommands to the pup CLI. When you run pup <command>, pup first checks if <command> is a built-in. If not, it searches for an installed executable named pup-<command> and runs it, passing your arguments and authentication credentials.

    This allows teams to ship experimental features or custom tools independently of the core pup release cycle. Extensions can be written in any language (Shell, Python, Rust, etc.) as long as they are executable files.

    # If an extension named 'pup-foo' is installed,
    # this command dispatches to the 'pup-foo' executable
    pup foo --some-flag value
  5. Understand Pup's PR Review Outcomes

    main

    Pup uses a specific workflow for handling Pull Requests to optimize for throughput. Reviewers categorize PRs into one of the following outcomes (ordered by preference):

    PriorityOutcomeDescription
    1MergePR meets all standards — merge as-is.
    2Merge-fixPR is mergeable but has minor issues — merge as-is, then push a follow-up fix to main.
    3Fix-mergePR has value but is broken (fails CI, has bugs) — pull locally, fix, and push with contributor attribution.
    4Cherry-pickPR bundles multiple changes and we only want some — cherry-pick the good parts locally, fix as needed, commit with attribution, and close the PR.
    5Split-mergePR mixes separate concerns that should be independent — pull locally, split into separate commits with attribution, and push each.
    6ReimplementPR solves a real problem but the design is wrong — reimplement the solution with a better approach, close the PR with thanks and an explanation.
    7RetirePR is obsolete — superseded by another PR, already fixed, or no longer relevant. Close with a thank-you.
    8RejectPR adds tech debt, is too niche for core, contains malicious code, or violates security rules. Close with a polite explanation.
    9Request changesLast resort. Sending a PR back for rework delays landing and risks contributor attrition. Only use when the contributor is best positioned to make the fix.
  6. Authentication requirements for Pup

    main

    Most Pup commands require valid authentication to function.

    • Workflow Commands: All workflow commands require both DD_API_KEY and DD_APP_KEY. Note that OAuth2 bearer tokens are not supported for workflow operations.
    • Command Status: In the command index, commands marked with ✅ are working and require valid auth. Commands marked with ⚠️ are waiting for API client library updates, and ⏳ are skeleton implementations.
  7. Security guidelines for Pup contributors

    main

    Adhere to these security practices to protect user data and credentials:

    Data Handling

    • Never commit: API keys, secrets, OAuth tokens, client secrets, environment variables with credentials, or real user test data.
    • Always: Validate user inputs to prevent injection and use parameterized queries for data storage.
    • Error Messages: Wrap errors using anyhow::Context but ensure sensitive data is never included in the error string.

    OAuth2 Security

    • Use PKCE S256 for code challenges.
    • Validate the state parameter to prevent CSRF.
    • Never log or print access/refresh tokens.
    • Use the OS keychain for primary token storage.
    • If falling back to file-based storage, restrict permissions to 0600.
  8. Understand Pup test organization

    main

    Pup uses two primary locations for testing:

    1. Module Tests (src/): Unit tests are co-located with the source code using #[cfg(test)] modules. This is the preferred pattern for testing logic within specific files like auth, client.rs, config.rs, etc.
    2. Integration Tests (tests/): These are located in the tests/ directory and are used for end-to-end testing and output comparison (e.g., tests/compare/).
  9. Enable Agent Mode for AI Coding Agents

    main

    When Pup is used by an AI coding agent, it can be put into agent mode. In this mode, Pup returns structured JSON responses optimized for machine consumption (including metadata, error details, and hints) and automatically approves confirmation prompts.

    Enabling Agent Mode

    1. Auto-detection

    Agent mode is automatically enabled if any of the following environment variables are set to 1 or true:

    • CLAUDE_CODE or CLAUDECODE (Claude Code)
    • CURSOR_AGENT (Cursor)
    • GITHUB_COPILOT (GitHub Copilot)
    • AIDER (Aider)
    • WINDSURF_AGENT (Windsurf)
    • GEMINI_CODE_ASSIST (Gemini Code Assist)
    • FORCE_AGENT_MODE (Manual override)
    • (And others like CODEX, CLINE, AMAZON_Q, SRC_CODY, PI_CODING_AGENT)

    2. Explicit Activation

    You can force agent mode using the --agent flag or the FORCE_AGENT_MODE environment variable.

    # Using the flag
    pup monitors list --agent
    
    # Using the environment variable
    FORCE_AGENT_MODE=1 pup monitors list
    FORCE_AGENT_MODE=1 pup monitors list
  10. Use capture expressions and templates

    main

    Capture expressions allow you to use dot notation for fields and brackets for array indexing to extract specific data points. You can also use --template to create custom log messages using {variable} placeholders.

    Capture specific fields and array elements:

    # Dot notation and array indexing
    --capture "user.name"
    --capture "orders[0].total"
    --capture "items[len(items)].name"

    Combine capture expressions with a template:

    pup debugger probes create \
      --service my-service --env prod \
      --probe-location "MyClass:myMethod" \
      --capture "user.id" \
      --template "Processing request for user={user.id}, took {@duration}ms"

    Use conditions to filter probe triggers:

    --condition "status == 'error'"
    --condition "@duration > 100"
  11. Understand the Pup command pattern

    main

    Pup uses a hierarchical command structure based on domains and actions. Commands follow two primary patterns depending on whether they are simple or nested:

    1. Simple commands: pup <domain> <action> [options]
    2. Nested commands: pup <domain> <subgroup> <action> [options]

    You can always view the live, exhaustive list of commands available in your specific binary by running pup --help or pup agent schema --compact.

    pup <domain> <action> [options]
    pup <domain> <subgroup> <action> [options]
  12. Avoid the Agent Envelope when authoring scripts

    main

    When Pup is in agent mode, it wraps all command outputs in a JSON envelope containing status, data, and metadata.

    Warning: If you write a script or runbook that a user will execute in a standard shell (where agent mode is NOT active), the output will be the raw payload, not the envelope. A script relying on the envelope structure (e.g., jq '.data[]') will break when run outside an agent session.

    Best Practice: Always append --no-agent to commands in scripts intended for end-users to ensure consistent raw output.

    # This might break if the user isn't in agent mode:
    pup monitors list | jq '.data[]'
    
    # This is safe for scripts:
    pup --no-agent monitors list | jq '.[].name'
    pup --no-agent monitors list --tag='env:prod' | jq '.[].name'