dtctl install + auth + skill setup for Claude Code environments 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. | /bin/bash | | | Fail-open: never block session start. | | | | | | Installs dtctl dynatrace-oss/dtctl and configures an authenticated | | | context from environment secrets. Both halves must live here in the | | | environment setup script because the container is ephemeral: the config | | | file dtctl writes ~/.config/dtctl/ and its keyring do NOT survive a | | | session, so auth has to be reconstructed on every start from durable | | | environment variables. | | | | | | Required environment variables set these as environment secrets/vars : | | | DT ENVIRONMENT e.g. https://cou8642d.dev.apps.dynatracelabs.com | | | IMPORTANT: dtctl talks to the PLATFORM / Grail query API, | | | which is on the .apps host. This is the OPPOSITE of the | | | CLAUDE.md OTLP-ingest rule OTLP goes to the non-.apps | | | host . Do not confuse the two: query - .apps, ingest - std. | | | DT API TOKEN a dt0c01. classic or dt0s16. platform token | | | with query read scopes: storage:logs:read, | | | storage:metrics:read, storage:events:read, | | | storage:spans:read, storage:buckets:read | | | set -uo pipefail | | | --- Install idempotent -------------------------------------------------- | | | NOTE: go install does NOT work for dtctl — its go.mod uses replace | | | directives, which Go unconditionally refuses for go install . Build from | | | source instead replace directives are allowed in the main module . | | | GOTOOLCHAIN=auto pulls the required Go toolchain dtctl needs = 1.26.5 . | | | if command -v dtctl /dev/null 2 &1; then | | | DTCTL BUILD DIR=$ mktemp -d | | | | | | git clone --quiet --depth=1 https://github.com/dynatrace-oss/dtctl "$DTCTL BUILD DIR/src" \ | | | && GOTOOLCHAIN=auto go build -C "$DTCTL BUILD DIR/src" -o /usr/local/bin/dtctl . | | | || echo "dtctl install failed; setup will retry next session start" | | | rm -rf "$DTCTL BUILD DIR" 2 /dev/null || true | | | fi | | | --- Authenticate idempotent --------------------------------------------- | | | Rebuild the context each session from the stored secret. Uses file-backed | | | token storage since no OS keyring is available in the container. | | | export DTCTL TOKEN STORAGE=file | | | if command -v dtctl /dev/null 2 &1; then | | | if -n "${DT ENVIRONMENT:-}" && -n "${DT API TOKEN:-}" ; then | | | dtctl config set-credentials dynadev --token "$DT API TOKEN" /dev/null 2 &1 \ | | | && dtctl config set-context dynadev \ | | | --environment "$DT ENVIRONMENT" \ | | | --token-ref dynadev \ | | | --safety-level readonly /dev/null 2 &1 \ | | | && dtctl config use-context dynadev /dev/null 2 &1 \ | | | && echo "dtctl context 'dynadev' configured readonly " \ | | | || echo "dtctl auth config failed; check DT ENVIRONMENT / DT API TOKEN" | | | else | | | echo "dtctl installed but not authenticated: set DT ENVIRONMENT and DT API TOKEN env secrets" | | | fi | | | --- Install the dtctl AI-assistant skill idempotent ------------------- | | | dtctl embeds its own skill SKILL.md + references . Reinstall each session | | | so the skill tracks the installed dtctl version. --global lands in | | | ~/.claude/skills/dtctl regardless of cwd; both that dir and the repo's | | | .claude/ are ephemeral .claude/ is gitignored here , so this must run | | | on every start rather than being committed. | | | dtctl skills install --for claude --global --force /dev/null 2 &1 \ | | | && echo "dtctl skill installed for claude ~/.claude/skills/dtctl " \ | | | || echo "dtctl skill install failed" | | | fi | | | command -v dtctl /dev/null 2 &1 && dtctl version || true |