feat: Add CLI telemetry instrumentation and remove deprecated SDK#233
Merged
leggetter merged 10 commits intoclaude/hookdeck-gateway-mcp-Xe6WQfrom Mar 11, 2026
Merged
Conversation
Extend the telemetry header with source, environment, command_path, invocation_id, and mcp_client fields so the API server can distinguish CLI from MCP requests and correlate multiple API calls to a single command invocation. Phase 1 - Telemetry struct & CLI wiring: - Add Source, Environment, InvocationID, MCPClient fields to CLITelemetry - Add NewInvocationID() generator (8 random bytes, hex-encoded) - Add initTelemetry() helper called from root PersistentPreRun - Fix Cobra PersistentPreRun chaining for connection command Phase 2 - MCP per-request telemetry: - Add Telemetry field + WithTelemetry() clone method on Client - Update PerformRequest to use per-request telemetry when set - Wrap MCP tool handlers to set per-invocation telemetry context - Extract MCP client info from ServerSession.InitializeParams() Phase 3 - SDK client: - Works automatically: PersistentPreRun populates singleton before GetClient() bakes headers at construction time Phase 5 - Config-based opt-out: - Add TelemetryDisabled to Config, read from config.toml - Update telemetryOptedOut() to accept config flag - Thread TelemetryDisabled through API and SDK client construction Phase 6 - CI detection: - Add DetectEnvironment() checking CI, GITHUB_ACTIONS, GITLAB_CI, JENKINS_URL, CODEBUILD_BUILD_ID, BUILDKITE, TF_BUILD env vars - Tag requests with environment: "ci" or "interactive" https://claude.ai/code/session_01TQFynqFrXsP38LuYmdERYL
Add 6 integration tests that exercise the full pipeline: MCP tool call → wrapWithTelemetry → HTTP request → mock API server, verifying the Hookdeck-CLI-Telemetry header arrives with correct content. Tests cover: - Header sent with correct source/command_path/invocation_id/mcp_client - Each tool call gets a unique invocation ID - Command path reflects the action (hookdeck_sources/list vs /get) - Telemetry disabled by config (TelemetryDisabled=true) - Telemetry disabled by env var (HOOKDECK_CLI_TELEMETRY_OPTOUT=true) - Multiple API calls within one tool invocation share the same ID https://claude.ai/code/session_01TQFynqFrXsP38LuYmdERYL
Adds a telemetry subcommand with enable/disable actions so users can toggle anonymous telemetry without manually editing config.toml. https://claude.ai/code/session_01TQFynqFrXsP38LuYmdERYL
Instead of separate subcommands, `hookdeck telemetry enable` and `hookdeck telemetry disable` now use a single command with a required positional argument. Also adds telemetry section to the README. https://claude.ai/code/session_01TQFynqFrXsP38LuYmdERYL
Add ResetTelemetryInstanceForTesting() and ResetAPIClientForTesting() to enable isolated testing of the CLI telemetry path. Add tests that verify the singleton reset → populate → HTTP request → header cycle, singleton isolation between sequential commands, and initTelemetry correctness including generated resource detection. https://claude.ai/code/session_01TQFynqFrXsP38LuYmdERYL
Add TelemetryHeaderName constant to avoid hardcoded header strings across the codebase. Include a comment explaining why we omit the "X-" prefix (deprecated by RFC 6648). https://claude.ai/code/session_01TQFynqFrXsP38LuYmdERYL
The listen command was the only consumer of the hookdeck-go-sdk (pinned to API version 2024-03-01). This migrates it to use the direct hookdeck.Client which hits the current API version (2025-07-01) and reads telemetry from the singleton on every request — fixing the gap where the SDK client baked headers at creation time and never updated. - Replace all hookdecksdk types with hookdeck types (Source, Connection, Destination) across listen/, proxy/, and tui/ packages - Replace SDK client calls (Source.List, Connection.Create, etc.) with direct Client methods (ListSources, CreateConnection, etc.) - Use Destination.GetCLIPath()/SetCLIPath() instead of direct CliPath field - Delete pkg/hookdeck/sdkclient.go and pkg/config/sdkclient.go - Remove github.com/hookdeck/hookdeck-go-sdk from go.mod https://claude.ai/code/session_01TQFynqFrXsP38LuYmdERYL
Add X- prefix for consistency with X-Hookdeck-Client-User-Agent. https://claude.ai/code/session_01TQFynqFrXsP38LuYmdERYL
* docs: generate REFERENCE.md in-place, remove REFERENCE.template.md - Default input is REFERENCE.md; run with no args for in-place update - Update README generator instructions and --check example - Remove REFERENCE.template.md Made-with: Cursor * feat!: introduce Hookdeck config file and root --hookdeck-config flag - Rename root-level --config to --hookdeck-config to avoid conflict with source/destination --config (JSON body) and --config-file (JSON path). - Add HOOKDECK_CONFIG_FILE env var for config path; precedence is flag, then env, then .hookdeck/config.toml, then default location. - Document env var and flag in README (precedence list and Global Flags). - Update REFERENCE.md global options and acceptance tests. Made-with: Cursor * test: parallelize acceptance tests into three slices - Add feature build tags to all automated acceptance test files so tests can be split across parallel runs (CI and local). - CI: run three matrix jobs with tags split by estimated runtime; each job uses its own API key (HOOKDECK_CLI_TESTING_API_KEY, _2, _3). - Local: run_parallel.sh runs three slices in parallel, writing to test/acceptance/logs/slice0.log, slice1.log, slice2.log; add logs/ to .gitignore. - Helpers: support ACCEPTANCE_SLICE=2 and HOOKDECK_CLI_TESTING_API_KEY_3; per-slice config path and API key selection for isolated projects. - Rebalance slices for ~5–5.5 min wall time (slice 0: connection/source/ destination/gateway/etc.; slice 1: request, event; slice 2: attempt, metrics, issue, transformation). - Document three-slice setup, tags, and run commands in test/acceptance/README.md. Made-with: Cursor
Several places constructed hookdeck.Client directly, bypassing GetAPIClient(). These clients didn't carry TelemetryDisabled from config, so they'd send telemetry even when the user had opted out. Two-layer fix: 1. Safety net: Add Disabled flag to the telemetry singleton. PerformRequest now checks both the per-client TelemetryDisabled and the singleton's Disabled flag, so even stray clients respect the config-level opt-out. 2. Consistency: Route as many callers as possible through GetAPIClient(): - project.go: use config.GetAPIClient() instead of raw construction - whoami.go: use Config.GetAPIClient().ValidateAPIKey() - Login() validate path: use config.GetAPIClient().ValidateAPIKey() - proxy.go createSession: receive APIClient via proxy.Config - tui/model.go: receive APIClient via tui.Config - Remove login/validate.go (no longer called) For unauthenticated login clients (Login, GuestLogin, CILogin, InteractiveLogin, MCP tool_login), pass TelemetryDisabled from config. https://claude.ai/code/session_01TQFynqFrXsP38LuYmdERYL
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds anonymous telemetry instrumentation to the CLI and MCP server, and removes the deprecated
hookdeck-go-sdkdependency — a prerequisite for the 2.0.0 release.Telemetry Instrumentation
CLITelemetry) populated during CobraPersistentPreRun, attached asX-Hookdeck-CLI-TelemetryJSON header on every API requestsource(cli/mcp),environment(ci/interactive),command_path,invocation_id,device_name,generated_resource,mcp_clienthookdeck telemetry enable/disablesubcommand for persistent opt-out via config fileHOOKDECK_CLI_TELEMETRY_OPTOUTenv var for per-invocation opt-outTelemetryDisabledfield + singletonDisabledfield, both checked inPerformRequest— ensures telemetry is never sent when disabled, even if a client is constructed directly withoutGetAPIClient()initializeparams and includes it in telemetryDeprecated SDK Removal (Breaking Change)
hookdeck-go-sdk(github.com/hookdeck/hookdeck-go-sdk v0.7.0) — the SDK was pinned to API version2024-03-01; all code now uses the directhookdeck.Clienttargeting2025-07-01listencommand:source.go,connection.go,listen.go,printer.go,proxy.go, TUI — all rewritten from SDK types to direct client typesId→ID,Url→URL,SourceId→SourceID[]*Sourcewith.Count→[]Sourcewith.PaginationDestination.CliPath→Destination.Config["path"]withGetCLIPath()/SetCLIPath()helperspkg/hookdeck/sdkclient.go,pkg/config/sdkclient.go,pkg/login/validate.goconfig.GetAPIClient()Other Changes
run_parallel.sh)project.goandwhoami.goto useGetAPIClient()TelemetryDisabledto pre-auth clientsBreaking Changes
hookdeck-go-sdkdependency — any downstream code relying on SDK types will need to use direct client types frompkg/hookdeck/2024-03-01→2025-07-01for all listen command operationsdestination.CliPath→destination.GetCLIPath()/destination.SetCLIPath()Test Coverage
Automated
initTelemetry(4), config flag (2)Manual Testing Recommended
hookdeck listen 3000— TUI renders correctly (source URLs, IDs, CLI paths)hookdeck listen 3000 --source new-source— new source/connection creationhookdeck listen 3000 --output compact— compact outputhookdeck login/hookdeck login --cli-key— both login flowshookdeck telemetry disablethen any command — verify header absentHOOKDECK_CLI_TELEMETRY_OPTOUT=1 hookdeck listen 3000— verify header absentCommits
eee24e5388f91453ce91ehookdeck telemetry enable/disablesubcommand03dd341267fe6030517f2ccbd229hookdeck-go-sdk, migrate listen to direct API clientcae9770X-Hookdeck-CLI-Telemetry29d812415af040