关于 dd-account-setup
dd-account-setup 是引导用户连接或创建 Datadog 账户的技能,适用于准备 API key、application key 和站点区域的场景。它检测已有凭据,支持 OAuth 登录或创建账户,并通过 Datadog API 验证密钥。
主要功能
- 01检测环境变量与 .env 凭据
- 02确认 Datadog 站点区域
- 03通过 OAuth 登录或创建账户
- 04生成并保存 API key
- 05调用 API 验证凭据
适用场景
- 01为 Datadog 初次配置凭据
- 02验证已有 API key 与站点
- 03为后续监控配置准备账户
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ datadog-labs/ agent-skills --skill dd-account-setup安装后在 Claude Code 中输入/dd-account-setup确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/authenticate.mdconventions.mdget-api-key.mdregions.mdtroubleshooting.md详细介绍
创建 / 连接 Datadog 账户
此技能会帮助用户达到已知的可用状态:有效的 API 密钥 + 应用密钥,位于正确的区域,并通过 Datadog API 验证。 这是设置 / 插桩技能所依赖的“第 0 步”——先运行此技能,然后再交接。
这是一个独立的引导流程:检测现有内容;如果没有找到可用的内容,则通过 OAuth(浏览器、PKCE + state)登录,或创建新账户(在终端内操作,并将生成的密码保存到 .env),然后将该会话转换为 API 密钥。所有操作都通过简短的内联 bash + curl 命令完成(OAuth 还会用到 openssl)——没有捆绑脚本,也不需要 node;支持跨平台(macOS、Linux、通过 WSL/Git Bash 使用 Windows)。
此 SKILL.md 是整个流程的主干——它内含简短步骤,并在需要时引导至 references/,获取每一步的详细操作。只有在到达提及相应参考文件的步骤时才阅读它。
流程一览
headless requested? ──yes──▶ Step H: env keys only (OAuth needs a browser), validate, done
│no (default — interactive)
▼
Step 1 Detect existing credentials (env)
│
▼
Step 2 Determine region / site (DD_SITE → validate; else ask → user picks, default US1)
│
▼
Step 3 Authenticate — ask first (even if env keys were detected) → references/authenticate.md
│ └─ ASK: how to connect? ↴
│ ├─ A. Use the detected env key (only if one exists) → validate → Step 5
│ ├─ B. Sign in (I have an account) → OAuth (browser, PKCE + state) ──▶ Bearer token
│ └─ C. Create a new account → Path C: auto in-terminal signup, generated password ──▶ then OAuth
▼
Step 4 Turn the OAuth session into an API key → references/get-api-key.md
│ (identity + region via /current_user; OAuth→retrieve most-recent key, app-key→create → write straight to .env; else guide to UI key page)
▼
Step 5 Load creds from .env, validate, hand off
黄金法则:绝不猜测或伪造 API 密钥、应用密钥、令牌或站点。 读取环境中的内容并进行验证;如果不存在,就进行身份验证——不要凭假设继续操作。
显示与措辞约定——在步骤 1 前阅读一次
每个步骤都遵循相同的规则,与用户交流并呈现进度:简洁状态行的呈现约定、使用宿主的原生选择器提问(绝不让用户输入字母),以及带有标记规范的实时进度清单。这些规则位于 references/conventions.md 中——在步骤 1 前阅读,并在整个流程中遵循。下方每个步骤末尾都有一个 ↳ Checklist: 提示,说明需要更新哪些项目。
步骤 0 — 预检(就绪状态面板)
先运行一次,让用户在任何操作开始前看到完整流程——有哪些工具可用、已检测到什么,以及流程将执行什么操作(包括会打开一次浏览器)。此步骤不会写入任何内容,也不会泄露秘密信息。每次调用都会从步骤 1 开始运行完整流程——不会恢复或跳过步骤,也不会沿用之前运行的结果。
DDLOG="${TMPDIR:-/tmp}/dd-onboard-$(id -u).log"; : >"$DDLOG" # fresh log for this run
mark(){ command -v "$1" >/dev/null 2>&1 && echo "✓" || echo "$2"; }
# python3 gates the auto browser-callback; fall back to python only if it's a real py3.
have_py3(){ command -v python3 >/dev/null 2>&1 && return 0; command -v python >/dev/null 2>&1 && python -c 'import sys;exit(0 if sys.version_info[0]==3 else 1)' 2>/dev/null; }
py3msg(){ have_py3 && echo '✓ (auto browser-callback)' || echo '⊘ (will paste the redirect URL)'; }
echo "Datadog account setup — preflight"
echo " deps (required): bash ✓ curl $(mark curl ✗) openssl $(mark openssl ✗)"
echo " deps (optional): python3 $(py3msg) browser-open $( { command -v open >/dev/null 2>&1 || command -v xdg-open >/dev/null 2>&1; } && echo ✓ || echo '⊘ (open URL manually)')"
# Canonical DD_* loader — this same block is repeated verbatim in later steps because each ```bash runs a fresh shell (not drift).
# Load DD_* with precedence: shell env > .env.local > .env. A real env var is never overwritten; surrounding quotes are stripped. *_SRC records where each came from (unset ⇒ from the shell env).
for f in .env.local .env; do [ -f "$f" ] || continue; for k in DD_SITE DD_API_KEY DD_APP_KEY; do eval "[ -n \"\${$k:-}\" ]" && continue; v=$(grep -E "^$k=" "$f" | head -1 | cut -d= -f2- | sed 's/^["'\'']//;s/["'\'']$//'); [ -n "$v" ] && { export "$k=$v"; eval "${k}_SRC=$f"; }; done; done
echo " detected creds: DD_SITE=${DD_SITE:-<unset>}${DD_SITE_SRC:+ [$DD_SITE_SRC]} DD_API_KEY=$([ -n "$DD_API_KEY" ] && echo "set …${DD_API_KEY: -4}${DD_API_KEY_SRC:+ [$DD_API_KEY_SRC]}" || echo '<unset>') DD_APP_KEY=$([ -n "$DD_APP_KEY" ] && echo "set${DD_APP_KEY_SRC:+ [$DD_APP_KEY_SRC]}" || echo '<unset>')"
echo " what happens: confirm region → authenticate (opens your browser once) → get an API key → write it to .env → validate. ~2 min, one browser approval."
[ "$(mark curl ✗)" = ✗ ] || [ "$(mark openssl ✗)" = ✗ ] && echo " ✗ missing a required dep above — install it before continuing."
原样向用户展示状态面板(它已经简洁明了)。如果缺少必需的依赖项,则停止并说明情况。然后勾选清单中的步骤 1 并继续——始终进入步骤 1;绝不能跳到后续步骤。
↳ 清单: 先展示状态面板,再展示清单;将1. 检测凭据标记为 ◔。
步骤 H — 无头 / 非交互模式(无浏览器、无提示)
首先判断是否属于此模式,因为没有人工参与就无法使用浏览器或注册流程。根据技能的调用方式判断无头模式,而不是根据环境判断——触发条件是用户的请求本身:用户明确要求在没有浏览器或交互式提示的情况下运行(例如“以非交互方式设置 Datadog”“我在 CI 环境中,没有浏览器”)。
不要仅因为缺少 TTY 就判断为无头模式——普通终端运行始终使用交互式流程。只有明确提出的请求才会关闭交互。
判断用户要求无头模式后,再运行下方代码块。OAuth 无法打开浏览器,注册提示也无人作答,因此达到有效状态的唯一方式是使用已提供的密钥。要求设置 DD_API_KEY、DD_APP_KEY 和 DD_SITE,否则立即失败:
# Run this block ONLY when you inferred a non-interactive request. It enforces the one thing
# headless needs — keys already present — and fails fast when any are missing.
# Load DD_* (env > .env.local > .env), same precedence as Step 1 — CI keys often live in .env, not exported.
for f in .env.local .env; do [ -f "$f" ] || continue; for k in DD_SITE DD_API_KEY DD_APP_KEY; do eval "[ -n \"\${$k:-}\" ]" && continue; v=$(grep -E "^$k=" "$f" | head -1 | cut -d= -f2- | sed 's/^["'\'']//;s/["'\'']$//'); [ -n "$v" ] && export "$k=$v"; done; done
missing=""
[ -z "$DD_API_KEY" ] && missing="$missing DD_API_KEY"
[ -z "$DD_APP_KEY" ] && missing="$missing DD_APP_KEY"
[ -z "$DD_SITE" ] && missing="$missing DD_SITE"
[ -n "$missing" ] && { echo "Non-interactive mode requires:$missing — set them and re-run. Sign-in and trial signup need a browser."; exit 1; }
如果这三项都已设置,则交接至步骤 5,通过 /api/v1/validate 验证密钥(支持使用 DD-API-KEY 请求头)。注意:/api/v1/validate 只检查 DD_API_KEY——DD_APP_KEY 虽为必需项,但不会在此单独验证;错误或过期的应用密钥会在首次调用需要应用密钥的接口时显现。无头模式下没有 OAuth 或注册的备用路径——这两种方式都需要浏览器——因此应使用上述消息报错,并确保日志便于采取后续操作。
↳ 清单(无头模式): 仅有两项——验证通过后勾选两项,并跳转至步骤 5。
步骤 1 — 检测现有凭据
读取环境变量以及项目的 .env / .env.local 文件。不要向用户完整显示这些值;请对其进行掩码处理。
# Load DD_* with precedence: shell env > .env.local > .env (real env var wins; quotes stripped). *_SRC = file it came from (unset ⇒ shell env).
for f in .env.local .env; do [ -f "$f" ] || continue; for k in DD_SITE DD_API_KEY DD_APP_KEY; do eval "[ -n \"\${$k:-}\" ]" && continue; v=$(grep -E "^$k=" "$f" | head -1 | cut -d= -f2- | sed 's/^["'\'']//;s/["'\'']$//'); [ -n "$v" ] && { export "$k=$v"; eval "${k}_SRC=$f"; }; done; done
echo "DD_SITE = ${DD_SITE:-<unset>}${DD_SITE_SRC:+ (from $DD_SITE_SRC)}"
echo "DD_API_KEY= $( [ -n "$DD_API_KEY" ] && echo "set (…${DD_API_KEY: -4})${DD_API_KEY_SRC:+ (from $DD_API_KEY_SRC)}" || echo "<unset>" )"
echo "DD_APP_KEY= $( [ -n "$DD_APP_KEY" ] && echo "set (…${DD_APP_KEY: -4})${DD_APP_KEY_SRC:+ (from $DD_APP_KEY_SRC)}" || echo "<unset>" )"
- 存在
DD_API_KEY(环境变量或.env/.env.local)→ 前往步骤 2(固定站点),然后执行步骤 3并询问(选项 A = 使用检测到的密钥,或选项 B/C 进行身份验证 / 创建其他账户)。检测到的密钥是用户在步骤 3 中确认后才可选择的选项,而不是默认静默使用的密钥——用户可能想使用其他组织或账户。 - 任何位置都没有
DD_API_KEY→ 用户目前没有可用的密钥。仍然执行步骤 2(确保注册页面落在正确的区域),然后前往步骤 3,询问用户如何连接。
只有应用密钥而没有 API 密钥是不够的;应视为“没有密钥”。由于 shell 不会在代码块之间持久保留,因此每个后续使用 $DD_API_KEY 的代码块都会在开头重新运行同一个加载器——这就是它会在路径 A、步骤 4 和步骤 5 中再次出现的原因。
↳ 清单: 现在发布列表 — 勾选 1. 检测凭据,将 2. 确认区域标记为 ◔。
步骤 2 — 确定区域 / 站点
站点会决定后续的所有 URL(注册、API 主机、密钥页面),因此请先固定站点,再进行验证。
区域表位于 references/regions.md。
-
如果已设置
DD_SITE(环境变量或.env):根据references/regions.md中的允许站点列表验证它。如果它不在列表中,请停止并显示清晰的错误:DD_SITE="<value>"不是已识别的 Datadog 站点。请从references/regions.md中选择一个区域,并相应地设置DD_SITE。 -
**如果未设置
DD_SITE:**请用户从references/regions.md中的表格选择一个区域——绝不要静默选定。不要尝试检测用户的位置(不要进行 IP 地理定位查询或其他第三方调用):正确的区域取决于其基础设施所在的位置,可能与用户所在地不同。如果用户没有偏好,默认使用 US1(datadoghq.com)。例如,告知用户:这个账户应位于哪个 Datadog 区域?请选择最靠近基础设施运行位置的区域(例如你的云区域)——将数据发送到很远的区域会增加延迟和出口流量成本,而且账户创建后无法更改区域。默认值:US1(弗吉尼亚州),
datadoghq.com。使用主机原生选择器,并将 **US1(默认)**放在首位。如果选项数量受限,请按以下顺序尽可能多地列出 — US1、EU1、AP1、UK1 — 并让选择器中的自由文本“Other”选项涵盖其余区域。
等待用户回复后再继续。用户简单地表示接受(“ok”“default”“sure”)即表示选择 US1。
API 主机统一为 https://api.${DD_SITE}。
↳ 清单: 用户确认区域后,勾选 2. 确认区域,将 3. 身份验证标记为 ◔。
第 3 步 — 身份验证
先询问如何连接 — 即使第 1 步检测到了环境凭据也要询问 — 然后执行用户选择的路径。在接触任何凭据之前,先展示“选项”:环境变量中的 DD_API_KEY 可能属于与用户预期不同的组织或账户,而区域无法揭示这一点,因此应让用户决定,而不是自行推断。(无头模式/第 H 步除外 — 没有 TTY 可供询问,只能使用环境变量中的密钥。)
完整详情 — “选项”的原生选择器措辞及全部三条路径 — 见 references/authenticate.md:
| 用户选择 | 路径 | 操作 |
|---|---|---|
| 使用我现有的凭据 (仅当第 1 步检测到密钥时才提供) | A | 验证检测到的密钥(也会发现区域错误的密钥 → 返回第 2 步)。 |
| 登录 — 我已有账户 | B | 在浏览器中进行 OAuth(PKCE + state),将 Bearer 令牌写入 0600 文件。 |
| 创建新账户 (默认) | C | 在终端中自动注册并生成密码 → 然后执行路径 B。 |
阅读 references/authenticate.md,通过宿主的原生选择器展示选项,然后执行匹配的路径。如果某条路径走不通,则重新提供选项(OAuth 未找到账户 → C;区域错误的密钥先让用户返回第 2 步)。
↳ 清单: 在实际拿到令牌或密钥之前,保持 3. 身份验证 ◔(参见
references/authenticate.md中各路径的提示)。
第 4 步 — 将 OAuth 会话转换为 API 密钥
OAuth 令牌用于验证用户身份,但下游检测需要 DD_API_KEY。使用 Bearer 令牌确认身份,然后获取密钥 — OAuth 会话应检索组织最新的密钥(OAuth 令牌无法创建密钥);使用应用密钥进行身份验证时则应创建密钥;否则,引导用户前往 UI 密钥页面。
完整分支流程(身份检查、检索或创建、带 HTTP 状态码标记的代码块,以及 EMPTY_ORG / LIST_DENIED / SECRET_DENIED / CREATE_DENIED / TRANSPORT_ERROR 的结果表)见 references/get-api-key.md — 请遵循其中的说明。密钥会直接写入 .env,绝不会回显。
↳ 清单: 拿到经过验证的密钥后,勾选 4. 获取并验证 API 密钥,将 5 标记为 ◔。
第 5 步 — 确认并移交
密钥已在 .env 中。加载并验证密钥(每次调用都使用全新的 shell — 始终先通过解析的方式加载 .env,绝不要 source 它,以免精心构造的 .env 执行代码;绝不要将密钥明文写入命令):
DDLOG="${TMPDIR:-/tmp}/dd-onboard-$(id -u).log"; tf="${TMPDIR:-/tmp}/dd-oauth-$(id -u).token"
# Load DD_* (env > .env.local > .env) — parse, don't source, so a crafted .env can't execute. Covers a Path-A key that lives only in the shell env or .env.local.
for f in .env.local .env; do [ -f "$f" ] || continue; for k in DD_SITE DD_API_KEY DD_APP_KEY; do eval "[ -n \"\${$k:-}\" ]" && continue; v=$(grep -E "^$k=" "$f" | head -1 | cut -d= -f2- | sed 's/^["'\'']//;s/["'\'']$//'); [ -n "$v" ] && export "$k=$v"; done; done
vcode=$(curl -sg -o "$DDLOG" -w '%{http_code}' -H "DD-API-KEY: $DD_API_KEY" "https://api.${DD_SITE}/api/v1/validate")
# re-derive org/email for the card (fresh shell — Step 4 vars don't persist); only if a token is still around
who=""; [ -s "$tf" ] && who=$(curl -sg -H "Authorization: Bearer $(cat "$tf")" "https://api.${DD_SITE}/api/v2/current_user" 2>>"$DDLOG" | grep -oE '"email"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | cut -d'"' -f4)
cmk="${TMPDIR:-/tmp}/dd-signup-$(id -u).created"; spw="" # marker exists only if THIS run created the account (Path C, C3) — no stale password from an earlier run
[ -f "$cmk" ] && spw=$(grep -E '^DD_SIGNUP_PASSWORD=' .env 2>/dev/null | tail -1 | cut -d= -f2-) # newest .env entry = the password this run generated (C2 appends to .env)
# consistent 🔑 credential card — the one place credential state is summarized; secret shown only as last4
echo "🔑 Datadog credential"
[ -n "$who" ] && echo " org: $who"
echo " region: ${DD_SITE}"
echo " api key: …${DD_API_KEY: -4} (in .env — never printed in full)"
[ -n "$spw" ] && echo " password: in .env as DD_SIGNUP_PASSWORD (ends …${spw: -4}) — you need it to sign in to Datadog"
echo " status: $([ "$vcode" = 200 ] && echo '✓ validated (HTTP 200)' || echo "✗ validate HTTP $vcode — see: tail -n 30 \"$DDLOG\"")"
- 上方的卡片是规范摘要 — 不要同时倾倒原始验证响应。若返回非 200 状态码,显示
tail -n 30 "$DDLOG",并按结果表处理(此处的403通常表示区域错误 → 第 2 步)。 - 报告身份调用返回的已验证组织/邮箱。
- 所有凭据都保存在
.env中(DD_SITE、DD_API_KEY,以及通过路径 C 创建账户时的DD_SIGNUP_PASSWORD)— 直接写入文件,绝不回显。清理注册临时文件以及 OAuth state 和 callback 文件:rm -f "${TMPDIR:-/tmp}"/dd-signup-$(id -u).* "${TMPDIR:-/tmp}"/dd-oauth-$(id -u).state "${TMPDIR:-/tmp}"/dd-oauth-$(id -u).cb。 - 下游移交 — 保留 OAuth 令牌。 保留
${TMPDIR:-/tmp}/dd-oauth-$(id -u).token(0600),不要删除。下游检测会重用此 Bearer 令牌来配置普通 API 密钥无法创建的资源 — 尤其是 RUM 应用。此令牌有效期短且有作用域限制;完成设置后,由引导调用方(例如编排器)将其删除(rm -f "${TMPDIR:-/tmp}"/dd-oauth-$(id -u).token)。如果单独运行检测,请在完成后自行删除。 - 返回:“账户已准备就绪。现在可以运行设置/检测步骤了。”(例如
studio-setup、browser-rum-setup、llm-observability-setup或其他任何*-setup技能)。
↳ 清单: 勾选 5. 已就绪 — 移交 — 显示已全部完成的清单,让用户知道整个流程已完成。
故障排查与参考
如果某个步骤失败,请参阅 references/troubleshooting.md — 症状→解决方法表(区域错误、OAuth 状态不匹配、无头模式退出、Path-C 注册错误等),以及设计决策和临时状态说明。