Skip to content
Closed
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
4 changes: 4 additions & 0 deletions experimental/aitools/cmd/aitools.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ Provides commands to:
}

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

Expand Down
113 changes: 107 additions & 6 deletions experimental/aitools/cmd/install.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,119 @@
package aitools

import (
"context"
"errors"
"fmt"
"strings"

"github.com/databricks/cli/experimental/aitools/lib/agents"
"github.com/databricks/cli/experimental/aitools/lib/installer"
"github.com/databricks/cli/libs/cmdio"
"github.com/fatih/color"
"github.com/spf13/cobra"
)

func newInstallCmd() *cobra.Command {
return &cobra.Command{
Use: "install [skill-name]",
Short: "Alias for skills install",
Long: `Alias for "databricks experimental aitools skills install".
var skillsFlag, agentsFlag string
var includeExperimental bool

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

Skills are installed globally to each agent's skills directory.
When multiple agents are detected, skills are stored in a canonical location
and symlinked to each agent to avoid duplication.

Installs Databricks skills for detected coding agents.`,
Supported agents: Claude Code, Cursor, Codex CLI, OpenCode, GitHub Copilot, Antigravity`,
RunE: func(cmd *cobra.Command, args []string) error {
return runSkillsInstall(cmd.Context(), args)
ctx := cmd.Context()

// Resolve target agents.
var targetAgents []*agents.Agent
if agentsFlag != "" {
var err error
targetAgents, err = resolveAgentNames(ctx, agentsFlag)
if err != nil {
return err
}
} else {
detected := agents.DetectInstalled(ctx)
if len(detected) == 0 {
printNoAgentsMessage(ctx)
return nil
}

switch {
case len(detected) == 1:
targetAgents = detected
case cmdio.IsPromptSupported(ctx):
var err error
targetAgents, err = promptAgentSelection(ctx, detected)
if err != nil {
return err
}
default:
targetAgents = detected
}
}

// Build install options.
opts := installer.InstallOptions{
IncludeExperimental: includeExperimental,
}
if skillsFlag != "" {
opts.SpecificSkills = strings.Split(skillsFlag, ",")
}

installer.PrintInstallingFor(ctx, targetAgents)

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

cmd.Flags().StringVar(&skillsFlag, "skills", "", "Specific skills to install (comma-separated)")
cmd.Flags().StringVar(&agentsFlag, "agents", "", "Agents to install for (comma-separated, e.g. claude-code,cursor)")
cmd.Flags().BoolVar(&includeExperimental, "include-experimental", false, "Include experimental skills")
return cmd
}

// resolveAgentNames parses a comma-separated list of agent names and validates
// them against the registry. Returns an error for unrecognized names.
func resolveAgentNames(ctx context.Context, names string) ([]*agents.Agent, error) {
available := make(map[string]*agents.Agent, len(agents.Registry))
var availableNames []string
for i := range agents.Registry {
a := &agents.Registry[i]
available[a.Name] = a
availableNames = append(availableNames, a.Name)
}

var result []*agents.Agent
for _, name := range strings.Split(names, ",") {
name = strings.TrimSpace(name)
if name == "" {
continue
}
agent, ok := available[name]
if !ok {
return nil, fmt.Errorf("unknown agent %q. Available agents: %s", name, strings.Join(availableNames, ", "))
}
result = append(result, agent)
}

if len(result) == 0 {
return nil, errors.New("no agents specified")
}
return result, nil
}

// printNoAgentsMessage prints the "no agents detected" message.
func printNoAgentsMessage(ctx context.Context) {
cmdio.LogString(ctx, color.YellowString("No supported coding agents detected."))
cmdio.LogString(ctx, "")
cmdio.LogString(ctx, "Supported agents: Claude Code, Cursor, Codex CLI, OpenCode, GitHub Copilot, Antigravity")
cmdio.LogString(ctx, "Please install at least one coding agent first.")
}
Loading
Loading