Pup CLI
repository·main·Indexed 21 days ago
https://github.com/datadog/pupA 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).
What's inside pup
- 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.
Manage multiple Datadog orgs using named sessions
mainPup 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 (orDD_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-sitefor 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- Standard login:
Choose between Pup CLI and Code Generation
mainThe 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).
How pup extensions work
mainPup extensions are standalone executables that add new subcommands to the
pupCLI. When you runpup <command>, pup first checks if<command>is a built-in. If not, it searches for an installed executable namedpup-<command>and runs it, passing your arguments and authentication credentials.This allows teams to ship experimental features or custom tools independently of the core
puprelease 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 valueUnderstand Pup's PR Review Outcomes
mainPup uses a specific workflow for handling Pull Requests to optimize for throughput. Reviewers categorize PRs into one of the following outcomes (ordered by preference):
Priority Outcome Description 1 Merge PR meets all standards — merge as-is. 2 Merge-fix PR is mergeable but has minor issues — merge as-is, then push a follow-up fix to main. 3 Fix-merge PR has value but is broken (fails CI, has bugs) — pull locally, fix, and push with contributor attribution. 4 Cherry-pick PR bundles multiple changes and we only want some — cherry-pick the good parts locally, fix as needed, commit with attribution, and close the PR. 5 Split-merge PR mixes separate concerns that should be independent — pull locally, split into separate commits with attribution, and push each. 6 Reimplement PR solves a real problem but the design is wrong — reimplement the solution with a better approach, close the PR with thanks and an explanation. 7 Retire PR is obsolete — superseded by another PR, already fixed, or no longer relevant. Close with a thank-you. 8 Reject PR adds tech debt, is too niche for core, contains malicious code, or violates security rules. Close with a polite explanation. 9 Request changes Last 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. Authentication requirements for Pup
mainMost Pup commands require valid authentication to function.
- Workflow Commands: All workflow commands require both
DD_API_KEYandDD_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.
- Workflow Commands: All workflow commands require both
Security guidelines for Pup contributors
mainAdhere 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::Contextbut ensure sensitive data is never included in the error string.
OAuth2 Security
- Use PKCE S256 for code challenges.
- Validate the
stateparameter 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.
Understand Pup test organization
mainPup uses two primary locations for testing:
- 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 likeauth,client.rs,config.rs, etc. - Integration Tests (
tests/): These are located in thetests/directory and are used for end-to-end testing and output comparison (e.g.,tests/compare/).
- Module Tests (
Enable Agent Mode for AI Coding Agents
mainWhen 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
1ortrue:CLAUDE_CODEorCLAUDECODE(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
--agentflag or theFORCE_AGENT_MODEenvironment variable.# Using the flag pup monitors list --agent # Using the environment variable FORCE_AGENT_MODE=1 pup monitors listFORCE_AGENT_MODE=1 pup monitors listUse capture expressions and templates
mainCapture expressions allow you to use dot notation for fields and brackets for array indexing to extract specific data points. You can also use
--templateto 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"Understand the Pup command pattern
mainPup uses a hierarchical command structure based on domains and actions. Commands follow two primary patterns depending on whether they are simple or nested:
- Simple commands:
pup <domain> <action> [options] - 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 --helporpup agent schema --compact.pup <domain> <action> [options] pup <domain> <subgroup> <action> [options]- Simple commands:
Avoid the Agent Envelope when authoring scripts
mainWhen Pup is in agent mode, it wraps all command outputs in a JSON envelope containing
status,data, andmetadata.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-agentto 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'