Introduction
About
kiro-generator (kg) is a CLI tool for managing and generating Kiro agent files.
Why?
Because managing config files via JSON is the second worse format. Obviously YAML files takes 1st prize
Prerequisites
- kiro-cli
- A distaste for
JSONconfig files
Features
Config Hierarchy
KG provides a hierarchical configuration system that allows you to define and override settings at different levels. The schemas is mostly the same as kiro-cli JSON’s format but defined as TOML, with a few added fields explained in usage
Agent Declaration
By default Agents can be declared globally ~/.kiro/generators/kg.toml or locally .kiro/generators/kg.toml. If both are present, the local configuration takes precedence, however both configurations are merged together. You can use --local argument to ignore global configuration.
Force Permissions
You can override toolsettings permissions. For example, you can have your default agent deny executing git push, but override this for special use cases, see inheritance and usage for more information.
Installation
Cargo
cargo install kiro-generator
Arch Linux AUR package
paru -S kiro-generator
Ubuntu/Debian
todo
Homebrew
brew install kiro-generator
From Source
git clone https://github.com/carteraMesh/kiro-generator.git
cd kiro-generator
cargo install --path .
Verify
kg --version
Quick Start
- Define your agents in
~/.kiro/generators/kg.tomlcat ~/.kiro/generators/kg.toml
[agents]
default = { } # default is the agent name
rust = { inherits = ["default"] } # rust agent config is merged with default
- Define your agent configurations in
~/.kiro/generators/<agent name>.toml
cat ~/.kiro/generators/default.toml
description = "Default agent"
tools = ["*"]
allowedTools = ["read", "knowledge", "web_search"]
resources = ["file://README.md", "file://AGENTS.md"]
[toolsSettings.shell]
allowedCommands = ["git status", "git fetch", "git diff .*" ]
deniedCommands = ["git commit .*", "git push .*" ]
autoAllowReadonly = true
cat ~/.kiro/generators/rust.toml
description = "General Rust agent"
resources = ["file://RUST.md"]
allowedTools = [ "@rustdocs", "@cargo" ] # also ["read", "knowledge", "web_search"] from default.toml
[mcpServers]
rustdocs = { type = "stdio" , command = "rust-docs-mcp", timeout = 1000 }
cargo = { command = "cargo-mcp" , timeout = 1200 }
[toolsSettings]
[toolsSettings.shell]
allowedCommands = ["cargo .+" ] # inherits allowedCommands from default.toml
deniedCommands = ["cargo publish .*"] # inherits deniedCommands from default.toml
- Validate
$ kg validate
╭────────────────────┬─────┬─────────────────┬────────────────────────────────────────────────┬────────────────────┬────────┬────────┬────────╮
│ Agent 🤖 (PREVIEW) ┆ Loc ┆ MCP 💻 ┆ Allowed Tools ⚙️ ┆ Resources 📋 ┆ Forced Permissions │
╞════════════════════╪═════╪═════════════════╪════════════════════════════════════════════════╪════════════════════╪══════════════════════════╡
│ default ┆ 📁 ┆ ┆ knowledge, read, web_search ┆ - file://README.md ┆ │
│ ┆ ┆ ┆ ┆ - file://AGENTS.md ┆ │
│ ┆ ┆ ┆ ┆ ┆ │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ rust ┆ 📁 ┆ cargo, rustdocs ┆ @cargo, @rustdocs, knowledge, read, web_search ┆ - file://README.md ┆ │
│ ┆ ┆ ┆ ┆ - file://AGENTS.md ┆ │
│ ┆ ┆ ┆ ┆ - file://RUST.md ┆ │
│ ┆ ┆ ┆ ┆ ┆ │
╰────────────────────┴─────┴─────────────────┴────────────────────────────────────────────────┴────────────────────┴──────────────────────────╯
🎉 Config is valid
→ Run kg generate to generate agent files
Config Files
kg uses a hierarchical TOML-based configuration system. Configuration can be defined globally, locally, or both.
File Locations
Configuration is loaded in order from least to most precedence:
~/.kiro/generators/[agent-name].toml- Global agent config~/.kiro/generators/kg.toml- Global agent declarations.kiro/generators/[agent-name].toml- Local agent config.kiro/generators/kg.toml- Local agent declarations
Local settings override global settings. Both are merged together unless you use --local to ignore global config.
File Types
kg.toml
The main configuration file that declares agents and their relationships.
[agents]
default = { inherits = [] }
rust = { inherits = ["default"] }
agent-name.toml
Individual agent configuration files containing the actual settings.
description = "Default agent"
tools = ["*"]
allowedTools = ["read", "knowledge", "web_search"]
resources = ["file://README.md"]
[toolsSettings.shell]
allowedCommands = ["git status", "git fetch"]
autoAllowReadonly = true
Inline Configuration
You can define agent properties directly in kg.toml:
[agents.default]
inherits = []
allowedTools = ["read", "knowledge"]
resources = ["file://README.md"]
[agents.rust]
inherits = ["default"]
allowedTools = ["@rustdocs", "@cargo"]
This is useful for simple agents or when you want everything in one file.
Agent Declaration
Agents are declared in kg.toml files using the [agents] table.
Basic Declaration
[agents]
default = { inherits = [] }
The key (default) is the agent name. This creates an agent that looks for configuration in:
~/.kiro/generators/default.toml.kiro/generators/default.toml
Agent Properties
inherits
List of parent agents to inherit configuration from.
[agents]
default = { inherits = [] }
rust = { inherits = ["default"] }
python = { inherits = ["default"] }
skeleton
Mark an agent as a template that won’t generate a JSON file.
[agents]
git-base = { skeleton = true }
See Skeletons for details.
Inline vs External Config
You can define agent configuration inline or in separate files:
Inline:
[agents.default]
inherits = []
allowedTools = ["read", "knowledge"]
External:
[agents]
default = { inherits = [] }
Then create ~/.kiro/generators/default.toml:
allowedTools = ["read", "knowledge"]
Both approaches can be mixed. Inline config takes precedence.
Location
Agents can be declared globally or locally:
- Global:
~/.kiro/generators/kg.toml- Available in all projects - Local:
.kiro/generators/kg.toml- Project-specific agents
Use kg validate to see the merged configuration.
Inheritance
Agents can inherit configuration from other agents using the inherits field.
Basic Inheritance
[agents]
default = { inherits = [] }
rust = { inherits = ["default"] }
The rust agent inherits all configuration from default and can override or extend it.
Multiple Parents
Agents can inherit from multiple parents:
[agents]
git-base = { skeleton = true }
rust-base = { skeleton = true }
rust-dev = { inherits = ["git-base", "rust-base"] }
Configuration is merged left-to-right. Later parents override earlier ones.
Merge Behavior
Arrays (allowedTools, resources, etc.)
Arrays are merged (combined):
Parent:
[agents.default]
allowedTools = ["read", "knowledge"]
Child:
[agents.rust]
inherits = ["default"]
allowedTools = ["@rustdocs", "@cargo"]
Result:
allowedTools = ["read", "knowledge", "@rustdocs", "@cargo"]
Objects (toolsSettings, mcpServers, etc.)
Objects are deep merged:
Parent:
[agents.default.toolsSettings.shell]
allowedCommands = ["git status", "git fetch"]
autoAllowReadonly = true
Child:
[agents.rust.toolsSettings.shell]
allowedCommands = ["cargo .*"]
Result:
[toolsSettings.shell]
allowedCommands = ["git status", "git fetch", "cargo .*"]
autoAllowReadonly = true
Scalars (description, timeout, etc.)
Scalars are replaced:
Parent:
description = "Default agent"
Child:
description = "Rust development agent"
Result:
description = "Rust development agent"
Inheritance Chain
You can create deep inheritance hierarchies:
[agents]
base = { inherits = [] }
dev = { inherits = ["base"] }
rust-dev = { inherits = ["dev"] }
Configuration is merged from root to leaf: base → dev → rust-dev
Force Properties
Force properties override permission restrictions in child agents. They ensure specific commands or paths are always allowed, even if a child tries to deny them.
forceAllowedCommands
Force specific shell commands to be allowed:
[agents.git-pusher]
skeleton = true
[agents.git-pusher.toolsSettings.shell]
forceAllowedCommands = ["git commit .*", "git push .*"]
Child agents cannot deny these commands:
[agents.dependabot]
inherits = ["git-pusher"]
[agents.dependabot.toolsSettings.shell]
deniedCommands = ["git push .*"] # Ignored - git push is forced allowed
The forced commands are added to allowedCommands and removed from deniedCommands.
forceAllowedPaths
Force specific paths to be readable or writable:
[agents.cargo-editor]
skeleton = true
[agents.cargo-editor.toolsSettings.read]
forceAllowedPaths = [".*Cargo.toml.*"]
[agents.cargo-editor.toolsSettings.write]
forceAllowedPaths = [".*Cargo.toml.*"]
Child agents must allow access to these paths:
[agents.dependabot]
inherits = ["cargo-editor"]
[agents.dependabot.toolsSettings.write]
deniedPaths = [".*Cargo.toml.*"] # Ignored - Cargo.toml is forced allowed
Use Cases
Force properties are useful for:
- Ensuring critical permissions in specialized agents (like dependabot needing git push)
- Creating permission templates that can’t be accidentally restricted
- Building agent hierarchies with guaranteed capabilities
Validation
Use kg validate to see the final merged configuration:
kg validate
This shows exactly what each agent will generate, including inherited settings and forced permissions.
Skeletons
Skeletons are agent templates that don’t generate JSON files. They exist only to be inherited by other agents.
Purpose
Use skeletons to:
- Create reusable configuration components
- Define common tool settings
- Build agent templates
- Organize complex inheritance hierarchies
Declaration
Mark an agent as a skeleton with skeleton = true:
[agents]
git-base = { skeleton = true }
kg will skip generating ~/.kiro/agents/git-base.json but the configuration is available for inheritance.
Example: Git Permissions
Create a skeleton with git commands:
[agents.git-readonly]
skeleton = true
[agents.git-readonly.toolsSettings.execute_bash]
allowedCommands = [
"git status .*",
"git fetch .*",
"git diff .*",
"git log .*"
]
autoAllowReadonly = true
Use it in real agents:
[agents.rust]
inherits = ["git-readonly"]
allowedTools = ["@rustdocs", "@cargo"]
Example: Permission Levels
Create a hierarchy of permission skeletons:
[agents.git-readonly]
skeleton = true
[agents.git-readonly.toolsSettings.execute_bash]
allowedCommands = ["git status .*", "git fetch .*", "git diff .*"]
[agents.git-write]
skeleton = true
inherits = ["git-readonly"]
[agents.git-write.toolsSettings.execute_bash]
allowedCommands = ["git add .*", "git commit .*"]
[agents.git-full]
skeleton = true
inherits = ["git-write"]
[agents.git-full.toolsSettings.execute_bash]
allowedCommands = ["git push .*", "git pull .*"]
Then use them:
[agents.reviewer]
inherits = ["git-readonly"]
[agents.developer]
inherits = ["git-write"]
[agents.maintainer]
inherits = ["git-full"]
Validation
Skeletons appear in kg validate output but are marked as templates:
kg validate
They won’t appear in the generated agents directory.
Best Practices
- Use descriptive names that indicate purpose (
git-readonly, notgit1) - Keep skeletons focused on a single concern
- Document what each skeleton provides
- Avoid deep skeleton-only inheritance chains (max 2-3 levels)
CLI Commands
Global Options
kg [OPTIONS] <COMMAND>
Options:
-d, --debug- Enable debug output-t, --trace <AGENT_NAME>- Enable trace logging for specific agent (useallfor everything)-c, --color <WHEN>- Control color output:always,auto,never(default:auto)-f, --format <FORMAT>- Output format:table,json(default:table)-h, --help- Show help-V, --version- Show version
Commands
validate
Validate configuration without generating files.
kg validate [OPTIONS]
Options:
--local- Ignore global~/.kiro/generators/config--global- Ignore local.kiro/generators/config--show-skeletons- Include skeleton agents in output
Output:
Table view shows:
- Agent name
- Location (📁 local, 🏠 global, 🌍 both)
- MCP servers configured
- Allowed tools
- Resources
- Forced permissions
Examples:
# Validate all agents
kg validate
# Only validate local agents
kg validate --local
# Show skeletons in output
kg validate --show-skeletons
# JSON output for scripting
kg validate --format json
generate
Generate agent JSON files for kiro-cli.
kg generate [OPTIONS]
Options:
--local- Ignore global config, only generate local agents--global- Ignore local config, only generate global agents--show-skeletons- Include skeleton agents in output
Output:
Generates JSON files:
- Global agents →
~/.kiro/agents/<agent-name>.json - Local agents →
.kiro/agents/<agent-name>.json
Skeletons are never generated.
Examples:
# Generate all agents
kg generate
# Only generate global agents
kg generate --global
# Only generate local agents
kg generate --local
# Debug specific agent generation
kg generate --trace rust
version
Display version information.
kg version
Shows kg version and build info.
Output Formats
Table (default)
Human-readable table with agent details:
╭────────────────────┬─────┬─────────────────┬────────────────────────────────────────────────╮
│ Agent 🤖 (PREVIEW) ┆ Loc ┆ MCP 💻 ┆ Allowed Tools ⚙️ │
╞════════════════════╪═════╪═════════════════╪════════════════════════════════════════════════╡
│ rust ┆ 📁 ┆ cargo, rustdocs ┆ @cargo, @rustdocs, knowledge, read, web_search │
╰────────────────────┴─────┴─────────────────┴────────────────────────────────────────────────╯
JSON
Machine-readable output for scripting:
kg validate --format json | jq '.agents[] | select(.name == "rust")'
Debugging
Use trace logging to debug configuration issues:
# Trace specific agent
kg validate --trace rust
# Trace all agents (very verbose)
kg validate --trace all
# Debug mode (less verbose than trace)
kg validate --debug
Trace output shows:
- Configuration file loading
- Inheritance resolution
- Merge operations
- Force property application
Configuration Schema
kg provides JSON schemas for IDE autocompletion and validation.
kg.toml Schema
For agent declarations in kg.toml:
"$schema" = "https://raw.githubusercontent.com/CarteraMesh/kiro-generator/refs/heads/main/schemas/kg.json"
[agents]
default = { inherits = [] }
Agent Configuration Schema
For individual agent files like default.toml, rust.toml:
"$schema" = "https://raw.githubusercontent.com/CarteraMesh/kiro-generator/refs/heads/main/schemas/kiro-agent.json"
description = "Default agent"
allowedTools = ["read", "knowledge"]
LSP Configuration
taplo (Recommended)
Add to .taplo.toml in your project or ~/.config/taplo/.taplo.toml:
[schema]
enabled = true
[[schema.associations]]
path = "**/kg.toml"
url = "https://raw.githubusercontent.com/CarteraMesh/kiro-generator/refs/heads/main/schemas/kg.json"
[[schema.associations]]
path = "**/.kiro/generators/*.toml"
url = "https://raw.githubusercontent.com/CarteraMesh/kiro-generator/refs/heads/main/schemas/kiro-agent.json"
VS Code
Install the Even Better TOML extension. It uses taplo and will automatically pick up the $schema field from your TOML files.
Neovim
Using nvim-lspconfig:
require('lspconfig').taplo.setup({
settings = {
evenBetterToml = {
schema = {
enabled = true,
associations = {
["**/kg.toml"] = "https://raw.githubusercontent.com/CarteraMesh/kiro-generator/refs/heads/main/schemas/kg.json",
["**/.kiro/generators/*.toml"] = "https://raw.githubusercontent.com/CarteraMesh/kiro-generator/refs/heads/main/schemas/kiro-agent.json"
}
}
}
}
})
Benefits
With schema validation you get:
- Autocompletion - Field suggestions as you type
- Validation - Immediate feedback on typos and invalid values
- Documentation - Hover tooltips explaining each field
- Type checking - Catch errors before running
kg validate
Schema Location
The schema is versioned with releases:
- Latest:
https://raw.githubusercontent.com/CarteraMesh/kiro-generator/refs/heads/main/schemas/kg.json - Specific version:
https://raw.githubusercontent.com/CarteraMesh/kiro-generator/refs/tags/v0.1.0/schemas/kg.json
Pin to a specific version for stability or use main for latest features.