Skip to main content

CmdForge Design Document

A lightweight personal tool builder for AI-powered CLI commands

Overview

CmdForge lets you create custom AI-powered terminal commands. You define a tool once (name, steps, provider), then use it like any Linux command.

Example:

# Create a summarizer tool, then use it:
sum -i text.txt -o summary.txt --max 512

Core Concepts

Tool = Directory + Config

~/.cmdforge/
sum/
config.yaml
processed.py # Optional external code file
reviewer/
config.yaml
translator/
config.yaml

config.yaml Format

name: sum
description: "Summarize documents"
arguments:
- flag: --max
variable: max
default: "500"
description: "Maximum words in summary"
steps:
- type: prompt
prompt: |
Summarize the following text in {max} words or less:

{input}
provider: claude
output_var: response
output: "{response}"

# Optional: declare dependencies for meta-tools
dependencies:
- official/summarize
- official/translate@^1.0.0 # With version constraint

Step Types

Prompt Step - Calls an AI provider:

- type: prompt
prompt: "Your prompt template with {variables}"
provider: claude
output_var: response

Code Step - Runs Python code:

- type: code
code: |
processed = input.upper()
count = len(processed.split())
output_var: processed, count
code_file: processed.py # Optional: external file storage

Tool Step - Calls another CmdForge tool (meta-tools):

- type: tool
tool: official/summarize # Tool reference (owner/name or just name for local)
input: "{input}" # Input to pass (supports variable substitution)
args: # Optional arguments
max_words: "100"
output_var: summary # Variable to store the tool's output
provider: claude # Optional: override the called tool's provider

Steps execute in order. Each step's output_var becomes available to subsequent steps.

Variables

  • {input} - Always available, contains stdin or input file content (empty string if no input)
  • {variable_name} - From arguments (e.g., {max})
  • {output_var} - From previous steps (e.g., {response}, {processed})

Output Variables

The output_var field specifies which Python variable(s) to capture from your code:

Single variable:

output_var: processed
processed = input.upper()  # This gets captured

Multiple variables (comma-separated):

output_var: processed, count, summary
processed = input.upper()
count = len(processed.split())
summary = f"Processed {count} words"
# All three are captured and available as {processed}, {count}, {summary}

CLI Interface

Running Tools

# Basic usage (wrapper script in ~/.local/bin)
sum -i document.txt -o summary.txt

# With custom args
sum -i document.txt --max 200

# Preview prompt without calling AI
sum -i document.txt --dry-run

# Test with mock (no API call)
sum -i document.txt --provider mock

# Read from stdin, write to stdout
cat doc.txt | sum | less

# Or via cmdforge run
cmdforge run sum -i document.txt

Input Handling

ScenarioBehavior
Piped stdinAutomatically read (cat file.txt | mytool)
-i file.txtRead from file
--stdinInteractive input (type then Ctrl+D)
No inputEmpty string (useful for argument-only tools)

Universal Flags (all tools)

FlagShortDescription
--input-iInput file
--output-oOutput file (or stdout if omitted)
--stdinRead input interactively (type then Ctrl+D)
--dry-runShow prompt, don't call AI
--show-promptCall AI but also print prompt to stderr
--provider-pOverride provider (e.g., --provider mock)
--verbose-vShow debug info
--help-hShow help

Managing Tools

cmdforge list              # List all tools
cmdforge create sum # Create new tool (basic)
cmdforge edit sum # Edit tool config in $EDITOR
cmdforge delete sum # Delete tool
cmdforge test sum # Test with mock provider
cmdforge run sum # Run tool for real
cmdforge refresh # Refresh all wrapper scripts
cmdforge check sum # Check dependencies for meta-tools
cmdforge ui # Launch interactive UI

Tool Composition

CmdForge tools are designed to chain together like any Unix command.

External Pipelines (Tool-to-Tool)

# Chain multiple CmdForge tools
cat logs.txt | log-errors | summarize | translate --lang Japanese

# Mix with standard Unix tools
git log --oneline | head -20 | changelog | tee CHANGELOG.md

# Build complex workflows
cat *.py | review-code --focus security | json-extract --fields "issue, severity, file" | json2csv

Each tool reads stdin and writes stdout. No special integration needed.

Internal Pipelines (Multi-Step)

Within a single tool, chain steps for preprocessing/validation:

steps:
- type: code # Preprocess
code: |
filtered = '\n'.join(l for l in input.split('\n') if 'ERROR' in l)
output_var: filtered
- type: prompt # AI processes filtered input
prompt: "Explain these errors: {filtered}"
provider: claude-haiku
output_var: explanation
- type: code # Post-process
code: |
result = f"Found {len(filtered.split(chr(10)))} errors:\n\n{explanation}"
output_var: result
output: "{result}"

When to use which:

  • External pipelines: Reusable tools, different providers per stage, standard Unix interop
  • Internal pipelines: Tightly coupled steps, shared context, validation of AI output

What This Design Doesn't Include

Intentionally omitted (not needed for personal use):

  • Trust tiers / security levels
  • Cryptographic signing
  • Container isolation / sandboxing
  • Certification testing
  • Distribution packaging
  • PII redaction
  • Audit logging
  • Provider capability negotiation

Why? This is a personal tool builder. You write the tools, you run the tools, you accept the responsibility. Just like any bash script you write.

Dependencies

Required:

  • Python 3.10+
  • PyYAML
  • urwid (for TUI)

Optional fallbacks:

  • python3-newt/snack (simpler TUI)
  • dialog/whiptail (basic TUI)

Example Workflow

  1. Run cmdforge to open UI
  2. Select "Create" to create a new tool
  3. Fill in: name, description, output template
  4. Add arguments (e.g., --max with default 500)
  5. Add a prompt step with your prompt template and provider
  6. Click "Save"
  7. Exit UI
  8. Run sum -i myfile.txt -o summary.txt

Done. No containers, no signing, no certification. Just a tool that works.