diff --git a/.nextchanges/cli/aitools-kiro.md b/.nextchanges/cli/aitools-kiro.md new file mode 100644 index 00000000000..a442974a2c1 --- /dev/null +++ b/.nextchanges/cli/aitools-kiro.md @@ -0,0 +1 @@ +* `databricks aitools install` now supports Kiro, installing Databricks agent skills into its skills directory. ([#6908](https://github.com/databricks/cli/pull/6908)) diff --git a/cmd/aitools/install_test.go b/cmd/aitools/install_test.go index 8be4b4b150a..deb25154472 100644 --- a/cmd/aitools/install_test.go +++ b/cmd/aitools/install_test.go @@ -185,6 +185,7 @@ func TestAgentChoicesOnlyOffersActionableAgents(t *testing.T) { assert.Contains(t, names, agents.NamePi) assert.Contains(t, names, agents.NameGemini) assert.Contains(t, names, agents.NameGoose) + assert.Contains(t, names, agents.NameKiro) assert.NotContains(t, names, agents.NameCursor) assert.NotContains(t, names, agents.NameCodex) assert.NotContains(t, names, agents.NameOpenCode) diff --git a/cmd/aitools/telemetry.go b/cmd/aitools/telemetry.go index 09eed34f3b2..8ecf0c46542 100644 --- a/cmd/aitools/telemetry.go +++ b/cmd/aitools/telemetry.go @@ -117,6 +117,8 @@ func agentType(name string) protos.AitoolsAgentType { return protos.AitoolsAgentTypeGemini case agents.NameGoose: return protos.AitoolsAgentTypeGoose + case agents.NameKiro: + return protos.AitoolsAgentTypeKiro default: return protos.AitoolsAgentTypeUnspecified } diff --git a/cmd/aitools/update_test.go b/cmd/aitools/update_test.go index 0167d9d751b..183cbc0205a 100644 --- a/cmd/aitools/update_test.go +++ b/cmd/aitools/update_test.go @@ -400,6 +400,7 @@ func TestUpdateProjectIncludesProjectSkillAgents(t *testing.T) { require.NoError(t, os.MkdirAll(filepath.Join(projectRoot, ".pi", "skills", "databricks-core"), 0o755)) require.NoError(t, os.MkdirAll(filepath.Join(projectRoot, ".gemini", "skills", "databricks-core"), 0o755)) require.NoError(t, os.MkdirAll(filepath.Join(projectRoot, ".goose", "skills", "databricks-core"), 0o755)) + require.NoError(t, os.MkdirAll(filepath.Join(projectRoot, ".kiro", "skills", "databricks-core"), 0o755)) ctx := cmdio.MockDiscard(t.Context()) dir, err := installer.ProjectSkillsDir(ctx) @@ -433,4 +434,5 @@ func TestUpdateProjectIncludesProjectSkillAgents(t *testing.T) { assert.Contains(t, names, agents.NamePi) assert.Contains(t, names, agents.NameGemini) assert.Contains(t, names, agents.NameGoose) + assert.Contains(t, names, agents.NameKiro) } diff --git a/libs/aitools/agents/agents.go b/libs/aitools/agents/agents.go index 1e54492d65e..0c6cdfcbfb2 100644 --- a/libs/aitools/agents/agents.go +++ b/libs/aitools/agents/agents.go @@ -132,6 +132,7 @@ const ( NamePi = "pi" NameGemini = "gemini" NameGoose = "goose" + NameKiro = "kiro" ) // Databricks plugin identity, shared across the agents that ship a plugin. @@ -254,6 +255,19 @@ var Registry = []*Agent{ // Goose reads agent skills (SKILL.md) but has no databricks plugin, so it is // skills-only (Plugin nil). }, + { + Name: NameKiro, + DisplayName: "Kiro", + ConfigDir: homeSubdir(".kiro"), + SupportsProjectScope: true, + ProjectConfigDir: ".kiro", + Binary: "kiro", + // Kiro reads agent skills (SKILL.md) but has no databricks plugin, so it is + // skills-only (Plugin nil). Kiro's own picker text documents both scopes: + // "Skills can be added to ~/.kiro/skills/ (user-level) or .kiro/skills/ + // (workspace-level)". Kiro is IDE-first, so `kiro` is frequently absent from + // PATH; detection then falls back to ConfigDir and reports files-only. + }, } // claudeConfigDir follows Claude Code's configuration directory override. diff --git a/libs/aitools/agents/agents_test.go b/libs/aitools/agents/agents_test.go index 90562cf5d98..79cc0b79f58 100644 --- a/libs/aitools/agents/agents_test.go +++ b/libs/aitools/agents/agents_test.go @@ -49,6 +49,7 @@ func TestSkillsOnlyNamesMatchesRegistry(t *testing.T) { assert.Contains(t, names, "Pi") assert.Contains(t, names, "Gemini CLI") assert.Contains(t, names, "Goose") + assert.Contains(t, names, "Kiro") assert.NotContains(t, names, "Claude Code") for _, a := range Registry { if a.Plugin != nil { diff --git a/libs/aitools/agents/registry_test.go b/libs/aitools/agents/registry_test.go index f94e2ddcc6f..20eca404cdf 100644 --- a/libs/aitools/agents/registry_test.go +++ b/libs/aitools/agents/registry_test.go @@ -33,6 +33,7 @@ func TestSkillAgentRegistryPaths(t *testing.T) { {NamePi, "pi", "Pi", filepath.Join(home, ".pi", "agent", "skills"), filepath.Join(cwd, ".pi", "skills")}, {NameGemini, "gemini", "Gemini CLI", filepath.Join(home, ".gemini", "skills"), filepath.Join(cwd, ".gemini", "skills")}, {NameGoose, "goose", "Goose", gooseGlobalDir, filepath.Join(cwd, ".goose", "skills")}, + {NameKiro, "kiro", "Kiro", filepath.Join(home, ".kiro", "skills"), filepath.Join(cwd, ".kiro", "skills")}, } for _, tc := range tests { @@ -54,7 +55,7 @@ func TestSkillAgentRegistryPaths(t *testing.T) { func TestDetectProjectInstalled(t *testing.T) { cwd := t.TempDir() - for _, name := range []string{NamePi, NameGemini, NameGoose} { + for _, name := range []string{NamePi, NameGemini, NameGoose, NameKiro} { dir := filepath.Join(ByName(name).ProjectSkillsDir(cwd), "databricks-core") require.NoError(t, os.MkdirAll(dir, 0o755)) } @@ -65,5 +66,5 @@ func TestDetectProjectInstalled(t *testing.T) { for _, a := range DetectProjectInstalled(cwd) { names = append(names, a.Name) } - assert.ElementsMatch(t, []string{NamePi, NameGemini, NameGoose}, names) + assert.ElementsMatch(t, []string{NamePi, NameGemini, NameGoose, NameKiro}, names) } diff --git a/libs/aitools/installer/installer_test.go b/libs/aitools/installer/installer_test.go index a0846c67fa7..47138e543fc 100644 --- a/libs/aitools/installer/installer_test.go +++ b/libs/aitools/installer/installer_test.go @@ -1032,6 +1032,7 @@ func TestSupportsProjectScopeSetCorrectly(t *testing.T) { "pi": true, "gemini": true, "goose": true, + "kiro": true, } for _, agent := range agents.Registry { diff --git a/libs/telemetry/protos/aitools_install.go b/libs/telemetry/protos/aitools_install.go index 152d599671d..a90cc22d4df 100644 --- a/libs/telemetry/protos/aitools_install.go +++ b/libs/telemetry/protos/aitools_install.go @@ -16,6 +16,7 @@ const ( AitoolsAgentTypePi AitoolsAgentType = "PI" AitoolsAgentTypeGemini AitoolsAgentType = "GEMINI_CLI" AitoolsAgentTypeGoose AitoolsAgentType = "GOOSE" + AitoolsAgentTypeKiro AitoolsAgentType = "KIRO" ) // AitoolsInstallScope mirrors AitoolsInstallScope.Type in the databricks_cli