commit ba18c0feaa43b3f34f5348208f15f9396e6b7dc9 Author: rob Date: Fri Nov 28 04:30:55 2025 -0400 Initial commit: SmartTools design and README A lightweight personal tool builder for AI-powered CLI commands. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..138c396 --- /dev/null +++ b/.gitignore @@ -0,0 +1,39 @@ +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# Virtual environments +.venv/ +venv/ +ENV/ + +# IDE +.idea/ +.vscode/ +*.swp +*.swo + +# OS +.DS_Store +Thumbs.db + +# Project specific +*.log diff --git a/README.md b/README.md new file mode 100644 index 0000000..a2a6783 --- /dev/null +++ b/README.md @@ -0,0 +1,79 @@ +# SmartTools + +A lightweight personal tool builder for AI-powered CLI commands. + +## What is this? + +SmartTools lets you create custom AI-powered terminal commands. You define a tool once (name, prompt, provider), then use it like any Linux command. + +```bash +# Create a summarizer, then use it like any command: +sum -i document.txt -o summary.txt --max 512 +``` + +## Quick Example + +A tool is just a YAML config: + +```yaml +# ~/.smarttools/sum/config.yaml +name: sum +description: "Summarize documents" +prompt: | + Summarize the following text in {max} words or less: + {input} +provider: codex +provider_args: "-p" +inputs: + - name: max + flag: --max + default: 500 +``` + +Then run it: + +```bash +sum -i myfile.txt -o summary.txt +sum -i myfile.txt --dry-run # preview prompt +sum -i myfile.txt --provider mock # test without API +``` + +## Features + +- **Simple UI** - Create/edit/delete tools with `dialog`-based interface +- **CLI-first** - Tools work like regular Linux commands +- **Provider-agnostic** - Use Codex, Claude, Gemini, or any CLI AI tool +- **Testing built-in** - `--dry-run`, `--show-prompt`, `--provider mock` +- **Minimal** - ~430 lines of Python, minimal dependencies + +## Installation + +```bash +pip install smarttools +``` + +## Usage + +```bash +# Launch UI to manage tools +smarttools + +# Or use CLI: +smarttools list +smarttools create mytool +smarttools edit mytool +smarttools delete mytool +smarttools test mytool +``` + +## Documentation + +See [docs/DESIGN.md](docs/DESIGN.md) for the full design document. + +## Philosophy + +This is a **personal power tool**. You write the tools, you run the tools, you accept the responsibility. No trust tiers, no sandboxing, no signing - just like any bash script you write. + +## License + +MIT diff --git a/docs/DESIGN.md b/docs/DESIGN.md new file mode 100644 index 0000000..587ebe7 --- /dev/null +++ b/docs/DESIGN.md @@ -0,0 +1,304 @@ +# 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:** +```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 + post.py # optional post-processing script + reviewer/ + config.yaml + translator/ + config.yaml +``` + +### Minimal config.yaml + +```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 + +```bash +# 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 + +```bash +# 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) + +```python +# 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) + +```python +# 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: + +```bash +#!/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.