Skip to content

feat: track cli usage in request headers#302

Merged
gnapse merged 5 commits intomainfrom
ernesto/cli-usage-tracking
Apr 30, 2026
Merged

feat: track cli usage in request headers#302
gnapse merged 5 commits intomainfrom
ernesto/cli-usage-tracking

Conversation

@gnapse
Copy link
Copy Markdown
Collaborator

@gnapse gnapse commented Apr 29, 2026

Summary

This PR makes Todoist CLI identify itself consistently to Todoist backend services.

Every Todoist-bound request now carries a shared header contract so backend logs can reliably recognize CLI traffic, attribute it to a low-cardinality command label, and correlate related requests from the same CLI process.

That coverage applies across the main SDK-backed API client as well as direct Todoist fetch paths such as OAuth and legacy auth migration, so the backend sees the same shape regardless of how the request was made.

Why

Before this change, the CLI did not consistently describe itself across outbound requests to Todoist services.

This PR standardizes that request-level contract so backend tracking can happen from normal API logs instead of requiring a separate client-side telemetry system.

What changed

  • Introduced one shared request-metadata layer for Todoist-bound requests instead of piecemeal per-call headers.
  • Standardized command attribution so backend logs receive a stable low-cardinality command label, including routed td view ... flows and internal non-Commander flows.
  • Added tests around header generation and auth-related request paths, and documented the shared contract in the codebase.

What every request now sends

All requests from the CLI to Todoist backend services now send the following headers:

  • User-Agent: todoist-cli/<version>
    Identifies the binary and its version in the conventional user-agent slot.

  • doist-platform: cli
    Explicit machine-readable platform marker for backend classification.

  • doist-version: <version>
    Dedicated version field so backend consumers do not need to parse User-Agent.

  • doist-os: <normalized os>
    Normalized operating-system label for environment-level usage analysis.

  • X-TD-Request-Id: <uuid>
    A new UUID for every outbound request. This is request-scoped, not process-scoped.

  • X-TD-Session-Id: <uuid>
    A stable UUID for the lifetime of the current CLI process. Multiple requests from the same run share this value.

  • X-TD-CLI-Command: <command label>
    A low-cardinality, lower-case, colon-separated label describing the CLI action responsible for the request.
    Examples include today, task:add, project:list, task:view, and postinstall:auth-migrate.

A few details about X-TD-CLI-Command:

  • Normal Commander-driven commands derive it automatically from the active command path.
  • Routed td view ... flows override the top-level view label with the routed target command, so backend logs see the real action rather than just view.
  • Internal flows that do not naturally run under Commander can provide an explicit low-cardinality override.
  • If no specific command context is available, the fallback value is unknown, so the header is still present.

@gnapse gnapse force-pushed the ernesto/cli-usage-tracking branch from f85849b to 3710d63 Compare April 29, 2026 21:18
@gnapse gnapse changed the title [codex] Track CLI usage in request headers feat: track cli usage in request headers Apr 29, 2026
@gnapse gnapse self-assigned this Apr 29, 2026
@gnapse gnapse force-pushed the ernesto/cli-usage-tracking branch from 3710d63 to 03121ff Compare April 29, 2026 21:24
@gnapse gnapse marked this pull request as ready for review April 29, 2026 21:48
@doistbot doistbot requested a review from henningmu April 29, 2026 21:48
@gnapse gnapse requested a review from scottlovegrove April 29, 2026 21:52
Copy link
Copy Markdown
Member

@doistbot doistbot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR establishes a consistent mechanism for tracking CLI usage by injecting standard client identity headers and command paths into all backend requests. This is a great addition that will significantly improve observability and our ability to correlate backend logs with specific CLI interactions. There is just one flagged issue to address regarding the custom fetch wrapper inadvertently stripping the timeout property, which could lead to indefinitely hanging network requests if not mapped to an AbortSignal.

Share FeedbackReview Logs

Comment thread src/lib/usage-tracking.ts Outdated
@gnapse gnapse added the 🙋 Ask PR PR must be reviewed before merging label Apr 29, 2026
Copy link
Copy Markdown
Contributor

@henningmu henningmu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No objections, this is privacy-friendly tracking. Please double-check that backend actually forwards the relevant headers into Datadog (might be selective)

Comment thread src/lib/usage-tracking.ts Outdated
Comment thread src/commands/view.ts
@scottlovegrove scottlovegrove force-pushed the ernesto/cli-usage-tracking branch from 8dd1e22 to 81b1892 Compare April 30, 2026 09:12
Comment thread src/lib/usage-tracking.ts Outdated
@gnapse
Copy link
Copy Markdown
Collaborator Author

gnapse commented Apr 30, 2026

double-check that backend actually forwards the relevant headers into Datadog

Mostly yes, but not completely. User-Agent, doist-platform, doist-version, doist-os, X-TD-Request-Id, and X-TD-Session-Id already make it into Datadog logs via the existing backend log context. X-Todoist-CLI-Command does not currently get promoted into Datadog, so command-level attribution still needs backend work if we want that visible there. I knew this beforehand. I added that tracking value just in case we do the change in the future.

@gnapse gnapse merged commit 5c692f8 into main Apr 30, 2026
5 checks passed
@gnapse gnapse deleted the ernesto/cli-usage-tracking branch April 30, 2026 12:53
doist-release-bot Bot added a commit that referenced this pull request Apr 30, 2026
## [1.60.0](v1.59.0...v1.60.0) (2026-04-30)

### Features

* track cli usage in request headers ([#302](#302)) ([5c692f8](5c692f8))
@doist-release-bot
Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 1.60.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🙋 Ask PR PR must be reviewed before merging released

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants