🏛️ Architecture
Understanding Code Puppy's internal architecture helps you extend and customize it effectively.
Architecture Overview
┌─────────────────────────────────────────────────────────┐
│ Main CLI Loop │
│ (main.py) │
├─────────────────────────────────────────────────────────┤
│ Agent Manager │
│ (Discovery, Loading, Switching, Session Tracking) │
├──────────────┬──────────────┬──────────────┬────────────┤
│ BaseAgent │ JSONAgent │ Specialized │ Custom │
│ (Abstract) │ (From JSON) │ Agents │ Agents │
├──────────────┴──────────────┴──────────────┴────────────┤
│ Tool System │
│ (File Ops, Shell, Browser, Agent Invocation) │
├─────────────────────────────────────────────────────────┤
│ Model Factory │
│ (OpenAI, Anthropic, Google, Mistral, etc.) │
├─────────────────────────────────────────────────────────┤
│ MCP Manager │
│ (External Tool Integration via MCP Protocol) │
└─────────────────────────────────────────────────────────┘
Package Structure
Core Package: code_puppy/
| File | Purpose |
|---|---|
main.py | CLI loop and main application logic |
config.py | Global configuration manager |
model_factory.py | Constructs LLM models from configuration |
models.json | Available models and metadata registry |
callbacks.py | Plugin callback system |
session_storage.py | Session persistence |
Agents Package: code_puppy/agents/
| File | Purpose |
|---|---|
base_agent.py | Abstract base class for all agents |
agent_manager.py | Agent discovery, loading, switching |
json_agent.py | JSON-based agent configuration system |
agent_code_puppy.py | Default code generation agent |
agent_*.py | Specialized agents (planning, review, etc.) |
Tools Package: code_puppy/tools/
| File | Purpose |
|---|---|
file_operations.py | List, read, grep filesystem operations |
file_modifications.py | File editing with diffs |
command_runner.py | Shell command execution |
agent_tools.py | Agent invocation and reasoning tools |
browser/ | Browser automation tools (30+) |
Command Line: code_puppy/command_line/
| File | Purpose |
|---|---|
command_handler.py | Command dispatch and routing |
command_registry.py | Command registration system |
core_commands.py | Core CLI commands |
config_commands.py | Configuration commands |
session_commands.py | Session management commands |
mcp/ | MCP subcommands |
MCP System: code_puppy/mcp_/
| File | Purpose |
|---|---|
manager.py | MCP server lifecycle management |
health_monitor.py | Server health monitoring |
circuit_breaker.py | Circuit breaker pattern |
retry_manager.py | Retry logic |
Agent System
The agent system uses inheritance and composition:
BaseAgent (Abstract)
├── CodePuppyAgent (Built-in Python agent)
├── PlanningAgent (Built-in Python agent)
├── CodeReviewerAgent (Built-in Python agent)
├── ...
└── JSONAgent (Loads from JSON config)
├── user-agent-1.json
├── user-agent-2.json
└── ...
Tool Registration
Tools are registered using decorators:
from code_puppy.tools import register_tool
@register_tool("my_custom_tool")
async def my_tool(param1: str, param2: int = 10) -> dict:
"""Tool description for the LLM.
Args:
param1: Description of param1
param2: Description of param2 (default: 10)
Returns:
Result dictionary
"""
return {"success": True, "result": "..."}
Message Flow
User Input
↓
[Command Handler] ───────── /command? ───▶ Execute Command
↓ (chat message)
[Plugin Callbacks: before_message]
↓
[Current Agent] ───▶ Prepares context + system prompt
↓
[Model Factory] ───▶ Routes to appropriate provider
↓
[LLM Provider] ───▶ API call (OpenAI, Anthropic, etc.)
↓
[Response Stream] ──▶ Streaming output to console
↓
[Tool Calls?] ────────── Yes ───▶ Execute Tools ───▶ Loop back
↓ No
[Plugin Callbacks: after_response]
↓
Display to User
File Size Guidelines
🧘 Zen Puppy Approves
Keep files under 600 lines! If a file grows beyond that, split it into smaller, composable files.