Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .agent/skills/pr-checklist/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Before submitting a PR, run these commands to match what CI checks. CI uses the
# 5. If you changed files in python/:
./task pydabs-codegen pydabs-test pydabs-lint pydabs-docs

# 6. If you changed experimental/aitools or experimental/ssh:
# 6. If you changed aitools or experimental/ssh:
./task test-exp-aitools # only if aitools code changed
./task test-exp-ssh # only if ssh code changed
```
Expand Down
4 changes: 2 additions & 2 deletions .github/OWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,5 @@
# Internal
/internal/ team:platform

# Experimental
/experimental/aitools/ team:eng-apps-devex @lennartkats-db
# AI tools
/aitools/ team:eng-apps-devex @lennartkats-db
2 changes: 2 additions & 0 deletions NEXT_CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

### CLI

* Promote the aitools skills-management surface (`install`, `update`, `uninstall`, `list`, `version`, `skills`) from `databricks experimental aitools` to top-level `databricks aitools`. The old `experimental aitools` path remains as a hidden, deprecated alias for these commands and prints a deprecation warning. The `tools` subtree (`query`, `discover-schema`, `get-default-warehouse`, `statement …`) stays under `databricks experimental aitools tools` for now and does not warn.

### Bundles

### Dependency updates
6 changes: 3 additions & 3 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -606,17 +606,17 @@ tasks:
# generic `test` target (the catch-all) instead.

test-exp-aitools:
desc: Run experimental aitools unit and acceptance tests
desc: Run aitools unit and acceptance tests
sources:
- experimental/aitools/**
- aitools/**
- acceptance/apps/**
- "{{.EMBED_SOURCES}}"
cmds:
- |
{{.GO_TOOL}} gotestsum \
--format ${GOTESTSUM_FORMAT:-pkgname-and-test-fails} \
--no-summary=skipped \
--packages ./experimental/aitools/... \
--packages ./aitools/... \
-- -timeout=${LOCAL_TIMEOUT:-30m}
- |
{{.GO_TOOL}} gotestsum \
Expand Down
1 change: 1 addition & 0 deletions acceptance/help/output.txt
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ Developer Tools

Additional Commands:
account Databricks Account Commands
aitools Databricks AI Tools for coding agents
api Perform Databricks API call
auth Authentication related commands
cache Local cache related commands
Expand Down
72 changes: 72 additions & 0 deletions aitools/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# AI Tools

`databricks aitools` exposes commands for coding-agent workflows.

Two surfaces with different stability tiers:

- **`databricks aitools …`** (top-level) — skills management. Stable.
- **`databricks experimental aitools tools …`** — workspace helpers used by
AI agents. Still experimental; commands and output may change.

## Skills management (stable)

Top-level commands for installing and managing Databricks skills in detected
coding agents:

- `databricks aitools install [skill-name]`
- `databricks aitools update`
- `databricks aitools uninstall`
- `databricks aitools list`
- `databricks aitools version`

The hidden `databricks aitools skills {list,install}` subgroup exists as a
backward-compatibility alias for the flat top-level commands.

## Tools (experimental)

These commands live under `databricks experimental aitools tools` and are
optimized for AI coding agents like Claude Code and Cursor. Names and output
shapes can change.

- `databricks experimental aitools tools query`
- `databricks experimental aitools tools discover-schema`
- `databricks experimental aitools tools get-default-warehouse`
- `databricks experimental aitools tools statement submit`
- `databricks experimental aitools tools statement get`
- `databricks experimental aitools tools statement status`
- `databricks experimental aitools tools statement cancel`

### `tools query`

Accepts a single SQL or multiple SQLs in one invocation. Pass several
positional arguments and/or repeat `--file` to run them in parallel against the
warehouse. Multi-query output is always JSON; control parallelism with
`--concurrency` (default 8).

```bash
databricks experimental aitools tools query \
--warehouse <wh> --output json \
"SELECT count(*) FROM samples.nyctaxi.trips" \
"SELECT min(tpep_pickup_datetime), max(tpep_pickup_datetime) FROM samples.nyctaxi.trips" \
"SELECT vendor_id, count(*) FROM samples.nyctaxi.trips GROUP BY 1"
```

### `tools statement`

Low-level lifecycle for asynchronous statements. `submit` returns a
`statement_id` immediately, `get` polls until terminal and emits rows, `status`
peeks without blocking, and `cancel` requests termination. Ctrl+C on `get`
stops polling but does NOT cancel the server-side statement; use `cancel` for
that.

```bash
SID=$(databricks experimental aitools tools statement submit \
--warehouse <wh> "SELECT pg_sleep(5)" | jq -r '.statement_id')
databricks experimental aitools tools statement status "$SID"
databricks experimental aitools tools statement get "$SID"
```

## Removed behavior

- there is no MCP server under `aitools`
- the old `deploy` and `validate` flows were removed
38 changes: 38 additions & 0 deletions aitools/cmd/aitools.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package aitools

import (
"github.com/spf13/cobra"
)

// NewAitoolsCmd builds the skills-management surface — install, update,
// uninstall, list, version, and the (hidden) skills alias group. The `tools`
// subtree is intentionally not attached here: it remains under
// `databricks experimental aitools tools` until it graduates separately. See
// NewToolsCmd.
func NewAitoolsCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "aitools",
Short: "Databricks AI Tools for coding agents",
Long: `Manage Databricks AI Tools.

Provides commands to:
- Install the AI tools in coding agents (install)
- Manage skills (skills)`,
}

cmd.AddCommand(newInstallCmd())
cmd.AddCommand(newUpdateCmd())
cmd.AddCommand(newUninstallCmd())
cmd.AddCommand(newListCmd())
cmd.AddCommand(newVersionCmd())
cmd.AddCommand(newSkillsCmd())

return cmd
}

// NewToolsCmd exposes the experimental tools subtree (query, discover-schema,
// get-default-warehouse, statement) so wrappers can attach it under their own
// parent. Currently only `databricks experimental aitools tools`.
func NewToolsCmd() *cobra.Command {
return newToolsCmd()
}
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ import (
"sync"
"syscall"

"github.com/databricks/cli/aitools/lib/middlewares"
"github.com/databricks/cli/aitools/lib/session"
"github.com/databricks/cli/cmd/root"
"github.com/databricks/cli/experimental/aitools/lib/middlewares"
"github.com/databricks/cli/experimental/aitools/lib/session"
"github.com/databricks/cli/libs/cmdctx"
"github.com/databricks/cli/libs/cmdio"
"github.com/databricks/cli/libs/log"
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package aitools

import (
"github.com/databricks/cli/aitools/lib/middlewares"
"github.com/databricks/cli/aitools/lib/session"
"github.com/databricks/cli/cmd/root"
"github.com/databricks/cli/experimental/aitools/lib/middlewares"
"github.com/databricks/cli/experimental/aitools/lib/session"
"github.com/databricks/cli/libs/cmdctx"
"github.com/databricks/cli/libs/cmdio"
"github.com/databricks/databricks-sdk-go/service/sql"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import (
"fmt"
"strings"

"github.com/databricks/cli/experimental/aitools/lib/agents"
"github.com/databricks/cli/experimental/aitools/lib/installer"
"github.com/databricks/cli/aitools/lib/agents"
"github.com/databricks/cli/aitools/lib/installer"
"github.com/databricks/cli/libs/cmdio"
"github.com/fatih/color"
"github.com/spf13/cobra"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (
"path/filepath"
"testing"

"github.com/databricks/cli/experimental/aitools/lib/agents"
"github.com/databricks/cli/experimental/aitools/lib/installer"
"github.com/databricks/cli/aitools/lib/agents"
"github.com/databricks/cli/aitools/lib/installer"
"github.com/databricks/cli/libs/cmdio"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand Down
2 changes: 1 addition & 1 deletion experimental/aitools/cmd/list.go → aitools/cmd/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"strings"
"text/tabwriter"

"github.com/databricks/cli/experimental/aitools/lib/installer"
"github.com/databricks/cli/aitools/lib/installer"
"github.com/databricks/cli/libs/cmdio"
"github.com/databricks/cli/libs/log"
"github.com/spf13/cobra"
Expand Down
File renamed without changes.
4 changes: 2 additions & 2 deletions experimental/aitools/cmd/query.go → aitools/cmd/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ import (
"syscall"
"time"

"github.com/databricks/cli/aitools/lib/middlewares"
"github.com/databricks/cli/aitools/lib/session"
"github.com/databricks/cli/cmd/root"
"github.com/databricks/cli/experimental/aitools/lib/middlewares"
"github.com/databricks/cli/experimental/aitools/lib/session"
"github.com/databricks/cli/libs/cmdctx"
"github.com/databricks/cli/libs/cmdio"
"github.com/databricks/cli/libs/env"
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
6 changes: 3 additions & 3 deletions experimental/aitools/cmd/scope.go → aitools/cmd/scope.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"path/filepath"

"github.com/charmbracelet/huh"
"github.com/databricks/cli/experimental/aitools/lib/installer"
"github.com/databricks/cli/aitools/lib/installer"
"github.com/databricks/cli/libs/cmdio"
"github.com/databricks/cli/libs/env"
)
Expand Down Expand Up @@ -230,10 +230,10 @@ func scopeNotInstalledError(scope, verb, projectDir string, hasGlobal, hasProjec
"no project-scoped skills found in the current directory.\n\n"+
"Project-scoped skills are detected based on your working directory.\n"+
"Make sure you are in the project root where you originally ran\n"+
"'databricks experimental aitools install --project'.\n\n"+
"'databricks aitools install --project'.\n\n"+
"Expected location: %s/", expectedPath)
} else {
msg = "no globally-scoped skills installed. Run 'databricks experimental aitools install --global' to install"
msg = "no globally-scoped skills installed. Run 'databricks aitools install --global' to install"
}

hint := crossScopeHint(scope, verb, hasGlobal, hasProject)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"path/filepath"
"testing"

"github.com/databricks/cli/experimental/aitools/lib/installer"
"github.com/databricks/cli/aitools/lib/installer"
"github.com/databricks/cli/libs/cmdio"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand Down
4 changes: 2 additions & 2 deletions experimental/aitools/cmd/skills.go → aitools/cmd/skills.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import (
"errors"

"github.com/charmbracelet/huh"
"github.com/databricks/cli/experimental/aitools/lib/agents"
"github.com/databricks/cli/experimental/aitools/lib/installer"
"github.com/databricks/cli/aitools/lib/agents"
"github.com/databricks/cli/aitools/lib/installer"
"github.com/spf13/cobra"
)

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package aitools

import (
"github.com/databricks/cli/experimental/aitools/lib/installer"
"github.com/databricks/cli/aitools/lib/installer"
"github.com/spf13/cobra"
)

Expand Down
4 changes: 2 additions & 2 deletions experimental/aitools/cmd/update.go → aitools/cmd/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package aitools
import (
"fmt"

"github.com/databricks/cli/experimental/aitools/lib/agents"
"github.com/databricks/cli/experimental/aitools/lib/installer"
"github.com/databricks/cli/aitools/lib/agents"
"github.com/databricks/cli/aitools/lib/installer"
"github.com/databricks/cli/libs/cmdio"
"github.com/spf13/cobra"
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"fmt"
"strings"

"github.com/databricks/cli/experimental/aitools/lib/installer"
"github.com/databricks/cli/aitools/lib/installer"
"github.com/databricks/cli/libs/cmdio"
"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -40,7 +40,7 @@ func newVersionCmd() *cobra.Command {
if globalState == nil && projectState == nil {
cmdio.LogString(ctx, "No Databricks AI Tools components installed.")
cmdio.LogString(ctx, "")
cmdio.LogString(ctx, "Run 'databricks experimental aitools install' to get started.")
cmdio.LogString(ctx, "Run 'databricks aitools install' to get started.")
return nil
}

Expand Down Expand Up @@ -89,6 +89,6 @@ func printVersionLine(ctx context.Context, label string, state *installer.Instal
cmdio.LogString(ctx, " Update available: v"+latestVersion)
cmdio.LogString(ctx, " Last updated: "+state.LastUpdated.Format("2006-01-02"))
cmdio.LogString(ctx, "")
cmdio.LogString(ctx, "Run 'databricks experimental aitools update' to update.")
cmdio.LogString(ctx, "Run 'databricks aitools update' to update.")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"testing"
"time"

"github.com/databricks/cli/experimental/aitools/lib/installer"
"github.com/databricks/cli/aitools/lib/installer"
"github.com/databricks/cli/libs/cmdio"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ func RecommendSkillsInstall(ctx context.Context, installFn func(context.Context)
}

if !cmdio.IsPromptSupported(ctx) {
cmdio.LogString(ctx, "Tip: coding agents detected without Databricks skills. Run 'databricks experimental aitools skills install' to install them.")
cmdio.LogString(ctx, "Tip: coding agents detected without Databricks skills. Run 'databricks aitools skills install' to install them.")
return nil
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func TestRecommendSkillsInstallNonInteractive(t *testing.T) {
ctx, stderr := cmdio.NewTestContextWithStderr(t.Context())
err := RecommendSkillsInstall(ctx, noopInstall)
require.NoError(t, err)
assert.Contains(t, stderr.String(), "databricks experimental aitools skills install")
assert.Contains(t, stderr.String(), "databricks aitools skills install")
}

func TestRecommendSkillsInstallInteractiveDecline(t *testing.T) {
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
"strings"
"time"

"github.com/databricks/cli/experimental/aitools/lib/agents"
"github.com/databricks/cli/aitools/lib/agents"
"github.com/databricks/cli/internal/build"
"github.com/databricks/cli/libs/cmdio"
"github.com/databricks/cli/libs/env"
Expand Down Expand Up @@ -135,7 +135,7 @@ func InstallSkillsForAgents(ctx context.Context, src ManifestSource, targetAgent
if state == nil && scope == ScopeGlobal {
isLegacy := checkLegacyInstall(ctx, baseDir)
if isLegacy && len(opts.SpecificSkills) > 0 {
return errors.New("legacy install detected without state tracking; run 'databricks experimental aitools install' (without a skill name) first to rebuild state")
return errors.New("legacy install detected without state tracking; run 'databricks aitools install' (without a skill name) first to rebuild state")
}
}

Expand Down Expand Up @@ -314,7 +314,7 @@ func printNoAgentsDetected(ctx context.Context) {
// Returns true if a legacy install was detected.
func checkLegacyInstall(ctx context.Context, globalDir string) bool {
if hasSkillsOnDisk(globalDir) {
cmdio.LogString(ctx, "Found skills installed before state tracking was added. Run 'databricks experimental aitools install' to refresh.")
cmdio.LogString(ctx, "Found skills installed before state tracking was added. Run 'databricks aitools install' to refresh.")
return true
}
homeDir, err := env.UserHomeDir(ctx)
Expand All @@ -323,7 +323,7 @@ func checkLegacyInstall(ctx context.Context, globalDir string) bool {
}
legacyDir := filepath.Join(homeDir, ".databricks", "agent-skills")
if hasSkillsOnDisk(legacyDir) {
cmdio.LogString(ctx, "Found skills installed before state tracking was added. Run 'databricks experimental aitools install' to refresh.")
cmdio.LogString(ctx, "Found skills installed before state tracking was added. Run 'databricks aitools install' to refresh.")
return true
}
return false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"strings"
"testing"

"github.com/databricks/cli/experimental/aitools/lib/agents"
"github.com/databricks/cli/aitools/lib/agents"
"github.com/databricks/cli/internal/build"
"github.com/databricks/cli/libs/cmdio"
"github.com/databricks/cli/libs/log"
Expand Down
Loading
Loading