# SmartTools - Design Document > 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, steps, provider), then use it like any Linux command. **Example:** ```bash # 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 processed.py # Optional external code file reviewer/ config.yaml translator/ config.yaml ``` ### config.yaml Format ```yaml 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}" ``` ### Step Types **Prompt Step** - Calls an AI provider: ```yaml - type: prompt prompt: "Your prompt template with {variables}" provider: claude output_var: response ``` **Code Step** - Runs Python code: ```yaml - type: code code: | processed = input.upper() count = len(processed.split()) output_var: processed, count code_file: processed.py # Optional: external file storage ``` 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:** ```yaml output_var: processed ``` ```python processed = input.upper() # This gets captured ``` **Multiple variables (comma-separated):** ```yaml output_var: processed, count, summary ``` ```python 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 ```bash # 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 # 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 # Interactive stdin input sum --stdin # No input (empty string) - useful for tools using only arguments sum --max 100 # Or via smarttools run smarttools run sum -i document.txt ``` ### Input Handling | Scenario | Behavior | |----------|----------| | Piped stdin | Automatically read (`cat file.txt \| mytool`) | | `-i file.txt` | Read from file | | `--stdin` | Interactive input (type then Ctrl+D) | | No input | Empty string (useful for argument-only tools) | ### Universal Flags (all tools) | Flag | Short | Description | |------|-------|-------------| | `--input` | `-i` | Input file | | `--output` | `-o` | Output file (or stdout if omitted) | | `--stdin` | | Read input interactively (type then Ctrl+D) | | `--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 ```bash # Launch the UI to manage tools smarttools # Or use CLI directly: smarttools list # List all tools smarttools create sum # Create new tool (basic) smarttools edit sum # Edit tool config in $EDITOR smarttools delete sum # Delete tool smarttools test sum # Test with mock provider smarttools run sum # Run tool for real smarttools refresh # Refresh all wrapper scripts smarttools ui # Launch interactive UI ``` ## Terminal UI A BIOS-style terminal UI using `urwid` with full mouse support. ### Main Menu ``` ┌──────────────────────────────────────┐ │ SmartTools Manager │ ├──────────────────────────────────────┤ │ Tools: │ │ ┌────────────────────────────────┐ │ │ │ sum │ │ │ │ reviewer │ │ │ │ translator │ │ │ └────────────────────────────────┘ │ │ │ │ [Create] [Edit] [Delete] [Test] │ │ │ │ Tool Info: │ │ Name: sum │ │ Description: Summarize documents │ │ Arguments: --max │ │ Steps: PROMPT[claude] -> {response} │ │ │ │ [EXIT] │ └──────────────────────────────────────┘ ``` ### Tool Builder ``` ┌──────────────────────────────────────────────────────────────┐ │ New Tool │ ├──────────────────────────────────────────────────────────────┤ │ ┌─[ Tool Info ]──────────┐ ┌─ Arguments ─────────────────┐ │ │ │ Name: [sum__________] │ │ --max -> {max} │ │ │ │ │ │ │ │ │ │ Desc: [Summarize____] │ └─────────────────────────────┘ │ │ │ │ [Add] [Edit] [Delete] │ │ │ Output: [{response}_] │ │ │ └────────────────────────┘ ┌─ Execution Steps ───────────┐ │ │ │ P:claude -> {response} │ │ │ │ │ │ │ └─────────────────────────────┘ │ │ [Add] [Edit] [Delete] │ │ │ │ [Save] [Cancel] │ └──────────────────────────────────────────────────────────────┘ ``` **Navigation:** - **Tab** - Cycle between sections (Tool Info -> Arguments -> Steps -> Buttons) - **Arrow keys** - Navigate within lists - **Enter/Click** - Select/activate - **Escape** - Cancel/back - **Shift + mouse** - Terminal-native text selection (bypasses UI mouse handling) - **Ctrl+Shift+V** - Paste The current section's title is highlighted with brackets: `[ Tool Info ]` **Copy/Paste tip:** Hold `Shift` while dragging with mouse to select text, then use your terminal's copy function (usually right-click or Ctrl+Shift+C). ### Code Step Dialog ``` ┌──────────────── Add Code Step ─────────────────┐ │ Variables: input, max, response │ │ │ │ File: [processed.py______________] < Load > │ │ │ │ ┌─ Code ─────────────────────────────────────┐ │ │ │processed = input.upper() │ │ │ │count = len(processed.split()) │ │ │ │ │ │ │ └────────────────────────────────────────────┘ │ │ │ │ Output var: [processed, count____] │ ├────────────────────────────────────────────────┤ │ < OK > < Cancel > │ └────────────────────────────────────────────────┘ ``` **Code Step Features:** - **Multiline editor** - Write multi-line Python code - **External file storage** - Code is auto-saved to `~/.smarttools//` on OK - **Load button** - Load code from external file (with confirmation) - **Multiple output vars** - Capture multiple variables (comma-separated) ## Implementation ### Directory Structure ``` smarttools/ __init__.py cli.py # Entry point, argument parsing ui.py # UI dispatcher (chooses urwid/snack/dialog) ui_urwid.py # Urwid-based BIOS-style UI ui_snack.py # Snack/newt fallback UI tool.py # Tool loading/saving/wrapper scripts runner.py # Execute tools providers.py # Provider abstraction ``` ### Provider System Providers are defined in `~/.smarttools/providers.yaml`: ```yaml providers: - name: claude command: "claude -p" description: "Anthropic Claude" - name: codex command: "codex -p" description: "OpenAI Codex" - name: gemini command: "gemini" description: "Google Gemini" ``` The provider command receives the prompt via stdin and outputs to stdout. ### Wrapper Scripts When you save a tool, SmartTools creates a wrapper script in `~/.local/bin/`: ```bash #!/bin/bash # SmartTools wrapper for 'sum' # Auto-generated - do not edit exec /path/to/python -m smarttools.runner sum "$@" ``` The wrapper uses the full Python path to ensure the correct environment is used. Use `smarttools refresh` to regenerate all wrapper scripts (e.g., after changing Python environments). ### Tool Name Validation Tool names must: - Start with a letter or underscore - Contain only letters, numbers, underscores, and dashes - Not contain spaces or shell-problematic characters (`/\|&;$`"'<>(){}[]!?*#~`) ## 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 `smarttools` 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. ## Default Values | Step Type | Default Output Var | Default File | |-----------|-------------------|--------------| | Prompt | `response` | n/a | | Code | `processed` | `processed.py` |