CmdForge Architecture
Module Structure
-src/cmdforge/
├── cli/ # CLI commands
│ ├── __init__.py
│ ├── tool_commands.py # list, create, edit, delete
│ ├── provider_commands.py # providers management
│ └── registry_commands.py # publish, install
├── registry/ # Registry API
│ ├── app.py # Flask API endpoints
│ ├── db.py # SQLite schema and queries
│ ├── sync.py # Git repo sync
│ └── rate_limit.py
├── web/ # Web UI
│ ├── app.py # Flask app factory
│ ├── routes.py # Page routes
│ ├── auth.py # User authentication
│ ├── forum/ # Forum feature
│ ├── templates/ # Jinja2 templates
│ └── static/ # CSS, JS
├── ui_urwid/ # Terminal UI
│ ├── __init__.py # Main TUI
│ ├── widgets.py # Custom widgets
│ └── palette.py # Color scheme
├── tool.py # Tool dataclass and loading
├── runner.py # Tool execution engine
└── providers.py # AI provider abstraction
src/cmdforge/
├── cli/ # CLI commands
│ ├── __init__.py
│ ├── tool_commands.py # list, create, edit, delete
│ ├── provider_commands.py # providers management
│ └── registry_commands.py # publish, install
├── registry/ # Registry API
│ ├── app.py # Flask API endpoints
│ ├── db.py # SQLite schema and queries
│ ├── sync.py # Git repo sync
│ └── rate_limit.py
├── web/ # Web UI (cmdforge.brrd.tech)
│ ├── app.py # Flask app factory
│ ├── routes.py # Page routes
│ ├── auth.py # User authentication
│ ├── forum/ # Forum feature
│ ├── templates/ # Jinja2 templates
│ └── static/ # CSS, JS
├── gui/ # Desktop GUI (PySide6)
│ ├── __init__.py # Entry point, run_gui()
│ ├── main_window.py # Main window with sidebar
│ ├── styles.py # QSS stylesheet
│ ├── pages/ # Application pages
│ │ ├── tools_page.py # Tool list and details
│ │ ├── tool_builder_page.py # Create/edit tools
│ │ ├── registry_page.py # Browse/install tools
│ │ └── providers_page.py # Provider management
│ └── dialogs/ # Modal dialogs
│ ├── step_dialog.py # Prompt/code step editors
│ ├── argument_dialog.py
│ ├── provider_dialog.py
│ ├── connect_dialog.py # Registry connect
│ └── publish_dialog.py
├── tool.py # Tool dataclass and loading
├── runner.py # Tool execution engine
└── providers.py # AI provider abstraction
Data Flow
CLI Tool Execution
User Input (stdin)
│
▼
┌─────────────┐
│ runner.py │ ──── Loads tool from ~/.cmdforge/<name>/config.yaml
└─────────────┘
│
▼
┌─────────────┐
│ Steps │
│ (prompt/ │ ──── For prompt steps, calls providers.py
│ code) │ ──── For code steps, exec() Python
└─────────────┘
│
▼
Output (stdout)
@dataclass
class ToolSource:
type: str # "original", "imported", "forked"
license: str
url: str
author: str
original_tool: str # e.g., "fabric/patterns/extract_wisdom"
Provider (providers.py)
@dataclass
class Provider:
name: str # e.g., "opencode-pickle"
command: str # e.g., "$HOME/.opencode/bin/opencode run --model ..."
description: str
Error Handling
+The runner provides detailed error messages for debugging:
+Code Step Errors
+When Python code fails in a code step, shows:
+-
+
- Step number and error type +
- Offending line with context (line before/after) +
- Visual pointer (
>>>) to error line
+ - List of available variables +
Error in code step (step 2):
NameError: name 'undefined_var' is not defined
1: data = input.split('\n')
>>> 2: result = undefined_var + data
3: output = result
Available variables: ['input', 'max_size', 'step1_output']
YAML Syntax Errors
+When a tool's config.yaml has syntax errors:
+-
+
- Line and column number +
- Visual pointer to exact position +
- Context line above +
Error loading tool 'my-tool': YAML syntax error
Line 15, column 8
14: steps:
> 15: - type prompt # missing colon
^
Problem: expected ',' or ']'
Nested Tool Errors
+When a tool calls another tool that fails, shows the full call stack:
+Error in tool chain:
my-wrapper (step 2)
-> summarize (step 1)
-> Tool 'missing-tool' not found
Registry Database
+SQLite schema for published tools:
+CREATE TABLE tools (
id INTEGER PRIMARY KEY,
name TEXT UNIQUE NOT NULL,
description TEXT,
category TEXT DEFAULT 'Other',
config_yaml TEXT NOT NULL, -- Full tool YAML
source TEXT, -- Deprecated (type only)
source_url TEXT, -- Deprecated
source_json TEXT, -- Full ToolSource as JSON
published_at TIMESTAMP,
downloads INTEGER DEFAULT 0,
owner_id INTEGER REFERENCES users(id)
);
The source_json column stores the complete ToolSource object, preserving all attribution fields when tools are published.
Configuration Files
-| File | Location | Purpose |
|---|---|---|
| Tool config | ~/.cmdforge/<name>/config.yaml | Tool definition |
| Providers | ~/.cmdforge/providers.yaml | AI provider commands |
| Main config | ~/.cmdforge/config.yaml | Registry URL, client ID |