Skip to content
Open
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
e672906
Add endless-scrolling TUI table for interactive list commands
simonfaltum Mar 12, 2026
78f3489
Add curated TUI table overrides for 15 list commands
simonfaltum Mar 12, 2026
2183ede
Add TUI table overrides for 5 high-traffic list commands
simonfaltum Mar 13, 2026
5217d6c
Format secret timestamps as human-readable dates
simonfaltum Mar 13, 2026
d7a7104
Fix stale fetch race condition and empty-table search restore
simonfaltum Mar 13, 2026
17b9e11
Escape pipeline search wildcards and add override tests
simonfaltum Mar 13, 2026
8b589d1
Merge branch 'main' into simonfaltum/list-tui-paginated
simonfaltum Mar 13, 2026
56ebde4
Preserve user --filter when TUI search is used for pipelines list
simonfaltum Mar 13, 2026
8d942f8
Replace unused listReq parameters with _ in list override functions
simonfaltum Mar 13, 2026
b7ca3d8
Add debounced live search to paginated TUI table
simonfaltum Mar 13, 2026
c3ff734
Fix operator precedence bug when combining user filter with name search
simonfaltum Mar 13, 2026
c35aefb
Propagate iterator fetch errors from TUI model to command exit code
simonfaltum Mar 13, 2026
aa4cdb0
Fix search/fetch race conditions, esc restore, and error propagation
simonfaltum Mar 13, 2026
dbd2241
Fix lint: use assert.NoError per testifylint rule
simonfaltum Mar 13, 2026
e76dee4
Merge branch 'simonfaltum/list-tui-paginated' into simonfaltum/list-t…
simonfaltum Mar 13, 2026
9360cf6
Merge branch 'simonfaltum/list-tui-overrides' into simonfaltum/list-t…
simonfaltum Mar 13, 2026
c1cdd19
Remove duplicate Err() method on paginatedModel
simonfaltum Mar 14, 2026
2ddfdf0
Sanitize pipeline event messages and increase MaxWidth
simonfaltum Mar 16, 2026
c0475fc
Clean up PaginatedModel alias, duplicate test, and verbose comment
simonfaltum Mar 16, 2026
5158ea6
Merge branch 'main' into simonfaltum/list-tui-overrides-2
simonfaltum Mar 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmd/root/io.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ func (f *outputFlag) initializeIO(ctx context.Context, cmd *cobra.Command) (cont

cmdIO := cmdio.NewIO(ctx, f.output, cmd.InOrStdin(), cmd.OutOrStdout(), cmd.ErrOrStderr(), headerTemplate, template)
ctx = cmdio.InContext(ctx, cmdIO)
ctx = cmdio.WithCommand(ctx, cmd)
cmd.SetContext(ctx)
return ctx, nil
}
32 changes: 32 additions & 0 deletions cmd/workspace/alerts/overrides.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package alerts

import (
"github.com/databricks/cli/libs/cmdio"
"github.com/databricks/cli/libs/tableview"
"github.com/databricks/databricks-sdk-go/service/sql"
"github.com/spf13/cobra"
)

func listOverride(listCmd *cobra.Command, _ *sql.ListAlertsRequest) {
listCmd.Annotations["template"] = cmdio.Heredoc(`
{{range .}}{{green "%s" .Id}} {{.DisplayName}} {{.State}}
{{end}}`)

columns := []tableview.ColumnDef{
{Header: "ID", Extract: func(v any) string {
return v.(sql.ListAlertsResponseAlert).Id
}},
{Header: "Name", Extract: func(v any) string {
return v.(sql.ListAlertsResponseAlert).DisplayName
}},
{Header: "State", Extract: func(v any) string {
return string(v.(sql.ListAlertsResponseAlert).State)
}},
}

tableview.RegisterConfig(listCmd, tableview.TableConfig{Columns: columns})
}

func init() {
listOverrides = append(listOverrides, listOverride)
}
28 changes: 26 additions & 2 deletions cmd/workspace/apps/overrides.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,43 @@ import (

appsCli "github.com/databricks/cli/cmd/apps"
"github.com/databricks/cli/libs/cmdio"
"github.com/databricks/cli/libs/tableview"
"github.com/databricks/databricks-sdk-go/service/apps"
"github.com/spf13/cobra"
)

func listOverride(listCmd *cobra.Command, listReq *apps.ListAppsRequest) {
func listOverride(listCmd *cobra.Command, _ *apps.ListAppsRequest) {
listCmd.Annotations["headerTemplate"] = cmdio.Heredoc(`
{{header "Name"}} {{header "Url"}} {{header "ComputeStatus"}} {{header "DeploymentStatus"}}`)
listCmd.Annotations["template"] = cmdio.Heredoc(`
{{range .}}{{.Name | green}} {{.Url}} {{if .ComputeStatus}}{{if eq .ComputeStatus.State "ACTIVE"}}{{green "%s" .ComputeStatus.State }}{{else}}{{blue "%s" .ComputeStatus.State}}{{end}}{{end}} {{if .ActiveDeployment}}{{if eq .ActiveDeployment.Status.State "SUCCEEDED"}}{{green "%s" .ActiveDeployment.Status.State }}{{else}}{{blue "%s" .ActiveDeployment.Status.State}}{{end}}{{end}}
{{end}}`)

columns := []tableview.ColumnDef{
{Header: "Name", Extract: func(v any) string {
return v.(apps.App).Name
}},
{Header: "URL", Extract: func(v any) string {
return v.(apps.App).Url
}},
{Header: "Compute Status", Extract: func(v any) string {
if v.(apps.App).ComputeStatus != nil {
return string(v.(apps.App).ComputeStatus.State)
}
return ""
}},
{Header: "Deploy Status", Extract: func(v any) string {
if v.(apps.App).ActiveDeployment != nil && v.(apps.App).ActiveDeployment.Status != nil {
return string(v.(apps.App).ActiveDeployment.Status.State)
}
return ""
}},
}

tableview.RegisterConfig(listCmd, tableview.TableConfig{Columns: columns})
}

func listDeploymentsOverride(listDeploymentsCmd *cobra.Command, listDeploymentsReq *apps.ListAppDeploymentsRequest) {
func listDeploymentsOverride(listDeploymentsCmd *cobra.Command, _ *apps.ListAppDeploymentsRequest) {
listDeploymentsCmd.Annotations["headerTemplate"] = cmdio.Heredoc(`
{{header "DeploymentId"}} {{header "State"}} {{header "CreatedAt"}}`)
listDeploymentsCmd.Annotations["template"] = cmdio.Heredoc(`
Expand Down
68 changes: 68 additions & 0 deletions cmd/workspace/apps/overrides_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package apps

import (
"testing"

"github.com/databricks/cli/libs/tableview"
sdkapps "github.com/databricks/databricks-sdk-go/service/apps"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestListTableConfig(t *testing.T) {
cmd := newList()

cfg := tableview.GetConfig(cmd)
require.NotNil(t, cfg)
require.Len(t, cfg.Columns, 4)

tests := []struct {
name string
app sdkapps.App
wantName string
wantURL string
wantCompute string
wantDeploy string
}{
{
name: "with nested fields",
app: sdkapps.App{
Name: "test-app",
Url: "https://example.com",
ComputeStatus: &sdkapps.ComputeStatus{
State: sdkapps.ComputeStateActive,
},
ActiveDeployment: &sdkapps.AppDeployment{
Status: &sdkapps.AppDeploymentStatus{
State: sdkapps.AppDeploymentStateSucceeded,
},
},
},
wantName: "test-app",
wantURL: "https://example.com",
wantCompute: "ACTIVE",
wantDeploy: "SUCCEEDED",
},
{
name: "nil nested fields",
app: sdkapps.App{
Name: "test-app",
Url: "https://example.com",
ActiveDeployment: &sdkapps.AppDeployment{},
},
wantName: "test-app",
wantURL: "https://example.com",
wantCompute: "",
wantDeploy: "",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equal(t, tt.wantName, cfg.Columns[0].Extract(tt.app))
assert.Equal(t, tt.wantURL, cfg.Columns[1].Extract(tt.app))
assert.Equal(t, tt.wantCompute, cfg.Columns[2].Extract(tt.app))
assert.Equal(t, tt.wantDeploy, cfg.Columns[3].Extract(tt.app))
})
}
}
17 changes: 16 additions & 1 deletion cmd/workspace/catalogs/overrides.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,31 @@ package catalogs

import (
"github.com/databricks/cli/libs/cmdio"
"github.com/databricks/cli/libs/tableview"
"github.com/databricks/databricks-sdk-go/service/catalog"
"github.com/spf13/cobra"
)

func listOverride(listCmd *cobra.Command, listReq *catalog.ListCatalogsRequest) {
func listOverride(listCmd *cobra.Command, _ *catalog.ListCatalogsRequest) {
listCmd.Annotations["headerTemplate"] = cmdio.Heredoc(`
{{header "Name"}} {{header "Type"}} {{header "Comment"}}`)
listCmd.Annotations["template"] = cmdio.Heredoc(`
{{range .}}{{.Name|green}} {{blue "%s" .CatalogType}} {{.Comment}}
{{end}}`)

columns := []tableview.ColumnDef{
{Header: "Name", Extract: func(v any) string {
return v.(catalog.CatalogInfo).Name
}},
{Header: "Type", Extract: func(v any) string {
return string(v.(catalog.CatalogInfo).CatalogType)
}},
{Header: "Comment", MaxWidth: 40, Extract: func(v any) string {
return v.(catalog.CatalogInfo).Comment
}},
}

tableview.RegisterConfig(listCmd, tableview.TableConfig{Columns: columns})
}

func init() {
Expand Down
18 changes: 18 additions & 0 deletions cmd/workspace/cluster-policies/overrides.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cluster_policies

import (
"github.com/databricks/cli/libs/cmdio"
"github.com/databricks/cli/libs/tableview"
"github.com/databricks/databricks-sdk-go/service/compute"
"github.com/spf13/cobra"
)
Expand All @@ -10,6 +11,23 @@ func listOverride(listCmd *cobra.Command, _ *compute.ListClusterPoliciesRequest)
listCmd.Annotations["template"] = cmdio.Heredoc(`
{{range .}}{{.PolicyId | green}} {{.Name}}
{{end}}`)

columns := []tableview.ColumnDef{
{Header: "Policy ID", Extract: func(v any) string {
return v.(compute.Policy).PolicyId
}},
{Header: "Name", Extract: func(v any) string {
return v.(compute.Policy).Name
}},
{Header: "Default", Extract: func(v any) string {
if v.(compute.Policy).IsDefault {
return "yes"
}
return ""
}},
}

tableview.RegisterConfig(listCmd, tableview.TableConfig{Columns: columns})
}

func getOverride(getCmd *cobra.Command, _ *compute.GetClusterPolicyRequest) {
Expand Down
15 changes: 15 additions & 0 deletions cmd/workspace/clusters/overrides.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"strings"

"github.com/databricks/cli/libs/cmdio"
"github.com/databricks/cli/libs/tableview"
"github.com/databricks/databricks-sdk-go/service/compute"
"github.com/spf13/cobra"
)
Expand All @@ -17,6 +18,20 @@ func listOverride(listCmd *cobra.Command, listReq *compute.ListClustersRequest)
{{range .}}{{.ClusterId | green}} {{.ClusterName | cyan}} {{if eq .State "RUNNING"}}{{green "%s" .State}}{{else if eq .State "TERMINATED"}}{{red "%s" .State}}{{else}}{{blue "%s" .State}}{{end}}
{{end}}`)

columns := []tableview.ColumnDef{
{Header: "Cluster ID", Extract: func(v any) string {
return v.(compute.ClusterDetails).ClusterId
}},
{Header: "Name", Extract: func(v any) string {
return v.(compute.ClusterDetails).ClusterName
}},
{Header: "State", Extract: func(v any) string {
return string(v.(compute.ClusterDetails).State)
}},
}

tableview.RegisterConfig(listCmd, tableview.TableConfig{Columns: columns})

listReq.FilterBy = &compute.ListClustersFilterBy{}
listCmd.Flags().BoolVar(&listReq.FilterBy.IsPinned, "is-pinned", false, "Filter clusters by pinned status")
listCmd.Flags().StringVar(&listReq.FilterBy.PolicyId, "policy-id", "", "Filter clusters by policy id")
Expand Down
17 changes: 16 additions & 1 deletion cmd/workspace/external-locations/overrides.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,31 @@ package external_locations

import (
"github.com/databricks/cli/libs/cmdio"
"github.com/databricks/cli/libs/tableview"
"github.com/databricks/databricks-sdk-go/service/catalog"
"github.com/spf13/cobra"
)

func listOverride(listCmd *cobra.Command, listReq *catalog.ListExternalLocationsRequest) {
func listOverride(listCmd *cobra.Command, _ *catalog.ListExternalLocationsRequest) {
listCmd.Annotations["headerTemplate"] = cmdio.Heredoc(`
{{header "Name"}} {{header "Credential"}} {{header "URL"}}`)
listCmd.Annotations["template"] = cmdio.Heredoc(`
{{range .}}{{.Name|green}} {{.CredentialName|cyan}} {{.Url}}
{{end}}`)

columns := []tableview.ColumnDef{
{Header: "Name", Extract: func(v any) string {
return v.(catalog.ExternalLocationInfo).Name
}},
{Header: "Credential", Extract: func(v any) string {
return v.(catalog.ExternalLocationInfo).CredentialName
}},
{Header: "URL", Extract: func(v any) string {
return v.(catalog.ExternalLocationInfo).Url
}},
}

tableview.RegisterConfig(listCmd, tableview.TableConfig{Columns: columns})
}

func init() {
Expand Down
19 changes: 19 additions & 0 deletions cmd/workspace/instance-pools/overrides.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,32 @@ package instance_pools

import (
"github.com/databricks/cli/libs/cmdio"
"github.com/databricks/cli/libs/tableview"
"github.com/databricks/databricks-sdk-go/service/compute"
"github.com/spf13/cobra"
)

func listOverride(listCmd *cobra.Command) {
listCmd.Annotations["template"] = cmdio.Heredoc(`
{{range .}}{{.InstancePoolId|green}} {{.InstancePoolName}} {{.NodeTypeId}} {{.State}}
{{end}}`)

columns := []tableview.ColumnDef{
{Header: "Pool ID", Extract: func(v any) string {
return v.(compute.InstancePoolAndStats).InstancePoolId
}},
{Header: "Name", Extract: func(v any) string {
return v.(compute.InstancePoolAndStats).InstancePoolName
}},
{Header: "Node Type", Extract: func(v any) string {
return v.(compute.InstancePoolAndStats).NodeTypeId
}},
{Header: "State", Extract: func(v any) string {
return string(v.(compute.InstancePoolAndStats).State)
}},
}

tableview.RegisterConfig(listCmd, tableview.TableConfig{Columns: columns})
}

func init() {
Expand Down
32 changes: 31 additions & 1 deletion cmd/workspace/jobs/overrides.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package jobs

import (
"context"
"strconv"

"github.com/databricks/cli/libs/cmdctx"
"github.com/databricks/cli/libs/cmdio"
"github.com/databricks/cli/libs/tableview"
"github.com/databricks/databricks-sdk-go/service/jobs"
"github.com/spf13/cobra"
)
Expand All @@ -10,9 +15,34 @@ func listOverride(listCmd *cobra.Command, listReq *jobs.ListJobsRequest) {
listCmd.Annotations["template"] = cmdio.Heredoc(`
{{range .}}{{green "%d" .JobId}} {{.Settings.Name}}
{{end}}`)

columns := []tableview.ColumnDef{
{Header: "Job ID", Extract: func(v any) string {
return strconv.FormatInt(v.(jobs.BaseJob).JobId, 10)
}},
{Header: "Name", Extract: func(v any) string {
if v.(jobs.BaseJob).Settings != nil {
return v.(jobs.BaseJob).Settings.Name
}
return ""
}},
}

tableview.RegisterConfig(listCmd, tableview.TableConfig{
Columns: columns,
Search: &tableview.SearchConfig{
Placeholder: "Search by exact name...",
NewIterator: func(ctx context.Context, query string) tableview.RowIterator {
req := *listReq
req.Name = query
w := cmdctx.WorkspaceClient(ctx)
return tableview.WrapIterator(w.Jobs.List(ctx, req), columns)
},
},
})
}

func listRunsOverride(listRunsCmd *cobra.Command, listRunsReq *jobs.ListRunsRequest) {
func listRunsOverride(listRunsCmd *cobra.Command, _ *jobs.ListRunsRequest) {
listRunsCmd.Annotations["headerTemplate"] = cmdio.Heredoc(`
{{header "Job ID"}} {{header "Run ID"}} {{header "Result State"}} URL`)
listRunsCmd.Annotations["template"] = cmdio.Heredoc(`
Expand Down
Loading