{"slug": "dtctl-install-auth-skill-setup-for-claude-code-environments", "title": "dtctl install + auth + skill setup for Claude Code environments", "summary": "Dynatrace engineer shares a bash script that installs dtctl, configures authenticated contexts from environment secrets, and installs the dtctl AI-assistant skill for Claude Code environments. The script handles ephemeral container constraints by rebuilding auth and skills on every session start, and it builds dtctl from source because go install fails due to replace directives.", "body_md": "| #!/bin/bash | |\n| # Fail-open: never block session start. | |\n| # | |\n| # Installs dtctl (dynatrace-oss/dtctl) and configures an authenticated | |\n| # context from environment secrets. Both halves must live here (in the | |\n| # environment setup script) because the container is ephemeral: the config | |\n| # file dtctl writes (~/.config/dtctl/) and its keyring do NOT survive a | |\n| # session, so auth has to be reconstructed on every start from durable | |\n| # environment variables. | |\n| # | |\n| # Required environment variables (set these as environment secrets/vars): | |\n| # DT_ENVIRONMENT e.g. https://cou8642d.dev.apps.dynatracelabs.com | |\n| # IMPORTANT: dtctl talks to the PLATFORM / Grail query API, | |\n| # which is on the .apps host. This is the OPPOSITE of the | |\n| # CLAUDE.md OTLP-ingest rule (OTLP goes to the non-.apps | |\n| # host). Do not confuse the two: query -> .apps, ingest -> std. | |\n| # DT_API_TOKEN a dt0c01.* (classic) or dt0s16.* (platform) token | |\n| # with query read scopes: storage:logs:read, | |\n| # storage:metrics:read, storage:events:read, | |\n| # storage:spans:read, storage:buckets:read | |\n| set -uo pipefail | |\n| # --- Install (idempotent) -------------------------------------------------- | |\n| # NOTE: `go install` does NOT work for dtctl — its go.mod uses replace | |\n| # directives, which Go unconditionally refuses for `go install`. Build from | |\n| # source instead (replace directives are allowed in the main module). | |\n| # GOTOOLCHAIN=auto pulls the required Go toolchain (dtctl needs >= 1.26.5). | |\n| if ! command -v dtctl >/dev/null 2>&1; then | |\n| DTCTL_BUILD_DIR=$(mktemp -d) | |\n| ( | |\n| git clone --quiet --depth=1 https://github.com/dynatrace-oss/dtctl \"$DTCTL_BUILD_DIR/src\" \\ | |\n| && GOTOOLCHAIN=auto go build -C \"$DTCTL_BUILD_DIR/src\" -o /usr/local/bin/dtctl . | |\n| ) || echo \"dtctl install failed; setup will retry next session start\" | |\n| rm -rf \"$DTCTL_BUILD_DIR\" 2>/dev/null || true | |\n| fi | |\n| # --- Authenticate (idempotent) --------------------------------------------- | |\n| # Rebuild the context each session from the stored secret. Uses file-backed | |\n| # token storage since no OS keyring is available in the container. | |\n| export DTCTL_TOKEN_STORAGE=file | |\n| if command -v dtctl >/dev/null 2>&1; then | |\n| if [ -n \"${DT_ENVIRONMENT:-}\" ] && [ -n \"${DT_API_TOKEN:-}\" ]; then | |\n| dtctl config set-credentials dynadev --token \"$DT_API_TOKEN\" >/dev/null 2>&1 \\ | |\n| && dtctl config set-context dynadev \\ | |\n| --environment \"$DT_ENVIRONMENT\" \\ | |\n| --token-ref dynadev \\ | |\n| --safety-level readonly >/dev/null 2>&1 \\ | |\n| && dtctl config use-context dynadev >/dev/null 2>&1 \\ | |\n| && echo \"dtctl context 'dynadev' configured (readonly)\" \\ | |\n| || echo \"dtctl auth config failed; check DT_ENVIRONMENT / DT_API_TOKEN\" | |\n| else | |\n| echo \"dtctl installed but not authenticated: set DT_ENVIRONMENT and DT_API_TOKEN env secrets\" | |\n| fi | |\n| # --- Install the dtctl AI-assistant skill (idempotent) ------------------- | |\n| # dtctl embeds its own skill (SKILL.md + references). Reinstall each session | |\n| # so the skill tracks the installed dtctl version. --global lands in | |\n| # ~/.claude/skills/dtctl regardless of cwd; both that dir and the repo's | |\n| # .claude/ are ephemeral (.claude/ is gitignored here), so this must run | |\n| # on every start rather than being committed. | |\n| dtctl skills install --for claude --global --force >/dev/null 2>&1 \\ | |\n| && echo \"dtctl skill installed for claude (~/.claude/skills/dtctl)\" \\ | |\n| || echo \"dtctl skill install failed\" | |\n| fi | |\n| command -v dtctl >/dev/null 2>&1 && dtctl version || true |", "url": "https://wpnews.pro/news/dtctl-install-auth-skill-setup-for-claude-code-environments", "canonical_source": "https://gist.github.com/dt-benedict/a766ba6fa4c3f87f5f91211703494c9e", "published_at": "2026-08-04 08:47:32+00:00", "updated_at": "2026-08-05 15:39:23.691442+00:00", "lang": "en", "topics": ["developer-tools", "ai-tools"], "entities": ["Dynatrace", "dtctl", "Claude Code", "Grail"], "alternates": {"html": "https://wpnews.pro/news/dtctl-install-auth-skill-setup-for-claude-code-environments", "markdown": "https://wpnews.pro/news/dtctl-install-auth-skill-setup-for-claude-code-environments.md", "text": "https://wpnews.pro/news/dtctl-install-auth-skill-setup-for-claude-code-environments.txt", "jsonld": "https://wpnews.pro/news/dtctl-install-auth-skill-setup-for-claude-code-environments.jsonld"}}