Charlie
Configure different AI agents (slash commands, MCP servers, and rules) with a single configuration.
Ask AI about Charlie
Powered by Claude Β· Grounded in docs
I know everything about Charlie. Ask me about installation, configuration, usage, or troubleshooting.
0/500
Reviews
Documentation
Charlie - Universal Agent Config Generator
Define once in YAML/Markdown. Generate agent-specific commands, MCP config, and rules.
Charlie is a universal agent configuration generator that produces agent-specific commands, MCP configurations, and rules from a single YAML/Markdown spec.
Features
- β¨ Single Definition: Write settings once in YAML or Markdown
- π€ Multi-Agent Support: Generate for different AI agents (Claude, Cursor, GitHub Copilot, and OpenCode supported)
- βοΈ Slash Commands Integration: Generate slash commands from a single definition.
- π MCP Integration: Generate MCP server configurations with tool schemas
- π Rules Generation: Create agent-specific rules files with manual preservation
- π΅οΈ Subagent Support: Define specialized AI sub-assistants once
- π§ Skills Support: Package domain knowledge as reusable skills agents invoke automatically
- π― Auto-Detection: Automatically finds
charlie.yamlor.charlie/directory - β‘ Runtime Targeting: Choose which agents to generate for at runtime
- π¦ Library & CLI: Use as CLI tool or import as Python library
- π Configuration Inheritance: Extend configurations from external Git repositories
Quick Start
Installation
Install via pip
pip install charlie-agents
Use Docker
Charlie is available as a Docker image, so you don't need to install Python dependencies:
# Pull the image from GitHub Container Registry
docker pull ghcr.io/henriquemoody/charlie:latest
# Run charlie commands (mount your project directory)
docker run --rm -v $(pwd):/workspace ghcr.io/henriquemoody/charlie list-agents
# Generate configuration
docker run --rm -v $(pwd):/workspace ghcr.io/henriquemoody/charlie generate claude
Create an alias for convenience:
Add to your .bashrc or .zshrc:
alias charlie='docker run --rm -v $(pwd):/workspace ghcr.io/henriquemoody/charlie'
Then use it like the native CLI:
charlie generate claude
charlie validate
charlie list-agents
Configuration
For advanced features, Charlie supports two configuration approaches:
- Monolithic - Single YAML file (good for small projects)
- Directory-Based - Modular files in
.charlie/directories (good for large projects)
Monolithic Configuration
For advanced features, create charlie.yaml in your project:
version: "1.0" # Optional: Schema version (defaults to "1.0")
extends: # Optional: Define it when you want to extend another repository's configuration
- git@github.com:MyOrg/team-config.git#v1.0
project:
name: "My project" # Optional: Inferred from directory name if omitted
namespace: "my" # Optional: Used to prefix commands, rules, and MCP servers.
variables:
mcp_api_token: ~ # It will ask the user to provide an API token, if the environment variable is not set
# Command definitions
commands:
- name: "commit"
description: "Analyze changes and create a high-quality git commit"
prompt: "Check what changed, and commit your changes. The body of the message explains WHY it changed"
- name: "command-handler"
description: "Creates a command handler"
prompt: "Create a command handler using src/examples/handler.py as an reference"
# MCP server definitions
mcp_servers:
- name: "local_server"
type: "stdio"
command: "node"
args: ["server.js"]
env:
KEY: "value"
- name: "remote_server"
url: "https://example.com/mcp"
headers:
Authorization: "Bearer {{var:mcp_api_token}}"
Content-Type: "application/json"
# Rules configuration (rules)
rules:
- description: "Commit message standards"
prompt: "Use [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/)"
- description: "Coding standards"
prompt: "All code should follow PEP 8"
# Subagent definitions (optional)
subagents:
- name: "code-reviewer"
description: "Expert code reviewer. Use proactively after code changes."
prompt: |
You are a senior code reviewer. When invoked:
1. Run git diff to see recent changes
2. Review for quality, security, and best practices
3. Provide feedback organized by priority
metadata:
tools: "Read, Grep, Glob, Bash"
model: sonnet
# Skill definitions (optional)
skills:
- name: "explain-code"
description: "Explains code with visual diagrams and analogies. Use when explaining how code works."
prompt: |
When explaining code, always include:
1. An analogy from everyday life
2. An ASCII diagram showing the flow
3. A step-by-step walkthrough
4. A common gotcha or misconception
- name: "deploy"
description: "Deploy the application to production"
prompt: |
Deploy the application:
1. Run the test suite
2. Build the application
3. Push to the deployment target
4. Verify the deployment succeeded
metadata:
disable-model-invocation: true
# Ignore patterns (optional) -- will be added to agent-specific ignore files
ignore_patterns:
- "*.log"
- "tmp/"
- "node_modules/"
Charlie will also read charlie.dist.yaml, unless you have a charlie.yaml in the directory.
See examples/ directory for complete examples:
examples/simple/- Basic configurationexamples/speckit/- Spec-kit inspired configuration
Configuration Inheritance (extends)
Charlie supports inheriting configuration from external Git repositories. This allows you to share common configurations across multiple projects or organizations:
extends:
- https://github.com/MyOrg/shared-agent-config
- git@github.com:MyOrg/team-config.git#v1.0
# Local commands, rules, etc. will be merged with extended configs
commands:
- name: "local-command"
description: "A project-specific command"
prompt: "Do something specific to this project"
How it works:
- Charlie fetches each repository in the
extendslist (in order) - Configurations are merged sequentially - later entries override earlier ones
- Your local configuration is merged last, taking highest precedence
- Duplicate items (commands, rules, MCP servers, variables) are overwritten with a warning
When duplicates are detected, Charlie displays a warning:
β Overwriting command 'init' from https://github.com/MyOrg/shared-config
β Overwriting rule 'coding-standards' from https://github.com/MyOrg/shared-config
Version/Branch Support:
Use URL fragments to specify a branch or tag:
https://github.com/Org/Config#main- use themainbranchhttps://github.com/Org/Config#v1.0.0- use thev1.0.0taggit@github.com:Org/Config.git#feature-branch- use a specific branch
Directory-Based Configuration
For better organization and collaboration, use the directory-based approach. The charlie.yaml file is optional - if you only have a .charlie/ directory, Charlie will infer the project name from the directory:
project/
βββ charlie.yaml # Optional: Project metadata (name inferred if omitted)
βββ .charlieignore # Optional: Patterns to exclude from AI agents
βββ .charlie/
βββ commands/
β βββ init.yaml # One file per command (Markdown or YAML supported)
β βββ deploy.md
βββ rules/
β βββ commit-messages.yaml # One file per rule (Markdown or YAML supported)
β βββ code-style.md
βββ agents/
β βββ code-reviewer.md # One file per subagent (Markdown with YAML frontmatter)
β βββ debugger.md
βββ skills/
β βββ explain-code.md # Flat file skill (Markdown with YAML frontmatter)
β βββ deploy/ # Directory-based skill
β βββ SKILL.md # Skill definition (required)
β βββ deploy.sh # Companion files (copied to output)
β βββ templates/
β βββ config.yaml
βββ mcp-servers/
βββ local-tools.yaml # MCP servers in YAML
See examples/directory-based/ for a complete example.
Benefits:
- Clear organization (one file per command/rule)
- No merge conflicts on single file
- Easy to add/remove components
- Better for version control diffs
- Native markdown support for rich documentation
Generate Agent-specific Configuration
# Generate configuration files for a specific agent (generates commands, MCP, and rules by default)
charlie generate claude
Placeholders
Charlie supports these universal placeholders in commands, rules, and MCP configurations:
Project Placeholders:
{{project_dir}}β Resolves to the project root directory{{project_name}}β Replaced with the project name (e.g.,My Project){{project_namespace}}β Replaced with the project namespace (e.g.,my)
Agent Placeholders:
{{agent_name}}β Replaced with the agent's full name (e.g.,Claude Code,Cursor){{agent_shortname}}β Replaced with the agent's short identifier (e.g.,claude,cursor){{agent_dir}}β Resolves to agent's base directory (e.g.,.claude,.cursor){{commands_shorthand_injection}}β Agent-specific command shorthand (e.g.,$ARGUMENTSfor supported agents)
Agent Path Placeholders:
{{commands_dir}}β Resolves to agent's commands directory (e.g.,.claude/skills,.cursor/commands){{rules_dir}}β Resolves to agent's rules directory (e.g.,.claude/rules/){{rules_file}}β Resolves to agent's rules file path (e.g.,CLAUDE.md,.cursor/rules){{subagents_dir}}β Resolves to agent's subagents directory (e.g.,.claude/agents){{skills_dir}}β Resolves to agent's skills directory (e.g.,.claude/skills){{mcp_file}}β Resolves to agent's MCP configuration file name (e.g.,mcp.json){{assets_dir}}β Resolves to agent's assets directory (e.g.,.claude/assets)
Variable Placeholders:
{{var:VARIABLE_NAME}}β Replaced with the value of a variable defined in yourcharlie.yaml- Variables can be defined in the
variables:section - Use
~as value to prompt user for input if not set as environment variable - Example:
{{var:mcp_api_token}} - Charlie will prompt user for input if variable is not set.
- Variables can be defined in the
Environment Variable Placeholders:
{{env:VAR_NAME}}β Replaced with the value of the environment variable- Loads from system environment or
.envfile in root directory - Raises
EnvironmentVariableNotFoundErrorif variable doesn't exist - System environment variables take precedence over
.envfile
- Loads from system environment or
Custom Replacements:
- Custom placeholders can be defined per-command or per-rule using the
replacementsfield - See the Library API section for examples
These placeholders work in commands, rules, and MCP server configurations (command, args, URL, and headers fields).
Usage
CLI Commands
charlie generate <agent>
Setup agent-specific configurations (generates commands, MCP config, and rules by default):
# Auto-detect charlie.yaml (generates all artifacts)
charlie generate claude
# Setup without MCP config
charlie generate cursor --no-mcp
# Setup without rules (rules)
charlie generate claude --no-rules
# Setup without commands
charlie generate claude --no-commands
# Setup without subagents
charlie generate claude --no-subagents
# Setup without skills
charlie generate claude --no-skills
# Explicit config file
charlie generate cursor --config my-config.yaml
# Custom output directory
charlie generate cursor --output ./build
charlie validate
Validate YAML configuration:
# Auto-detect charlie.yaml
charlie validate
# Specific file
charlie validate my-config.yaml
charlie list-agents
List all supported AI agents:
charlie list-agents
charlie info <agent>
Show detailed information about an agent:
charlie info claude
charlie info cursor
Library API
Use Charlie programmatically in Python:
from charlie import AgentRegistry, AgentConfiguratorFactory, Tracker
from charlie.schema import Project, Command, Rule, Skill, Subagent, HttpMCPServer, StdioMCPServer, ValueReplacement
from charlie.enums import RuleMode
# Initialize registry and get agent
registry = AgentRegistry()
agent = registry.get("claude")
# Create project configuration
project = Project(
name="My Project",
namespace="my",
dir="/path/to/project",
)
# Create configurator
configurator = AgentConfiguratorFactory.create(
agent=agent,
project=project,
tracker=Tracker()
)
# Generate commands
configurator.commands([
Command(
name="commit",
description="Analyze changes and create a high-quality git commit",
prompt="Check what changed, and commit your changes. The body of the message explains WHY it changed",
metadata={
"allowed-tools": "Bash(git add:*), Bash(git status:*), Bash(git commit:*)"
},
replacements={}
),
Command(
name="deploy",
description="Deploy the application",
prompt="Run {{script}}",
metadata={},
replacements={
"script": ValueReplacement(
type="value",
value=".claude/assets/deploy.sh"
)
}
)
])
# Generate MCP configuration
configurator.mcp_servers([
HttpMCPServer(
name="my-http-server",
type="http",
url="https://example.com/mcp",
headers={
"Authorization": "Bearer F8417EA8-94F3-447C-A108-B0AD7E428BE6",
"Content-Type": "application/json"
},
),
StdioMCPServer(
name="my-stdio-server",
type="stdio",
command="node",
args=["server.js"],
env={
"API_TOKEN": "84EBB71B-0FF8-49D8-84C8-55FF9550CA2C"
},
),
])
# Generate rules (rules)
configurator.rules(
[
Rule(
name="commit-messages",
description="Commit message standards",
prompt="Use [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/)",
metadata={
"alwaysApply": True,
},
replacements={}
),
Rule(
name="coding-standards",
description="Coding standards",
prompt="All code should follow {{standard}}",
metadata={},
replacements={
"standard": ValueReplacement(
type="value",
value="PEP 8"
)
}
)
],
RuleMode.MERGED
)
# Generate subagents
configurator.subagents([
Subagent(
name="code-reviewer",
description="Expert code reviewer. Use proactively after code changes.",
prompt="You are a senior code reviewer. Analyze code for quality, security, and best practices.",
metadata={
"tools": "Read, Grep, Glob, Bash",
"model": "sonnet",
},
)
])
# Generate skills
configurator.skills([
Skill(
name="explain-code",
description="Explains code with visual diagrams and analogies. Use when explaining how code works.",
prompt="When explaining code, always include an analogy, an ASCII diagram, and a step-by-step walkthrough.",
),
Skill(
name="deploy",
description="Deploy the application to production",
prompt="Deploy the application: run tests, build, push, verify.",
metadata={
"disable-model-invocation": True,
"allowed-tools": "Bash(./deploy.sh)",
},
),
])
# Copy assets to the agent's directory
configurator.assets([
".charlie/assets/deploy.sh",
])
Supported Agents
Charlie currently supports the following AI agents:
- Claude Code (
claude) - Claude's AI coding assistant - Cursor (
cursor) - AI-powered code editor - GitHub Copilot (
copilot) - GitHub's AI pair programmer - OpenCode (
opencode) - Open-source AI coding agent
Run charlie list-agents to see all available agents.
Note: Claude Code has merged custom commands into skills. Charlie generates Claude commands as
.claude/skills/{name}/SKILL.md(the same format as skills). OpenCode also treats commands as skills, generating them as.opencode/skills/{name}/SKILL.md. For Cursor, commands are still generated as.cursor/commands/{name}.md.
Metadata support
Charlie uses pass-through metadata - add any agent-specific metadata to your commands or rules, and Charlie will include them in generated output:
Charlie extracts these fields and includes them in agent-specific output (YAML frontmatter for Markdown agents, TOML fields for TOML agents). See AGENT_FIELDS.md for details on which agents support which fields.
Rules Generation Modes
Rules (rules) can be generated in two modes:
Merged Mode (default) - Single file with all sections:
charlie generate cursor --rules-mode merged
Separate Mode - One file per section:
charlie generate cursor --rules-mode separate
Use merged mode for simple projects, separate mode for better organization in complex projects.
Subagents
Subagents are specialized AI sub-assistants that handle specific types of tasks. Charlie lets you define them once and generate the appropriate files for each supported tool.
Define subagents
Directory-based β create .charlie/agents/<name>.md:
---
description: Expert code reviewer. Use proactively after code changes.
tools: Read, Grep, Glob, Bash
model: sonnet
---
You are a senior code reviewer. When invoked:
1. Run git diff to see recent changes
2. Review for quality, security, and best practices
3. Provide feedback organized by priority: Critical / Warnings / Suggestions
The filename becomes the subagent name (e.g., code-reviewer.md β code-reviewer). Override it with a name: field in the frontmatter.
YAML inline β add a subagents: section to charlie.yaml:
subagents:
- name: code-reviewer
description: Expert code reviewer. Use proactively after code changes.
prompt: |
You are a senior code reviewer...
metadata:
tools: "Read, Grep, Glob, Bash"
model: sonnet
Generated output
| Agent | Output | Supported metadata |
|---|---|---|
| Claude Code | .claude/agents/{name}.md | tools, disallowedTools, model, permissionMode, maxTurns, skills, mcpServers, hooks, memory, background, isolation |
| Cursor | .cursor/agents/{name}.md | model, readonly, is_background |
| GitHub Copilot | β (skipped) | β |
| OpenCode | .opencode/agents/{name}.md | description, tools, model, permission |
See AGENT_FIELDS.md for a full metadata field reference.
Namespace support
When a namespace is set, subagent filenames are prefixed:
- Claude:
.claude/agents/myapp-code-reviewer.md - Cursor:
.cursor/agents/myapp.code-reviewer.md
Skills
Skills are portable, version-controlled packages that teach agents how to perform domain-specific tasks. Unlike commands (which users invoke explicitly), skills can be loaded automatically by the agent when relevant to the conversation.
Define skills
Charlie supports three ways to define skills:
Flat file β create .charlie/skills/<name>.md:
---
description: Explains code with visual diagrams and analogies. Use when explaining how code works.
---
When explaining code, always include:
1. **Start with an analogy**: Compare the code to something from everyday life
2. **Draw a diagram**: Use ASCII art to show the flow, structure, or relationships
3. **Walk through the code**: Explain step-by-step what happens
4. **Highlight a gotcha**: What's a common mistake or misconception?
The filename becomes the skill name (e.g., explain-code.md β explain-code). Override it with a name: field in the frontmatter.
Directory-based β create .charlie/skills/<name>/SKILL.md:
.charlie/skills/deploy/
βββ SKILL.md # Skill definition (required)
βββ deploy.sh # Companion files (copied to output)
βββ templates/
βββ config.yaml
---
description: Deploy the application to production
disable-model-invocation: true
---
Deploy the application:
1. Run the test suite
2. Build using the template at `{{skills_dir}}/deploy/templates/config.yaml`
3. Execute `{{skills_dir}}/deploy/deploy.sh`
4. Verify the deployment succeeded
The directory name becomes the skill name (e.g., deploy/ β deploy). Any files alongside SKILL.md are automatically copied to the output skill directory, preserving the relative path structure. This lets skills bundle scripts, templates, or reference material that the agent can access at runtime.
YAML inline β add a skills: section to charlie.yaml:
skills:
- name: explain-code
description: Explains code with visual diagrams and analogies. Use when explaining how code works.
prompt: |
When explaining code, always include an analogy, an ASCII diagram, and a step-by-step walkthrough.
- name: deploy
description: Deploy the application to production
prompt: |
Deploy the application:
1. Run the test suite
2. Build the application
3. Push to the deployment target
metadata:
disable-model-invocation: true
Both flat and directory-based skills can coexist in the same .charlie/skills/ folder.
Generated output
| Agent | Output | Supported metadata |
|---|---|---|
| Claude Code | .claude/skills/{name}/SKILL.md | description, argument-hint, disable-model-invocation, user-invocable, allowed-tools, model, context, agent, hooks |
| Cursor | .cursor/skills/{name}/SKILL.md | description, disable-model-invocation, license, compatibility |
| GitHub Copilot | β (skipped) | β |
| OpenCode | .opencode/skills/{name}/SKILL.md | description, license, compatibility |
Each skill is output as a directory containing a SKILL.md file, following the Agent Skills open standard. Companion files from directory-based skills are copied alongside SKILL.md in the output.
Namespace support
When a namespace is set, skill directory names are prefixed:
- Claude:
.claude/skills/myapp-explain-code/SKILL.md - Cursor:
.cursor/skills/myapp.explain-code/SKILL.md
Invocation control
Use disable-model-invocation: true in metadata to prevent the agent from loading the skill automatically β useful for workflows with side effects (deploys, commits, etc.) that you want to trigger manually with /skill-name.
Development
Use Dev Container (optional)
Open the project in VS Code with the Dev Containers extension:
- Open the project in VS Code
- Press
F1and select "Dev Containers: Reopen in Container" - Wait for the container to build (first time only)
- Start coding with all tools pre-configured (pytest, mypy, ruff)
The Dev Container provides a consistent development environment with all dependencies and VS Code extensions pre-installed.
Developer commands
# Install dev dependencies
pip install -e ".[dev]"
# Run tests
pytest # or `make test`
# Run with coverage
pytest --cov=charlie # or `make test-coverage`
# Run ruff
ruff check . # or `make lint` (`make format` to format the code)
# Run mypy
mypy --install-types --non-interactive src/charlie # or `make analyze`
Contributing
Contributions welcome! Key areas:
- Adding support for new AI agents
- Improving documentation
- Adding more examples
- Bug fixes and tests
License
MIT
Acknowledgments
Charlie was inspired by the need to maintain consistent command definitions across multiple AI agents in the Spec Kit project.
