Skip to content

feat(kilocode): add support for Kilo Code agent#161

Merged
Alan-TheGentleman merged 2 commits intoGentleman-Programming:mainfrom
yllada:feat/kilocode-support
Apr 13, 2026
Merged

feat(kilocode): add support for Kilo Code agent#161
Alan-TheGentleman merged 2 commits intoGentleman-Programming:mainfrom
yllada:feat/kilocode-support

Conversation

@yllada
Copy link
Copy Markdown
Contributor

@yllada yllada commented Mar 29, 2026

🔗 Linked Issue

Closes #118

🏷️ PR Type

  • type:bug — Bug fix (non-breaking change that fixes an issue)
  • type:feature — New feature (non-breaking change that adds functionality)
  • type:docs — Documentation only
  • type:refactor — Code refactoring (no functional changes)
  • type:chore — Build, CI, or tooling changes
  • type:breaking-change — Breaking change

📝 Summary

Adds full support for Kilo Code CLI agent. Kilo Code is a fork of OpenCode, so this implementation follows the same patterns with adapted paths and binary detection.
Configuration paths were verified against a real Kilo CLI installation using kilo debug paths:

  • Config dir: ~/.config/kilo/
  • Settings file: ~/.config/kilo/opencode.json
  • System prompt: ~/.config/kilo/AGENTS.md
  • Skills: ~/.config/kilo/skills/
  • Binary: kilo

📂 Changes

File / Area What Changed
internal/model/types.go Added AgentKilocode constant
internal/agents/kilocode/ NEW - adapter package (adapter.go, paths.go, adapter_test.go)
internal/agents/factory.go Registered Kilocode adapter
internal/catalog/agents.go Added Kilo Code metadata
internal/system/config_scan.go Added Kilocode config detection
internal/installcmd/resolver.go Added npm install command (@kilocode/cli)
internal/components/sdd/inject.go Handle Kilocode same as OpenCode
internal/components/engram/inject.go Handle Kilocode MCP format
internal/components/engram/setup.go Added kilocode slug mapping
internal/components/mcp/inject.go Handle Kilocode Context7 overlay
internal/components/persona/inject.go Handle Kilocode persona injection
internal/components/permissions/inject.go Handle Kilocode permissions
internal/cli/install_test.go Updated expected agents list

🧪 Test Plan

Unit Tests

go test ./...
Kilocode Adapter Tests
go test -v ./internal/agents/kilocode/...
- [x] Unit tests pass (go test ./...)
- [ ] E2E tests pass (cd e2e && ./docker-test.sh) — requires Docker
- [x] Manually tested locally with kilo debug paths verification
- [x] Dry-run install verified: GENTLE_AI_NO_SELF_UPDATE=1 ./gentle-ai install --agents kilocode --dry-run
✅ Contributor Checklist
- [x] PR is linked to an issue with status:approved
- [x] I have added the appropriate type:* label to this PR
- [x] Unit tests pass (go test ./...)
- [ ] E2E tests pass (cd e2e && ./docker-test.sh)
- [x] I have updated documentation if necessary
- [x] My commits follow Conventional Commits format
- [x] My commits do not include Co-Authored-By trailers

Copilot AI review requested due to automatic review settings March 29, 2026 20:24
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new first-class agent integration for Kilo Code (an OpenCode fork), wiring it into detection, installation, catalog metadata, and multiple component injection paths so it can participate in the Gentle AI ecosystem similarly to OpenCode.

Changes:

  • Introduces a new internal/agents/kilocode adapter (detection, paths, install command, and tests) and registers it in the agent factory/registry.
  • Adds Kilocode to agent metadata/catalog and config directory scanning, plus default install selection expectations.
  • Extends multiple components (SDD, Persona, Engram, MCP/Context7, Permissions) to treat Kilocode as OpenCode-like where required.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
internal/system/config_scan.go Adds Kilocode config-dir presence scanning.
internal/model/types.go Adds AgentKilocode identifier constant.
internal/installcmd/resolver.go Adds npm-based install command resolution for Kilocode.
internal/components/sdd/inject.go Treats Kilocode as OpenCode-like for SDD injection paths.
internal/components/persona/inject.go Enables persona + agent-definition injection for OpenCode/Kilocode settings.
internal/components/permissions/inject.go Enables OpenCode-style permissions overlay for Kilocode.
internal/components/mcp/inject.go Uses OpenCode Context7 overlay format for Kilocode.
internal/components/engram/setup.go Adds engram setup slug mapping for Kilocode.
internal/components/engram/inject.go Uses OpenCode/Kilocode MCP schema differences for engram overlay.
internal/cli/install_test.go Updates default expected agent list to include Kilocode.
internal/catalog/agents.go Adds Kilocode metadata (name/tier/config path).
internal/agents/kilocode/paths.go Defines Kilocode config root path helper.
internal/agents/kilocode/adapter.go Implements Kilocode adapter (detect/install/paths/strategies/capabilities).
internal/agents/kilocode/adapter_test.go Adds unit tests for Kilocode adapter behavior.
internal/agents/factory.go Registers Kilocode adapter + includes it in the default registry.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

return []ConfigState{
{Agent: "claude-code", Path: filepath.Join(homeDir, ".claude")},
{Agent: "opencode", Path: filepath.Join(homeDir, ".config", "opencode")},
{Agent: "kilocode", Path: filepath.Join(homeDir, ".config", "kilo")},
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding the "kilocode" entry here updates system.ScanConfigs output, but the CLI mapping in defaultAgentsFromDetection (internal/cli/validate.go) does not currently handle "kilocode". As a result, a system with only Kilocode installed won’t select it as the default agent and may fall back to “all agents”. Please add the kilocode→model.AgentKilocode mapping in that switch (and update/extend the corresponding tests).

Suggested change
{Agent: "kilocode", Path: filepath.Join(homeDir, ".config", "kilo")},

Copilot uses AI. Check for mistakes.
Comment on lines 45 to 47
want := model.Selection{
Agents: []model.AgentID{model.AgentClaudeCode, model.AgentOpenCode, model.AgentGeminiCLI, model.AgentCodex, model.AgentCursor, model.AgentVSCodeCopilot, model.AgentAntigravity, model.AgentWindsurf},
Agents: []model.AgentID{model.AgentClaudeCode, model.AgentOpenCode, model.AgentKilocode, model.AgentGeminiCLI, model.AgentCodex, model.AgentCursor, model.AgentVSCodeCopilot, model.AgentAntigravity, model.AgentWindsurf},
Persona: model.PersonaGentleman,
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default agents list now includes model.AgentKilocode, but the test suite still doesn’t assert that detection output "kilocode" maps to model.AgentKilocode (see TestDefaultAgentsFromDetection_AllAgentsMappedCorrectly). Add a test case for kilocode so this mapping can’t regress silently.

Copilot uses AI. Check for mistakes.
Comment on lines +281 to 284
if adapter.Agent() == model.AgentOpenCode || adapter.Agent() == model.AgentKilocode {
settingsPath := adapter.SettingsPath(homeDir)
if settingsPath != "" {
overlayContent, err := assets.Read(overlayAssetPath(sddMode))
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change makes the OpenCode-only SDD settings branch run for Kilocode too, but that branch also calls installOpenCodePlugins(), which hardcodes ~/.config/opencode as the target directory. For Kilocode this will write the plugin and node_modules into the wrong config dir. Refactor plugin installation to use the adapter’s GlobalConfigDir (and corresponding plugins/node_modules paths) or add a Kilocode-specific plugin installer before enabling this branch for Kilocode.

Copilot uses AI. Check for mistakes.
Comment thread internal/components/sdd/inject.go Outdated
Comment on lines 188 to 190
// rely on prompt files. OpenCode is handled differently: its orchestrator
// instructions must be scoped to the sdd-orchestrator agent only, otherwise
// the SDD phase sub-agents inherit coordinator-only delegation rules.
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment above this condition says “OpenCode is handled differently”, but Kilocode is now handled the same way (it’s excluded from global system prompt injection here too). Update the comment to mention Kilocode as well so future changes don’t accidentally treat it as a normal prompt-file agent.

Suggested change
// rely on prompt files. OpenCode is handled differently: its orchestrator
// instructions must be scoped to the sdd-orchestrator agent only, otherwise
// the SDD phase sub-agents inherit coordinator-only delegation rules.
// rely on prompt files. OpenCode and Kilocode are handled differently: their
// orchestrator instructions must be scoped to the sdd-orchestrator agent only,
// otherwise the SDD phase sub-agents inherit coordinator-only delegation rules.

Copilot uses AI. Check for mistakes.
@yllada
Copy link
Copy Markdown
Contributor Author

yllada commented Mar 29, 2026

All 4 points have been addressed in commit 78cd025

  1. Added kilocode case in defaultAgentsFromDetection switch
  2. Added test case for kilocode detection mapping
  3. Refactored installOpenCodePlugins to use adapter.GlobalConfigDir() instead of hardcoded path
  4. Updated comment to mention both OpenCode and Kilocode

Ready for re-review when you have a chance!

@isaacramirez-inge
Copy link
Copy Markdown

isaacramirez-inge commented Mar 30, 2026

Great work, thank u, I still testing and validating everything works with kilocode
#118

Copy link
Copy Markdown
Contributor

@Alan-TheGentleman Alan-TheGentleman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR has merge conflicts with main. Please rebase against the latest main and force-push to update.

git fetch origin main
git rebase origin/main
git push --force-with-lease

Once conflicts are resolved, we'll review. Thanks!

Copilot AI review requested due to automatic review settings April 12, 2026 13:34
@yllada yllada force-pushed the feat/kilocode-support branch from 78cd025 to 96100f3 Compare April 12, 2026 13:34
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 18 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +660 to 663
func installOpenCodePlugins(homeDir string, adapter agents.Adapter) (InjectionResult, error) {
opencodeDir := adapter.GlobalConfigDir(homeDir)
pluginsDir := filepath.Join(opencodeDir, "plugins")

Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

installOpenCodePlugins now installs into whatever adapter.GlobalConfigDir(homeDir) returns, but the local variable is still named opencodeDir and is used in paths and error messages. This is misleading for Kilocode (and any future reuse) and makes debugging harder; rename it to something agent-neutral (e.g. configDir) and update related strings accordingly.

Copilot uses AI. Check for mistakes.
// 2. OpenCode agent definitions — Tab-switchable agents in opencode.json.
if adapter.Agent() == model.AgentOpenCode && persona != model.PersonaCustom {
// 2. OpenCode/Kilocode agent definitions — Tab-switchable agents in settings.
if (adapter.Agent() == model.AgentOpenCode || adapter.Agent() == model.AgentKilocode) && persona != model.PersonaCustom {
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This condition redundantly checks persona != model.PersonaCustom even though the function returns early when persona == model.PersonaCustom. Removing the extra check simplifies the logic and avoids implying this branch can run for custom personas.

Suggested change
if (adapter.Agent() == model.AgentOpenCode || adapter.Agent() == model.AgentKilocode) && persona != model.PersonaCustom {
if adapter.Agent() == model.AgentOpenCode || adapter.Agent() == model.AgentKilocode {

Copilot uses AI. Check for mistakes.
Comment on lines +81 to +83
func (a *Adapter) GlobalConfigDir(homeDir string) string {
return filepath.Join(homeDir, ".config", "kilo")
}
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are multiple hard-coded filepath.Join(homeDir, ".config", "kilo", ...) path constructions in this adapter, while a ConfigPath(homeDir) helper already exists. To avoid drift (e.g., if the base dir changes), consider deriving these paths from ConfigPath(homeDir) (or a single baseDir := ConfigPath(homeDir)), rather than repeating the join segments in each method.

Copilot uses AI. Check for mistakes.
Comment thread informe-neural-labs.html Outdated
Comment on lines +482 to +506
<div class="cover-badge">Informe Confidencial</div>
<h1 class="cover-title">
Capacitacion <span>IA</span><br>
Neural Labs
</h1>
<p class="cover-subtitle">
Sprint de adopcion completado. Diagnostico inicial, resultados obtenidos, impacto por miembro del equipo y recomendaciones para escalar.
</p>

<div class="cover-meta">
<div class="cover-meta-item">
<span class="cover-meta-label">Preparado por</span>
<span class="cover-meta-value">Alan Buscaglia</span>
</div>
<div class="cover-meta-item">
<span class="cover-meta-label">Empresa</span>
<span class="cover-meta-value">Neural Labs</span>
</div>
<div class="cover-meta-item">
<span class="cover-meta-label">CTO</span>
<span class="cover-meta-value">Damian</span>
</div>
<div class="cover-meta-item">
<span class="cover-meta-label">Stack</span>
<span class="cover-meta-value">Angular / .NET / Azure DevOps</span>
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This HTML report appears unrelated to the Kilocode agent feature and includes content explicitly labeled "Informe Confidencial" plus personal/company-identifying information. Shipping this in the repository (and in the same PR) risks accidental disclosure and adds a large, non-product artifact; it should be removed from the PR or moved to an appropriate private/documentation location if it must exist.

Suggested change
<div class="cover-badge">Informe Confidencial</div>
<h1 class="cover-title">
Capacitacion <span>IA</span><br>
Neural Labs
</h1>
<p class="cover-subtitle">
Sprint de adopcion completado. Diagnostico inicial, resultados obtenidos, impacto por miembro del equipo y recomendaciones para escalar.
</p>
<div class="cover-meta">
<div class="cover-meta-item">
<span class="cover-meta-label">Preparado por</span>
<span class="cover-meta-value">Alan Buscaglia</span>
</div>
<div class="cover-meta-item">
<span class="cover-meta-label">Empresa</span>
<span class="cover-meta-value">Neural Labs</span>
</div>
<div class="cover-meta-item">
<span class="cover-meta-label">CTO</span>
<span class="cover-meta-value">Damian</span>
</div>
<div class="cover-meta-item">
<span class="cover-meta-label">Stack</span>
<span class="cover-meta-value">Angular / .NET / Azure DevOps</span>
<div class="cover-badge">Documento de ejemplo</div>
<h1 class="cover-title">
Capacitacion <span>IA</span><br>
Plantilla de referencia
</h1>
<p class="cover-subtitle">
Ejemplo de informe con contenido anonimo para fines de demostracion, maquetacion y revision visual.
</p>
<div class="cover-meta">
<div class="cover-meta-item">
<span class="cover-meta-label">Preparado por</span>
<span class="cover-meta-value">Equipo del proyecto</span>
</div>
<div class="cover-meta-item">
<span class="cover-meta-label">Empresa</span>
<span class="cover-meta-value">Organizacion de ejemplo</span>
</div>
<div class="cover-meta-item">
<span class="cover-meta-label">Responsable</span>
<span class="cover-meta-value">No aplica</span>
</div>
<div class="cover-meta-item">
<span class="cover-meta-label">Stack</span>
<span class="cover-meta-value">Tecnologias de ejemplo</span>

Copilot uses AI. Check for mistakes.
@yllada
Copy link
Copy Markdown
Contributor Author

yllada commented Apr 12, 2026

Rebase done

Note: informe-neural-labs.html and .pdf were already in main before the rebase — they're not part of this PR's changes.


@Alan-TheGentleman
Copy link
Copy Markdown
Contributor

Alan-TheGentleman commented Apr 12, 2026

Hey! Thanks for the rebase. The merge conflicts are resolved now, but the diff still includes two files that shouldn't be part of this PR.
These are not related to the Kilocode feature. Please remove them from your branch before we can merge:

git rm of the files
git commit -m "chore: remove unrelated files"
git push --force-with-lease

Once those are gone, we'll re-review. Thanks!

@Alan-TheGentleman
Copy link
Copy Markdown
Contributor

Also — make sure your fork is up to date with main before the rebase. This ensures you're working against the latest codebase:

git remote add upstream https://github.com/Gentleman-Programming/gentle-ai.git  # if not already added
git fetch upstream main
git rebase upstream/main
git push --force-with-lease

That should also clean up those unrelated files from the diff.

Copy link
Copy Markdown
Contributor

@Alan-TheGentleman Alan-TheGentleman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: feat(kilocode) — Kilo Code agent support

Clean implementation that follows the established OpenCode adapter pattern. Once the unrelated files are removed and the fork is synced with main, this is good to go.

What works well

  • Adapter structure is a clean mirror of the OpenCode adapter with correct path substitutions (~/.config/kilo/, binary kilo, settings opencode.json)
  • All component injectors correctly treat Kilocode alongside OpenCode where behavior is shared
  • installOpenCodePlugins refactored to use adapter.GlobalConfigDir() instead of hardcoded path — nice improvement
  • Test coverage is thorough — detection, paths, capabilities, strategies, install commands across platforms
  • Config scan, catalog, factory, CLI validation all wired up consistently

Suggestions (non-blocking)

  1. resolveKilocodeInstall simplicity: Unlike resolveOpenCodeInstall (which handles brew/apt/winget/unsupported), resolveKilocodeInstall only checks linux-needs-sudo vs. everything-else. This makes sense since Kilo is npm-only, but a one-line comment explaining the difference would help future readers.

  2. Growing || chains: Several files now check agent == OpenCode || agent == Kilocode. If another fork appears, consider extracting a helper like isOpenCodeFamily(id AgentID) bool. Not blocking for two agents, but worth keeping in mind.

Security

No concerns. No new dependencies, no build hooks, no credential exposure, no injection vectors. The @kilocode/cli npm package is the official distribution.

Will approve once the branch is synced with upstream main and the unrelated files are cleaned up.

@Alan-TheGentleman Alan-TheGentleman added the type:feature New feature label Apr 12, 2026
@yllada yllada force-pushed the feat/kilocode-support branch from 96100f3 to c0532b3 Compare April 12, 2026 14:37
@Alan-TheGentleman
Copy link
Copy Markdown
Contributor

Heads up — CI passed unit tests but E2E fails on Fedora with the same issue as #263:

[FAIL] settings.json changed between runs

414/415 tests pass (Ubuntu + Arch green, Fedora fails). Main is green, so this is introduced by the PR. The idempotency test runs install twice and diffs settings.json — any change between runs = failure.

Could you investigate alongside the other pending items (sync fork with upstream, remove unrelated files)?

yllada added 2 commits April 12, 2026 17:14
Kilo Code (CLI) is a fork of OpenCode, so this implementation follows
the same patterns with adapted paths and binary detection.

Changes:
- Add AgentKilocode constant and adapter package
- Register in factory, catalog, and config scanner
- Add npm install command resolution (@kilocode/cli)
- Handle Kilocode in SDD, engram, MCP, persona, and permissions
- Add comprehensive adapter tests

Config paths (verified against kilo debug paths):
- Config dir: ~/.config/kilo/
- Settings: ~/.config/kilo/opencode.json
- System prompt: ~/.config/kilo/AGENTS.md
- Skills: ~/.config/kilo/skills/

Closes Gentleman-Programming#118
- Add test case for kilocode detection mapping
- Add kilocode case in defaultAgentsFromDetection switch
- Refactor installOpenCodePlugins to use adapter.GlobalConfigDir
- Update comment to mention both OpenCode and Kilocode
Copilot AI review requested due to automatic review settings April 12, 2026 21:14
@yllada yllada force-pushed the feat/kilocode-support branch from c0532b3 to f590e4d Compare April 12, 2026 21:14
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread internal/model/types.go
const (
AgentClaudeCode AgentID = "claude-code"
AgentOpenCode AgentID = "opencode"
AgentKilocode AgentID = "kilocode"
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new constant name AgentKilocode breaks the established CamelCase naming used for multi-word agent identifiers in this file (e.g., AgentOpenCode, AgentClaudeCode, AgentVSCodeCopilot). Consider renaming to AgentKiloCode for consistency and readability (and update references accordingly).

Suggested change
AgentKilocode AgentID = "kilocode"
AgentKiloCode AgentID = "kilocode"

Copilot uses AI. Check for mistakes.
Comment on lines 40 to 46
func SetupAgentSlug(agent model.AgentID) (string, bool) {
switch agent {
case model.AgentOpenCode:
return "opencode", true
case model.AgentKilocode:
return "kilocode", true
case model.AgentClaudeCode:
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SetupAgentSlug now supports Kilocode, but there’s no test coverage asserting the new mapping (see internal/components/engram/setup_test.go, which currently enumerates several agents but not Kilocode). Adding a test case for model.AgentKilocode -> "kilocode" would prevent regressions.

Copilot uses AI. Check for mistakes.
@Alan-TheGentleman Alan-TheGentleman merged commit e0361dd into Gentleman-Programming:main Apr 13, 2026
8 of 9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type:feature New feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(kilocode): agregar soporte para agente kilocode(fork de opencode)

4 participants