Skip to content
Open
4 changes: 2 additions & 2 deletions .agent/skills/pr-checklist/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ 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:
./task test-exp-aitools # only if aitools code changed
# 6. If you changed aitools/, experimental/aitools/, or experimental/ssh/:
./task test-exp-aitools # only if aitools code changed (top-level or experimental)
./task test-exp-ssh # only if ssh code changed
```

Expand Down
3 changes: 2 additions & 1 deletion .github/OWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,6 @@
# Internal
/internal/ team:platform

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

### CLI

* Promote the aitools skills-management surface (`install`, `update`, `uninstall`, `list`, `version`) from `databricks experimental aitools` to top-level `databricks aitools`. The old paths under `databricks experimental aitools` continue to work as silent backward-compat aliases. The `tools` subtree (`query`, `discover-schema`, `get-default-warehouse`, `statement …`) and the `skills` alias group remain under `databricks experimental aitools`.
* `databricks api` now works against unified hosts. Adds `--account` to scope a call to the account API and `--workspace-id` to override the workspace routing identifier per call. A `?o=<workspace-id>` query parameter on the path (the SPOG URL convention used by the Databricks UI) is also recognized as a per-call workspace override, so URLs pasted from the browser route correctly.

### Bundles
Expand Down
5 changes: 3 additions & 2 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -606,8 +606,9 @@ tasks:
# generic `test` target (the catch-all) instead.

test-exp-aitools:
desc: Run experimental aitools unit and acceptance tests
desc: Run aitools (top-level + experimental) unit and acceptance tests
sources:
- aitools/**
- experimental/aitools/**
- acceptance/apps/**
- "{{.EMBED_SOURCES}}"
Expand All @@ -616,7 +617,7 @@ tasks:
{{.GO_TOOL}} gotestsum \
--format ${GOTESTSUM_FORMAT:-pkgname-and-test-fails} \
--no-summary=skipped \
--packages ./experimental/aitools/... \
--packages "./aitools/... ./experimental/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
15 changes: 15 additions & 0 deletions aitools/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Databricks AI Tools

`databricks aitools` installs and manages Databricks skills for detected coding agents.

## Commands

- `databricks aitools install [skill-name]` (or `--skills <name>[,<name>...]` for multiple)
- `databricks aitools update`
- `databricks aitools uninstall`
- `databricks aitools list`
- `databricks aitools version`

Supported agents: Claude Code, Cursor, Codex CLI, OpenCode, GitHub Copilot, Antigravity.

The `tools` subtree (`query`, `discover-schema`, `get-default-warehouse`, `statement …`) and the `skills` alias group remain under `databricks experimental aitools` while their stability story is still in flux.
25 changes: 25 additions & 0 deletions aitools/cmd/aitools.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package aitools

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

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, update, and manage Databricks skills for
detected coding agents (Claude Code, Cursor, Codex CLI, OpenCode, GitHub
Copilot, Antigravity).`,
}

cmd.AddCommand(NewInstallCmd())
cmd.AddCommand(NewUpdateCmd())
cmd.AddCommand(NewUninstallCmd())
cmd.AddCommand(NewListCmd())
cmd.AddCommand(NewVersionCmd())

return cmd
}
File renamed without changes.
File renamed without changes.
63 changes: 56 additions & 7 deletions experimental/aitools/cmd/install.go → aitools/cmd/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,59 @@ import (
"fmt"
"strings"

"github.com/databricks/cli/experimental/aitools/lib/agents"
"github.com/databricks/cli/experimental/aitools/lib/installer"
"github.com/charmbracelet/huh"
"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"
)

func newInstallCmd() *cobra.Command {
// PromptAgentSelection and InstallSkillsForAgentsFn are package-level for
// testability. They are exported so wrappers in other packages
// (experimental/aitools/cmd/skills.go) can override them in tests.
var (
PromptAgentSelection = defaultPromptAgentSelection
InstallSkillsForAgentsFn = installer.InstallSkillsForAgents
)

func defaultPromptAgentSelection(ctx context.Context, detected []*agents.Agent) ([]*agents.Agent, error) {
options := make([]huh.Option[string], 0, len(detected))
agentsByName := make(map[string]*agents.Agent, len(detected))
for _, a := range detected {
options = append(options, huh.NewOption(a.DisplayName, a.Name).Selected(true))
agentsByName[a.Name] = a
}

var selected []string
err := huh.NewMultiSelect[string]().
Title("Select coding agents to install skills for").
Description("space to toggle, enter to confirm").
Options(options...).
Value(&selected).
Run()
if err != nil {
return nil, err
}

if len(selected) == 0 {
return nil, errors.New("at least one agent must be selected")
}

result := make([]*agents.Agent, 0, len(selected))
for _, name := range selected {
result = append(result, agentsByName[name])
}
return result, nil
}

func NewInstallCmd() *cobra.Command {
var skillsFlag, agentsFlag string
var includeExperimental bool
var projectFlag, globalFlag bool

cmd := &cobra.Command{
Use: "install",
Use: "install [skill-name]",
Short: "Install AI skills for coding agents",
Long: `Install Databricks AI skills for detected coding agents.

Expand All @@ -28,11 +67,21 @@ Use --project to install to the current project directory instead.
When multiple agents are detected, skills are stored in a canonical location
and symlinked to each agent to avoid duplication.

Pass a single skill name as a positional argument to install just that skill,
or use --skills name1,name2 for multiple. The two forms are mutually exclusive.

Supported agents: Claude Code, Cursor, Codex CLI, OpenCode, GitHub Copilot, Antigravity`,
Args: cobra.NoArgs,
Args: cobra.MaximumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()

if len(args) == 1 {
if skillsFlag != "" {
return errors.New("cannot use positional [skill-name] together with --skills; pick one")
}
skillsFlag = args[0]
}

// Resolve scope.
scope, err := resolveScopeWithPrompt(ctx, projectFlag, globalFlag)
if err != nil {
Expand Down Expand Up @@ -65,7 +114,7 @@ Supported agents: Claude Code, Cursor, Codex CLI, OpenCode, GitHub Copilot, Anti
case len(detected) == 1:
targetAgents = detected
case cmdio.IsPromptSupported(ctx):
targetAgents, err = promptAgentSelection(ctx, detected)
targetAgents, err = PromptAgentSelection(ctx, detected)
if err != nil {
return err
}
Expand All @@ -84,7 +133,7 @@ Supported agents: Claude Code, Cursor, Codex CLI, OpenCode, GitHub Copilot, Anti
installer.PrintInstallingFor(ctx, targetAgents)

src := &installer.GitHubManifestSource{}
return installSkillsForAgentsFn(ctx, src, targetAgents, opts)
return InstallSkillsForAgentsFn(ctx, src, targetAgents, opts)
},
}

Expand Down
Loading
Loading