Skip to content

Add Kiro support #276

@avifenesh

Description

@avifenesh

Summary

Add Kiro (IDE + CLI) as a fifth supported platform in agentsys, alongside Claude Code, Codex CLI, OpenCode, and Cursor.

Background

Kiro is an agentic AI IDE from AWS built on Code OSS. It uses a .kiro/ directory for all configuration. agentsys already supports 4 platforms with a clear pattern: detect platform, transform files, copy to platform-specific directories. Kiro follows the same model.

Platform Detection

Directory detection (add to bin/cli.js ~lines 942-953)

// Kiro: check for .kiro/ in cwd (project-scoped like Cursor) OR ~/.kiro/ (global)
kiro: fs.existsSync(path.join(process.cwd(), '.kiro')) || 
      fs.existsSync(path.join(os.homedir(), '.kiro'))

State directory (add to lib/platform/state-dir.js)

STATE_DIRS['kiro'] = '.kiro';
// Detection priority: KIRO_HOME env var → .kiro/ directory exists

CLI flag

agentsys install <plugin> --tool kiro
agentsys --tool kiro              # Interactive installer

Add 'kiro' to VALID_TOOLS array in bin/cli.js (~line 114).

Kiro Directory Structure

agentsys needs to generate files into this structure:

.kiro/                              # Project-scoped (workspace)
  steering/                         # Persistent context files
    product.md                      # Auto-generated by Kiro IDE
    tech.md                         # Auto-generated by Kiro IDE
    structure.md                    # Auto-generated by Kiro IDE
    <custom>.md                     # agentsys can add custom steering files here
  
  settings/
    mcp.json                        # MCP server configuration
  
  skills/
    <skill-name>/
      SKILL.md                      # Skill definitions (compatible format)
  
  hooks/
    <hook-name>.kiro.hook           # IDE hook JSON files
  
  agents/
    <agent-name>.json               # Custom agent definitions (CLI)
  
  specs/                            # AI-generated, agentsys should NOT write here

~/.kiro/                            # Global (user-level)
  steering/
    AGENTS.md                       # Always included, no mode support
    <global>.md                     # Global steering files
  settings/
    mcp.json                        # Global MCP config
  agents/
    <agent-name>.json               # Global custom agents

Precedence: Workspace .kiro/ overrides global ~/.kiro/ on conflict.

What agentsys Should Generate for Kiro

1. Skills → .kiro/skills/<name>/SKILL.md

Skills are the primary agentsys artifact. Kiro skills use the same SKILL.md format with YAML frontmatter. Kiro explicitly states drop-in compatibility with skills from other AI tools.

---
name: "skill-name"
description: "What this skill does"
---

# Skill content here...

Transform: Minimal - Kiro reads standard SKILL.md format. Only need path variable substitution.

2. Agents → .kiro/agents/<name>.json

agentsys agents should be transformed into Kiro's JSON agent format.

Kiro agent JSON schema (full reference):

{
  "name": "agent-name",
  "description": "Human-readable purpose",
  "prompt": "System instructions (inline text or file:// URI)",
  "model": "claude-sonnet-4",
  "keyboardShortcut": "ctrl+shift+m",
  "welcomeMessage": "Hello! I'm ready to help.",
  "tools": ["read", "write", "shell", "aws", "web", "knowledge"],
  "allowedTools": ["read", "@git/*"],
  "toolAliases": { "my_read": "fs_read" },
  "toolsSettings": {},
  "resources": [
    "file://README.md",
    "file://.kiro/steering/**/*.md",
    "skill://.kiro/skills/**/SKILL.md"
  ],
  "mcpServers": {
    "server-name": {
      "command": "npx",
      "args": ["-y", "@org/mcp-server"],
      "env": { "API_KEY": "${API_KEY}" },
      "timeout": 120000
    }
  },
  "includeMcpJson": true,
  "hooks": {
    "agentSpawn": [{ "command": "git status" }],
    "userPromptSubmit": [{ "command": "echo context" }],
    "preToolUse": [{
      "matcher": "execute_bash",
      "command": "audit-script.sh",
      "timeout_ms": 30000,
      "cache_ttl_seconds": 0
    }],
    "postToolUse": [{
      "matcher": "fs_write",
      "command": "cargo fmt --all"
    }],
    "stop": [{ "command": "npm test" }]
  }
}

Valid tools values: read, write, shell, aws, web, knowledge, @builtin, *, @<server-name>, @<server-name>/<tool-name>

Valid model values: claude-sonnet-4, claude-sonnet4.5, claude-opus4.5, Auto

Resource protocols: file://path (eager load), skill://path (lazy load), { "type": "knowledgeBase", ... } (indexed)

tools vs allowedTools: tools = what agent CAN access; allowedTools = subset that runs WITHOUT user confirmation (supports */? globs but NOT bare "*")

includeMcpJson: true merges .kiro/settings/mcp.json + ~/.kiro/settings/mcp.json into agent. Default false.

Transform: Convert agentsys agent markdown → Kiro JSON. Map Claude Code tool names to Kiro canonical names:

  • Readread / fs_read
  • Writewrite / fs_write
  • Bashshell / execute_bash
  • Agent / Task → not directly available (Kiro uses different sub-agent model)

3. Commands → .kiro/steering/<command>.md (as steering files)

Kiro doesn't have a direct "commands" concept like OpenCode. Commands should be installed as steering files with manual inclusion mode so users can invoke them via #steering-file-name in chat.

---
inclusion: manual
name: "command-name"
description: "What this command does when invoked"
---

# Command instructions here...

Transform: Add YAML frontmatter with inclusion: manual, strip Task() calls, replace PLUGIN_ROOT variables.

4. MCP Configuration → .kiro/settings/mcp.json

If a plugin provides MCP servers, merge them into .kiro/settings/mcp.json.

Kiro MCP format (identical JSON schema to Claude Code and Cursor):

{
  "mcpServers": {
    "server-name": {
      "command": "npx",
      "args": ["-y", "@org/mcp-server"],
      "env": {
        "API_KEY": "${API_KEY}"
      },
      "disabled": false,
      "autoApprove": [],
      "disabledTools": []
    }
  }
}

Remote server variant:

{
  "mcpServers": {
    "remote-server": {
      "url": "https://mcp.example.com/api",
      "headers": {
        "Authorization": "Bearer ${TOKEN}"
      },
      "disabled": false,
      "autoApprove": []
    }
  }
}

MCP field reference:

Field Type Required Default Notes
command string Yes (local) - Executable to run
args string[] Yes (local) - Command arguments
url string Yes (remote) - HTTPS endpoint (HTTP for localhost)
headers object No {} HTTP headers for remote
env object No {} Use ${VAR} for secret expansion
disabled boolean No false Toggle without removing
autoApprove string[] No [] Tool names auto-approved ("*" for all)
disabledTools string[] No [] Tool names to exclude

Transform: Same JSON schema as Claude Code - can reuse existing MCP config generation with path change only.

5. IDE Hooks → .kiro/hooks/<name>.kiro.hook (optional)

If a plugin provides hooks, they can be installed as .kiro.hook JSON files.

Kiro IDE hook schema:

{
  "title": "Hook display name",
  "description": "What this hook does",
  "event": "fileEdited",
  "patterns": ["**/*.ts", "**/*.tsx"],
  "then": {
    "type": "runCommand",
    "command": "npm run lint"
  }
}

Or with agent prompt:

{
  "title": "Auto-document on save",
  "description": "Update docs when source changes",
  "event": "fileEdited",
  "patterns": ["src/**/*.ts"],
  "then": {
    "type": "askAgent",
    "prompt": "Update documentation for the changed file"
  }
}

Valid IDE hook events: fileEdited, fileCreate, fileDelete, promptSubmit, agentStop, preToolUse, postToolUse, manual

Tool hooks need toolTypes instead of patterns:

{
  "event": "preToolUse",
  "toolTypes": ["execute_bash", "fs_write"],
  "then": { "type": "runCommand", "command": "security-check.sh" }
}

Transform: Convert Claude Code hooks (from settings.json format) → Kiro .kiro.hook JSON files. Map event types:

  • Claude PreToolUse → Kiro preToolUse
  • Claude PostToolUse → Kiro postToolUse
  • Claude Stop → Kiro agentStop

Implementation Checklist

Core installer (bin/cli.js)

  • Add 'kiro' to VALID_TOOLS array
  • Add Kiro platform detection (.kiro/ directory check)
  • Add installForKiro() function following the pattern of installForCursor()

Install function (installForKiro())

async function installForKiro(plugin, components, options) {
  const kiroDir = path.join(process.cwd(), '.kiro');
  
  // Create directories
  await fs.ensureDir(path.join(kiroDir, 'skills'));
  await fs.ensureDir(path.join(kiroDir, 'steering'));
  await fs.ensureDir(path.join(kiroDir, 'agents'));
  await fs.ensureDir(path.join(kiroDir, 'hooks'));
  await fs.ensureDir(path.join(kiroDir, 'settings'));
  
  // Install skills → .kiro/skills/<name>/SKILL.md
  for (const skill of components.skills) {
    const dest = path.join(kiroDir, 'skills', skill.name, 'SKILL.md');
    await fs.writeFile(dest, transformSkillForKiro(skill.content));
  }
  
  // Install agents → .kiro/agents/<name>.json
  for (const agent of components.agents) {
    const dest = path.join(kiroDir, 'agents', `${agent.name}.json`);
    await fs.writeFile(dest, transformAgentForKiro(agent));
  }
  
  // Install commands → .kiro/steering/<name>.md (manual inclusion)
  for (const command of components.commands) {
    const dest = path.join(kiroDir, 'steering', `${command.name}.md`);
    await fs.writeFile(dest, transformCommandForKiro(command.content));
  }
  
  // Install MCP servers → .kiro/settings/mcp.json (merge)
  if (components.mcpServers) {
    await mergeKiroMcpConfig(kiroDir, components.mcpServers);
  }
  
  // Install hooks → .kiro/hooks/<name>.kiro.hook
  for (const hook of components.hooks || []) {
    const dest = path.join(kiroDir, 'hooks', `${hook.name}.kiro.hook`);
    await fs.writeFile(dest, JSON.stringify(transformHookForKiro(hook), null, 2));
  }
}

Transform functions (lib/adapter-transforms.js)

  • transformSkillForKiro() - Minimal: path substitution, preserve SKILL.md format
  • transformAgentForKiro() - Convert agent markdown → Kiro JSON schema
  • transformCommandForKiro() - Add inclusion: manual frontmatter, strip Task() calls
  • transformHookForKiro() - Convert Claude hook format → .kiro.hook JSON
  • mergeKiroMcpConfig() - Read existing .kiro/settings/mcp.json, merge new servers

Discovery (lib/discovery/index.js)

  • Add getKiroSkillMappings() - Map skills with Kiro-specific frontmatter
  • Add getKiroAgentMappings() - Map agents to JSON format

Platform utilities (lib/cross-platform/index.js)

  • Add 'kiro' to PLATFORMS enum
  • Add getKiroConfig() - Return MCP config structure for Kiro
  • Update getInstructionFiles() to include .kiro/steering/*.md

State directory (lib/platform/state-dir.js)

  • Add 'kiro': '.kiro' to STATE_DIRS
  • Add KIRO_HOME env var support in detection priority

Cleanup on reinstall

  • Track installed files in ~/.agentsys/installed.json with platforms: ["kiro"]
  • On reinstall: remove known agentsys-generated files from .kiro/ (preserve user files)
  • Pattern: remove .kiro/skills/<agentsys-skill>/ but never touch .kiro/steering/product.md etc.

Kiro vs Other Platforms - Key Differences

Aspect Claude Code OpenCode Codex Cursor Kiro
Scope Global (marketplace) Global (XDG) Global (~/) Project (.cursor/) Project (.kiro/) + Global (~/.kiro/)
Skills Plugin SKILL.md ~/.config/opencode/skills/ ~/.codex/skills/ .cursor/skills/ .kiro/skills/
Agents Sub-agents via Task ~/.config/opencode/agents/ N/A N/A .kiro/agents/*.json
Commands Slash commands ~/.config/opencode/commands/ N/A .cursor/commands/ .kiro/steering/*.md (manual mode)
MCP .claude/mcp.json opencode.json mcp section config.toml .cursor/mcp.json .kiro/settings/mcp.json
Hooks settings.json N/A N/A N/A .kiro/hooks/*.kiro.hook
Rules CLAUDE.md AGENTS.md AGENTS.md .cursor/rules/*.mdc .kiro/steering/*.md
Install Marketplace CLI File copy File copy File copy File copy

Kiro-Specific Features (Optional/Future)

Powers support

Kiro Powers (POWER.md + mcp.json + steering/) are a unique Kiro concept. A plugin could optionally install as a Kiro Power:

.kiro/powers/<power-name>/
  POWER.md              # Required: YAML frontmatter with name, description, keywords
  mcp.json              # Optional: MCP servers for this power
  steering/             # Optional: workflow-specific guidance

POWER.md format:

---
name: "power-name"
displayName: "Display Name"
description: "Brief description"
keywords: ["keyword1", "keyword2"]
author: "Author Name"
---

## Onboarding
...
## Common Workflows
...

Powers activate dynamically based on keywords in user messages, solving MCP context overload. This is a natural evolution for agentsys plugins that bundle MCP servers + steering.

AGENTS.md compatibility

Kiro reads AGENTS.md from workspace root as an always-included steering file (no frontmatter, no inclusion modes). If agentsys generates an AGENTS.md for other tools, Kiro picks it up automatically.

Chat Modes Context

Kiro has 4 modes that affect how steering/skills are consumed:

  • Vibe + Autopilot - All steering loaded, full autonomy
  • Vibe + Supervised - All steering loaded, per-hunk approval
  • Spec + Autopilot - Spec context + steering, full autonomy
  • Spec + Supervised - Spec context + steering, per-hunk approval

agentsys-installed skills and steering work in all modes.

Testing

  • Unit tests for all transform functions
  • Integration test: install plugin for Kiro, verify file structure
  • Cross-platform test: install same plugin for all 5 tools, verify parity
  • Cleanup test: reinstall preserves user files, replaces agentsys files
  • MCP merge test: existing mcp.json preserved, new servers added

Acceptance Criteria

  • agentsys --tool kiro installs skills, agents, commands, MCP, hooks
  • agentsys install <plugin> --tool kiro works for all plugins
  • Kiro auto-detected when .kiro/ exists
  • Skills format compatible (drop-in from other platforms)
  • Agents converted to Kiro JSON schema
  • Commands installed as manual steering files
  • MCP config merged into .kiro/settings/mcp.json
  • Hooks converted to .kiro.hook JSON format
  • Uninstall/reinstall cleans up agentsys files only
  • README and website updated with Kiro as supported platform

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions