smarttools/docs/DESIGN.md

8.7 KiB

SmartTools - Simple Design

A lightweight personal tool builder for AI-powered CLI commands

Overview

SmartTools lets you create custom AI-powered terminal commands. You define a tool once (name, prompt, 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

~/.smarttools/
  sum/
    config.yaml
    post.py          # optional post-processing script
  reviewer/
    config.yaml
  translator/
    config.yaml

Minimal config.yaml

name: sum
description: "Summarize documents"
prompt: |
  Summarize the following text in {max} words or less:

  {input}  

provider: codex
provider_args: "-p"

# Optional
inputs:
  - name: max
    flag: --max
    default: 500

# Optional post-processing script
post_process: post.py

That's it. No trust tiers, no signing, no containers.

CLI Interface

Running Tools

# Basic usage
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

# See what prompt gets sent
sum -i document.txt --show-prompt

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

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

Universal Flags (all tools)

Flag Short Description
--input -i Input file (or stdin if omitted)
--output -o Output file (or stdout if omitted)
--dry-run Show prompt, don't call AI
--show-prompt Call AI but also print prompt to stderr
--provider -p Override provider (e.g., --provider mock)
--verbose -v Show debug info
--help -h Show help

Managing Tools

# Launch the UI to manage tools
smarttools

# Or use CLI directly:
smarttools list              # List all tools
smarttools create sum        # Create new tool
smarttools edit sum          # Edit existing tool
smarttools delete sum        # Delete tool
smarttools test sum          # Test with mock provider

Lightweight UI

A simple terminal UI using dialog or whiptail (available on most Linux systems).

Main Menu

┌──────────────────────────────────────┐
│         SmartTools Manager           │
├──────────────────────────────────────┤
│  > List Tools                        │
│    Create New Tool                   │
│    Edit Tool                         │
│    Delete Tool                       │
│    Test Tool                         │
│    Exit                              │
└──────────────────────────────────────┘

Create/Edit Tool Form

┌──────────────────────────────────────┐
│           Create New Tool            │
├──────────────────────────────────────┤
│ Name:        [sum________________]   │
│ Description: [Summarize documents_]  │
│ Provider:    [codex_____________]    │
│ Provider Args: [-p________________]  │
│                                      │
│ Prompt:                              │
│ ┌──────────────────────────────────┐ │
│ │ Summarize the following text     │ │
│ │ in {max} words or less:          │ │
│ │                                  │ │
│ │ {input}                          │ │
│ └──────────────────────────────────┘ │
│                                      │
│ Custom Arguments:                    │
│   --max (default: 500)               │
│   [Add Argument]                     │
│                                      │
│ Post-process Script: [none______▼]   │
│                                      │
│     [Save]  [Test]  [Cancel]         │
└──────────────────────────────────────┘

Test Tool

┌──────────────────────────────────────┐
│            Test Tool: sum            │
├──────────────────────────────────────┤
│ Input: [Select file...] or [Paste]   │
│                                      │
│ ┌─ Final Prompt ───────────────────┐ │
│ │ Summarize the following text     │ │
│ │ in 500 words or less:            │ │
│ │                                  │ │
│ │ Lorem ipsum dolor sit amet...    │ │
│ └──────────────────────────────────┘ │
│                                      │
│ Provider: [mock_____▼]               │
│                                      │
│     [Run Test]  [Copy Command]       │
└──────────────────────────────────────┘

"Copy Command" shows: sum -i test.txt --dry-run

Implementation

Directory Structure

smarttools/
  __init__.py
  cli.py           # Entry point, argument parsing
  ui.py            # Dialog-based UI
  tool.py          # Tool loading/saving
  runner.py        # Execute tools
  providers.py     # Provider abstraction (minimal)

Provider Abstraction (Simple)

# providers.py
import subprocess

def call_provider(provider: str, args: str, prompt: str) -> str:
    """Call an AI CLI tool with the given prompt."""
    cmd = f"{provider} {args}"
    result = subprocess.run(
        cmd,
        shell=True,
        input=prompt,
        capture_output=True,
        text=True
    )
    if result.returncode != 0:
        raise RuntimeError(f"Provider failed: {result.stderr}")
    return result.stdout

def mock_provider(prompt: str) -> str:
    """Return a mock response for testing."""
    return f"[MOCK RESPONSE]\nReceived prompt of {len(prompt)} chars"

Tool Runner (Simple)

# runner.py
import yaml
from pathlib import Path

TOOLS_DIR = Path.home() / ".smarttools"

def load_tool(name: str) -> dict:
    config_path = TOOLS_DIR / name / "config.yaml"
    return yaml.safe_load(config_path.read_text())

def build_prompt(tool: dict, input_text: str, args: dict) -> str:
    prompt = tool["prompt"]
    prompt = prompt.replace("{input}", input_text)
    for key, value in args.items():
        prompt = prompt.replace(f"{{{key}}}", str(value))
    return prompt

def run_tool(name: str, input_text: str, args: dict, provider_override: str = None) -> str:
    tool = load_tool(name)
    prompt = build_prompt(tool, input_text, args)

    provider = provider_override or tool["provider"]
    if provider == "mock":
        return mock_provider(prompt)

    return call_provider(provider, tool.get("provider_args", ""), prompt)

Generated Wrapper Script

When you create a tool, SmartTools generates a wrapper script:

#!/bin/bash
# ~/.smarttools/sum/sum (auto-generated)
exec python3 -m smarttools.run sum "$@"

And symlinks it to ~/.local/bin/sum so you can call sum directly.

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

Minimal:

  • Python 3.10+
  • PyYAML
  • dialog or whiptail (pre-installed on most Linux)

Optional:

  • textual (if you want a fancier TUI later)

File Sizes

Estimated implementation:

  • cli.py: ~100 lines
  • ui.py: ~150 lines
  • tool.py: ~80 lines
  • runner.py: ~60 lines
  • providers.py: ~40 lines

Total: ~430 lines of Python

Example Workflow

  1. Run smarttools to open UI
  2. Select "Create New Tool"
  3. Fill in: name=sum, prompt, provider=codex
  4. Click "Test" to verify with mock provider
  5. Click "Save"
  6. Exit UI
  7. Run sum -i myfile.txt -o summary.txt

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