Skip to content

Commit c6e0c03

Browse files
simonfaltumclaude
andauthored
Add interactive mode to user agent (#4497)
## Changes This PR adds terminal capability detection to the user agent string to track what proportion of CLI invocations support interactive features. Having a better understanding of how the CLI is being used, and which commands are called in which context, can help guide us to improve the UX without over-investing in commands that are never used in a certain context The user agent will include one of three values: - `interactive/full`: Both interactive output (spinners, colors) and user prompts are supported. Requires stderr to be a TTY, color enabled, stdin to be a TTY, and not running in Git Bash. - `interactive/output`: Interactive output is supported but prompts are not. This occurs when stdin is not a TTY (e.g., input piped) or when running in Git Bash (which has broken readline/ANSI support). - `interactive/none`: Non-interactive environment where neither spinners nor prompts work. This includes CI/CD pipelines, cron jobs, and cases where stderr is redirected. ## Implementation - Add `InteractiveMode()` method to `Capabilities` struct in `libs/cmdio` - Add `GetInteractiveMode(ctx)` public function using `fromContext` (consistent with other accessors) - Create `cmd/root/user_agent_interactive_mode.go` to integrate with user agent - Add `withInteractiveModeInUserAgent()` call in `root.go` - Comprehensive test coverage for all three interactive modes ## Why User Agent Instead of Telemetry As discussed with @pietern, this should be added to the user agent rather than telemetry because: - **Broader coverage**: User agent data is captured on every authenticated API call across all commands, while telemetry only fires on `bundle deploy` - **No latency impact**: Telemetry is sent synchronously which adds latency; user agent has no performance impact ## Use Case This telemetry helps inform decisions about when the CLI can prompt users for missing information versus requiring explicit flags. By measuring the proportion of invocations in each mode, we can understand how often interactive prompts would actually be shown to users. This will also help track the impact of changes that affect interactive behavior. ## Tests Added comprehensive unit tests covering: - All three interactive modes (full, output, none) - Various TTY configurations (stdin, stderr combinations) - Git Bash detection - User agent integration --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 0987065 commit c6e0c03

34 files changed

Lines changed: 348 additions & 179 deletions

acceptance/auth/credentials/basic/out.requests.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"Basic [ENCODED_AUTH]"
55
],
66
"User-Agent": [
7-
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/current-user_me cmd-exec-id/[UUID] auth/basic"
7+
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/current-user_me cmd-exec-id/[UUID] interactive/none auth/basic"
88
]
99
},
1010
"method": "GET",

acceptance/auth/credentials/oauth/out.requests.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
"Bearer oauth-token"
2727
],
2828
"User-Agent": [
29-
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/current-user_me cmd-exec-id/[UUID] auth/oauth-m2m"
29+
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/current-user_me cmd-exec-id/[UUID] interactive/none auth/oauth-m2m"
3030
]
3131
},
3232
"method": "GET",

acceptance/auth/credentials/pat/out.requests.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"Bearer dapi1234"
55
],
66
"User-Agent": [
7-
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/current-user_me cmd-exec-id/[UUID] auth/pat"
7+
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/current-user_me cmd-exec-id/[UUID] interactive/none auth/pat"
88
]
99
},
1010
"method": "GET",

acceptance/auth/credentials/unified-host/out.requests.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"Bearer dapi-unified-token"
55
],
66
"User-Agent": [
7-
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/current-user_me cmd-exec-id/[UUID] auth/pat"
7+
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/current-user_me cmd-exec-id/[UUID] interactive/none auth/pat"
88
],
99
"X-Databricks-Org-Id": [
1010
"[NUMID]"

acceptance/bundle/migrate/basic/output.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ Plan: 0 to add, 0 to change, 0 to delete, 3 unchanged
5858
{
5959
"headers": {
6060
"User-Agent": [
61-
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/bundle_plan cmd-exec-id/[UUID] engine/direct auth/pat"
61+
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/bundle_plan cmd-exec-id/[UUID] interactive/none engine/direct auth/pat"
6262
]
6363
},
6464
"method": "GET",
@@ -70,7 +70,7 @@ Plan: 0 to add, 0 to change, 0 to delete, 3 unchanged
7070
{
7171
"headers": {
7272
"User-Agent": [
73-
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/bundle_plan cmd-exec-id/[UUID] engine/direct auth/pat"
73+
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/bundle_plan cmd-exec-id/[UUID] interactive/none engine/direct auth/pat"
7474
]
7575
},
7676
"method": "GET",
@@ -87,8 +87,8 @@ Updating deployment state...
8787
Deployment complete!
8888

8989
>>> print_requests.py --get //jobs/get
90-
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/bundle_deploy cmd-exec-id/[UUID] engine/direct auth/pat"
91-
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/bundle_deploy cmd-exec-id/[UUID] engine/direct auth/pat"
90+
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/bundle_deploy cmd-exec-id/[UUID] interactive/none engine/direct auth/pat"
91+
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/bundle_deploy cmd-exec-id/[UUID] interactive/none engine/direct auth/pat"
9292

9393
=== Should show that it's already migrated
9494
>>> musterr [CLI] bundle deployment migrate

acceptance/bundle/migrate/permissions/output.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ Plan: 0 to add, 0 to change, 0 to delete, 4 unchanged
4343
{
4444
"headers": {
4545
"User-Agent": [
46-
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/bundle_plan cmd-exec-id/[UUID] engine/direct auth/pat"
46+
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/bundle_plan cmd-exec-id/[UUID] interactive/none engine/direct auth/pat"
4747
]
4848
},
4949
"method": "GET",
@@ -55,7 +55,7 @@ Plan: 0 to add, 0 to change, 0 to delete, 4 unchanged
5555
{
5656
"headers": {
5757
"User-Agent": [
58-
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/bundle_plan cmd-exec-id/[UUID] engine/direct auth/pat"
58+
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/bundle_plan cmd-exec-id/[UUID] interactive/none engine/direct auth/pat"
5959
]
6060
},
6161
"method": "GET",
@@ -72,8 +72,8 @@ Updating deployment state...
7272
Deployment complete!
7373

7474
>>> print_requests.py --get //jobs/get
75-
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/bundle_deploy cmd-exec-id/[UUID] engine/direct auth/pat"
76-
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/bundle_deploy cmd-exec-id/[UUID] engine/direct auth/pat"
75+
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/bundle_deploy cmd-exec-id/[UUID] interactive/none engine/direct auth/pat"
76+
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/bundle_deploy cmd-exec-id/[UUID] interactive/none engine/direct auth/pat"
7777

7878
=== Should show that it's already migrated
7979
>>> musterr [CLI] bundle deployment migrate

acceptance/bundle/state/state_present/output.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ Updating deployment state...
8282
Deployment complete!
8383

8484
>>> print_requests.py //api/2.1/unity-catalog/schemas
85-
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/bundle_deploy cmd-exec-id/[UUID] engine/direct auth/pat"
85+
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/bundle_deploy cmd-exec-id/[UUID] interactive/none engine/direct auth/pat"
8686

8787
>>> print_state.py
8888
3
@@ -104,7 +104,7 @@ Updating deployment state...
104104
Deployment complete!
105105

106106
>>> print_requests.py --get //api/2.1/unity-catalog/schemas
107-
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/bundle_deploy cmd-exec-id/[UUID] engine/direct auth/pat"
107+
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/bundle_deploy cmd-exec-id/[UUID] interactive/none engine/direct auth/pat"
108108

109109
>>> print_state.py
110110
3

acceptance/bundle/templates/telemetry/custom-template/out.requests.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"headers": {
33
"User-Agent": [
4-
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/bundle_init cmd-exec-id/[CMD-EXEC-ID] auth/pat"
4+
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/bundle_init cmd-exec-id/[CMD-EXEC-ID] interactive/none auth/pat"
55
]
66
},
77
"method": "POST",

acceptance/bundle/templates/telemetry/dbt-sql/out.requests.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"headers": {
33
"User-Agent": [
4-
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/bundle_init cmd-exec-id/[CMD-EXEC-ID] auth/pat"
4+
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/bundle_init cmd-exec-id/[CMD-EXEC-ID] interactive/none auth/pat"
55
]
66
},
77
"method": "GET",
@@ -10,7 +10,7 @@
1010
{
1111
"headers": {
1212
"User-Agent": [
13-
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/bundle_init cmd-exec-id/[CMD-EXEC-ID] auth/pat"
13+
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/bundle_init cmd-exec-id/[CMD-EXEC-ID] interactive/none auth/pat"
1414
]
1515
},
1616
"method": "GET",
@@ -19,7 +19,7 @@
1919
{
2020
"headers": {
2121
"User-Agent": [
22-
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/bundle_init cmd-exec-id/[CMD-EXEC-ID] auth/pat"
22+
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/bundle_init cmd-exec-id/[CMD-EXEC-ID] interactive/none auth/pat"
2323
]
2424
},
2525
"method": "POST",

acceptance/bundle/templates/telemetry/default-python/out.requests.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"headers": {
33
"User-Agent": [
4-
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/bundle_init cmd-exec-id/[CMD-EXEC-ID] auth/pat"
4+
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/bundle_init cmd-exec-id/[CMD-EXEC-ID] interactive/none auth/pat"
55
]
66
},
77
"method": "GET",
@@ -10,7 +10,7 @@
1010
{
1111
"headers": {
1212
"User-Agent": [
13-
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/bundle_init cmd-exec-id/[CMD-EXEC-ID] auth/pat"
13+
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/bundle_init cmd-exec-id/[CMD-EXEC-ID] interactive/none auth/pat"
1414
]
1515
},
1616
"method": "GET",
@@ -19,7 +19,7 @@
1919
{
2020
"headers": {
2121
"User-Agent": [
22-
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/bundle_init cmd-exec-id/[CMD-EXEC-ID] auth/pat"
22+
"cli/[DEV_VERSION] databricks-sdk-go/[SDK_VERSION] go/[GO_VERSION] os/[OS] cmd/bundle_init cmd-exec-id/[CMD-EXEC-ID] interactive/none auth/pat"
2323
]
2424
},
2525
"method": "POST",

0 commit comments

Comments
 (0)