Rename project from SmartTools to CmdForge

Major rename operation:
- Rename Python package: smarttools -> cmdforge
- Update CLI entry point: smarttools -> cmdforge
- Update all imports and module references
- Update pyproject.toml with new name, URLs, entry point
- Update all HTML templates with new branding
- Update documentation (CLAUDE.md, README.md, docs/*, wiki/*)
- Update environment variables:
  - SMARTTOOLS_ENV -> CMDFORGE_ENV
  - SMARTTOOLS_REGISTRY_DB -> CMDFORGE_REGISTRY_DB
  - SMARTTOOLS_TOKEN -> CMDFORGE_TOKEN
  - SMARTTOOLS_REGISTRY_* -> CMDFORGE_REGISTRY_*
- Update Dockerfile and docker-compose.yml
- Update tests to use new package name
- Update scripts and examples
- Update package.json and tailwind.config.js

All 158 unit tests pass. The CLI is working correctly with the
new cmdforge command.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
rob 2026-01-02 22:15:55 -04:00
parent 2939dd806b
commit 497fe87fc5
113 changed files with 822 additions and 822 deletions

View File

@ -21,7 +21,7 @@ What should have happened?
## Environment ## Environment
- OS: - OS:
- SmartTools version: - CmdForge version:
- Provider: - Provider:
- Docker or native install? - Docker or native install?

View File

@ -1,6 +1,6 @@
--- ---
name: Question name: Question
about: Ask a question about SmartTools about: Ask a question about CmdForge
labels: question labels: question
--- ---

View File

@ -1,7 +1,7 @@
# Repository Guidelines # Repository Guidelines
## Project Structure & Module Organization ## Project Structure & Module Organization
- `src/smarttools/` contains the core Python package (CLI entry point, tool model, runner, providers, UI backends). - `src/cmdforge/` contains the core Python package (CLI entry point, tool model, runner, providers, UI backends).
- `tests/` holds pytest suites. - `tests/` holds pytest suites.
- `docs/` includes installation, provider setup, examples, and design notes. - `docs/` includes installation, provider setup, examples, and design notes.
- `examples/` provides sample tools and an installer script. - `examples/` provides sample tools and an installer script.
@ -15,11 +15,11 @@
- `ui_urwid.py` and `ui_snack.py` provide the TUI implementations, selected by `ui.py`. - `ui_urwid.py` and `ui_snack.py` provide the TUI implementations, selected by `ui.py`.
## Build, Test, and Development Commands ## Build, Test, and Development Commands
- `pip install -e ".[dev]"` installs SmartTools in editable mode with dev dependencies. - `pip install -e ".[dev]"` installs CmdForge in editable mode with dev dependencies.
- `pytest` runs the full test suite. - `pytest` runs the full test suite.
- `pytest tests/test.py::test_name` runs a focused test. - `pytest tests/test.py::test_name` runs a focused test.
- `python -m smarttools.cli` runs the CLI module directly. - `python -m cmdforge.cli` runs the CLI module directly.
- `smarttools ui` launches the TUI (requires `urwid` or `python-newt`). - `cmdforge ui` launches the TUI (requires `urwid` or `python-newt`).
- `docker-compose build` builds the dev container image. - `docker-compose build` builds the dev container image.
- `docker-compose run --rm test` runs tests inside Docker. - `docker-compose run --rm test` runs tests inside Docker.
@ -38,5 +38,5 @@
- PRs should include a clear summary, test results (or rationale if tests are skipped), and screenshots when UI behavior changes. - PRs should include a clear summary, test results (or rationale if tests are skipped), and screenshots when UI behavior changes.
## Security & Configuration Tips ## Security & Configuration Tips
- Provider credentials live in `~/.smarttools/providers.yaml`; avoid committing secrets. - Provider credentials live in `~/.cmdforge/providers.yaml`; avoid committing secrets.
- User tool configs live in `~/.smarttools/<toolname>/config.yaml` and should not be added to the repo. - User tool configs live in `~/.cmdforge/<toolname>/config.yaml` and should not be added to the repo.

View File

@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## Project Overview ## Project Overview
SmartTools is a lightweight personal tool builder for AI-powered CLI commands. It lets users create custom terminal commands that call AI providers, chain prompts with Python code steps, and use them like any Unix pipe command. CmdForge is a lightweight personal tool builder for AI-powered CLI commands. It lets users create custom terminal commands that call AI providers, chain prompts with Python code steps, and use them like any Unix pipe command.
## Development Commands ## Development Commands
@ -19,29 +19,29 @@ pytest
pytest tests/test.py::test_name pytest tests/test.py::test_name
# Run the CLI # Run the CLI
python -m smarttools.cli python -m cmdforge.cli
# Launch the UI # Launch the UI
smarttools ui cmdforge ui
``` ```
## Architecture ## Architecture
### Core Modules (`src/smarttools/`) ### Core Modules (`src/cmdforge/`)
- **cli.py**: Entry point (`smarttools` command). Routes subcommands: list, create, edit, delete, test, run, ui, refresh - **cli.py**: Entry point (`cmdforge` command). Routes subcommands: list, create, edit, delete, test, run, ui, refresh
- **tool.py**: Tool definition dataclasses (`Tool`, `ToolArgument`, `PromptStep`, `CodeStep`), YAML config loading/saving, wrapper script generation - **tool.py**: Tool definition dataclasses (`Tool`, `ToolArgument`, `PromptStep`, `CodeStep`), YAML config loading/saving, wrapper script generation
- **runner.py**: Execution engine. Runs tool steps sequentially, handles variable substitution (`{input}`, `{varname}`), executes Python code steps via `exec()` - **runner.py**: Execution engine. Runs tool steps sequentially, handles variable substitution (`{input}`, `{varname}`), executes Python code steps via `exec()`
- **providers.py**: Provider abstraction. Calls AI CLI tools via subprocess, reads provider configs from `~/.smarttools/providers.yaml` - **providers.py**: Provider abstraction. Calls AI CLI tools via subprocess, reads provider configs from `~/.cmdforge/providers.yaml`
- **ui.py**: UI dispatcher - selects between urwid and snack implementations - **ui.py**: UI dispatcher - selects between urwid and snack implementations
- **ui_urwid.py**: Full TUI implementation using urwid library - **ui_urwid.py**: Full TUI implementation using urwid library
- **ui_snack.py**: Fallback TUI using python-newt/snack - **ui_snack.py**: Fallback TUI using python-newt/snack
### Key Paths ### Key Paths
- **Tools storage**: `~/.smarttools/<toolname>/config.yaml` - **Tools storage**: `~/.cmdforge/<toolname>/config.yaml`
- **Wrapper scripts**: `~/.local/bin/<toolname>` (auto-generated bash scripts) - **Wrapper scripts**: `~/.local/bin/<toolname>` (auto-generated bash scripts)
- **Provider config**: `~/.smarttools/providers.yaml` - **Provider config**: `~/.cmdforge/providers.yaml`
### Tool Structure ### Tool Structure
@ -67,7 +67,7 @@ Variable substitution is simple string replacement in `runner.py:substitute_vari
## Provider System ## Provider System
Providers are CLI tools that accept prompts via stdin and output to stdout. Defined in `~/.smarttools/providers.yaml`: Providers are CLI tools that accept prompts via stdin and output to stdout. Defined in `~/.cmdforge/providers.yaml`:
```yaml ```yaml
providers: providers:
@ -81,9 +81,9 @@ The `mock` provider is built-in for testing without API calls.
## Web UI & Registry ## Web UI & Registry
SmartTools includes a web interface and tool registry: CmdForge includes a web interface and tool registry:
### Web Modules (`src/smarttools/web/`) ### Web Modules (`src/cmdforge/web/`)
- **app.py**: Flask app factory, registers blueprints - **app.py**: Flask app factory, registers blueprints
- **routes.py**: Main web routes (docs, tutorials, tools, etc.) - **routes.py**: Main web routes (docs, tutorials, tools, etc.)
@ -93,7 +93,7 @@ SmartTools includes a web interface and tool registry:
- **filters.py**: Jinja2 filters (timeago, markdown, etc.) - **filters.py**: Jinja2 filters (timeago, markdown, etc.)
- **docs_content.py**: Documentation and tutorial content - **docs_content.py**: Documentation and tutorial content
### Registry Modules (`src/smarttools/registry/`) ### Registry Modules (`src/cmdforge/registry/`)
- **app.py**: Registry API (tool publishing, search, downloads) - **app.py**: Registry API (tool publishing, search, downloads)
- **db.py**: SQLite schema and queries - **db.py**: SQLite schema and queries
@ -109,8 +109,8 @@ SmartTools includes a web interface and tool registry:
```bash ```bash
# Development # Development
python -m smarttools.web.app python -m cmdforge.web.app
# Production (example) # Production (example)
SMARTTOOLS_REGISTRY_DB=/path/to/db PORT=5050 python -m smarttools.web.app CMDFORGE_REGISTRY_DB=/path/to/db PORT=5050 python -m cmdforge.web.app
``` ```

View File

@ -1,11 +1,11 @@
# SmartTools - AI-powered CLI command builder # CmdForge - AI-powered CLI command builder
# Build: docker build -t smarttools . # Build: docker build -t cmdforge .
# Run: docker run -it --rm -v ~/.smarttools:/root/.smarttools smarttools # Run: docker run -it --rm -v ~/.cmdforge:/root/.cmdforge cmdforge
FROM python:3.12-slim FROM python:3.12-slim
LABEL maintainer="rob" LABEL maintainer="rob"
LABEL description="SmartTools - Personal AI-powered CLI command builder" LABEL description="CmdForge - Personal AI-powered CLI command builder"
# Install system dependencies # Install system dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \ RUN apt-get update && apt-get install -y --no-install-recommends \
@ -34,24 +34,24 @@ COPY examples/ ./examples/
COPY docs/ ./docs/ COPY docs/ ./docs/
COPY tests/ ./tests/ COPY tests/ ./tests/
# Install SmartTools and all dependencies (CLI, TUI, registry) # Install CmdForge and all dependencies (CLI, TUI, registry)
RUN pip install --no-cache-dir -e ".[all,dev]" RUN pip install --no-cache-dir -e ".[all,dev]"
# Create smarttools directory # Create cmdforge directory
RUN mkdir -p /root/.smarttools /root/.local/bin RUN mkdir -p /root/.cmdforge /root/.local/bin
# Install example tools # Install example tools
RUN python examples/install.py RUN python examples/install.py
# Generate CLI wrappers # Generate CLI wrappers
RUN smarttools refresh RUN cmdforge refresh
# Add local bin to PATH # Add local bin to PATH
ENV PATH="/root/.local/bin:${PATH}" ENV PATH="/root/.local/bin:${PATH}"
# Default command - show help # Default command - show help
CMD ["smarttools", "--help"] CMD ["cmdforge", "--help"]
# For interactive use: # For interactive use:
# docker run -it --rm smarttools smarttools ui # docker run -it --rm cmdforge cmdforge ui
# docker run -it --rm smarttools bash # docker run -it --rm cmdforge bash

View File

@ -1,4 +1,4 @@
# SmartTools # CmdForge
**A lightweight personal tool builder for AI-powered CLI commands.** **A lightweight personal tool builder for AI-powered CLI commands.**
@ -20,7 +20,7 @@ echo "Price $49.99, SKU ABC-123" | json-extract --fields "price, sku"
# Output: {"price": 49.99, "sku": "ABC-123"} # Output: {"price": 49.99, "sku": "ABC-123"}
``` ```
## Why SmartTools? ## Why CmdForge?
- **Unix Philosophy** - Tools that do one thing well, composable with pipes - **Unix Philosophy** - Tools that do one thing well, composable with pipes
- **Provider Agnostic** - Works with Claude, GPT, Gemini, DeepSeek, local models - **Provider Agnostic** - Works with Claude, GPT, Gemini, DeepSeek, local models
@ -30,17 +30,17 @@ echo "Price $49.99, SKU ABC-123" | json-extract --fields "price, sku"
## Try It Now (60 seconds) ## Try It Now (60 seconds)
See SmartTools in action without installing anything on your system: See CmdForge in action without installing anything on your system:
```bash ```bash
# Pull the container # Pull the container
docker pull gitea.brrd.tech/rob/smarttools:latest docker pull gitea.brrd.tech/rob/cmdforge:latest
# Run it # Run it
docker run -it --rm gitea.brrd.tech/rob/smarttools bash docker run -it --rm gitea.brrd.tech/rob/cmdforge bash
# Inside the container - install OpenCode (includes free AI models) # Inside the container - install OpenCode (includes free AI models)
smarttools providers install # Select option 4, then 'y' cmdforge providers install # Select option 4, then 'y'
source ~/.bashrc source ~/.bashrc
# Try it! This explains the README using the free Big Pickle model # Try it! This explains the README using the free Big Pickle model
@ -55,21 +55,21 @@ For regular use, install natively:
```bash ```bash
# Clone and install # Clone and install
git clone https://gitea.brrd.tech/rob/SmartTools.git git clone https://gitea.brrd.tech/rob/CmdForge.git
cd SmartTools cd CmdForge
pip install -e . pip install -e .
# Ensure ~/.local/bin is in PATH # Ensure ~/.local/bin is in PATH
export PATH="$HOME/.local/bin:$PATH" export PATH="$HOME/.local/bin:$PATH"
# Install an AI provider (interactive guide) # Install an AI provider (interactive guide)
smarttools providers install cmdforge providers install
# Launch the UI # Launch the UI
smarttools ui cmdforge ui
# Or create your first tool # Or create your first tool
smarttools create summarize cmdforge create summarize
``` ```
## Installation ## Installation
@ -77,16 +77,16 @@ smarttools create summarize
### Native Install ### Native Install
```bash ```bash
git clone https://gitea.brrd.tech/rob/SmartTools.git git clone https://gitea.brrd.tech/rob/CmdForge.git
cd SmartTools cd CmdForge
pip install -e . pip install -e .
``` ```
### With Development Dependencies ### With Development Dependencies
```bash ```bash
git clone https://gitea.brrd.tech/rob/SmartTools.git git clone https://gitea.brrd.tech/rob/CmdForge.git
cd SmartTools cd CmdForge
pip install -e ".[dev]" pip install -e ".[dev]"
``` ```
@ -107,7 +107,7 @@ export PATH="$HOME/.local/bin:$PATH"
Then refresh wrapper scripts: Then refresh wrapper scripts:
```bash ```bash
smarttools refresh cmdforge refresh
``` ```
## Usage ## Usage
@ -115,7 +115,7 @@ smarttools refresh
### UI Mode (Recommended for Beginners) ### UI Mode (Recommended for Beginners)
```bash ```bash
smarttools ui cmdforge ui
``` ```
Navigate with arrow keys, Tab, Enter, and mouse. Create tools visually with the built-in prompt editor. Navigate with arrow keys, Tab, Enter, and mouse. Create tools visually with the built-in prompt editor.
@ -123,13 +123,13 @@ Navigate with arrow keys, Tab, Enter, and mouse. Create tools visually with the
### CLI Mode ### CLI Mode
```bash ```bash
smarttools list # List all tools cmdforge list # List all tools
smarttools create mytool # Create new tool cmdforge create mytool # Create new tool
smarttools edit mytool # Edit in $EDITOR cmdforge edit mytool # Edit in $EDITOR
smarttools delete mytool # Delete tool cmdforge delete mytool # Delete tool
smarttools run mytool # Run a tool cmdforge run mytool # Run a tool
smarttools test mytool # Test with mock provider cmdforge test mytool # Test with mock provider
smarttools refresh # Update executable wrappers cmdforge refresh # Update executable wrappers
``` ```
### Running Tools ### Running Tools
@ -155,10 +155,10 @@ cat file.txt | mytool --provider mock
### Composing Tools ### Composing Tools
SmartTools follows Unix philosophy: each tool does one thing well, and tools chain together for complex workflows. CmdForge follows Unix philosophy: each tool does one thing well, and tools chain together for complex workflows.
```bash ```bash
# Chain SmartTools together # Chain CmdForge together
cat error.log | log-errors | summarize | translate --lang Spanish cat error.log | log-errors | summarize | translate --lang Spanish
# Code review pipeline: focus on changes, review, then summarize # Code review pipeline: focus on changes, review, then summarize
@ -208,7 +208,7 @@ translate-doc() {
## Example Tools ## Example Tools
SmartTools comes with 28 pre-built examples you can install: CmdForge comes with 28 pre-built examples you can install:
### Text Processing ### Text Processing
@ -259,14 +259,14 @@ SmartTools comes with 28 pre-built examples you can install:
### Install Example Tools ### Install Example Tools
```bash ```bash
# Run the example installer (from the SmartTools directory) # Run the example installer (from the CmdForge directory)
python examples/install.py python examples/install.py
smarttools refresh cmdforge refresh
``` ```
## Providers ## Providers
SmartTools works with any AI CLI tool. We've profiled 12 providers: CmdForge works with any AI CLI tool. We've profiled 12 providers:
| Provider | Speed | Accuracy | Cost | Best For | | Provider | Speed | Accuracy | Cost | Best For |
|----------|-------|----------|------|----------| |----------|-------|----------|------|----------|
@ -281,7 +281,7 @@ See [docs/PROVIDERS.md](docs/PROVIDERS.md) for setup instructions.
## Tool Anatomy ## Tool Anatomy
A tool is a YAML config file in `~/.smarttools/<name>/config.yaml`: A tool is a YAML config file in `~/.cmdforge/<name>/config.yaml`:
```yaml ```yaml
name: summarize name: summarize
@ -429,7 +429,7 @@ This lets you generate or modify Python code using AI directly within the tool b
## Philosophy ## Philosophy
SmartTools is built on **Unix philosophy**: CmdForge is built on **Unix philosophy**:
1. **Do one thing well** - Each tool solves one problem. `summarize` summarizes. `translate` translates. No bloated mega-tools. 1. **Do one thing well** - Each tool solves one problem. `summarize` summarizes. `translate` translates. No bloated mega-tools.
@ -444,15 +444,15 @@ SmartTools is built on **Unix philosophy**:
## Contributing ## Contributing
```bash ```bash
git clone https://gitea.brrd.tech/rob/smarttools.git git clone https://gitea.brrd.tech/rob/cmdforge.git
cd smarttools cd cmdforge
pip install -e ".[dev]" pip install -e ".[dev]"
pytest pytest
``` ```
## Support ## Support
If SmartTools saves you time, consider supporting the project: If CmdForge saves you time, consider supporting the project:
**Bitcoin:** `3KeLqGv2Xo8jGYkqA1i68a6nXwgQnuJoza` **Bitcoin:** `3KeLqGv2Xo8jGYkqA1i68a6nXwgQnuJoza`
@ -470,16 +470,16 @@ Pull and run the pre-built image directly:
```bash ```bash
# Pull from registry # Pull from registry
docker pull gitea.brrd.tech/rob/smarttools:latest docker pull gitea.brrd.tech/rob/cmdforge:latest
# Run SmartTools # Run CmdForge
docker run -it --rm gitea.brrd.tech/rob/smarttools smarttools --help docker run -it --rm gitea.brrd.tech/rob/cmdforge cmdforge --help
# List available tools # List available tools
docker run -it --rm gitea.brrd.tech/rob/smarttools smarttools list docker run -it --rm gitea.brrd.tech/rob/cmdforge cmdforge list
# Interactive shell # Interactive shell
docker run -it --rm gitea.brrd.tech/rob/smarttools bash docker run -it --rm gitea.brrd.tech/rob/cmdforge bash
``` ```
### Build from Source ### Build from Source
@ -488,8 +488,8 @@ Alternatively, build the container yourself:
```bash ```bash
# Clone the repo # Clone the repo
git clone https://gitea.brrd.tech/rob/SmartTools.git git clone https://gitea.brrd.tech/rob/CmdForge.git
cd SmartTools cd CmdForge
# Build the container # Build the container
docker-compose build docker-compose build
@ -498,7 +498,7 @@ docker-compose build
docker-compose run --rm test docker-compose run --rm test
# Use the CLI # Use the CLI
docker-compose run --rm cli smarttools list docker-compose run --rm cli cmdforge list
# Interactive shell # Interactive shell
docker-compose run --rm shell docker-compose run --rm shell
@ -518,12 +518,12 @@ xhost +local:docker
docker run -it --rm \ docker run -it --rm \
-e DISPLAY=$DISPLAY \ -e DISPLAY=$DISPLAY \
-v /tmp/.X11-unix:/tmp/.X11-unix \ -v /tmp/.X11-unix:/tmp/.X11-unix \
-v smarttools-data:/root/.smarttools \ -v cmdforge-data:/root/.cmdforge \
--network host \ --network host \
gitea.brrd.tech/rob/smarttools bash gitea.brrd.tech/rob/cmdforge bash
# Inside the container: # Inside the container:
smarttools providers install cmdforge providers install
``` ```
**Using docker-compose (build from source):** **Using docker-compose (build from source):**
@ -533,14 +533,14 @@ xhost +local:docker
docker-compose run --rm setup docker-compose run --rm setup
# Inside the container: # Inside the container:
smarttools providers install cmdforge providers install
``` ```
**After installing a provider:** **After installing a provider:**
```bash ```bash
# Test the provider works # Test the provider works
smarttools providers test claude cmdforge providers test claude
``` ```
**Available Providers:** **Available Providers:**

View File

@ -1,9 +1,9 @@
# SmartTools - AI-powered CLI command builder # CmdForge - AI-powered CLI command builder
# #
# Quick Start: # Quick Start:
# docker-compose build # Build the image # docker-compose build # Build the image
# docker-compose run --rm test # Run tests # docker-compose run --rm test # Run tests
# docker-compose run --rm cli smarttools list # docker-compose run --rm cli cmdforge list
# #
# This is a standalone project with no external dependencies. # This is a standalone project with no external dependencies.
@ -17,10 +17,10 @@ services:
build: build:
context: . context: .
dockerfile: Dockerfile dockerfile: Dockerfile
image: smarttools:latest image: cmdforge:latest
volumes: volumes:
- smarttools-data:/root/.smarttools - cmdforge-data:/root/.cmdforge
command: ["smarttools", "--help"] command: ["cmdforge", "--help"]
# ============================================================================ # ============================================================================
# Tests # Tests
@ -29,9 +29,9 @@ services:
build: build:
context: . context: .
dockerfile: Dockerfile dockerfile: Dockerfile
image: smarttools:latest image: cmdforge:latest
volumes: volumes:
- smarttools-data:/root/.smarttools - cmdforge-data:/root/.cmdforge
command: ["pytest", "-v"] command: ["pytest", "-v"]
# ============================================================================ # ============================================================================
@ -41,9 +41,9 @@ services:
build: build:
context: . context: .
dockerfile: Dockerfile dockerfile: Dockerfile
image: smarttools:latest image: cmdforge:latest
volumes: volumes:
- smarttools-data:/root/.smarttools - cmdforge-data:/root/.cmdforge
command: ["/bin/bash"] command: ["/bin/bash"]
stdin_open: true stdin_open: true
tty: true tty: true
@ -57,11 +57,11 @@ services:
build: build:
context: . context: .
dockerfile: Dockerfile dockerfile: Dockerfile
image: smarttools:latest image: cmdforge:latest
environment: environment:
- DISPLAY=${DISPLAY:-:0} - DISPLAY=${DISPLAY:-:0}
volumes: volumes:
- smarttools-data:/root/.smarttools - cmdforge-data:/root/.cmdforge
- /tmp/.X11-unix:/tmp/.X11-unix:ro - /tmp/.X11-unix:/tmp/.X11-unix:ro
command: ["/bin/bash"] command: ["/bin/bash"]
stdin_open: true stdin_open: true
@ -69,8 +69,8 @@ services:
network_mode: host network_mode: host
volumes: volumes:
smarttools-data: cmdforge-data:
# Persists ~/.smarttools between container runs # Persists ~/.cmdforge between container runs
# ============================================================================== # ==============================================================================
# Usage Examples # Usage Examples
@ -83,8 +83,8 @@ volumes:
# docker-compose run --rm test # docker-compose run --rm test
# #
# Use CLI: # Use CLI:
# docker-compose run --rm cli smarttools list # docker-compose run --rm cli cmdforge list
# docker-compose run --rm cli smarttools run hello-world # docker-compose run --rm cli cmdforge run hello-world
# #
# Interactive shell: # Interactive shell:
# docker-compose run --rm shell # docker-compose run --rm shell
@ -93,5 +93,5 @@ volumes:
# xhost +local:docker # xhost +local:docker
# docker-compose run --rm setup # docker-compose run --rm setup
# # Inside container: # # Inside container:
# smarttools providers install # Interactive guide # cmdforge providers install # Interactive guide
# # Select a provider, it will install and open browser for auth # # Select a provider, it will install and open browser for auth

View File

@ -1,17 +1,17 @@
# SmartTools Deployment Guide # CmdForge Deployment Guide
This guide covers deploying the SmartTools Registry web application. This guide covers deploying the CmdForge Registry web application.
## Quick Start (Development) ## Quick Start (Development)
```bash ```bash
# Clone and install # Clone and install
git clone https://gitea.brrd.tech/rob/SmartTools.git git clone https://gitea.brrd.tech/rob/CmdForge.git
cd SmartTools cd CmdForge
pip install -e ".[dev]" pip install -e ".[dev]"
# Initialize database # Initialize database
cd src/smarttools/web cd src/cmdforge/web
python -c "from app import create_app; create_app()" python -c "from app import create_app; create_app()"
# Run development server # Run development server
@ -33,12 +33,12 @@ Access at `http://localhost:5050`
```bash ```bash
# Create application directory # Create application directory
sudo mkdir -p /opt/smarttools sudo mkdir -p /opt/cmdforge
sudo chown $USER:$USER /opt/smarttools sudo chown $USER:$USER /opt/cmdforge
cd /opt/smarttools cd /opt/cmdforge
# Clone repository # Clone repository
git clone https://gitea.brrd.tech/rob/SmartTools.git . git clone https://gitea.brrd.tech/rob/CmdForge.git .
# Create virtual environment # Create virtual environment
python3 -m venv venv python3 -m venv venv
@ -51,7 +51,7 @@ pip install gunicorn
### 2. Configure Environment ### 2. Configure Environment
Create `/opt/smarttools/.env`: Create `/opt/cmdforge/.env`:
```bash ```bash
# Required # Required
@ -60,40 +60,40 @@ SECRET_KEY=your-secret-key-here # Generate with: python -c "import secrets; pri
# Optional # Optional
SENTRY_DSN=https://xxx@sentry.io/xxx # Error monitoring SENTRY_DSN=https://xxx@sentry.io/xxx # Error monitoring
SITE_URL=https://registry.smarttools.dev # For sitemap/SEO SITE_URL=https://cmdforge.brrd.tech # For sitemap/SEO
``` ```
### 3. Initialize Database ### 3. Initialize Database
```bash ```bash
cd /opt/smarttools/src/smarttools/web cd /opt/cmdforge/src/cmdforge/web
python -c "from app import create_app; create_app()" python -c "from app import create_app; create_app()"
``` ```
Database will be created at `data/smarttools.db`. Database will be created at `data/cmdforge.db`.
### 4. systemd Service ### 4. systemd Service
Create `/etc/systemd/system/smarttools-web.service`: Create `/etc/systemd/system/cmdforge-web.service`:
```ini ```ini
[Unit] [Unit]
Description=SmartTools Registry Web Application Description=CmdForge Registry Web Application
After=network.target After=network.target
[Service] [Service]
Type=simple Type=simple
User=www-data User=www-data
Group=www-data Group=www-data
WorkingDirectory=/opt/smarttools WorkingDirectory=/opt/cmdforge
Environment="PATH=/opt/smarttools/venv/bin" Environment="PATH=/opt/cmdforge/venv/bin"
EnvironmentFile=/opt/smarttools/.env EnvironmentFile=/opt/cmdforge/.env
ExecStart=/opt/smarttools/venv/bin/gunicorn \ ExecStart=/opt/cmdforge/venv/bin/gunicorn \
--workers 4 \ --workers 4 \
--bind 127.0.0.1:5050 \ --bind 127.0.0.1:5050 \
--access-logfile /var/log/smarttools/access.log \ --access-logfile /var/log/cmdforge/access.log \
--error-logfile /var/log/smarttools/error.log \ --error-logfile /var/log/cmdforge/error.log \
'smarttools.web.app:create_app()' 'cmdforge.web.app:create_app()'
Restart=always Restart=always
RestartSec=5 RestartSec=5
@ -105,26 +105,26 @@ Enable and start:
```bash ```bash
# Create log directory # Create log directory
sudo mkdir -p /var/log/smarttools sudo mkdir -p /var/log/cmdforge
sudo chown www-data:www-data /var/log/smarttools sudo chown www-data:www-data /var/log/cmdforge
# Enable service # Enable service
sudo systemctl daemon-reload sudo systemctl daemon-reload
sudo systemctl enable smarttools-web sudo systemctl enable cmdforge-web
sudo systemctl start smarttools-web sudo systemctl start cmdforge-web
# Check status # Check status
sudo systemctl status smarttools-web sudo systemctl status cmdforge-web
``` ```
### 5. nginx Configuration ### 5. nginx Configuration
Create `/etc/nginx/sites-available/smarttools`: Create `/etc/nginx/sites-available/cmdforge`:
```nginx ```nginx
server { server {
listen 80; listen 80;
server_name registry.smarttools.dev; server_name cmdforge.brrd.tech;
# Redirect HTTP to HTTPS # Redirect HTTP to HTTPS
return 301 https://$server_name$request_uri; return 301 https://$server_name$request_uri;
@ -132,11 +132,11 @@ server {
server { server {
listen 443 ssl http2; listen 443 ssl http2;
server_name registry.smarttools.dev; server_name cmdforge.brrd.tech;
# SSL certificates (use certbot for Let's Encrypt) # SSL certificates (use certbot for Let's Encrypt)
ssl_certificate /etc/letsencrypt/live/registry.smarttools.dev/fullchain.pem; ssl_certificate /etc/letsencrypt/live/cmdforge.brrd.tech/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/registry.smarttools.dev/privkey.pem; ssl_certificate_key /etc/letsencrypt/live/cmdforge.brrd.tech/privkey.pem;
# SSL settings # SSL settings
ssl_protocols TLSv1.2 TLSv1.3; ssl_protocols TLSv1.2 TLSv1.3;
@ -145,7 +145,7 @@ server {
# Static files (optional - Flask can serve these) # Static files (optional - Flask can serve these)
location /static/ { location /static/ {
alias /opt/smarttools/src/smarttools/web/static/; alias /opt/cmdforge/src/cmdforge/web/static/;
expires 1d; expires 1d;
add_header Cache-Control "public, immutable"; add_header Cache-Control "public, immutable";
} }
@ -164,7 +164,7 @@ server {
Enable site: Enable site:
```bash ```bash
sudo ln -s /etc/nginx/sites-available/smarttools /etc/nginx/sites-enabled/ sudo ln -s /etc/nginx/sites-available/cmdforge /etc/nginx/sites-enabled/
sudo nginx -t sudo nginx -t
sudo systemctl reload nginx sudo systemctl reload nginx
``` ```
@ -173,7 +173,7 @@ sudo systemctl reload nginx
```bash ```bash
sudo apt install certbot python3-certbot-nginx sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d registry.smarttools.dev sudo certbot --nginx -d cmdforge.brrd.tech
``` ```
## Environment Variables ## Environment Variables
@ -184,16 +184,16 @@ sudo certbot --nginx -d registry.smarttools.dev
| `SECRET_KEY` | Yes | Secret key for sessions (32+ chars) | | `SECRET_KEY` | Yes | Secret key for sessions (32+ chars) |
| `SENTRY_DSN` | No | Sentry error monitoring DSN | | `SENTRY_DSN` | No | Sentry error monitoring DSN |
| `SITE_URL` | No | Public URL for sitemap generation | | `SITE_URL` | No | Public URL for sitemap generation |
| `DATABASE_PATH` | No | Override database path (default: `data/smarttools.db`) | | `DATABASE_PATH` | No | Override database path (default: `data/cmdforge.db`) |
## Database Backup ## Database Backup
```bash ```bash
# Backup # Backup
cp /opt/smarttools/data/smarttools.db /backup/smarttools-$(date +%Y%m%d).db cp /opt/cmdforge/data/cmdforge.db /backup/cmdforge-$(date +%Y%m%d).db
# Or use SQLite backup command for consistency # Or use SQLite backup command for consistency
sqlite3 /opt/smarttools/data/smarttools.db ".backup '/backup/smarttools.db'" sqlite3 /opt/cmdforge/data/cmdforge.db ".backup '/backup/cmdforge.db'"
``` ```
## Monitoring ## Monitoring
@ -202,11 +202,11 @@ sqlite3 /opt/smarttools/data/smarttools.db ".backup '/backup/smarttools.db'"
```bash ```bash
# Application logs # Application logs
tail -f /var/log/smarttools/error.log tail -f /var/log/cmdforge/error.log
tail -f /var/log/smarttools/access.log tail -f /var/log/cmdforge/access.log
# systemd logs # systemd logs
journalctl -u smarttools-web -f journalctl -u cmdforge-web -f
``` ```
### Sentry Integration ### Sentry Integration
@ -225,33 +225,33 @@ curl http://localhost:5050/api/v1/tools
```bash ```bash
# Check logs # Check logs
journalctl -u smarttools-web -n 50 journalctl -u cmdforge-web -n 50
# Verify Python path # Verify Python path
/opt/smarttools/venv/bin/python -c "import smarttools" /opt/cmdforge/venv/bin/python -c "import cmdforge"
# Test gunicorn manually # Test gunicorn manually
cd /opt/smarttools cd /opt/cmdforge
source venv/bin/activate source venv/bin/activate
gunicorn --bind 127.0.0.1:5050 'smarttools.web.app:create_app()' gunicorn --bind 127.0.0.1:5050 'cmdforge.web.app:create_app()'
``` ```
### Database errors ### Database errors
```bash ```bash
# Check database exists and is readable # Check database exists and is readable
ls -la /opt/smarttools/data/smarttools.db ls -la /opt/cmdforge/data/cmdforge.db
# Verify permissions # Verify permissions
chown www-data:www-data /opt/smarttools/data/ chown www-data:www-data /opt/cmdforge/data/
chown www-data:www-data /opt/smarttools/data/smarttools.db chown www-data:www-data /opt/cmdforge/data/cmdforge.db
``` ```
### Static files not loading ### Static files not loading
```bash ```bash
# Rebuild Tailwind CSS # Rebuild Tailwind CSS
cd /opt/smarttools cd /opt/cmdforge
npm install npm install
npm run css:build npm run css:build

View File

@ -1,10 +1,10 @@
# SmartTools - Design Document # CmdForge - Design Document
> A lightweight personal tool builder for AI-powered CLI commands > A lightweight personal tool builder for AI-powered CLI commands
## Overview ## 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. 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:** **Example:**
```bash ```bash
@ -17,7 +17,7 @@ sum -i text.txt -o summary.txt --max 512
### Tool = Directory + Config ### Tool = Directory + Config
``` ```
~/.smarttools/ ~/.cmdforge/
sum/ sum/
config.yaml config.yaml
processed.py # Optional external code file processed.py # Optional external code file
@ -128,8 +128,8 @@ sum --stdin
# No input (empty string) - useful for tools using only arguments # No input (empty string) - useful for tools using only arguments
sum --max 100 sum --max 100
# Or via smarttools run # Or via cmdforge run
smarttools run sum -i document.txt cmdforge run sum -i document.txt
``` ```
### Input Handling ### Input Handling
@ -158,17 +158,17 @@ smarttools run sum -i document.txt
```bash ```bash
# Launch the UI to manage tools # Launch the UI to manage tools
smarttools cmdforge
# Or use CLI directly: # Or use CLI directly:
smarttools list # List all tools cmdforge list # List all tools
smarttools create sum # Create new tool (basic) cmdforge create sum # Create new tool (basic)
smarttools edit sum # Edit tool config in $EDITOR cmdforge edit sum # Edit tool config in $EDITOR
smarttools delete sum # Delete tool cmdforge delete sum # Delete tool
smarttools test sum # Test with mock provider cmdforge test sum # Test with mock provider
smarttools run sum # Run tool for real cmdforge run sum # Run tool for real
smarttools refresh # Refresh all wrapper scripts cmdforge refresh # Refresh all wrapper scripts
smarttools ui # Launch interactive UI cmdforge ui # Launch interactive UI
``` ```
## Terminal UI ## Terminal UI
@ -179,7 +179,7 @@ A BIOS-style terminal UI using `urwid` with full mouse support.
``` ```
┌──────────────────────────────────────┐ ┌──────────────────────────────────────┐
SmartTools Manager │ CmdForge Manager │
├──────────────────────────────────────┤ ├──────────────────────────────────────┤
│ Tools: │ │ Tools: │
│ ┌────────────────────────────────┐ │ │ ┌────────────────────────────────┐ │
@ -256,7 +256,7 @@ The current section's title is highlighted with brackets: `[ Tool Info ]`
**Code Step Features:** **Code Step Features:**
- **Multiline editor** - Write multi-line Python code - **Multiline editor** - Write multi-line Python code
- **External file storage** - Code is auto-saved to `~/.smarttools/<toolname>/<filename>` on OK - **External file storage** - Code is auto-saved to `~/.cmdforge/<toolname>/<filename>` on OK
- **Load button** - Load code from external file (with confirmation) - **Load button** - Load code from external file (with confirmation)
- **Multiple output vars** - Capture multiple variables (comma-separated) - **Multiple output vars** - Capture multiple variables (comma-separated)
@ -265,7 +265,7 @@ The current section's title is highlighted with brackets: `[ Tool Info ]`
### Directory Structure ### Directory Structure
``` ```
smarttools/ cmdforge/
__init__.py __init__.py
cli.py # Entry point, argument parsing cli.py # Entry point, argument parsing
ui.py # UI dispatcher (chooses urwid/snack/dialog) ui.py # UI dispatcher (chooses urwid/snack/dialog)
@ -278,7 +278,7 @@ smarttools/
### Provider System ### Provider System
Providers are defined in `~/.smarttools/providers.yaml`: Providers are defined in `~/.cmdforge/providers.yaml`:
```yaml ```yaml
providers: providers:
@ -297,18 +297,18 @@ The provider command receives the prompt via stdin and outputs to stdout.
### Wrapper Scripts ### Wrapper Scripts
When you save a tool, SmartTools creates a wrapper script in `~/.local/bin/`: When you save a tool, CmdForge creates a wrapper script in `~/.local/bin/`:
```bash ```bash
#!/bin/bash #!/bin/bash
# SmartTools wrapper for 'sum' # CmdForge wrapper for 'sum'
# Auto-generated - do not edit # Auto-generated - do not edit
exec /path/to/python -m smarttools.runner sum "$@" exec /path/to/python -m cmdforge.runner sum "$@"
``` ```
The wrapper uses the full Python path to ensure the correct environment is used. 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). Use `cmdforge refresh` to regenerate all wrapper scripts (e.g., after changing Python environments).
### Tool Name Validation ### Tool Name Validation
@ -319,12 +319,12 @@ Tool names must:
## Tool Composition ## Tool Composition
SmartTools are designed to chain together like any Unix command. CmdForge are designed to chain together like any Unix command.
### External Pipelines (Tool-to-Tool) ### External Pipelines (Tool-to-Tool)
```bash ```bash
# Chain multiple SmartTools # Chain multiple CmdForge
cat logs.txt | log-errors | summarize | translate --lang Japanese cat logs.txt | log-errors | summarize | translate --lang Japanese
# Mix with standard Unix tools # Mix with standard Unix tools
@ -389,7 +389,7 @@ Optional fallbacks:
## Example Workflow ## Example Workflow
1. Run `smarttools` to open UI 1. Run `cmdforge` to open UI
2. Select "Create" to create a new tool 2. Select "Create" to create a new tool
3. Fill in: name, description, output template 3. Fill in: name, description, output template
4. Add arguments (e.g., `--max` with default `500`) 4. Add arguments (e.g., `--max` with default `500`)

View File

@ -1,13 +1,13 @@
# Example Tools # Example Tools
This document contains all 28 pre-built SmartTools with their full configurations. This document contains all 28 pre-built CmdForge with their full configurations.
## Quick Install ## Quick Install
```bash ```bash
# Install all example tools (from the SmartTools directory) # Install all example tools (from the CmdForge directory)
python examples/install.py python examples/install.py
smarttools refresh cmdforge refresh
``` ```
## Text Processing Tools ## Text Processing Tools
@ -17,7 +17,7 @@ smarttools refresh
Condense long documents to key points. Condense long documents to key points.
```yaml ```yaml
# ~/.smarttools/summarize/config.yaml # ~/.cmdforge/summarize/config.yaml
name: summarize name: summarize
description: Condense long documents to key points description: Condense long documents to key points
arguments: arguments:
@ -963,7 +963,7 @@ output: "{result}"
## Pipeline Recipes ## Pipeline Recipes
SmartTools chain together like Unix commands. Here are practical examples: CmdForge chain together like Unix commands. Here are practical examples:
### Development Workflows ### Development Workflows

View File

@ -1,15 +1,15 @@
# Installation Guide # Installation Guide
Complete installation instructions for SmartTools. Complete installation instructions for CmdForge.
## Quick Install ## Quick Install
```bash ```bash
git clone https://gitea.brrd.tech/rob/SmartTools.git git clone https://gitea.brrd.tech/rob/CmdForge.git
cd SmartTools cd CmdForge
pip install -e . pip install -e .
export PATH="$HOME/.local/bin:$PATH" export PATH="$HOME/.local/bin:$PATH"
smarttools providers install cmdforge providers install
``` ```
## Detailed Installation ## Detailed Installation
@ -32,11 +32,11 @@ brew install python@3.11
python3 --version # Should be 3.10 or higher python3 --version # Should be 3.10 or higher
``` ```
### Step 2: Install SmartTools ### Step 2: Install CmdForge
```bash ```bash
git clone https://gitea.brrd.tech/rob/SmartTools.git git clone https://gitea.brrd.tech/rob/CmdForge.git
cd SmartTools cd CmdForge
pip install -e . pip install -e .
``` ```
@ -47,7 +47,7 @@ pip install -e ".[dev]"
### Step 3: Configure PATH ### Step 3: Configure PATH
SmartTools creates executable wrappers in `~/.local/bin/`. Add this to your shell config: CmdForge creates executable wrappers in `~/.local/bin/`. Add this to your shell config:
**Bash (~/.bashrc):** **Bash (~/.bashrc):**
```bash ```bash
@ -74,7 +74,7 @@ source ~/.bashrc # or restart terminal
You need at least one AI CLI tool. The easiest way is the interactive installer: You need at least one AI CLI tool. The easiest way is the interactive installer:
```bash ```bash
smarttools providers install cmdforge providers install
``` ```
This guides you through installing and authenticating providers. This guides you through installing and authenticating providers.
@ -110,7 +110,7 @@ gemini # Opens browser for Google sign-in
```bash ```bash
curl -fsSL https://ollama.ai/install.sh | bash curl -fsSL https://ollama.ai/install.sh | bash
ollama pull llama3 ollama pull llama3
smarttools providers add ollama "ollama run llama3" -d "Local Llama 3" cmdforge providers add ollama "ollama run llama3" -d "Local Llama 3"
``` ```
See [PROVIDERS.md](PROVIDERS.md) for full provider setup instructions. See [PROVIDERS.md](PROVIDERS.md) for full provider setup instructions.
@ -118,17 +118,17 @@ See [PROVIDERS.md](PROVIDERS.md) for full provider setup instructions.
### Step 5: Verify Installation ### Step 5: Verify Installation
```bash ```bash
# Check SmartTools is installed # Check CmdForge is installed
smarttools --version cmdforge --version
# List configured providers # List configured providers
smarttools providers list cmdforge providers list
# Check which providers are available # Check which providers are available
smarttools providers check cmdforge providers check
# Test with mock provider (no AI needed) # Test with mock provider (no AI needed)
echo "hello world" | smarttools run --provider mock echo "hello world" | cmdforge run --provider mock
``` ```
### Step 6: Create Wrapper Scripts ### Step 6: Create Wrapper Scripts
@ -136,7 +136,7 @@ echo "hello world" | smarttools run --provider mock
After installation or any Python environment change: After installation or any Python environment change:
```bash ```bash
smarttools refresh cmdforge refresh
``` ```
This creates executable scripts in `~/.local/bin/` for all your tools. This creates executable scripts in `~/.local/bin/` for all your tools.
@ -147,18 +147,18 @@ This creates executable scripts in `~/.local/bin/` for all your tools.
```bash ```bash
python examples/install.py python examples/install.py
smarttools refresh cmdforge refresh
``` ```
### Manual Install ### Manual Install
Copy individual tool configs to `~/.smarttools/<toolname>/config.yaml`. Copy individual tool configs to `~/.cmdforge/<toolname>/config.yaml`.
See [EXAMPLES.md](EXAMPLES.md) for all tool configurations. See [EXAMPLES.md](EXAMPLES.md) for all tool configurations.
## Troubleshooting ## Troubleshooting
### "smarttools: command not found" ### "cmdforge: command not found"
PATH is not configured. Add to your shell config: PATH is not configured. Add to your shell config:
```bash ```bash
@ -168,14 +168,14 @@ export PATH="$HOME/.local/bin:$PATH"
### "Provider 'X' not found" ### "Provider 'X' not found"
1. Check provider is installed: `which claude` or `which opencode` 1. Check provider is installed: `which claude` or `which opencode`
2. Check provider is configured: `smarttools providers` 2. Check provider is configured: `cmdforge providers`
3. Add missing provider: `smarttools providers add` 3. Add missing provider: `cmdforge providers add`
### "Permission denied" on tool execution ### "Permission denied" on tool execution
Refresh wrapper scripts: Refresh wrapper scripts:
```bash ```bash
smarttools refresh cmdforge refresh
``` ```
### TUI doesn't start / looks broken ### TUI doesn't start / looks broken
@ -187,28 +187,28 @@ pip install urwid
Ensure your terminal supports mouse (most modern terminals do). Ensure your terminal supports mouse (most modern terminals do).
### Tools work with `smarttools run` but not directly ### Tools work with `cmdforge run` but not directly
The wrapper scripts may be outdated. Refresh them: The wrapper scripts may be outdated. Refresh them:
```bash ```bash
smarttools refresh cmdforge refresh
``` ```
### Python version mismatch ### Python version mismatch
If you have multiple Python versions, ensure SmartTools uses the right one: If you have multiple Python versions, ensure CmdForge uses the right one:
```bash ```bash
python3.11 -m pip install smarttools python3.11 -m pip install cmdforge
``` ```
## Uninstalling ## Uninstalling
```bash ```bash
# Remove package # Remove package
pip uninstall smarttools pip uninstall cmdforge
# Remove config and tools (optional) # Remove config and tools (optional)
rm -rf ~/.smarttools rm -rf ~/.cmdforge
# Remove wrapper scripts (optional) # Remove wrapper scripts (optional)
rm ~/.local/bin/{summarize,translate,fix-grammar,...} rm ~/.local/bin/{summarize,translate,fix-grammar,...}
@ -217,8 +217,8 @@ rm ~/.local/bin/{summarize,translate,fix-grammar,...}
## Upgrading ## Upgrading
```bash ```bash
pip install --upgrade smarttools pip install --upgrade cmdforge
smarttools refresh cmdforge refresh
``` ```
## Directory Structure ## Directory Structure
@ -226,7 +226,7 @@ smarttools refresh
After installation: After installation:
``` ```
~/.smarttools/ ~/.cmdforge/
├── providers.yaml # Provider configurations ├── providers.yaml # Provider configurations
├── summarize/ ├── summarize/
│ └── config.yaml # Tool config │ └── config.yaml # Tool config
@ -236,7 +236,7 @@ After installation:
└── ... └── ...
~/.local/bin/ ~/.local/bin/
├── smarttools # Main command ├── cmdforge # Main command
├── summarize # Tool wrapper script ├── summarize # Tool wrapper script
├── translate # Tool wrapper script ├── translate # Tool wrapper script
└── ... └── ...
@ -246,4 +246,4 @@ After installation:
1. [Set up providers](PROVIDERS.md) 1. [Set up providers](PROVIDERS.md)
2. [Browse example tools](EXAMPLES.md) 2. [Browse example tools](EXAMPLES.md)
3. Run `smarttools ui` to create your first tool 3. Run `cmdforge ui` to create your first tool

View File

@ -1,12 +1,12 @@
# SmartTools Project Overview # CmdForge Project Overview
This document provides a comprehensive overview of the SmartTools project structure, components, and how everything fits together. This document provides a comprehensive overview of the CmdForge project structure, components, and how everything fits together.
## What is SmartTools? ## What is CmdForge?
SmartTools is a personal tool builder for AI-powered CLI commands. It consists of three main components: CmdForge is a personal tool builder for AI-powered CLI commands. It consists of three main components:
1. **CLI Tool** (`smarttools`) - Create, manage, and run AI-powered command-line tools 1. **CLI Tool** (`cmdforge`) - Create, manage, and run AI-powered command-line tools
2. **Registry API** - REST API for publishing and discovering tools 2. **Registry API** - REST API for publishing and discovering tools
3. **Web UI** - Browser interface for the registry with docs, search, and user dashboard 3. **Web UI** - Browser interface for the registry with docs, search, and user dashboard
@ -14,11 +14,11 @@ SmartTools is a personal tool builder for AI-powered CLI commands. It consists o
| Component | Location | Purpose | | Component | Location | Purpose |
|-----------|----------|---------| |-----------|----------|---------|
| CLI | `src/smarttools/cli.py` | Main entry point for `smarttools` command | | CLI | `src/cmdforge/cli.py` | Main entry point for `cmdforge` command |
| Registry API | `src/smarttools/registry/` | REST API for tool registry | | Registry API | `src/cmdforge/registry/` | REST API for tool registry |
| Web UI | `src/smarttools/web/` | Flask web application | | Web UI | `src/cmdforge/web/` | Flask web application |
| Tool Storage | `~/.smarttools/` | User's installed tools | | Tool Storage | `~/.cmdforge/` | User's installed tools |
| Database | `data/smarttools.db` | SQLite with FTS5 search | | Database | `data/cmdforge.db` | SQLite with FTS5 search |
## Architecture Diagrams ## Architecture Diagrams
@ -31,7 +31,7 @@ See `docs/diagrams/` for visual representations:
## Source Code Structure ## Source Code Structure
``` ```
src/smarttools/ src/cmdforge/
├── cli.py # Entry point, subcommand routing ├── cli.py # Entry point, subcommand routing
├── tool.py # Tool dataclasses, YAML loading ├── tool.py # Tool dataclasses, YAML loading
├── runner.py # Step execution engine ├── runner.py # Step execution engine
@ -68,7 +68,7 @@ src/smarttools/
## Database Schema ## Database Schema
SQLite database at `data/smarttools.db`: SQLite database at `data/cmdforge.db`:
| Table | Purpose | | Table | Purpose |
|-------|---------| |-------|---------|
@ -106,9 +106,9 @@ Base URL: `/api/v1/`
## Key Files to Know ## Key Files to Know
### Configuration ### Configuration
- `~/.smarttools/providers.yaml` - AI provider configurations - `~/.cmdforge/providers.yaml` - AI provider configurations
- `~/.smarttools/config.yaml` - Global settings - `~/.cmdforge/config.yaml` - Global settings
- `~/.smarttools/<tool>/config.yaml` - Individual tool configs - `~/.cmdforge/<tool>/config.yaml` - Individual tool configs
### Development ### Development
- `pyproject.toml` - Package configuration - `pyproject.toml` - Package configuration
@ -130,10 +130,10 @@ Base URL: `/api/v1/`
pip install -e ".[dev]" pip install -e ".[dev]"
# Run CLI # Run CLI
python -m smarttools.cli python -m cmdforge.cli
# Run web server (development) # Run web server (development)
cd src/smarttools/web cd src/cmdforge/web
flask run --port 5050 flask run --port 5050
``` ```
@ -141,7 +141,7 @@ flask run --port 5050
```bash ```bash
# Using gunicorn # Using gunicorn
gunicorn -w 4 -b 0.0.0.0:5050 'smarttools.web.app:create_app()' gunicorn -w 4 -b 0.0.0.0:5050 'cmdforge.web.app:create_app()'
# Environment variables needed: # Environment variables needed:
# FLASK_ENV=production # FLASK_ENV=production
@ -164,7 +164,7 @@ pytest
pytest tests/test_name.py::test_function pytest tests/test_name.py::test_function
# Run with coverage # Run with coverage
pytest --cov=smarttools pytest --cov=cmdforge
``` ```
## Design Documents ## Design Documents

View File

@ -1,6 +1,6 @@
# Provider Setup Guide # Provider Setup Guide
SmartTools works with any AI CLI tool that accepts input via stdin or arguments. This guide covers setup for the most popular providers. CmdForge works with any AI CLI tool that accepts input via stdin or arguments. This guide covers setup for the most popular providers.
## Provider Comparison ## Provider Comparison
@ -139,7 +139,7 @@ echo "Hello" | gemini --model gemini-2.5-flash
The easiest way to install providers: The easiest way to install providers:
```bash ```bash
smarttools providers install cmdforge providers install
``` ```
This interactive guide: This interactive guide:
@ -151,22 +151,22 @@ This interactive guide:
### List Providers ### List Providers
```bash ```bash
smarttools providers list cmdforge providers list
``` ```
### Check Availability ### Check Availability
```bash ```bash
smarttools providers check cmdforge providers check
``` ```
### Add Custom Provider ### Add Custom Provider
```bash ```bash
smarttools providers add myname "my-command --args" -d "Description" cmdforge providers add myname "my-command --args" -d "Description"
``` ```
Or edit `~/.smarttools/providers.yaml`: Or edit `~/.cmdforge/providers.yaml`:
```yaml ```yaml
providers: providers:
@ -242,9 +242,9 @@ cat file.txt | summarize --provider claude-opus
### "Provider 'X' not found" ### "Provider 'X' not found"
1. Check it's in your providers list: `smarttools providers` 1. Check it's in your providers list: `cmdforge providers`
2. Verify the command works: `echo "test" | <command>` 2. Verify the command works: `echo "test" | <command>`
3. Add it: `smarttools providers add` 3. Add it: `cmdforge providers add`
### "Command 'X' not found" ### "Command 'X' not found"
@ -273,8 +273,8 @@ echo "Say hello" | claude -p
echo "Say hello" | ~/.opencode/bin/opencode run echo "Say hello" | ~/.opencode/bin/opencode run
``` ```
If it works directly but not in SmartTools, check: If it works directly but not in CmdForge, check:
1. Provider command in `~/.smarttools/providers.yaml` 1. Provider command in `~/.cmdforge/providers.yaml`
2. Environment variables are expanded correctly 2. Environment variables are expanded correctly
## Cost Optimization ## Cost Optimization

View File

@ -1,7 +1,7 @@
# SmartTools Registry Design # CmdForge Registry Design
## Purpose ## Purpose
Build a centralized registry for SmartTools to enable discovery, publishing, dependency management, and future curation at scale. Build a centralized registry for CmdForge to enable discovery, publishing, dependency management, and future curation at scale.
## Terminology ## Terminology
@ -9,20 +9,20 @@ Build a centralized registry for SmartTools to enable discovery, publishing, dep
|------|------------| |------|------------|
| **Tool definition** | The full YAML file in the registry (`config.yaml`) containing name, steps, arguments, etc. | | **Tool definition** | The full YAML file in the registry (`config.yaml`) containing name, steps, arguments, etc. |
| **Tool config** | The configuration within a tool definition (arguments, steps, provider settings) | | **Tool config** | The configuration within a tool definition (arguments, steps, provider settings) |
| **smarttools.yaml** | Project manifest file declaring tool dependencies and overrides | | **cmdforge.yaml** | Project manifest file declaring tool dependencies and overrides |
| **config.yaml** | The tool definition file, both in registry and when installed locally | | **config.yaml** | The tool definition file, both in registry and when installed locally |
| **Owner** | Immutable namespace slug identifying the publisher (e.g., `rob`, `alice`) | | **Owner** | Immutable namespace slug identifying the publisher (e.g., `rob`, `alice`) |
| **Publisher** | A registered user who can publish tools to the registry | | **Publisher** | A registered user who can publish tools to the registry |
| **Wrapper script** | Auto-generated bash script in `~/.local/bin/` that invokes a tool | | **Wrapper script** | Auto-generated bash script in `~/.local/bin/` that invokes a tool |
**Canonical naming:** Use `SmartTools-Registry` (capitalized, hyphenated) for the repository name. **Canonical naming:** Use `CmdForge-Registry` (capitalized, hyphenated) for the repository name.
## Diagram References ## Diagram References
- System overview: `discussions/diagrams/smarttools-registry_rob_1.puml` - System overview: `discussions/diagrams/cmdforge-registry_rob_1.puml`
- Data flows: `discussions/diagrams/smarttools-registry_rob_5.puml` - Data flows: `discussions/diagrams/cmdforge-registry_rob_5.puml`
## System Overview ## System Overview
Users interact via the CLI and a future Web UI. Both call a Registry API hosted at `https://gitea.brrd.tech/api/v1` (future alias: `registry.smarttools.dev/api/v1`). The API syncs from a Gitea-backed registry repo and maintains a SQLite cache/search index. Users interact via the CLI and a future Web UI. Both call a Registry API hosted at `https://gitea.brrd.tech/api/v1` (future alias: `cmdforge.brrd.tech/api/v1`). The API syncs from a Gitea-backed registry repo and maintains a SQLite cache/search index.
**Canonical API base path:** `https://gitea.brrd.tech/api/v1` **Canonical API base path:** `https://gitea.brrd.tech/api/v1`
@ -166,7 +166,7 @@ tool = ToolSchema.parse(response['data']) # May fail on new fields
**Client version header:** **Client version header:**
``` ```
X-SmartTools-Client: cli/1.2.0 X-CmdForge-Client: cli/1.2.0
``` ```
Helps server track client versions for deprecation decisions. Helps server track client versions for deprecation decisions.
@ -181,8 +181,8 @@ If the cache is stale, the API can fall back to repo reads; a warning header may
Support owner/name from day one: Support owner/name from day one:
- Registry path: `tools/{owner}/{name}/config.yaml` - Registry path: `tools/{owner}/{name}/config.yaml`
- API URL: `/tools/{owner}/{name}` - API URL: `/tools/{owner}/{name}`
- Install: `smarttools registry install rob/summarize` - Install: `cmdforge registry install rob/summarize`
- Shorthand: `smarttools registry install summarize` resolves to the official namespace. - Shorthand: `cmdforge registry install summarize` resolves to the official namespace.
PR branches: `submit/{owner}/{name}/{version}`. PR branches: `submit/{owner}/{name}/{version}`.
@ -227,7 +227,7 @@ tools/
README.md README.md
``` ```
Tool files match the existing SmartTools format. Registry-specific metadata is kept under `registry:`. Deprecation is tool-defined and top-level: Tool files match the existing CmdForge format. Registry-specific metadata is kept under `registry:`. Deprecation is tool-defined and top-level:
```yaml ```yaml
name: summarize name: summarize
version: "1.2.0" version: "1.2.0"
@ -239,7 +239,7 @@ registry:
downloads: 142 downloads: 142
``` ```
**Schema compatibility note:** The current SmartTools config parser may reject unknown top-level keys like `deprecated`, `replacement`, and `registry`. Before implementing registry features: **Schema compatibility note:** The current CmdForge config parser may reject unknown top-level keys like `deprecated`, `replacement`, and `registry`. Before implementing registry features:
1. Update the YAML parser to ignore unknown keys (permissive mode) 1. Update the YAML parser to ignore unknown keys (permissive mode)
2. Or explicitly define these fields in the Tool dataclass with defaults 2. Or explicitly define these fields in the Tool dataclass with defaults
3. Validate registry-specific fields only when publishing, not when running locally 3. Validate registry-specific fields only when publishing, not when running locally
@ -346,7 +346,7 @@ When resolving a version constraint:
### Prerelease Handling ### Prerelease Handling
- Prereleases are **not** returned for `*` or range constraints by default - Prereleases are **not** returned for `*` or range constraints by default
- To install prerelease: `smarttools registry install rob/summarize@2.0.0-beta.1` - To install prerelease: `cmdforge registry install rob/summarize@2.0.0-beta.1`
- To allow prereleases in manifest: `version: ">=2.0.0-0"` (the `-0` suffix includes prereleases) - To allow prereleases in manifest: `version: ">=2.0.0-0"` (the `-0` suffix includes prereleases)
### Download Endpoint Version Selection ### Download Endpoint Version Selection
@ -401,14 +401,14 @@ Response (404):
## Tool Resolution Order ## Tool Resolution Order
When a tool is invoked, the CLI searches in this order: When a tool is invoked, the CLI searches in this order:
1. **Local project**: `./.smarttools/<owner>/<name>/config.yaml` (or `./.smarttools/<name>/` for unnamespaced) 1. **Local project**: `./.cmdforge/<owner>/<name>/config.yaml` (or `./.cmdforge/<name>/` for unnamespaced)
2. **Global user**: `~/.smarttools/<owner>/<name>/config.yaml` 2. **Global user**: `~/.cmdforge/<owner>/<name>/config.yaml`
3. **Registry**: Fetch from API, install to global, then run 3. **Registry**: Fetch from API, install to global, then run
4. **Error**: `Tool '<toolname>' not found` 4. **Error**: `Tool '<toolname>' not found`
Step 3 only occurs if `auto_fetch_from_registry: true` in config (default: true). Step 3 only occurs if `auto_fetch_from_registry: true` in config (default: true).
**Path convention:** Use `.smarttools/` (with leading dot) for both local and global to maintain consistency. **Path convention:** Use `.cmdforge/` (with leading dot) for both local and global to maintain consistency.
Resolution also respects namespacing: Resolution also respects namespacing:
- `summarize` → searches for any tool named `summarize`, prefers `official/summarize` if exists - `summarize` → searches for any tool named `summarize`, prefers `official/summarize` if exists
@ -422,7 +422,7 @@ The slug `official` is reserved for curated, high-quality tools maintained by th
- If no `official/summarize`, falls back to most-downloaded tool named `summarize` - If no `official/summarize`, falls back to most-downloaded tool named `summarize`
- To avoid ambiguity, always use full `owner/name` in manifests - To avoid ambiguity, always use full `owner/name` in manifests
Reserved slugs that cannot be registered: `official`, `admin`, `system`, `api`, `registry`, `smarttools` Reserved slugs that cannot be registered: `official`, `admin`, `system`, `api`, `registry`, `cmdforge`
## Auto-Fetch Behavior ## Auto-Fetch Behavior
When enabled (`auto_fetch_from_registry: true`), missing tools are automatically fetched: When enabled (`auto_fetch_from_registry: true`), missing tools are automatically fetched:
@ -436,14 +436,14 @@ $ summarize < file.txt
``` ```
Behavior details: Behavior details:
- Fetches latest stable version unless pinned in `smarttools.yaml` - Fetches latest stable version unless pinned in `cmdforge.yaml`
- Installs to `~/.smarttools/<owner>/<name>/` - Installs to `~/.cmdforge/<owner>/<name>/`
- Generates wrapper script in `~/.local/bin/` - Generates wrapper script in `~/.local/bin/`
- Subsequent runs use local copy (no re-fetch) - Subsequent runs use local copy (no re-fetch)
To disable (require explicit install): To disable (require explicit install):
```yaml ```yaml
# ~/.smarttools/config.yaml # ~/.cmdforge/config.yaml
auto_fetch_from_registry: false auto_fetch_from_registry: false
``` ```
@ -467,11 +467,11 @@ summarize < file.txt
# Explicit owner form (always works) # Explicit owner form (always works)
rob-summarize < file.txt rob-summarize < file.txt
# Or via smarttools run # Or via cmdforge run
smarttools run rob/summarize < file.txt cmdforge run rob/summarize < file.txt
``` ```
## Project Manifest (smarttools.yaml) ## Project Manifest (cmdforge.yaml)
Defines tool dependencies with optional runtime overrides: Defines tool dependencies with optional runtime overrides:
``` ```
name: my-ai-project name: my-ai-project
@ -487,7 +487,7 @@ overrides:
Overrides are applied at runtime and do not mutate installed tool configs. Overrides are applied at runtime and do not mutate installed tool configs.
## CLI Config and Tokens ## CLI Config and Tokens
Global config lives in `~/.smarttools/config.yaml`: Global config lives in `~/.cmdforge/config.yaml`:
```yaml ```yaml
registry: registry:
url: https://gitea.brrd.tech/api/v1 # Must match canonical base path url: https://gitea.brrd.tech/api/v1 # Must match canonical base path
@ -540,7 +540,7 @@ Publishing uses registry accounts, not Gitea accounts:
**Update flow (new version, not overwrite):** **Update flow (new version, not overwrite):**
1. Developer modifies tool locally 1. Developer modifies tool locally
2. Bumps version in `config.yaml` (e.g., `1.2.0``1.3.0`) 2. Bumps version in `config.yaml` (e.g., `1.2.0``1.3.0`)
3. Runs `smarttools registry publish` 3. Runs `cmdforge registry publish`
4. New PR created for `1.3.0` 4. New PR created for `1.3.0`
5. Old version `1.2.0` remains available 5. Old version `1.2.0` remains available
@ -548,7 +548,7 @@ Publishing uses registry accounts, not Gitea accounts:
Publishers register on the registry website, not Gitea: Publishers register on the registry website, not Gitea:
**Registration flow:** **Registration flow:**
1. User visits `https://gitea.brrd.tech/registry/register` (or future `registry.smarttools.dev`) 1. User visits `https://gitea.brrd.tech/registry/register` (or future `cmdforge.brrd.tech`)
2. Creates account with email + password + slug 2. Creates account with email + password + slug
3. Receives verification email (optional in v1, but track `verified` status) 3. Receives verification email (optional in v1, but track `verified` status)
4. Logs into dashboard at `/dashboard` 4. Logs into dashboard at `/dashboard`
@ -690,7 +690,7 @@ Dashboard login uses session cookies (not tokens) for browser auth:
**Cookie settings:** **Cookie settings:**
```python ```python
SESSION_COOKIE_NAME = 'smarttools_session' SESSION_COOKIE_NAME = 'cmdforge_session'
SESSION_COOKIE_HTTPONLY = True # Prevent JS access SESSION_COOKIE_HTTPONLY = True # Prevent JS access
SESSION_COOKIE_SECURE = True # HTTPS only in production SESSION_COOKIE_SECURE = True # HTTPS only in production
SESSION_COOKIE_SAMESITE = 'Lax' # CSRF protection SESSION_COOKIE_SAMESITE = 'Lax' # CSRF protection
@ -844,7 +844,7 @@ CREATE TABLE tool_tags (
**CLI first-time publish flow:** **CLI first-time publish flow:**
```bash ```bash
$ smarttools registry publish $ cmdforge registry publish
No registry account configured. No registry account configured.
@ -853,7 +853,7 @@ No registry account configured.
3. Enter your token below 3. Enter your token below
Registry token: ******** Registry token: ********
Token saved to ~/.smarttools/config.yaml Token saved to ~/.cmdforge/config.yaml
Validating tool... Validating tool...
✓ config.yaml is valid ✓ config.yaml is valid
@ -861,7 +861,7 @@ Validating tool...
✓ Version 1.0.0 not yet published ✓ Version 1.0.0 not yet published
Publishing rob/my-tool@1.0.0... Publishing rob/my-tool@1.0.0...
✓ PR created: https://gitea.brrd.tech/rob/SmartTools-Registry/pulls/42 ✓ PR created: https://gitea.brrd.tech/rob/CmdForge-Registry/pulls/42
Your tool is pending review. You'll receive an email when it's approved. Your tool is pending review. You'll receive an email when it's approved.
``` ```
@ -873,67 +873,67 @@ Full mapping of CLI commands to API calls:
```bash ```bash
# Search for tools # Search for tools
$ smarttools registry search <query> [--category=<cat>] [--limit=20] $ cmdforge registry search <query> [--category=<cat>] [--limit=20]
→ GET /api/v1/tools/search?q=<query>&category=<cat>&limit=20 → GET /api/v1/tools/search?q=<query>&category=<cat>&limit=20
# Browse tools (TUI) # Browse tools (TUI)
$ smarttools registry browse [--category=<cat>] $ cmdforge registry browse [--category=<cat>]
→ GET /api/v1/tools?category=<cat>&page=1 → GET /api/v1/tools?category=<cat>&page=1
→ GET /api/v1/categories → GET /api/v1/categories
# View tool details # View tool details
$ smarttools registry info <owner/name> $ cmdforge registry info <owner/name>
→ GET /api/v1/tools/<owner>/<name> → GET /api/v1/tools/<owner>/<name>
# Install a tool # Install a tool
$ smarttools registry install <owner/name> [--version=<ver>] $ cmdforge registry install <owner/name> [--version=<ver>]
→ GET /api/v1/tools/<owner>/<name>/download?version=<ver>&install=true → GET /api/v1/tools/<owner>/<name>/download?version=<ver>&install=true
→ Writes to ~/.smarttools/<owner>/<name>/config.yaml → Writes to ~/.cmdforge/<owner>/<name>/config.yaml
→ Generates ~/.local/bin/<name> wrapper (or <owner>-<name> if collision) → Generates ~/.local/bin/<name> wrapper (or <owner>-<name> if collision)
# Uninstall a tool # Uninstall a tool
$ smarttools registry uninstall <owner/name> $ cmdforge registry uninstall <owner/name>
→ Removes ~/.smarttools/<owner>/<name>/ → Removes ~/.cmdforge/<owner>/<name>/
→ Removes wrapper script → Removes wrapper script
# Publish a tool # Publish a tool
$ smarttools registry publish [path] [--dry-run] $ cmdforge registry publish [path] [--dry-run]
→ POST /api/v1/tools (with registry token) → POST /api/v1/tools (with registry token)
→ Returns PR URL → Returns PR URL
# List my published tools # List my published tools
$ smarttools registry my-tools $ cmdforge registry my-tools
→ GET /api/v1/me/tools (with registry token) → GET /api/v1/me/tools (with registry token)
# Update index cache # Update index cache
$ smarttools registry update $ cmdforge registry update
→ GET /api/v1/index.json → GET /api/v1/index.json
→ Writes to ~/.smarttools/registry/index.json → Writes to ~/.cmdforge/registry/index.json
``` ```
### Project Commands ### Project Commands
```bash ```bash
# Install project dependencies from smarttools.yaml # Install project dependencies from cmdforge.yaml
$ smarttools install $ cmdforge install
→ Reads ./smarttools.yaml → Reads ./cmdforge.yaml
→ For each dependency: → For each dependency:
GET /api/v1/tools/<owner>/<name>/download?version=<constraint>&install=true GET /api/v1/tools/<owner>/<name>/download?version=<constraint>&install=true
→ Installs to ~/.smarttools/<owner>/<name>/ → Installs to ~/.cmdforge/<owner>/<name>/
# Add a dependency to smarttools.yaml # Add a dependency to cmdforge.yaml
$ smarttools add <owner/name> [--version=<constraint>] $ cmdforge add <owner/name> [--version=<constraint>]
→ Adds to ./smarttools.yaml dependencies → Adds to ./cmdforge.yaml dependencies
→ Runs install for that tool → Runs install for that tool
# Show project dependencies status # Show project dependencies status
$ smarttools deps $ cmdforge deps
→ Reads ./smarttools.yaml → Reads ./cmdforge.yaml
→ Shows installed status for each dependency → Shows installed status for each dependency
→ Note: "smarttools list" is reserved for listing installed tools → Note: "cmdforge list" is reserved for listing installed tools
``` ```
**Command naming note:** `smarttools list` already exists to list locally installed tools. Use `smarttools deps` to show project manifest dependencies. **Command naming note:** `cmdforge list` already exists to list locally installed tools. Use `cmdforge deps` to show project manifest dependencies.
### Flags available on most commands ### Flags available on most commands
@ -1081,7 +1081,7 @@ def sync_from_repo_atomic():
| Lock timeout | Skip this sync, next webhook will retry | | Lock timeout | Skip this sync, next webhook will retry |
## Automated CI Validation ## Automated CI Validation
PRs are validated automatically using SmartTools (dogfooding): PRs are validated automatically using CmdForge (dogfooding):
``` ```
PR Submitted PR Submitted
@ -1121,16 +1121,16 @@ jobs:
- name: Validate schema - name: Validate schema
run: python scripts/validate_tool.py ${{ github.event.pull_request.head.sha }} run: python scripts/validate_tool.py ${{ github.event.pull_request.head.sha }}
- name: Security scan - name: Security scan
run: smarttools run security-scanner < changed_files.txt run: cmdforge run security-scanner < changed_files.txt
- name: Check duplicates - name: Check duplicates
run: smarttools run duplicate-detector < changed_files.txt run: cmdforge run duplicate-detector < changed_files.txt
``` ```
## Registry Repository Structure ## Registry Repository Structure
Full structure of the SmartTools-Registry repo: Full structure of the CmdForge-Registry repo:
``` ```
SmartTools-Registry/ CmdForge-Registry/
├── README.md # Registry overview ├── README.md # Registry overview
├── CONTRIBUTING.md # How to submit tools ├── CONTRIBUTING.md # How to submit tools
├── LICENSE ├── LICENSE
@ -1236,7 +1236,7 @@ CLI generates a persistent anonymous ID on first run:
import uuid import uuid
import os import os
CONFIG_PATH = os.path.expanduser("~/.smarttools/config.yaml") CONFIG_PATH = os.path.expanduser("~/.cmdforge/config.yaml")
def get_or_create_client_id(): def get_or_create_client_id():
config = load_config() config = load_config()
@ -1424,7 +1424,7 @@ def search_tools(q):
"name": "bar", "name": "bar",
"suggestion": "Did you mean 'rob/bar'?" "suggestion": "Did you mean 'rob/bar'?"
}, },
"docs_url": "https://registry.smarttools.dev/docs/errors#TOOL_NOT_FOUND" "docs_url": "https://cmdforge.brrd.tech/docs/errors#TOOL_NOT_FOUND"
} }
} }
``` ```
@ -1482,17 +1482,17 @@ When `VALIDATION_ERROR` occurs, provide specific field errors:
} }
] ]
}, },
"docs_url": "https://registry.smarttools.dev/docs/tool-format" "docs_url": "https://cmdforge.brrd.tech/docs/tool-format"
} }
} }
``` ```
### Dependency Resolution Failures ### Dependency Resolution Failures
When `smarttools install` fails on a manifest: When `cmdforge install` fails on a manifest:
```bash ```bash
$ smarttools install $ cmdforge install
Error: Could not resolve all dependencies Error: Could not resolve all dependencies
@ -1511,7 +1511,7 @@ Suggestions:
| Component Down | Fallback Behavior | | Component Down | Fallback Behavior |
|----------------|-------------------| |----------------|-------------------|
| API server | CLI uses `~/.smarttools/registry/index.json` for search | | API server | CLI uses `~/.cmdforge/registry/index.json` for search |
| Gitea repo | API serves from DB cache (may be stale) | | Gitea repo | API serves from DB cache (may be stale) |
| FTS5 index | Fall back to LIKE queries (slower but works) | | FTS5 index | Fall back to LIKE queries (slower but works) |
| Network | Use locally installed tools, skip registry features | | Network | Use locally installed tools, skip registry features |
@ -1520,9 +1520,9 @@ Suggestions:
### Publishing UX ### Publishing UX
- `smarttools registry publish --dry-run` validates locally and shows what would be submitted: - `cmdforge registry publish --dry-run` validates locally and shows what would be submitted:
```bash ```bash
$ smarttools registry publish --dry-run $ cmdforge registry publish --dry-run
Validating tool... Validating tool...
✓ config.yaml is valid ✓ config.yaml is valid
@ -1559,7 +1559,7 @@ Suggestions:
Long-running operations show progress: Long-running operations show progress:
```bash ```bash
$ smarttools install $ cmdforge install
Installing project dependencies... Installing project dependencies...
[1/3] rob/summarize@^1.0.0 [1/3] rob/summarize@^1.0.0
@ -1579,24 +1579,24 @@ Installing project dependencies...
``` ```
```bash ```bash
$ smarttools registry publish $ cmdforge registry publish
Submitting rob/summarize@1.1.0... Submitting rob/summarize@1.1.0...
Validating... done ✓ Validating... done ✓
Uploading... done ✓ Uploading... done ✓
Creating PR... done ✓ Creating PR... done ✓
✓ PR created: https://gitea.brrd.tech/rob/SmartTools-Registry/pulls/42 ✓ PR created: https://gitea.brrd.tech/rob/CmdForge-Registry/pulls/42
Your tool is pending review. You'll receive an email when it's approved. Your tool is pending review. You'll receive an email when it's approved.
``` ```
### TUI Browse ### TUI Browse
`smarttools registry browse` opens a full-screen terminal UI: `cmdforge registry browse` opens a full-screen terminal UI:
``` ```
┌─ SmartTools Registry ───────────────────────────────────────┐ ┌─ CmdForge Registry ───────────────────────────────────────┐
│ Search: [________________] [All Categories ▼] [Sort: Popular ▼] │ │ Search: [________________] [All Categories ▼] [Sort: Popular ▼] │
├─────────────────────────────────────────────────────────────┤ ├─────────────────────────────────────────────────────────────┤
│ │ │ │
@ -1634,9 +1634,9 @@ Your tool is pending review. You'll receive an email when it's approved.
### Project Initialization ### Project Initialization
```bash ```bash
$ smarttools init $ cmdforge init
Creating smarttools.yaml... Creating cmdforge.yaml...
Project name [my-project]: my-ai-project Project name [my-project]: my-ai-project
Version [1.0.0]: Version [1.0.0]:
@ -1652,7 +1652,7 @@ Added rob/summarize@^1.2.0
Add tool (number, or Enter to finish): Add tool (number, or Enter to finish):
✓ Created smarttools.yaml ✓ Created cmdforge.yaml
name: my-ai-project name: my-ai-project
version: "1.0.0" version: "1.0.0"
@ -1660,7 +1660,7 @@ dependencies:
- name: rob/summarize - name: rob/summarize
version: "^1.2.0" version: "^1.2.0"
Run 'smarttools install' to install dependencies. Run 'cmdforge install' to install dependencies.
``` ```
### Accessibility ### Accessibility
@ -1676,7 +1676,7 @@ Run 'smarttools install' to install dependencies.
## Offline Cache ## Offline Cache
Cache registry index locally: Cache registry index locally:
``` ```
~/.smarttools/registry/index.json ~/.cmdforge/registry/index.json
``` ```
Refresh when older than 24 hours; support `--offline` and `--refresh` flags. Refresh when older than 24 hours; support `--offline` and `--refresh` flags.
@ -1730,7 +1730,7 @@ The registry includes a full website, not just an API:
**Site structure:** **Site structure:**
``` ```
registry.smarttools.dev (or gitea.brrd.tech/registry) cmdforge.brrd.tech (or gitea.brrd.tech/registry)
├── / # Landing page ├── / # Landing page
├── /tools # Browse all tools ├── /tools # Browse all tools
├── /tools/{owner}/{name} # Tool detail page ├── /tools/{owner}/{name} # Tool detail page
@ -1843,9 +1843,9 @@ def render_readme_safe(readme_raw: str) -> str:
## Implementation Phases ## Implementation Phases
### Phase 1: Foundation ### Phase 1: Foundation
- Define `smarttools.yaml` manifest format - Define `cmdforge.yaml` manifest format
- Implement tool resolution order (local → global → registry) - Implement tool resolution order (local → global → registry)
- Create SmartTools-Registry repo on Gitea (bootstrap) - Create CmdForge-Registry repo on Gitea (bootstrap)
- Add 3-5 example tools to seed the registry - Add 3-5 example tools to seed the registry
### Phase 2: Core Backend ### Phase 2: Core Backend
@ -1856,22 +1856,22 @@ def render_readme_safe(readme_raw: str) -> str:
- Set up HMAC verification - Set up HMAC verification
### Phase 3: CLI Commands ### Phase 3: CLI Commands
- `smarttools registry search` - `cmdforge registry search`
- `smarttools registry install` - `cmdforge registry install`
- `smarttools registry info` - `cmdforge registry info`
- `smarttools registry browse` (TUI) - `cmdforge registry browse` (TUI)
- Local index caching - Local index caching
### Phase 4: Publishing ### Phase 4: Publishing
- Publisher registration (web UI) - Publisher registration (web UI)
- Token management - Token management
- `smarttools registry publish` command - `cmdforge registry publish` command
- PR creation via Gitea API - PR creation via Gitea API
- CI validation workflows - CI validation workflows
### Phase 5: Project Dependencies ### Phase 5: Project Dependencies
- `smarttools install` (from manifest) - `cmdforge install` (from manifest)
- `smarttools add` command - `cmdforge add` command
- Runtime override application - Runtime override application
- Dependency resolution - Dependency resolution

View File

@ -1,10 +1,10 @@
# SmartTools Web UI Design # CmdForge Web UI Design
## Purpose ## Purpose
Deliver a professional web front-end that explains SmartTools, helps users discover tools, and supports a collaborative ecosystem. The site should drive sustainable revenue without undermining trust or usability. Deliver a professional web front-end that explains CmdForge, helps users discover tools, and supports a collaborative ecosystem. The site should drive sustainable revenue without undermining trust or usability.
## Mission Alignment ## Mission Alignment
This web UI serves the broader SmartTools mission: to provide a **universally accessible development ecosystem** that empowers regular people to collaborate and build upon each other's progress rather than compete. Revenue generated supports: This web UI serves the broader CmdForge mission: to provide a **universally accessible development ecosystem** that empowers regular people to collaborate and build upon each other's progress rather than compete. Revenue generated supports:
- Maintaining and expanding the project - Maintaining and expanding the project
- Future hosting of AI models for users with less access to paid services - Future hosting of AI models for users with less access to paid services
- Building a sustainable, community-first platform - Building a sustainable, community-first platform
@ -131,14 +131,14 @@ Use an 8px base grid for consistent spacing:
### Landing Page (`/`) ### Landing Page (`/`)
**Purpose:** Convert visitors to users by clearly communicating SmartTools' value proposition and providing immediate paths to explore. **Purpose:** Convert visitors to users by clearly communicating CmdForge' value proposition and providing immediate paths to explore.
**Reference mockup:** `discussions/diagrams/smarttools-registry_rob_6.svg` **Reference mockup:** `discussions/diagrams/cmdforge-registry_rob_6.svg`
#### Section 1: Hero (Above the Fold) #### Section 1: Hero (Above the Fold)
``` ```
┌─────────────────────────────────────────────────────────────────┐ ┌─────────────────────────────────────────────────────────────────┐
│ [SmartTools] Docs Tutorials Registry Community About 🔍 │ │ [CmdForge] Docs Tutorials Registry Community About 🔍 │
├─────────────────────────────────────────────────────────────────┤ ├─────────────────────────────────────────────────────────────────┤
│ │ │ │
│ Build Custom AI Commands in YAML │ │ Build Custom AI Commands in YAML │
@ -147,7 +147,7 @@ Use an 8px base grid for consistent spacing:
│ provider. Provider-agnostic and composable. │ │ provider. Provider-agnostic and composable. │
│ │ │ │
│ ┌──────────────────────────────────────────────────────┐ │ │ ┌──────────────────────────────────────────────────────┐ │
│ │ $ pip install smarttools && smarttools init │ [📋]│ │ │ $ pip install cmdforge && cmdforge init │ [📋]│
│ └──────────────────────────────────────────────────────┘ │ │ └──────────────────────────────────────────────────────┘ │
│ │ │ │
│ [Get Started] [View Tutorials] │ │ [Get Started] [View Tutorials] │
@ -158,7 +158,7 @@ Use an 8px base grid for consistent spacing:
**Content:** **Content:**
- **Headline:** "Build Custom AI Commands in YAML" (benefit-focused, differentiating) - **Headline:** "Build Custom AI Commands in YAML" (benefit-focused, differentiating)
- **Subheadline:** "Create Unix-style pipeable tools that work with any AI provider. Provider-agnostic and composable for ultimate flexibility." - **Subheadline:** "Create Unix-style pipeable tools that work with any AI provider. Provider-agnostic and composable for ultimate flexibility."
- **Install snippet:** `pip install smarttools && smarttools init` with copy button - **Install snippet:** `pip install cmdforge && cmdforge init` with copy button
- **Primary CTA:** "Get Started" → links to `/docs/getting-started` (indigo background) - **Primary CTA:** "Get Started" → links to `/docs/getting-started` (indigo background)
- **Secondary CTA:** "View Tutorials" → links to `/tutorials` (outlined, cyan border) - **Secondary CTA:** "View Tutorials" → links to `/tutorials` (outlined, cyan border)
@ -167,10 +167,10 @@ Use an 8px base grid for consistent spacing:
- Maximum content width: 1100px centered - Maximum content width: 1100px centered
- Install snippet: monospace font, light gray background (#E0E0E0), copy icon on right - Install snippet: monospace font, light gray background (#E0E0E0), copy icon on right
#### Section 2: Three Pillars (Why SmartTools?) #### Section 2: Three Pillars (Why CmdForge?)
``` ```
┌─────────────────────────────────────────────────────────────────┐ ┌─────────────────────────────────────────────────────────────────┐
│ Why SmartTools? │ │ Why CmdForge? │
├──────────────────┬──────────────────┬────────────────────────────┤ ├──────────────────┬──────────────────┬────────────────────────────┤
│ [✓] Easy │ [⚡] Powerful │ [👥] Community │ │ [✓] Easy │ [⚡] Powerful │ [👥] Community │
│ │ │ │ │ │ │ │
@ -267,7 +267,7 @@ Use an 8px base grid for consistent spacing:
#### Section 6: Footer Ad Zone (Optional) #### Section 6: Footer Ad Zone (Optional)
``` ```
┌─────────────────────────────────────────────────────────────────┐ ┌─────────────────────────────────────────────────────────────────┐
│ [Advertisement: Support SmartTools Development] │ │ [Advertisement: Support CmdForge Development] │
└─────────────────────────────────────────────────────────────────┘ └─────────────────────────────────────────────────────────────────┘
``` ```
@ -279,12 +279,12 @@ Use an 8px base grid for consistent spacing:
#### Section 7: Footer #### Section 7: Footer
``` ```
┌─────────────────────────────────────────────────────────────────┐ ┌─────────────────────────────────────────────────────────────────┐
SmartTools CmdForge
│ ───────────────────────────────────────────────────────────── │ │ ───────────────────────────────────────────────────────────── │
│ Docs | Registry | Community | About | Donate │ │ Docs | Registry | Community | About | Donate │
│ Privacy | Terms | GitHub | Twitter │ │ Privacy | Terms | GitHub | Twitter │
│ │ │ │
│ © 2025 SmartTools. Open source under MIT License. │ │ © 2025 CmdForge. Open source under MIT License. │
└─────────────────────────────────────────────────────────────────┘ └─────────────────────────────────────────────────────────────────┘
``` ```
@ -511,7 +511,7 @@ Use an 8px base grid for consistent spacing:
│ ⬇ 1,234 downloads │ │ ⬇ 1,234 downloads │
│ │ │ │
│ ┌─────────────────────────────────┐ │ │ ┌─────────────────────────────────┐ │
│ │ smarttools run owner/tool │ │ │ │ cmdforge run owner/tool │ │
│ └─────────────────────────────────┘ │ │ └─────────────────────────────────┘ │
└───────────────────────────────────────┘ └───────────────────────────────────────┘
``` ```
@ -637,7 +637,7 @@ Registry > owner > tool-name > v1.2.0
**Inline Code:** **Inline Code:**
```html ```html
<code>smarttools run foo</code> <code>cmdforge run foo</code>
``` ```
- Background: Light gray (#F3F4F6) - Background: Light gray (#F3F4F6)
- Font: Monospace - Font: Monospace
@ -1011,14 +1011,14 @@ Publisher dashboard uses auth endpoints:
Landing page: Landing page:
```html ```html
<title>SmartTools - Build Custom AI Commands in YAML</title> <title>CmdForge - Build Custom AI Commands in YAML</title>
<meta name="description" content="Create Unix-style pipeable tools that work with any AI provider. Provider-agnostic, composable, and community-driven."> <meta name="description" content="Create Unix-style pipeable tools that work with any AI provider. Provider-agnostic, composable, and community-driven.">
<meta name="keywords" content="ai cli tools, yaml automation, ai commands, smarttools"> <meta name="keywords" content="ai cli tools, yaml automation, ai commands, cmdforge">
``` ```
Tool detail page: Tool detail page:
```html ```html
<title>{tool-name} by {owner} - SmartTools Registry</title> <title>{tool-name} by {owner} - CmdForge Registry</title>
<meta name="description" content="{tool description, max 160 chars}"> <meta name="description" content="{tool description, max 160 chars}">
``` ```
@ -1036,7 +1036,7 @@ Tool detail page:
"@type": "Person", "@type": "Person",
"name": "owner-name" "name": "owner-name"
}, },
"downloadUrl": "https://registry.smarttools.dev/tools/owner/summarize", "downloadUrl": "https://cmdforge.brrd.tech/tools/owner/summarize",
"softwareVersion": "1.2.0", "softwareVersion": "1.2.0",
"aggregateRating": { "aggregateRating": {
"@type": "AggregateRating", "@type": "AggregateRating",
@ -1051,12 +1051,12 @@ Tool detail page:
{ {
"@context": "https://schema.org", "@context": "https://schema.org",
"@type": "Organization", "@type": "Organization",
"name": "SmartTools", "name": "CmdForge",
"url": "https://smarttools.dev", "url": "https://cmdforge.dev",
"logo": "https://smarttools.dev/logo.png", "logo": "https://cmdforge.dev/logo.png",
"sameAs": [ "sameAs": [
"https://github.com/your-org/smarttools", "https://github.com/your-org/cmdforge",
"https://twitter.com/smarttools" "https://twitter.com/cmdforge"
] ]
} }
``` ```
@ -1066,7 +1066,7 @@ Tool detail page:
{ {
"@context": "https://schema.org", "@context": "https://schema.org",
"@type": "TechArticle", "@type": "TechArticle",
"headline": "Getting Started with SmartTools", "headline": "Getting Started with CmdForge",
"author": {"@type": "Person", "name": "Author Name"}, "author": {"@type": "Person", "name": "Author Name"},
"datePublished": "2025-01-15", "datePublished": "2025-01-15",
"dateModified": "2025-01-20" "dateModified": "2025-01-20"
@ -1077,18 +1077,18 @@ Tool detail page:
```html ```html
<!-- Open Graph --> <!-- Open Graph -->
<meta property="og:title" content="SmartTools - AI CLI Tools"> <meta property="og:title" content="CmdForge - AI CLI Tools">
<meta property="og:description" content="Build custom AI commands..."> <meta property="og:description" content="Build custom AI commands...">
<meta property="og:image" content="https://smarttools.dev/og-image.png"> <meta property="og:image" content="https://cmdforge.dev/og-image.png">
<meta property="og:url" content="https://smarttools.dev"> <meta property="og:url" content="https://cmdforge.dev">
<meta property="og:type" content="website"> <meta property="og:type" content="website">
<!-- Twitter Card --> <!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image"> <meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@smarttools"> <meta name="twitter:site" content="@cmdforge">
<meta name="twitter:title" content="SmartTools"> <meta name="twitter:title" content="CmdForge">
<meta name="twitter:description" content="Build custom AI commands..."> <meta name="twitter:description" content="Build custom AI commands...">
<meta name="twitter:image" content="https://smarttools.dev/twitter-card.png"> <meta name="twitter:image" content="https://cmdforge.dev/twitter-card.png">
``` ```
### Sitemap ### Sitemap
@ -1104,12 +1104,12 @@ Auto-generate `sitemap.xml`:
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url> <url>
<loc>https://smarttools.dev/</loc> <loc>https://cmdforge.dev/</loc>
<priority>1.0</priority> <priority>1.0</priority>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://smarttools.dev/tools</loc> <loc>https://cmdforge.dev/tools</loc>
<priority>0.9</priority> <priority>0.9</priority>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
@ -1129,7 +1129,7 @@ Disallow: /register
Disallow: /dashboard Disallow: /dashboard
Disallow: /api/ Disallow: /api/
Sitemap: https://smarttools.dev/sitemap.xml Sitemap: https://cmdforge.dev/sitemap.xml
``` ```
### Canonical URLs ### Canonical URLs
@ -1297,11 +1297,11 @@ The web UI consumes these existing API endpoints:
## Diagram References ## Diagram References
- Landing page mockup: `discussions/diagrams/smarttools-registry_rob_6.svg` - Landing page mockup: `discussions/diagrams/cmdforge-registry_rob_6.svg`
- System overview: `discussions/diagrams/smarttools-registry_rob_1.puml` - System overview: `discussions/diagrams/cmdforge-registry_rob_1.puml`
- Data flows: `discussions/diagrams/smarttools-registry_rob_5.puml` - Data flows: `discussions/diagrams/cmdforge-registry_rob_5.puml`
- Web UI strategy: `discussions/diagrams/smarttools-web-ui-strategy.puml` - Web UI strategy: `discussions/diagrams/cmdforge-web-ui-strategy.puml`
- UI visual strategy: `discussions/diagrams/smarttools-web-ui-visual-strategy.puml` - UI visual strategy: `discussions/diagrams/cmdforge-web-ui-visual-strategy.puml`
## Deployment Guide ## Deployment Guide
@ -1315,8 +1315,8 @@ The web UI consumes these existing API endpoints:
```bash ```bash
# Clone the repository # Clone the repository
git clone https://gitea.brrd.tech/rob/SmartTools.git git clone https://gitea.brrd.tech/rob/CmdForge.git
cd SmartTools cd CmdForge
# Create virtual environment # Create virtual environment
python3 -m venv venv python3 -m venv venv
@ -1326,7 +1326,7 @@ source venv/bin/activate
pip install -e ".[registry]" pip install -e ".[registry]"
# Run the web server # Run the web server
python -m smarttools.web.app python -m cmdforge.web.app
``` ```
The server will start on `http://localhost:5000`. The server will start on `http://localhost:5000`.
@ -1337,47 +1337,47 @@ The server will start on `http://localhost:5000`.
```bash ```bash
# Required # Required
export SMARTTOOLS_REGISTRY_DB=/path/to/registry.db export CMDFORGE_REGISTRY_DB=/path/to/registry.db
export PORT=5050 export PORT=5050
# Optional # Optional
export SMARTTOOLS_ENV=production # Enables secure cookies export CMDFORGE_ENV=production # Enables secure cookies
export SMARTTOOLS_SHOW_ADS=true # Enable ad placeholders export CMDFORGE_SHOW_ADS=true # Enable ad placeholders
``` ```
#### 2. Database Location #### 2. Database Location
By default, the registry uses `~/.smarttools/registry.db`. For production: By default, the registry uses `~/.cmdforge/registry.db`. For production:
```bash ```bash
# Create dedicated directory # Create dedicated directory
mkdir -p /var/lib/smarttools mkdir -p /var/lib/cmdforge
export SMARTTOOLS_REGISTRY_DB=/var/lib/smarttools/registry.db export CMDFORGE_REGISTRY_DB=/var/lib/cmdforge/registry.db
``` ```
**Note**: If using a merged filesystem (e.g., mergerfs), store the database on a single disk or in `/tmp` to avoid SQLite WAL mode issues: **Note**: If using a merged filesystem (e.g., mergerfs), store the database on a single disk or in `/tmp` to avoid SQLite WAL mode issues:
```bash ```bash
export SMARTTOOLS_REGISTRY_DB=/tmp/smarttools-registry/registry.db export CMDFORGE_REGISTRY_DB=/tmp/cmdforge-registry/registry.db
``` ```
#### 3. Running with systemd #### 3. Running with systemd
Create `/etc/systemd/system/smarttools-registry.service`: Create `/etc/systemd/system/cmdforge-registry.service`:
```ini ```ini
[Unit] [Unit]
Description=SmartTools Registry Web Server Description=CmdForge Registry Web Server
After=network.target After=network.target
[Service] [Service]
Type=simple Type=simple
User=smarttools User=cmdforge
WorkingDirectory=/opt/smarttools WorkingDirectory=/opt/cmdforge
Environment=SMARTTOOLS_REGISTRY_DB=/var/lib/smarttools/registry.db Environment=CMDFORGE_REGISTRY_DB=/var/lib/cmdforge/registry.db
Environment=PORT=5050 Environment=PORT=5050
Environment=SMARTTOOLS_ENV=production Environment=CMDFORGE_ENV=production
ExecStart=/opt/smarttools/venv/bin/python -m smarttools.web.app ExecStart=/opt/cmdforge/venv/bin/python -m cmdforge.web.app
Restart=always Restart=always
RestartSec=5 RestartSec=5
@ -1387,8 +1387,8 @@ WantedBy=multi-user.target
```bash ```bash
sudo systemctl daemon-reload sudo systemctl daemon-reload
sudo systemctl enable smarttools-registry sudo systemctl enable cmdforge-registry
sudo systemctl start smarttools-registry sudo systemctl start cmdforge-registry
``` ```
#### 4. Reverse Proxy (nginx) #### 4. Reverse Proxy (nginx)
@ -1396,7 +1396,7 @@ sudo systemctl start smarttools-registry
```nginx ```nginx
server { server {
listen 80; listen 80;
server_name registry.smarttools.dev; server_name cmdforge.brrd.tech;
location / { location / {
proxy_pass http://127.0.0.1:5050; proxy_pass http://127.0.0.1:5050;
@ -1407,7 +1407,7 @@ server {
} }
location /static { location /static {
alias /opt/smarttools/src/smarttools/web/static; alias /opt/cmdforge/src/cmdforge/web/static;
expires 1y; expires 1y;
add_header Cache-Control "public, immutable"; add_header Cache-Control "public, immutable";
} }
@ -1417,7 +1417,7 @@ server {
#### 5. SSL with Certbot #### 5. SSL with Certbot
```bash ```bash
sudo certbot --nginx -d registry.smarttools.dev sudo certbot --nginx -d cmdforge.brrd.tech
``` ```
### Tailwind CSS Build ### Tailwind CSS Build
@ -1429,8 +1429,8 @@ The CSS is pre-built and committed. To rebuild after changes:
npm install npm install
# Build for production # Build for production
npx tailwindcss -i src/smarttools/web/static/css/input.css \ npx tailwindcss -i src/cmdforge/web/static/css/input.css \
-o src/smarttools/web/static/css/main.css \ -o src/cmdforge/web/static/css/main.css \
--minify --minify
``` ```
@ -1447,7 +1447,7 @@ curl http://localhost:5050/api/v1/tools
|-------|----------| |-------|----------|
| `disk I/O error` | Move database to non-merged filesystem | | `disk I/O error` | Move database to non-merged filesystem |
| Port already in use | Change PORT environment variable | | Port already in use | Change PORT environment variable |
| 500 errors | Check `/tmp/smarttools.log` for stack traces | | 500 errors | Check `/tmp/cmdforge.log` for stack traces |
| Static files not loading | Verify static folder path in deployment | | Static files not loading | Verify static folder path in deployment |
## Future Considerations (Phase 8+) ## Future Considerations (Phase 8+)

View File

@ -1,6 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
""" """
Install all SmartTools example tools. Install all CmdForge example tools.
Usage: Usage:
python3 install.py # Install all tools python3 install.py # Install all tools
@ -9,7 +9,7 @@ Usage:
python3 install.py --category dev # Install category python3 install.py --category dev # Install category
Run from anywhere: Run from anywhere:
curl -sSL https://gitea.brrd.tech/rob/smarttools/raw/branch/main/examples/install.py | python3 curl -sSL https://gitea.brrd.tech/rob/cmdforge/raw/branch/main/examples/install.py | python3
""" """
import argparse import argparse
@ -22,7 +22,7 @@ except ImportError:
print("PyYAML required. Install with: pip install pyyaml") print("PyYAML required. Install with: pip install pyyaml")
sys.exit(1) sys.exit(1)
TOOLS_DIR = Path.home() / ".smarttools" TOOLS_DIR = Path.home() / ".cmdforge"
# All example tool configurations # All example tool configurations
TOOLS = { TOOLS = {
@ -298,7 +298,7 @@ def list_tools():
def main(): def main():
parser = argparse.ArgumentParser(description="Install SmartTools example tools") parser = argparse.ArgumentParser(description="Install CmdForge example tools")
parser.add_argument("tools", nargs="*", help="Specific tools to install (default: all)") parser.add_argument("tools", nargs="*", help="Specific tools to install (default: all)")
parser.add_argument("--list", action="store_true", help="List available tools") parser.add_argument("--list", action="store_true", help="List available tools")
parser.add_argument("--category", "-c", choices=list(CATEGORIES.keys()), help="Install tools from category") parser.add_argument("--category", "-c", choices=list(CATEGORIES.keys()), help="Install tools from category")
@ -335,7 +335,7 @@ def main():
installed += 1 installed += 1
print(f"\nInstalled {installed} tools.") print(f"\nInstalled {installed} tools.")
print("\nRun 'smarttools refresh' to create executable wrappers.") print("\nRun 'cmdforge refresh' to create executable wrappers.")
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -1,9 +1,9 @@
{ {
"name": "smarttools-web", "name": "cmdforge-web",
"private": true, "private": true,
"scripts": { "scripts": {
"css:build": "tailwindcss -i src/smarttools/web/static/src/input.css -o src/smarttools/web/static/css/main.css --minify", "css:build": "tailwindcss -i src/cmdforge/web/static/src/input.css -o src/cmdforge/web/static/css/main.css --minify",
"css:watch": "tailwindcss -i src/smarttools/web/static/src/input.css -o src/smarttools/web/static/css/main.css --watch" "css:watch": "tailwindcss -i src/cmdforge/web/static/src/input.css -o src/cmdforge/web/static/css/main.css --watch"
}, },
"devDependencies": { "devDependencies": {
"tailwindcss": "^3.4.19" "tailwindcss": "^3.4.19"

View File

@ -3,9 +3,9 @@ requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta" build-backend = "setuptools.build_meta"
[project] [project]
name = "smarttools" name = "cmdforge"
version = "0.1.0" version = "0.1.0"
description = "A lightweight personal tool builder for AI-powered CLI commands" description = "Build custom AI-powered CLI commands in YAML"
readme = "README.md" readme = "README.md"
license = {text = "MIT"} license = {text = "MIT"}
requires-python = ">=3.10" requires-python = ">=3.10"
@ -56,13 +56,13 @@ all = [
] ]
[project.scripts] [project.scripts]
smarttools = "smarttools.cli:main" cmdforge = "cmdforge.cli:main"
[project.urls] [project.urls]
Homepage = "https://gitea.brrd.tech/rob/smarttools" Homepage = "https://cmdforge.brrd.tech"
Documentation = "https://gitea.brrd.tech/rob/smarttools#readme" Documentation = "https://cmdforge.brrd.tech/docs"
Repository = "https://gitea.brrd.tech/rob/smarttools.git" Repository = "https://gitea.brrd.tech/rob/CmdForge.git"
Issues = "https://gitea.brrd.tech/rob/smarttools/issues" Issues = "https://gitea.brrd.tech/rob/CmdForge/issues"
[tool.setuptools.packages.find] [tool.setuptools.packages.find]
where = ["src"] where = ["src"]

View File

@ -1,4 +1,4 @@
"""Basic health check for the SmartTools Registry API and DB.""" """Basic health check for the CmdForge Registry API and DB."""
from __future__ import annotations from __future__ import annotations
@ -17,13 +17,13 @@ def _add_src_to_path() -> None:
def _get_registry_url() -> str: def _get_registry_url() -> str:
from smarttools.config import get_registry_url from cmdforge.config import get_registry_url
return get_registry_url().rstrip("/") return get_registry_url().rstrip("/")
def _get_db_path() -> Path: def _get_db_path() -> Path:
from smarttools.registry.db import get_db_path from cmdforge.registry.db import get_db_path
return get_db_path() return get_db_path()

View File

@ -16,8 +16,8 @@ import yaml
# Allow running from repo root # Allow running from repo root
sys.path.append(str(Path(__file__).resolve().parents[1] / "src")) sys.path.append(str(Path(__file__).resolve().parents[1] / "src"))
from smarttools.registry.db import connect_db, query_one from cmdforge.registry.db import connect_db, query_one
from smarttools.registry.sync import ensure_publisher, normalize_tags from cmdforge.registry.sync import ensure_publisher, normalize_tags
def load_yaml(path: Path) -> Dict[str, Any]: def load_yaml(path: Path) -> Dict[str, Any]:

3
src/cmdforge/__init__.py Normal file
View File

@ -0,0 +1,3 @@
"""CmdForge - A lightweight personal tool builder for AI-powered CLI commands."""
__version__ = "0.1.0"

View File

@ -1,4 +1,4 @@
"""CLI entry point for SmartTools. """CLI entry point for CmdForge.
This module is a thin wrapper for backwards compatibility. This module is a thin wrapper for backwards compatibility.
The actual implementation is in the cli/ package. The actual implementation is in the cli/ package.

View File

@ -1,4 +1,4 @@
"""CLI entry point for SmartTools.""" """CLI entry point for CmdForge."""
import argparse import argparse
import sys import sys
@ -18,7 +18,7 @@ from .config_commands import cmd_config
def main(): def main():
"""Main CLI entry point.""" """Main CLI entry point."""
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
prog="smarttools", prog="cmdforge",
description="A lightweight personal tool builder for AI-powered CLI commands" description="A lightweight personal tool builder for AI-powered CLI commands"
) )
parser.add_argument("--version", action="version", version=f"%(prog)s {__version__}") parser.add_argument("--version", action="version", version=f"%(prog)s {__version__}")
@ -179,7 +179,7 @@ def main():
p_deps.set_defaults(func=cmd_deps) p_deps.set_defaults(func=cmd_deps)
# 'install' command (for dependencies) # 'install' command (for dependencies)
p_install = subparsers.add_parser("install", help="Install dependencies from smarttools.yaml") p_install = subparsers.add_parser("install", help="Install dependencies from cmdforge.yaml")
p_install.set_defaults(func=cmd_install_deps) p_install.set_defaults(func=cmd_install_deps)
# 'add' command # 'add' command
@ -190,7 +190,7 @@ def main():
p_add.set_defaults(func=cmd_add) p_add.set_defaults(func=cmd_add)
# 'init' command # 'init' command
p_init = subparsers.add_parser("init", help="Initialize smarttools.yaml") p_init = subparsers.add_parser("init", help="Initialize cmdforge.yaml")
p_init.add_argument("-n", "--name", help="Project name") p_init.add_argument("-n", "--name", help="Project name")
p_init.add_argument("-v", "--version", help="Project version") p_init.add_argument("-v", "--version", help="Project version")
p_init.add_argument("-f", "--force", action="store_true", help="Overwrite existing") p_init.add_argument("-f", "--force", action="store_true", help="Overwrite existing")

View File

@ -4,7 +4,7 @@ from ..config import load_config, save_config, set_registry_token
def cmd_config(args): def cmd_config(args):
"""Manage SmartTools configuration.""" """Manage CmdForge configuration."""
if args.config_cmd == "show": if args.config_cmd == "show":
return _cmd_config_show(args) return _cmd_config_show(args)
elif args.config_cmd == "set-token": elif args.config_cmd == "set-token":
@ -22,7 +22,7 @@ def cmd_config(args):
def _cmd_config_show(args): def _cmd_config_show(args):
"""Show current configuration.""" """Show current configuration."""
config = load_config() config = load_config()
print("SmartTools Configuration:") print("CmdForge Configuration:")
print(f" Registry URL: {config.registry.url}") print(f" Registry URL: {config.registry.url}")
print(f" Token: {'***' if config.registry.token else '(not set)'}") print(f" Token: {'***' if config.registry.token else '(not set)'}")
print(f" Client ID: {config.client_id}") print(f" Client ID: {config.client_id}")

View File

@ -13,12 +13,12 @@ from ..resolver import (
def cmd_deps(args): def cmd_deps(args):
"""Show project dependencies from smarttools.yaml.""" """Show project dependencies from cmdforge.yaml."""
manifest = load_manifest() manifest = load_manifest()
if manifest is None: if manifest is None:
print("No smarttools.yaml found in current project.") print("No cmdforge.yaml found in current project.")
print("Create one with: smarttools init") print("Create one with: cmdforge init")
return 1 return 1
print(f"Project: {manifest.name} v{manifest.version}") print(f"Project: {manifest.name} v{manifest.version}")
@ -26,7 +26,7 @@ def cmd_deps(args):
if not manifest.dependencies: if not manifest.dependencies:
print("No dependencies defined.") print("No dependencies defined.")
print("Add one with: smarttools add <owner/name>") print("Add one with: cmdforge add <owner/name>")
return 0 return 0
print(f"Dependencies ({len(manifest.dependencies)}):") print(f"Dependencies ({len(manifest.dependencies)}):")
@ -52,14 +52,14 @@ def cmd_deps(args):
def cmd_install_deps(args): def cmd_install_deps(args):
"""Install dependencies from smarttools.yaml.""" """Install dependencies from cmdforge.yaml."""
from ..registry_client import RegistryError from ..registry_client import RegistryError
manifest = load_manifest() manifest = load_manifest()
if manifest is None: if manifest is None:
print("No smarttools.yaml found in current project.") print("No cmdforge.yaml found in current project.")
print("Create one with: smarttools init") print("Create one with: cmdforge init")
return 1 return 1
if not manifest.dependencies: if not manifest.dependencies:
@ -150,19 +150,19 @@ def cmd_add(args):
print(f"It's been added to your dependencies - you can install it manually later.", file=sys.stderr) print(f"It's been added to your dependencies - you can install it manually later.", file=sys.stderr)
elif e.code == "CONNECTION_ERROR": elif e.code == "CONNECTION_ERROR":
print(f"Could not connect to registry.", file=sys.stderr) print(f"Could not connect to registry.", file=sys.stderr)
print("Run 'smarttools install' to try again later.", file=sys.stderr) print("Run 'cmdforge install' to try again later.", file=sys.stderr)
else: else:
print(f"Install failed: {e.message}", file=sys.stderr) print(f"Install failed: {e.message}", file=sys.stderr)
print("Run 'smarttools install' to try again.", file=sys.stderr) print("Run 'cmdforge install' to try again.", file=sys.stderr)
except Exception as e: except Exception as e:
print(f"Install failed: {e}", file=sys.stderr) print(f"Install failed: {e}", file=sys.stderr)
print("Run 'smarttools install' to try again.", file=sys.stderr) print("Run 'cmdforge install' to try again.", file=sys.stderr)
return 0 return 0
def cmd_init(args): def cmd_init(args):
"""Initialize a new smarttools.yaml.""" """Initialize a new cmdforge.yaml."""
manifest_path = Path.cwd() / MANIFEST_FILENAME manifest_path = Path.cwd() / MANIFEST_FILENAME
if manifest_path.exists() and not args.force: if manifest_path.exists() and not args.force:
@ -196,7 +196,7 @@ def cmd_init(args):
print(f"Created {MANIFEST_FILENAME}") print(f"Created {MANIFEST_FILENAME}")
print() print()
print("Add dependencies with: smarttools add <owner/name>") print("Add dependencies with: cmdforge add <owner/name>")
print("Install them with: smarttools install") print("Install them with: cmdforge install")
return 0 return 0

View File

@ -48,7 +48,7 @@ PROVIDER_INSTALL_INFO = {
"cost": "FREE (runs entirely on your machine)", "cost": "FREE (runs entirely on your machine)",
"variants": [], "variants": [],
"custom": True, "custom": True,
"post_install_note": "After installing, add the provider:\n smarttools providers add ollama 'ollama run llama3' -d 'Local Llama 3'", "post_install_note": "After installing, add the provider:\n cmdforge providers add ollama 'ollama run llama3' -d 'Local Llama 3'",
}, },
} }
@ -73,7 +73,7 @@ def cmd_providers(args):
def _cmd_providers_install(args): def _cmd_providers_install(args):
"""Interactive guide to install AI providers.""" """Interactive guide to install AI providers."""
print("=" * 60) print("=" * 60)
print("SmartTools Provider Installation Guide") print("CmdForge Provider Installation Guide")
print("=" * 60) print("=" * 60)
print() print()
@ -185,9 +185,9 @@ def _cmd_providers_install(args):
print(f" 2. {info['setup']}") print(f" 2. {info['setup']}")
if info.get('post_install_note'): if info.get('post_install_note'):
print(f" 3. {info['post_install_note']}") print(f" 3. {info['post_install_note']}")
print(f" 4. Test with: smarttools providers test {selected}") print(f" 4. Test with: cmdforge providers test {selected}")
else: else:
print(f" 3. Test with: smarttools providers test {info['variants'][0] if info['variants'] else selected}") print(f" 3. Test with: cmdforge providers test {info['variants'][0] if info['variants'] else selected}")
else: else:
print() print()
print(f"Installation failed (exit code {result.returncode})") print(f"Installation failed (exit code {result.returncode})")

View File

@ -86,7 +86,7 @@ def _cmd_registry_search(args):
return 1 return 1
except Exception as e: except Exception as e:
print(f"Error searching registry: {e}", file=sys.stderr) print(f"Error searching registry: {e}", file=sys.stderr)
print("If the problem persists, check: smarttools config show", file=sys.stderr) print("If the problem persists, check: cmdforge config show", file=sys.stderr)
return 1 return 1
return 0 return 0
@ -120,7 +120,7 @@ def _cmd_registry_install(args):
except RegistryError as e: except RegistryError as e:
if e.code == "TOOL_NOT_FOUND": if e.code == "TOOL_NOT_FOUND":
print(f"Tool '{tool_spec}' not found in the registry.", file=sys.stderr) print(f"Tool '{tool_spec}' not found in the registry.", file=sys.stderr)
print(f"Try: smarttools registry search {tool_spec.split('/')[-1]}", file=sys.stderr) print(f"Try: cmdforge registry search {tool_spec.split('/')[-1]}", file=sys.stderr)
elif e.code == "VERSION_NOT_FOUND" or e.code == "CONSTRAINT_UNSATISFIABLE": elif e.code == "VERSION_NOT_FOUND" or e.code == "CONSTRAINT_UNSATISFIABLE":
print(f"Error: {e.message}", file=sys.stderr) print(f"Error: {e.message}", file=sys.stderr)
if e.details and "available_versions" in e.details: if e.details and "available_versions" in e.details:
@ -191,12 +191,12 @@ def _cmd_registry_info(args):
if len(versions) > 5: if len(versions) > 5:
print(f" ...and {len(versions) - 5} more") print(f" ...and {len(versions) - 5} more")
print(f"\nInstall: smarttools registry install {tool_info.owner}/{tool_info.name}") print(f"\nInstall: cmdforge registry install {tool_info.owner}/{tool_info.name}")
except RegistryError as e: except RegistryError as e:
if e.code == "TOOL_NOT_FOUND": if e.code == "TOOL_NOT_FOUND":
print(f"Tool '{tool_spec}' not found in the registry.", file=sys.stderr) print(f"Tool '{tool_spec}' not found in the registry.", file=sys.stderr)
print(f"Try: smarttools registry search {parsed.name}", file=sys.stderr) print(f"Try: cmdforge registry search {parsed.name}", file=sys.stderr)
elif e.code == "CONNECTION_ERROR": elif e.code == "CONNECTION_ERROR":
print("Could not connect to the registry.", file=sys.stderr) print("Could not connect to the registry.", file=sys.stderr)
print("Check your internet connection or try again later.", file=sys.stderr) print("Check your internet connection or try again later.", file=sys.stderr)
@ -380,7 +380,7 @@ def _cmd_registry_my_tools(args):
if not tools: if not tools:
print("You haven't published any tools yet.") print("You haven't published any tools yet.")
print("Publish your first tool with: smarttools registry publish") print("Publish your first tool with: cmdforge registry publish")
return 0 return 0
print(f"Your published tools ({len(tools)}):\n") print(f"Your published tools ({len(tools)}):\n")
@ -393,7 +393,7 @@ def _cmd_registry_my_tools(args):
except RegistryError as e: except RegistryError as e:
if e.code == "UNAUTHORIZED": if e.code == "UNAUTHORIZED":
print("Not logged in. Set your registry token first:", file=sys.stderr) print("Not logged in. Set your registry token first:", file=sys.stderr)
print(" smarttools config set-token <token>", file=sys.stderr) print(" cmdforge config set-token <token>", file=sys.stderr)
print() print()
print("Don't have a token? Register at the registry website.", file=sys.stderr) print("Don't have a token? Register at the registry website.", file=sys.stderr)
elif e.code == "CONNECTION_ERROR": elif e.code == "CONNECTION_ERROR":
@ -418,8 +418,8 @@ def _cmd_registry_browse(args):
return run_registry_browser() return run_registry_browser()
except ImportError: except ImportError:
print("TUI browser requires urwid. Install with:", file=sys.stderr) print("TUI browser requires urwid. Install with:", file=sys.stderr)
print(" pip install 'smarttools[tui]'", file=sys.stderr) print(" pip install 'cmdforge[tui]'", file=sys.stderr)
print() print()
print("Or search from command line:", file=sys.stderr) print("Or search from command line:", file=sys.stderr)
print(" smarttools registry search <query>", file=sys.stderr) print(" cmdforge registry search <query>", file=sys.stderr)
return 1 return 1

View File

@ -16,7 +16,7 @@ def cmd_list(args):
if not tools: if not tools:
print("No tools found.") print("No tools found.")
print("Create your first tool with: smarttools ui") print("Create your first tool with: cmdforge ui")
return 0 return 0
print(f"Available tools ({len(tools)}):\n") print(f"Available tools ({len(tools)}):\n")
@ -76,7 +76,7 @@ def cmd_create(args):
path = save_tool(tool) path = save_tool(tool)
print(f"Created tool '{name}'") print(f"Created tool '{name}'")
print(f"Config: {path}") print(f"Config: {path}")
print(f"\nUse 'smarttools ui' to add arguments, steps, and customize.") print(f"\nUse 'cmdforge ui' to add arguments, steps, and customize.")
print(f"Or run: {name} < input.txt") print(f"Or run: {name} < input.txt")
return 0 return 0
@ -326,7 +326,7 @@ echo "input" | {args.name}
# View README # View README
if not readme_path.exists(): if not readme_path.exists():
print(f"No documentation found for '{args.name}'.") print(f"No documentation found for '{args.name}'.")
print(f"Create it with: smarttools docs {args.name} --edit") print(f"Create it with: cmdforge docs {args.name} --edit")
return 1 return 1
print(readme_path.read_text()) print(readme_path.read_text())

View File

@ -1,6 +1,6 @@
"""Global configuration handling for SmartTools. """Global configuration handling for CmdForge.
Manages ~/.smarttools/config.yaml with registry settings, tokens, and preferences. Manages ~/.cmdforge/config.yaml with registry settings, tokens, and preferences.
""" """
import uuid import uuid
@ -12,7 +12,7 @@ import yaml
# Default configuration directory # Default configuration directory
CONFIG_DIR = Path.home() / ".smarttools" CONFIG_DIR = Path.home() / ".cmdforge"
CONFIG_FILE = CONFIG_DIR / "config.yaml" CONFIG_FILE = CONFIG_DIR / "config.yaml"
# Default registry URL (canonical base path) # Default registry URL (canonical base path)
@ -41,7 +41,7 @@ class RegistryConfig:
@dataclass @dataclass
class Config: class Config:
"""Global SmartTools configuration.""" """Global CmdForge configuration."""
registry: RegistryConfig = field(default_factory=RegistryConfig) registry: RegistryConfig = field(default_factory=RegistryConfig)
client_id: str = "" client_id: str = ""
auto_fetch_from_registry: bool = True auto_fetch_from_registry: bool = True

View File

@ -1,4 +1,4 @@
"""Project manifest (smarttools.yaml) handling. """Project manifest (cmdforge.yaml) handling.
Manages project-level tool dependencies and overrides. Manages project-level tool dependencies and overrides.
""" """
@ -11,7 +11,7 @@ from typing import Optional, List, Dict
import yaml import yaml
MANIFEST_FILENAME = "smarttools.yaml" MANIFEST_FILENAME = "cmdforge.yaml"
@dataclass @dataclass
@ -76,7 +76,7 @@ class ToolOverride:
@dataclass @dataclass
class Manifest: class Manifest:
"""Project manifest (smarttools.yaml).""" """Project manifest (cmdforge.yaml)."""
name: str = "my-project" name: str = "my-project"
version: str = "1.0.0" version: str = "1.0.0"
dependencies: List[Dependency] = field(default_factory=list) dependencies: List[Dependency] = field(default_factory=list)
@ -144,7 +144,7 @@ class Manifest:
def find_manifest(start_dir: Optional[Path] = None) -> Optional[Path]: def find_manifest(start_dir: Optional[Path] = None) -> Optional[Path]:
""" """
Find smarttools.yaml by searching up from start_dir. Find cmdforge.yaml by searching up from start_dir.
Args: Args:
start_dir: Directory to start searching from (default: cwd) start_dir: Directory to start searching from (default: cwd)
@ -201,7 +201,7 @@ def save_manifest(manifest: Manifest, path: Optional[Path] = None) -> Path:
Args: Args:
manifest: Manifest to save manifest: Manifest to save
path: Path to save to (default: ./smarttools.yaml) path: Path to save to (default: ./cmdforge.yaml)
Returns: Returns:
Path where manifest was saved Path where manifest was saved

View File

@ -12,7 +12,7 @@ import yaml
# Default providers config location # Default providers config location
PROVIDERS_FILE = Path.home() / ".smarttools" / "providers.yaml" PROVIDERS_FILE = Path.home() / ".cmdforge" / "providers.yaml"
@dataclass @dataclass
@ -161,7 +161,7 @@ def call_provider(provider_name: str, prompt: str, timeout: int = 300) -> Provid
return ProviderResult( return ProviderResult(
text="", text="",
success=False, success=False,
error=f"Provider '{provider_name}' not found. Use 'smarttools providers' to manage providers." error=f"Provider '{provider_name}' not found. Use 'cmdforge providers' to manage providers."
) )
# Parse command (expand environment variables) # Parse command (expand environment variables)
@ -181,7 +181,7 @@ def call_provider(provider_name: str, prompt: str, timeout: int = 300) -> Provid
return ProviderResult( return ProviderResult(
text="", text="",
success=False, success=False,
error=f"Command '{base_cmd}' not found. Is it installed and in PATH?\n\nTo install AI providers, run: smarttools providers install" error=f"Command '{base_cmd}' not found. Is it installed and in PATH?\n\nTo install AI providers, run: cmdforge providers install"
) )
try: try:
@ -197,7 +197,7 @@ def call_provider(provider_name: str, prompt: str, timeout: int = 300) -> Provid
if result.returncode != 0: if result.returncode != 0:
error_msg = f"Provider exited with code {result.returncode}: {result.stderr}" error_msg = f"Provider exited with code {result.returncode}: {result.stderr}"
if "not found" in result.stderr.lower() or "not installed" in result.stderr.lower(): if "not found" in result.stderr.lower() or "not installed" in result.stderr.lower():
error_msg += "\n\nTo install AI providers, run: smarttools providers install" error_msg += "\n\nTo install AI providers, run: cmdforge providers install"
return ProviderResult( return ProviderResult(
text="", text="",
success=False, success=False,
@ -224,14 +224,14 @@ def call_provider(provider_name: str, prompt: str, timeout: int = 300) -> Provid
f"To fix this, either:\n" f"To fix this, either:\n"
f" 1. Run 'opencode' to connect the {provider_id} provider\n" f" 1. Run 'opencode' to connect the {provider_id} provider\n"
f" 2. Use --provider to pick a different model (e.g., --provider opencode-pickle)\n" f" 2. Use --provider to pick a different model (e.g., --provider opencode-pickle)\n"
f" 3. Run 'smarttools ui' to edit the tool's default provider" f" 3. Run 'cmdforge ui' to edit the tool's default provider"
) )
stderr_hint = f" (stderr: {stderr[:200]}...)" if len(stderr) > 200 else (f" (stderr: {stderr})" if stderr else "") stderr_hint = f" (stderr: {stderr[:200]}...)" if len(stderr) > 200 else (f" (stderr: {stderr})" if stderr else "")
return ProviderResult( return ProviderResult(
text="", text="",
success=False, success=False,
error=f"Provider returned empty output{stderr_hint}.\n\nThis may mean the model is not available. Try a different provider or run: smarttools providers install" error=f"Provider returned empty output{stderr_hint}.\n\nThis may mean the model is not available. Try a different provider or run: cmdforge providers install"
) )
return ProviderResult(text=result.stdout, success=True) return ProviderResult(text=result.stdout, success=True)

View File

@ -1,4 +1,4 @@
"""Flask app for SmartTools Registry API (Phase 2).""" """Flask app for CmdForge Registry API (Phase 2)."""
from __future__ import annotations from __future__ import annotations
@ -51,7 +51,7 @@ ALLOWED_SORT = {
TOOL_NAME_RE = re.compile(r"^[A-Za-z0-9-]{1,64}$") TOOL_NAME_RE = re.compile(r"^[A-Za-z0-9-]{1,64}$")
OWNER_RE = re.compile(r"^[a-z0-9][a-z0-9-]{0,37}[a-z0-9]$") OWNER_RE = re.compile(r"^[a-z0-9][a-z0-9-]{0,37}[a-z0-9]$")
EMAIL_RE = re.compile(r"^[^@\s]+@[^@\s]+\.[^@\s]+$") EMAIL_RE = re.compile(r"^[^@\s]+@[^@\s]+\.[^@\s]+$")
RESERVED_SLUGS = {"official", "admin", "system", "api", "registry", "smarttools"} RESERVED_SLUGS = {"official", "admin", "system", "api", "registry", "cmdforge"}
rate_limiter = RateLimiter() rate_limiter = RateLimiter()
password_hasher = PasswordHasher(memory_cost=65536, time_cost=3, parallelism=4) password_hasher = PasswordHasher(memory_cost=65536, time_cost=3, parallelism=4)
@ -1517,7 +1517,7 @@ def create_app() -> Flask:
status=413, status=413,
details={"limit": MAX_BODY_BYTES}, details={"limit": MAX_BODY_BYTES},
) )
secret = os.environ.get("SMARTTOOLS_REGISTRY_WEBHOOK_SECRET", "") secret = os.environ.get("CMDFORGE_REGISTRY_WEBHOOK_SECRET", "")
if not secret: if not secret:
return error_response("UNAUTHORIZED", "Webhook secret not configured", 401) return error_response("UNAUTHORIZED", "Webhook secret not configured", 401)
status, payload = process_webhook(request.data, dict(request.headers), secret) status, payload = process_webhook(request.data, dict(request.headers), secret)

View File

@ -232,8 +232,8 @@ CREATE INDEX IF NOT EXISTS idx_pageviews_date ON pageviews(date(viewed_at), path
def get_db_path() -> Path: def get_db_path() -> Path:
default_path = Path.home() / ".smarttools" / "registry" / "registry.db" default_path = Path.home() / ".cmdforge" / "registry" / "registry.db"
return Path(os.environ.get("SMARTTOOLS_REGISTRY_DB", default_path)) return Path(os.environ.get("CMDFORGE_REGISTRY_DB", default_path))
def ensure_db_directory(path: Path) -> None: def ensure_db_directory(path: Path) -> None:

View File

@ -19,22 +19,22 @@ from .db import connect_db, query_one
def get_repo_dir() -> Path: def get_repo_dir() -> Path:
default_dir = Path.home() / ".smarttools" / "registry" / "repo" default_dir = Path.home() / ".cmdforge" / "registry" / "repo"
return Path(os.environ.get("SMARTTOOLS_REGISTRY_REPO_DIR", default_dir)) return Path(os.environ.get("CMDFORGE_REGISTRY_REPO_DIR", default_dir))
def get_repo_url() -> str: def get_repo_url() -> str:
return os.environ.get("SMARTTOOLS_REGISTRY_REPO_URL", "https://gitea.brrd.tech/rob/SmartTools-Registry.git") return os.environ.get("CMDFORGE_REGISTRY_REPO_URL", "https://gitea.brrd.tech/rob/CmdForge-Registry.git")
def get_repo_branch() -> str: def get_repo_branch() -> str:
return os.environ.get("SMARTTOOLS_REGISTRY_REPO_BRANCH", "main") return os.environ.get("CMDFORGE_REGISTRY_REPO_BRANCH", "main")
def get_categories_cache_path() -> Path: def get_categories_cache_path() -> Path:
return Path(os.environ.get( return Path(os.environ.get(
"SMARTTOOLS_REGISTRY_CATEGORIES_CACHE", "CMDFORGE_REGISTRY_CATEGORIES_CACHE",
Path.home() / ".smarttools" / "registry" / "categories_cache.json", Path.home() / ".cmdforge" / "registry" / "categories_cache.json",
)) ))
@ -249,7 +249,7 @@ def process_webhook(body: bytes, headers: Dict[str, str], secret: str, timeout:
if is_delivery_processed(conn, delivery_id): if is_delivery_processed(conn, delivery_id):
return 200, {"data": {"status": "already_processed"}} return 200, {"data": {"status": "already_processed"}}
lock_path = Path.home() / ".smarttools" / "registry" / "locks" / "webhook.lock" lock_path = Path.home() / ".cmdforge" / "registry" / "locks" / "webhook.lock"
if not acquire_lock(lock_path, timeout): if not acquire_lock(lock_path, timeout):
return 200, {"data": {"status": "skipped", "reason": "sync_in_progress"}} return 200, {"data": {"status": "skipped", "reason": "sync_in_progress"}}

View File

@ -1,4 +1,4 @@
"""Registry API client for SmartTools. """Registry API client for CmdForge.
Handles all HTTP communication with the registry server. Handles all HTTP communication with the registry server.
""" """
@ -114,7 +114,7 @@ class DownloadResult:
class RegistryClient: class RegistryClient:
"""Client for interacting with the SmartTools registry API.""" """Client for interacting with the CmdForge registry API."""
def __init__( def __init__(
self, self,
@ -141,8 +141,8 @@ class RegistryClient:
# Session for connection pooling # Session for connection pooling
self._session = requests.Session() self._session = requests.Session()
self._session.headers.update({ self._session.headers.update({
"User-Agent": "SmartTools-CLI/1.0", "User-Agent": "CmdForge-CLI/1.0",
"X-SmartTools-Client": "cli/1.0.0", "X-CmdForge-Client": "cli/1.0.0",
"Accept": "application/json" "Accept": "application/json"
}) })
@ -198,7 +198,7 @@ class RegistryClient:
if not self.token: if not self.token:
raise RegistryError( raise RegistryError(
code="UNAUTHORIZED", code="UNAUTHORIZED",
message="Authentication required. Set registry token with 'smarttools config set-token'", message="Authentication required. Set registry token with 'cmdforge config set-token'",
http_status=401 http_status=401
) )
headers.update(self._auth_headers()) headers.update(self._auth_headers())

View File

@ -1,8 +1,8 @@
"""Tool resolution with proper search order. """Tool resolution with proper search order.
Implements the tool resolution order: Implements the tool resolution order:
1. Local project: ./.smarttools/<owner>/<name>/config.yaml 1. Local project: ./.cmdforge/<owner>/<name>/config.yaml
2. Global user: ~/.smarttools/<owner>/<name>/config.yaml 2. Global user: ~/.cmdforge/<owner>/<name>/config.yaml
3. Registry: Fetch from API, install to global, then run 3. Registry: Fetch from API, install to global, then run
4. Error if not found 4. Error if not found
""" """
@ -24,7 +24,7 @@ logger = logging.getLogger(__name__)
# Local project tools directories (support both legacy and documented paths) # Local project tools directories (support both legacy and documented paths)
LOCAL_TOOLS_DIRS = [Path(".smarttools"), Path("smarttools")] LOCAL_TOOLS_DIRS = [Path(".cmdforge"), Path("cmdforge")]
@dataclass @dataclass
@ -436,9 +436,9 @@ class ToolResolver:
python_path = sys.executable python_path = sys.executable
script = f"""#!/bin/bash script = f"""#!/bin/bash
# SmartTools wrapper for '{owner}/{name}' # CmdForge wrapper for '{owner}/{name}'
# Auto-generated - do not edit # Auto-generated - do not edit
exec {python_path} -m smarttools.runner {owner}/{name} "$@" exec {python_path} -m cmdforge.runner {owner}/{name} "$@"
""" """
wrapper_path.write_text(script) wrapper_path.write_text(script)
@ -450,9 +450,9 @@ exec {python_path} -m smarttools.runner {owner}/{name} "$@"
"""Extract owner from existing wrapper script.""" """Extract owner from existing wrapper script."""
try: try:
content = wrapper_path.read_text() content = wrapper_path.read_text()
# Look for pattern: smarttools.runner owner/name # Look for pattern: cmdforge.runner owner/name
# Owner slugs can contain lowercase alphanumeric and hyphens # Owner slugs can contain lowercase alphanumeric and hyphens
match = re.search(r'smarttools\.runner\s+([a-z0-9][a-z0-9-]*)/([a-zA-Z0-9_-]+)', content) match = re.search(r'cmdforge\.runner\s+([a-z0-9][a-z0-9-]*)/([a-zA-Z0-9_-]+)', content)
if match: if match:
return match.group(1) return match.group(1)
return None return None

View File

@ -210,7 +210,7 @@ def create_argument_parser(tool: Tool) -> argparse.ArgumentParser:
""" """
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
prog=tool.name, prog=tool.name,
description=tool.description or f"SmartTools: {tool.name}" description=tool.description or f"CmdForge: {tool.name}"
) )
# Universal flags # Universal flags
@ -244,7 +244,7 @@ def create_argument_parser(tool: Tool) -> argparse.ArgumentParser:
def main(): def main():
"""Entry point for tool execution via wrapper script.""" """Entry point for tool execution via wrapper script."""
if len(sys.argv) < 2: if len(sys.argv) < 2:
print("Usage: python -m smarttools.runner <tool_name> [args...]", file=sys.stderr) print("Usage: python -m cmdforge.runner <tool_name> [args...]", file=sys.stderr)
sys.exit(1) sys.exit(1)
tool_spec = sys.argv[1] tool_spec = sys.argv[1]

View File

@ -10,7 +10,7 @@ import yaml
# Default tools directory # Default tools directory
TOOLS_DIR = Path.home() / ".smarttools" TOOLS_DIR = Path.home() / ".cmdforge"
# Default bin directory for wrapper scripts # Default bin directory for wrapper scripts
BIN_DIR = Path.home() / ".local" / "bin" BIN_DIR = Path.home() / ".local" / "bin"
@ -106,7 +106,7 @@ DEFAULT_CATEGORIES = ["Text", "Developer", "Data", "Other"]
@dataclass @dataclass
class Tool: class Tool:
"""A SmartTools tool definition.""" """A CmdForge tool definition."""
name: str name: str
description: str = "" description: str = ""
category: str = "Other" # Tool category for organization category: str = "Other" # Tool category for organization
@ -275,13 +275,13 @@ def create_wrapper_script(name: str) -> Path:
bin_dir = get_bin_dir() bin_dir = get_bin_dir()
wrapper_path = bin_dir / name wrapper_path = bin_dir / name
# Use the current Python interpreter to ensure smarttools is available # Use the current Python interpreter to ensure cmdforge is available
python_path = sys.executable python_path = sys.executable
script = f"""#!/bin/bash script = f"""#!/bin/bash
# SmartTools wrapper for '{name}' # CmdForge wrapper for '{name}'
# Auto-generated - do not edit # Auto-generated - do not edit
exec {python_path} -m smarttools.runner {name} "$@" exec {python_path} -m cmdforge.runner {name} "$@"
""" """
wrapper_path.write_text(script) wrapper_path.write_text(script)

View File

@ -1,4 +1,4 @@
"""Dialog-based UI for managing SmartTools.""" """Dialog-based UI for managing CmdForge."""
import subprocess import subprocess
import sys import sys
@ -762,7 +762,7 @@ def main_menu(dialog_prog: str):
"""Show the main menu.""" """Show the main menu."""
while True: while True:
choice = show_menu( choice = show_menu(
"SmartTools Manager", "CmdForge Manager",
[ [
("list", "List all tools"), ("list", "List all tools"),
("create", "Create new tool"), ("create", "Create new tool"),

View File

@ -1,4 +1,4 @@
"""TUI for browsing the SmartTools Registry using urwid. """TUI for browsing the CmdForge Registry using urwid.
Uses threading for non-blocking network operations. Uses threading for non-blocking network operations.
""" """
@ -170,7 +170,7 @@ class AsyncOperation:
class RegistryBrowser: class RegistryBrowser:
"""TUI browser for the SmartTools Registry.""" """TUI browser for the CmdForge Registry."""
def __init__(self): def __init__(self):
self.client = get_client() self.client = get_client()
@ -195,7 +195,7 @@ class RegistryBrowser:
"""Build the main UI layout.""" """Build the main UI layout."""
# Header # Header
self.header = urwid.AttrMap( self.header = urwid.AttrMap(
urwid.Text(" SmartTools Registry Browser ", align='center'), urwid.Text(" CmdForge Registry Browser ", align='center'),
'header' 'header'
) )
@ -344,7 +344,7 @@ Downloads: {downloads}
Tags: {', '.join(tags) if tags else 'None'} Tags: {', '.join(tags) if tags else 'None'}
Install command: Install command:
smarttools registry install {owner}/{name} cmdforge registry install {owner}/{name}
Press 'i' to install this tool Press 'i' to install this tool
""" """

View File

@ -1,4 +1,4 @@
"""BIOS-style TUI for SmartTools using snack (python3-newt).""" """BIOS-style TUI for CmdForge using snack (python3-newt)."""
import sys import sys
# Ensure system packages are accessible # Ensure system packages are accessible
@ -15,8 +15,8 @@ from .tool import (
from .providers import Provider, load_providers, add_provider, delete_provider, get_provider from .providers import Provider, load_providers, add_provider, delete_provider, get_provider
class SmartToolsUI: class CmdForgeUI:
"""BIOS-style UI for SmartTools.""" """BIOS-style UI for CmdForge."""
def __init__(self): def __init__(self):
self.screen = None self.screen = None
@ -51,7 +51,7 @@ class SmartToolsUI:
for label, value in items: for label, value in items:
listbox.append(label, value) listbox.append(label, value)
grid = snack.GridForm(self.screen, "SmartTools Manager", 1, 1) grid = snack.GridForm(self.screen, "CmdForge Manager", 1, 1)
grid.add(listbox, 0, 0) grid.add(listbox, 0, 0)
result = grid.runOnce() result = grid.runOnce()
@ -698,7 +698,7 @@ class SmartToolsUI:
def run_ui(): def run_ui():
"""Entry point for the snack UI.""" """Entry point for the snack UI."""
ui = SmartToolsUI() ui = CmdForgeUI()
ui.run() ui.run()

View File

@ -1,10 +1,10 @@
"""BIOS-style TUI for SmartTools using urwid. """BIOS-style TUI for CmdForge using urwid.
This module is a thin wrapper for backwards compatibility. This module is a thin wrapper for backwards compatibility.
The actual implementation is in the ui_urwid/ package. The actual implementation is in the ui_urwid/ package.
""" """
from .ui_urwid import run_ui, SmartToolsUI from .ui_urwid import run_ui, CmdForgeUI
from .ui_urwid.palette import PALETTE from .ui_urwid.palette import PALETTE
from .ui_urwid.widgets import ( from .ui_urwid.widgets import (
SelectableText, Button3D, Button3DCompact, ClickableButton, SelectableText, Button3D, Button3DCompact, ClickableButton,
@ -13,7 +13,7 @@ from .ui_urwid.widgets import (
) )
__all__ = [ __all__ = [
'run_ui', 'SmartToolsUI', 'PALETTE', 'run_ui', 'CmdForgeUI', 'PALETTE',
'SelectableText', 'Button3D', 'Button3DCompact', 'ClickableButton', 'SelectableText', 'Button3D', 'Button3DCompact', 'ClickableButton',
'SelectableToolItem', 'ToolListBox', 'TabCyclePile', 'TabPassEdit', 'SelectableToolItem', 'ToolListBox', 'TabCyclePile', 'TabPassEdit',
'UndoableEdit', 'DOSScrollBar', 'ToolBuilderLayout', 'Dialog' 'UndoableEdit', 'DOSScrollBar', 'ToolBuilderLayout', 'Dialog'

View File

@ -1,4 +1,4 @@
"""BIOS-style TUI for SmartTools using urwid (with mouse support).""" """BIOS-style TUI for CmdForge using urwid (with mouse support)."""
import urwid import urwid
from typing import Optional, Callable from typing import Optional, Callable
@ -18,8 +18,8 @@ from .widgets import (
) )
class SmartToolsUI: class CmdForgeUI:
"""Urwid-based UI for SmartTools with mouse support.""" """Urwid-based UI for CmdForge with mouse support."""
def __init__(self): def __init__(self):
self.loop = None self.loop = None
@ -226,7 +226,7 @@ class SmartToolsUI:
], tab_positions=[0, 1, 5]) # Tool list, buttons row, exit button ], tab_positions=[0, 1, 5]) # Tool list, buttons row, exit button
# Header # Header
header = urwid.Text(('header', ' SmartTools Manager '), align='center') header = urwid.Text(('header', ' CmdForge Manager '), align='center')
# Footer # Footer
footer = urwid.Text(('footer', ' Arrow:Navigate list | Tab:Jump to buttons | Enter/Click:Select | Q:Quit '), align='center') footer = urwid.Text(('footer', ' Arrow:Navigate list | Tab:Jump to buttons | Enter/Click:Select | Q:Quit '), align='center')
@ -1566,5 +1566,5 @@ No explanations, no markdown fencing, just the code."""
def run_ui(): def run_ui():
"""Entry point for the urwid UI.""" """Entry point for the urwid UI."""
ui = SmartToolsUI() ui = CmdForgeUI()
ui.run() ui.run()

View File

@ -1,4 +1,4 @@
"""Web UI blueprint for SmartTools.""" """Web UI blueprint for CmdForge."""
import os import os
from flask import Blueprint from flask import Blueprint

View File

@ -1,4 +1,4 @@
"""Web app factory for SmartTools UI.""" """Web app factory for CmdForge UI."""
from __future__ import annotations from __future__ import annotations
@ -19,13 +19,13 @@ if _sentry_dsn:
integrations=[FlaskIntegration()], integrations=[FlaskIntegration()],
traces_sample_rate=float(os.environ.get("SENTRY_TRACES_RATE", "0.1")), traces_sample_rate=float(os.environ.get("SENTRY_TRACES_RATE", "0.1")),
profiles_sample_rate=float(os.environ.get("SENTRY_PROFILES_RATE", "0.1")), profiles_sample_rate=float(os.environ.get("SENTRY_PROFILES_RATE", "0.1")),
environment=os.environ.get("SMARTTOOLS_ENV", "development"), environment=os.environ.get("CMDFORGE_ENV", "development"),
send_default_pii=False, # Privacy: don't send user IPs, emails, etc. send_default_pii=False, # Privacy: don't send user IPs, emails, etc.
) )
except ImportError: except ImportError:
pass # sentry-sdk not installed pass # sentry-sdk not installed
from smarttools.registry import app as registry_app from cmdforge.registry import app as registry_app
from . import web_bp from . import web_bp
from .auth import login, register, logout from .auth import login, register, logout
@ -44,10 +44,10 @@ def create_web_app() -> Flask:
app.register_blueprint(forum_bp) app.register_blueprint(forum_bp)
# Session configuration # Session configuration
app.session_interface = SQLiteSessionInterface(cookie_name="smarttools_session") app.session_interface = SQLiteSessionInterface(cookie_name="cmdforge_session")
app.config["SESSION_COOKIE_NAME"] = "smarttools_session" app.config["SESSION_COOKIE_NAME"] = "cmdforge_session"
app.config["SESSION_COOKIE_SECURE"] = os.environ.get("SMARTTOOLS_ENV") == "production" app.config["SESSION_COOKIE_SECURE"] = os.environ.get("CMDFORGE_ENV") == "production"
app.config["SHOW_ADS"] = os.environ.get("SMARTTOOLS_SHOW_ADS", "").lower() == "true" app.config["SHOW_ADS"] = os.environ.get("CMDFORGE_SHOW_ADS", "").lower() == "true"
# CSRF token generator # CSRF token generator
app.config["CSRF_GENERATOR"] = lambda: secrets.token_urlsafe(32) app.config["CSRF_GENERATOR"] = lambda: secrets.token_urlsafe(32)

View File

@ -1,4 +1,4 @@
"""Documentation content for SmartTools web UI. """Documentation content for CmdForge web UI.
This module contains the actual documentation text that gets rendered This module contains the actual documentation text that gets rendered
on the /docs pages. Content is stored as markdown-ish HTML for simplicity. on the /docs pages. Content is stored as markdown-ish HTML for simplicity.
@ -7,13 +7,13 @@ on the /docs pages. Content is stored as markdown-ish HTML for simplicity.
DOCS = { DOCS = {
"getting-started": { "getting-started": {
"title": "Getting Started", "title": "Getting Started",
"description": "Learn how to install SmartTools and create your first AI-powered CLI tool", "description": "Learn how to install CmdForge and create your first AI-powered CLI tool",
"content": """ "content": """
<p class="lead">SmartTools lets you build custom AI-powered CLI commands using simple YAML configuration. <p class="lead">CmdForge lets you build custom AI-powered CLI commands using simple YAML configuration.
Create tools that work with any AI provider and compose them like Unix pipes.</p> Create tools that work with any AI provider and compose them like Unix pipes.</p>
<h2 id="what-is-smarttools">What is SmartTools?</h2> <h2 id="what-is-cmdforge">What is CmdForge?</h2>
<p>SmartTools is a lightweight personal tool builder that lets you:</p> <p>CmdForge is a lightweight personal tool builder that lets you:</p>
<ul> <ul>
<li><strong>Create custom CLI commands</strong> that call AI providers</li> <li><strong>Create custom CLI commands</strong> that call AI providers</li>
<li><strong>Chain prompts with Python code</strong> for complex workflows</li> <li><strong>Chain prompts with Python code</strong> for complex workflows</li>
@ -24,23 +24,23 @@ Create tools that work with any AI provider and compose them like Unix pipes.</p
<h2 id="quick-start">Quick Start</h2> <h2 id="quick-start">Quick Start</h2>
<p>Get up and running in under a minute:</p> <p>Get up and running in under a minute:</p>
<pre><code class="language-bash"># Install SmartTools <pre><code class="language-bash"># Install CmdForge
pip install smarttools pip install cmdforge
# Create your first tool (choose your style) # Create your first tool (choose your style)
smarttools ui # Visual builder with menus cmdforge ui # Visual builder with menus
smarttools create # CLI wizard cmdforge create # CLI wizard
# Or install a tool from the registry # Or install a tool from the registry
smarttools registry install official/summarize cmdforge registry install official/summarize
# Use it! # Use it!
cat article.txt | summarize</code></pre> cat article.txt | summarize</code></pre>
<div class="bg-cyan-50 border-l-4 border-cyan-500 p-4 my-4"> <div class="bg-cyan-50 border-l-4 border-cyan-500 p-4 my-4">
<p class="font-semibold text-cyan-800">Two Ways to Build</p> <p class="font-semibold text-cyan-800">Two Ways to Build</p>
<p class="text-cyan-700"><code>smarttools ui</code> launches a visual builder with menus and forms. <p class="text-cyan-700"><code>cmdforge ui</code> launches a visual builder with menus and forms.
<code>smarttools create</code> uses a command-line wizard. Both create the same YAML config files.</p> <code>cmdforge create</code> uses a command-line wizard. Both create the same YAML config files.</p>
</div> </div>
<h2 id="how-it-works">How It Works</h2> <h2 id="how-it-works">How It Works</h2>
@ -87,11 +87,11 @@ output: "{summary}"</code></pre>
<ul> <ul>
<li><a href="/forum">Community Forum</a> - Ask questions, share projects, and connect with other users</li> <li><a href="/forum">Community Forum</a> - Ask questions, share projects, and connect with other users</li>
<li><a href="/forum/c/help">Help &amp; Support</a> - Get help with installation, configuration, or usage</li> <li><a href="/forum/c/help">Help &amp; Support</a> - Get help with installation, configuration, or usage</li>
<li><a href="https://gitea.brrd.tech/rob/SmartTools/issues" target="_blank">Report a Bug</a> - Found an issue? Let us know</li> <li><a href="https://gitea.brrd.tech/rob/CmdForge/issues" target="_blank">Report a Bug</a> - Found an issue? Let us know</li>
</ul> </ul>
""", """,
"headings": [ "headings": [
("what-is-smarttools", "What is SmartTools?"), ("what-is-cmdforge", "What is CmdForge?"),
("quick-start", "Quick Start"), ("quick-start", "Quick Start"),
("how-it-works", "How It Works"), ("how-it-works", "How It Works"),
("next-steps", "Next Steps"), ("next-steps", "Next Steps"),
@ -101,24 +101,24 @@ output: "{summary}"</code></pre>
"installation": { "installation": {
"title": "Installation", "title": "Installation",
"description": "How to install SmartTools on your system", "description": "How to install CmdForge on your system",
"parent": "getting-started", "parent": "getting-started",
"content": """ "content": """
<p class="lead">SmartTools requires Python 3.8+ and works on Linux, macOS, and Windows.</p> <p class="lead">CmdForge requires Python 3.8+ and works on Linux, macOS, and Windows.</p>
<h2 id="pip-install">Install with pip</h2> <h2 id="pip-install">Install with pip</h2>
<p>The simplest way to install SmartTools:</p> <p>The simplest way to install CmdForge:</p>
<pre><code class="language-bash">pip install smarttools</code></pre> <pre><code class="language-bash">pip install cmdforge</code></pre>
<p>Or with pipx for isolated installation:</p> <p>Or with pipx for isolated installation:</p>
<pre><code class="language-bash">pipx install smarttools</code></pre> <pre><code class="language-bash">pipx install cmdforge</code></pre>
<h2 id="verify">Verify Installation</h2> <h2 id="verify">Verify Installation</h2>
<pre><code class="language-bash">smarttools --version <pre><code class="language-bash">cmdforge --version
smarttools --help</code></pre> cmdforge --help</code></pre>
<h2 id="configure-provider">Configure a Provider</h2> <h2 id="configure-provider">Configure a Provider</h2>
<p>SmartTools needs at least one AI provider configured. The easiest is Claude CLI:</p> <p>CmdForge needs at least one AI provider configured. The easiest is Claude CLI:</p>
<pre><code class="language-bash"># Install Claude CLI (if you have an Anthropic API key) <pre><code class="language-bash"># Install Claude CLI (if you have an Anthropic API key)
pip install claude-cli pip install claude-cli
@ -127,17 +127,17 @@ pip install claude-cli
pip install openai pip install openai
# Configure your provider # Configure your provider
smarttools config</code></pre> cmdforge config</code></pre>
<h2 id="wrapper-scripts">Wrapper Scripts Location</h2> <h2 id="wrapper-scripts">Wrapper Scripts Location</h2>
<p>SmartTools installs wrapper scripts to <code>~/.local/bin/</code>. Make sure this is in your PATH:</p> <p>CmdForge installs wrapper scripts to <code>~/.local/bin/</code>. Make sure this is in your PATH:</p>
<pre><code class="language-bash"># Add to ~/.bashrc or ~/.zshrc <pre><code class="language-bash"># Add to ~/.bashrc or ~/.zshrc
export PATH="$HOME/.local/bin:$PATH"</code></pre> export PATH="$HOME/.local/bin:$PATH"</code></pre>
<h2 id="development-install">Development Installation</h2> <h2 id="development-install">Development Installation</h2>
<p>To contribute or modify SmartTools:</p> <p>To contribute or modify CmdForge:</p>
<pre><code class="language-bash">git clone https://gitea.brrd.tech/rob/SmartTools.git <pre><code class="language-bash">git clone https://gitea.brrd.tech/rob/CmdForge.git
cd SmartTools cd CmdForge
pip install -e ".[dev]"</code></pre> pip install -e ".[dev]"</code></pre>
""", """,
"headings": [ "headings": [
@ -151,16 +151,16 @@ pip install -e ".[dev]"</code></pre>
"first-tool": { "first-tool": {
"title": "Your First Tool", "title": "Your First Tool",
"description": "Create your first SmartTools command step by step", "description": "Create your first CmdForge command step by step",
"parent": "getting-started", "parent": "getting-started",
"content": """ "content": """
<p class="lead">Let's create a simple tool that explains code. You'll learn the basics of tool configuration.</p> <p class="lead">Let's create a simple tool that explains code. You'll learn the basics of tool configuration.</p>
<h2 id="create-tool">Create the Tool</h2> <h2 id="create-tool">Create the Tool</h2>
<p>Run the interactive creator:</p> <p>Run the interactive creator:</p>
<pre><code class="language-bash">smarttools create</code></pre> <pre><code class="language-bash">cmdforge create</code></pre>
<p>Or create the file manually at <code>~/.smarttools/explain/config.yaml</code>:</p> <p>Or create the file manually at <code>~/.cmdforge/explain/config.yaml</code>:</p>
<pre><code class="language-yaml">name: explain <pre><code class="language-yaml">name: explain
version: "1.0.0" version: "1.0.0"
description: Explain code or concepts in simple terms description: Explain code or concepts in simple terms
@ -230,9 +230,9 @@ cat complex_algorithm.py | explain --level expert</code></pre>
"publishing": { "publishing": {
"title": "Publishing Tools", "title": "Publishing Tools",
"description": "Share your tools with the SmartTools community", "description": "Share your tools with the CmdForge community",
"content": """ "content": """
<p class="lead">Share your tools with the community by publishing to the SmartTools Registry.</p> <p class="lead">Share your tools with the community by publishing to the CmdForge Registry.</p>
<h2 id="before-publishing">Before Publishing</h2> <h2 id="before-publishing">Before Publishing</h2>
<p>Make sure your tool has:</p> <p>Make sure your tool has:</p>
@ -255,20 +255,20 @@ cat complex_algorithm.py | explain --level expert</code></pre>
<h2 id="publish">Publish Your Tool</h2> <h2 id="publish">Publish Your Tool</h2>
<pre><code class="language-bash"># Navigate to your tool directory <pre><code class="language-bash"># Navigate to your tool directory
cd ~/.smarttools/my-tool/ cd ~/.cmdforge/my-tool/
# First time: enter your token when prompted # First time: enter your token when prompted
smarttools registry publish cmdforge registry publish
# Dry run to validate without publishing # Dry run to validate without publishing
smarttools registry publish --dry-run</code></pre> cmdforge registry publish --dry-run</code></pre>
<h2 id="versioning">Versioning</h2> <h2 id="versioning">Versioning</h2>
<p>Published versions are <strong>immutable</strong>. To update a tool:</p> <p>Published versions are <strong>immutable</strong>. To update a tool:</p>
<ol> <ol>
<li>Make your changes</li> <li>Make your changes</li>
<li>Bump the version in <code>config.yaml</code></li> <li>Bump the version in <code>config.yaml</code></li>
<li>Run <code>smarttools registry publish</code></li> <li>Run <code>cmdforge registry publish</code></li>
</ol> </ol>
<h2 id="best-practices">Best Practices</h2> <h2 id="best-practices">Best Practices</h2>
@ -294,11 +294,11 @@ smarttools registry publish --dry-run</code></pre>
"title": "AI Providers", "title": "AI Providers",
"description": "Configure different AI providers for your tools", "description": "Configure different AI providers for your tools",
"content": """ "content": """
<p class="lead">SmartTools works with any AI provider that has a CLI interface. Configure providers in <p class="lead">CmdForge works with any AI provider that has a CLI interface. Configure providers in
<code>~/.smarttools/providers.yaml</code>.</p> <code>~/.cmdforge/providers.yaml</code>.</p>
<h2 id="provider-config">Provider Configuration</h2> <h2 id="provider-config">Provider Configuration</h2>
<p>Create or edit <code>~/.smarttools/providers.yaml</code>:</p> <p>Create or edit <code>~/.cmdforge/providers.yaml</code>:</p>
<pre><code class="language-yaml">providers: <pre><code class="language-yaml">providers:
- name: claude - name: claude
@ -397,9 +397,9 @@ providers:
"parallel-orchestration": { "parallel-orchestration": {
"title": "Parallel Orchestration", "title": "Parallel Orchestration",
"description": "Run multiple SmartTools concurrently for faster workflows", "description": "Run multiple CmdForge concurrently for faster workflows",
"content": """ "content": """
<p class="lead">SmartTools executes steps sequentially within a tool, but you can run <p class="lead">CmdForge executes steps sequentially within a tool, but you can run
<strong>multiple tools in parallel</strong> using Python's ThreadPoolExecutor. This pattern <strong>multiple tools in parallel</strong> using Python's ThreadPoolExecutor. This pattern
is ideal for multi-agent workflows, parallel analysis, or any task where you need responses is ideal for multi-agent workflows, parallel analysis, or any task where you need responses
from multiple AI providers simultaneously.</p> from multiple AI providers simultaneously.</p>
@ -412,7 +412,7 @@ from multiple AI providers simultaneously.</p>
</ul> </ul>
<h2 id="basic-pattern">Basic Pattern</h2> <h2 id="basic-pattern">Basic Pattern</h2>
<p>Use Python's <code>concurrent.futures</code> to run multiple SmartTools in parallel:</p> <p>Use Python's <code>concurrent.futures</code> to run multiple CmdForge in parallel:</p>
<pre><code class="language-python">import subprocess <pre><code class="language-python">import subprocess
from concurrent.futures import ThreadPoolExecutor, as_completed from concurrent.futures import ThreadPoolExecutor, as_completed
@ -604,11 +604,11 @@ def run_with_progress(tools: list[str], input_text: str):
</ul> </ul>
<h2 id="example-project">Full Example: orchestrated-discussions</h2> <h2 id="example-project">Full Example: orchestrated-discussions</h2>
<p>For a complete implementation of parallel SmartTools orchestration, see the <p>For a complete implementation of parallel CmdForge orchestration, see the
<a href="https://gitea.brrd.tech/rob/orchestrated-discussions" target="_blank">orchestrated-discussions</a> <a href="https://gitea.brrd.tech/rob/orchestrated-discussions" target="_blank">orchestrated-discussions</a>
project. It implements:</p> project. It implements:</p>
<ul> <ul>
<li>Multiple AI "participants" as SmartTools</li> <li>Multiple AI "participants" as CmdForge</li>
<li>Parallel execution with live progress logging</li> <li>Parallel execution with live progress logging</li>
<li>Shared log files for real-time monitoring</li> <li>Shared log files for real-time monitoring</li>
<li>Discussion workflows with voting and consensus</li> <li>Discussion workflows with voting and consensus</li>
@ -656,7 +656,7 @@ steps:
output: "{result}"</code></pre> output: "{result}"</code></pre>
<p>Save this to <code>~/.smarttools/shout/config.yaml</code> and you've got a working command:</p> <p>Save this to <code>~/.cmdforge/shout/config.yaml</code> and you've got a working command:</p>
<pre><code class="language-bash">$ echo "hello world" | shout <pre><code class="language-bash">$ echo "hello world" | shout
HELLO WORLD!!!</code></pre> HELLO WORLD!!!</code></pre>
@ -1697,7 +1697,7 @@ loops, and more.</p>
<li>Using different AI models for different tasks</li> <li>Using different AI models for different tasks</li>
<li>Building tools that adapt to their input</li> <li>Building tools that adapt to their input</li>
<li>Self-critiquing workflows that iterate to perfection</li> <li>Self-critiquing workflows that iterate to perfection</li>
<li>Calling external tools from within your SmartTools</li> <li>Calling external tools from within your CmdForge</li>
</ul> </ul>
</div> </div>
@ -1912,7 +1912,7 @@ output: "{result}"</code></pre>
<h2 id="external-tools">Calling External Tools</h2> <h2 id="external-tools">Calling External Tools</h2>
<p>SmartTools can wrap any command-line tool:</p> <p>CmdForge can wrap any command-line tool:</p>
<pre><code class="language-yaml">name: lint-explain <pre><code class="language-yaml">name: lint-explain
version: "1.0.0" version: "1.0.0"
@ -2087,7 +2087,7 @@ output: "{formatted}"</code></pre>
"title": "The Visual Builder", "title": "The Visual Builder",
"description": "Build tools without touching YAML using the terminal UI", "description": "Build tools without touching YAML using the terminal UI",
"content": """ "content": """
<p class="lead">Not everyone wants to write YAML by hand. SmartTools includes a full-featured <p class="lead">Not everyone wants to write YAML by hand. CmdForge includes a full-featured
terminal UI that lets you create, edit, and test tools with menus and formsno text editor required.</p> terminal UI that lets you create, edit, and test tools with menus and formsno text editor required.</p>
<div class="bg-indigo-50 border-l-4 border-indigo-500 p-4 my-6"> <div class="bg-indigo-50 border-l-4 border-indigo-500 p-4 my-6">
@ -2104,13 +2104,13 @@ terminal UI that lets you create, edit, and test tools with menus and forms—no
<p>Start the UI with a single command:</p> <p>Start the UI with a single command:</p>
<pre><code class="language-bash">smarttools ui</code></pre> <pre><code class="language-bash">cmdforge ui</code></pre>
<p>You'll see a menu-driven interface that works in any terminal:</p> <p>You'll see a menu-driven interface that works in any terminal:</p>
<div class="bg-gray-900 text-gray-100 rounded-lg p-4 my-6 font-mono text-sm"> <div class="bg-gray-900 text-gray-100 rounded-lg p-4 my-6 font-mono text-sm">
<pre> <pre>
SmartTools Manager CmdForge Manager
[ List all tools ] [ List all tools ]
@ -2158,7 +2158,7 @@ terminal UI that lets you create, edit, and test tools with menus and forms—no
<h3>Step-by-Step: Creating a Summarizer</h3> <h3>Step-by-Step: Creating a Summarizer</h3>
<ol class="space-y-3"> <ol class="space-y-3">
<li><strong>Launch:</strong> Run <code>smarttools ui</code></li> <li><strong>Launch:</strong> Run <code>cmdforge ui</code></li>
<li><strong>Select:</strong> Choose "Create new tool"</li> <li><strong>Select:</strong> Choose "Create new tool"</li>
<li><strong>Info:</strong> Go to "Info & Args", set name to <code>summarize</code></li> <li><strong>Info:</strong> Go to "Info & Args", set name to <code>summarize</code></li>
<li><strong>Add Argument:</strong> Click "Add Argument", set flag to <code>--length</code>, default to <code>100</code></li> <li><strong>Add Argument:</strong> Click "Add Argument", set flag to <code>--length</code>, default to <code>100</code></li>
@ -2243,7 +2243,7 @@ terminal UI that lets you create, edit, and test tools with menus and forms—no
<h2 id="ui-backends">UI Backends</h2> <h2 id="ui-backends">UI Backends</h2>
<p>SmartTools automatically uses the best available terminal UI library:</p> <p>CmdForge automatically uses the best available terminal UI library:</p>
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 my-6 text-sm"> <div class="grid grid-cols-1 md:grid-cols-3 gap-4 my-6 text-sm">
<div class="bg-green-50 border border-green-200 rounded-lg p-3"> <div class="bg-green-50 border border-green-200 rounded-lg p-3">
@ -2276,7 +2276,7 @@ terminal UI that lets you create, edit, and test tools with menus and forms—no
</thead> </thead>
<tbody> <tbody>
<tr class="border-b"> <tr class="border-b">
<td class="px-4 py-2">You're new to SmartTools</td> <td class="px-4 py-2">You're new to CmdForge</td>
<td class="px-4 py-2">You're comfortable with YAML</td> <td class="px-4 py-2">You're comfortable with YAML</td>
</tr> </tr>
<tr class="border-b"> <tr class="border-b">

View File

@ -0,0 +1,5 @@
"""Forum blueprint for CmdForge community discussions."""
from .routes import forum_bp
__all__ = ["forum_bp"]

View File

@ -6,7 +6,7 @@ import re
import sqlite3 import sqlite3
from typing import Any from typing import Any
from smarttools.registry.db import connect_db, query_one, query_all from cmdforge.registry.db import connect_db, query_one, query_all
FORUM_SCHEMA = """ FORUM_SCHEMA = """
@ -51,9 +51,9 @@ CREATE INDEX IF NOT EXISTS idx_forum_replies_topic ON forum_replies(topic_id);
""" """
DEFAULT_CATEGORIES = [ DEFAULT_CATEGORIES = [
("general", "General Discussion", "Chat about anything SmartTools related", "chat", 1), ("general", "General Discussion", "Chat about anything CmdForge related", "chat", 1),
("help", "Help & Support", "Get help with installation, configuration, or usage", "question", 2), ("help", "Help & Support", "Get help with installation, configuration, or usage", "question", 2),
("showcase", "Showcase", "Share tools and projects you've built with SmartTools", "star", 3), ("showcase", "Showcase", "Share tools and projects you've built with CmdForge", "star", 3),
("ideas", "Ideas & Feedback", "Suggest features and improvements", "lightbulb", 4), ("ideas", "Ideas & Feedback", "Suggest features and improvements", "lightbulb", 4),
("tutorials", "Tutorials & Guides", "Community-written guides and how-tos", "book", 5), ("tutorials", "Tutorials & Guides", "Community-written guides and how-tos", "book", 5),
] ]

View File

@ -19,7 +19,7 @@ from flask import (
url_for, url_for,
) )
from smarttools.registry.db import connect_db from cmdforge.registry.db import connect_db
from .models import ( from .models import (
create_reply, create_reply,

View File

@ -1,4 +1,4 @@
"""Public web routes for the SmartTools UI.""" """Public web routes for the CmdForge UI."""
from __future__ import annotations from __future__ import annotations
@ -8,7 +8,7 @@ from typing import Any, Dict, List, Optional, Tuple
from markupsafe import Markup, escape from markupsafe import Markup, escape
from flask import current_app, redirect, render_template, request, session, url_for from flask import current_app, redirect, render_template, request, session, url_for
from smarttools.registry.db import connect_db, query_all, query_one from cmdforge.registry.db import connect_db, query_all, query_one
from . import web_bp from . import web_bp
@ -499,7 +499,7 @@ def docs(path: str):
else: else:
page = SimpleNamespace( page = SimpleNamespace(
title=_title_case(current), title=_title_case(current),
description="SmartTools documentation", description="CmdForge documentation",
content_html=Markup(f"<p>Documentation for <strong>{escape(current)}</strong> is coming soon.</p>"), content_html=Markup(f"<p>Documentation for <strong>{escape(current)}</strong> is coming soon.</p>"),
headings=[], headings=[],
parent=None, parent=None,

View File

@ -7,7 +7,7 @@ from typing import List
from flask import Response, current_app, url_for from flask import Response, current_app, url_for
from smarttools.registry.db import connect_db, query_all from cmdforge.registry.db import connect_db, query_all
SITEMAP_TTL = timedelta(hours=6) SITEMAP_TTL = timedelta(hours=6)
_sitemap_cache = {"generated_at": None, "xml": ""} _sitemap_cache = {"generated_at": None, "xml": ""}

View File

@ -10,7 +10,7 @@ from typing import Optional
from flask.sessions import SessionInterface, SessionMixin from flask.sessions import SessionInterface, SessionMixin
from werkzeug.datastructures import CallbackDict from werkzeug.datastructures import CallbackDict
from smarttools.registry.db import connect_db from cmdforge.registry.db import connect_db
SESSION_TTL = timedelta(days=7) SESSION_TTL = timedelta(days=7)
@ -22,7 +22,7 @@ class SQLiteSession(CallbackDict, SessionMixin):
class SQLiteSessionInterface(SessionInterface): class SQLiteSessionInterface(SessionInterface):
def __init__(self, cookie_name: str = "smarttools_session"): def __init__(self, cookie_name: str = "cmdforge_session"):
self.cookie_name = cookie_name self.cookie_name = cookie_name
def open_session(self, app, request): def open_session(self, app, request):

View File

@ -1,5 +1,5 @@
/** /**
* SmartTools Web UI - Main JavaScript * CmdForge Web UI - Main JavaScript
*/ */
// Copy to clipboard utility // Copy to clipboard utility

View File

@ -1,6 +1,6 @@
# SmartTools Registry - robots.txt # CmdForge Registry - robots.txt
# We welcome all crawlers! Index everything to help users find us # We welcome all crawlers! Index everything to help users find us
# and enable AI assistants to help solve SmartTools issues. # and enable AI assistants to help solve CmdForge issues.
User-agent: * User-agent: *
Allow: / Allow: /
@ -11,7 +11,7 @@ Allow: /tutorials/
Allow: /tools/ Allow: /tools/
Allow: /categories/ Allow: /categories/
# Allow AI crawlers explicitly (we want AI to learn about SmartTools) # Allow AI crawlers explicitly (we want AI to learn about CmdForge)
User-agent: GPTBot User-agent: GPTBot
Allow: / Allow: /
@ -42,6 +42,6 @@ Disallow: /api/v1/tokens
Allow: /api/ Allow: /api/
# Sitemap location # Sitemap location
Sitemap: https://registry.smarttools.dev/sitemap.xml Sitemap: https://cmdforge.brrd.tech/sitemap.xml
# Crawl-delay: none - crawl as fast as you want! # Crawl-delay: none - crawl as fast as you want!

View File

@ -3,14 +3,14 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}SmartTools{% endblock %} - Build Custom AI Commands</title> <title>{% block title %}CmdForge{% endblock %} - Build Custom AI Commands</title>
<!-- Meta tags --> <!-- Meta tags -->
<meta name="description" content="{% block meta_description %}Create Unix-style pipeable tools that work with any AI provider. Provider-agnostic, composable, and community-driven.{% endblock %}"> <meta name="description" content="{% block meta_description %}Create Unix-style pipeable tools that work with any AI provider. Provider-agnostic, composable, and community-driven.{% endblock %}">
{% block meta_extra %}{% endblock %} {% block meta_extra %}{% endblock %}
<!-- Open Graph --> <!-- Open Graph -->
<meta property="og:title" content="{% block og_title %}SmartTools{% endblock %}"> <meta property="og:title" content="{% block og_title %}CmdForge{% endblock %}">
<meta property="og:description" content="{% block og_description %}Build custom AI commands in YAML{% endblock %}"> <meta property="og:description" content="{% block og_description %}Build custom AI commands in YAML{% endblock %}">
<meta property="og:type" content="website"> <meta property="og:type" content="website">
<meta property="og:url" content="{{ request.url }}"> <meta property="og:url" content="{{ request.url }}">
@ -18,7 +18,7 @@
<!-- Twitter Card --> <!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image"> <meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="{% block twitter_title %}SmartTools{% endblock %}"> <meta name="twitter:title" content="{% block twitter_title %}CmdForge{% endblock %}">
<meta name="twitter:description" content="{% block twitter_description %}Build custom AI commands in YAML{% endblock %}"> <meta name="twitter:description" content="{% block twitter_description %}Build custom AI commands in YAML{% endblock %}">
{% block twitter_extra %}{% endblock %} {% block twitter_extra %}{% endblock %}
@ -40,7 +40,7 @@
{ {
"@context": "https://schema.org", "@context": "https://schema.org",
"@type": "Organization", "@type": "Organization",
"name": "SmartTools", "name": "CmdForge",
"url": "{{ request.host_url }}", "url": "{{ request.host_url }}",
"description": "Build custom AI commands in YAML" "description": "Build custom AI commands in YAML"
} }

View File

@ -3,19 +3,19 @@
<div class="grid grid-cols-1 md:grid-cols-4 gap-8"> <div class="grid grid-cols-1 md:grid-cols-4 gap-8">
<!-- Brand --> <!-- Brand -->
<div class="col-span-1 md:col-span-2"> <div class="col-span-1 md:col-span-2">
<a href="{{ url_for('web.index') }}" class="text-xl font-bold">SmartTools</a> <a href="{{ url_for('web.index') }}" class="text-xl font-bold">CmdForge</a>
<p class="mt-2 text-gray-400 text-sm max-w-md"> <p class="mt-2 text-gray-400 text-sm max-w-md">
Build custom AI commands in YAML. Create Unix-style pipeable tools that work with any AI provider. Build custom AI commands in YAML. Create Unix-style pipeable tools that work with any AI provider.
Provider-agnostic, composable, and community-driven. Provider-agnostic, composable, and community-driven.
</p> </p>
<div class="mt-4 flex space-x-4"> <div class="mt-4 flex space-x-4">
<a href="https://github.com/rob/smarttools" target="_blank" rel="noopener noreferrer" <a href="https://github.com/rob/cmdforge" target="_blank" rel="noopener noreferrer"
class="text-gray-400 hover:text-white transition-colors" aria-label="GitHub"> class="text-gray-400 hover:text-white transition-colors" aria-label="GitHub">
<svg class="w-6 h-6" fill="currentColor" viewBox="0 0 24 24"> <svg class="w-6 h-6" fill="currentColor" viewBox="0 0 24 24">
<path fill-rule="evenodd" d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" clip-rule="evenodd"/> <path fill-rule="evenodd" d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" clip-rule="evenodd"/>
</svg> </svg>
</a> </a>
<a href="https://twitter.com/smarttools" target="_blank" rel="noopener noreferrer" <a href="https://twitter.com/cmdforge" target="_blank" rel="noopener noreferrer"
class="text-gray-400 hover:text-white transition-colors" aria-label="Twitter"> class="text-gray-400 hover:text-white transition-colors" aria-label="Twitter">
<svg class="w-6 h-6" fill="currentColor" viewBox="0 0 24 24"> <svg class="w-6 h-6" fill="currentColor" viewBox="0 0 24 24">
<path d="M8.29 20.251c7.547 0 11.675-6.253 11.675-11.675 0-.178 0-.355-.012-.53A8.348 8.348 0 0022 5.92a8.19 8.19 0 01-2.357.646 4.118 4.118 0 001.804-2.27 8.224 8.224 0 01-2.605.996 4.107 4.107 0 00-6.993 3.743 11.65 11.65 0 01-8.457-4.287 4.106 4.106 0 001.27 5.477A4.072 4.072 0 012.8 9.713v.052a4.105 4.105 0 003.292 4.022 4.095 4.095 0 01-1.853.07 4.108 4.108 0 003.834 2.85A8.233 8.233 0 012 18.407a11.616 11.616 0 006.29 1.84"/> <path d="M8.29 20.251c7.547 0 11.675-6.253 11.675-11.675 0-.178 0-.355-.012-.53A8.348 8.348 0 0022 5.92a8.19 8.19 0 01-2.357.646 4.118 4.118 0 001.804-2.27 8.224 8.224 0 01-2.605.996 4.107 4.107 0 00-6.993 3.743 11.65 11.65 0 01-8.457-4.287 4.106 4.106 0 001.27 5.477A4.072 4.072 0 012.8 9.713v.052a4.105 4.105 0 003.292 4.022 4.095 4.095 0 01-1.853.07 4.108 4.108 0 003.834 2.85A8.233 8.233 0 012 18.407a11.616 11.616 0 006.29 1.84"/>
@ -50,7 +50,7 @@
<div class="mt-8 pt-8 border-t border-slate-700 flex flex-col sm:flex-row justify-between items-center"> <div class="mt-8 pt-8 border-t border-slate-700 flex flex-col sm:flex-row justify-between items-center">
<p class="text-gray-400 text-sm"> <p class="text-gray-400 text-sm">
&copy; {{ now().year }} SmartTools. Open source under MIT License. &copy; {{ now().year }} CmdForge. Open source under MIT License.
</p> </p>
<p class="text-gray-300 text-xs mt-2 sm:mt-0"> <p class="text-gray-300 text-xs mt-2 sm:mt-0">
Made with care for the developer community. Made with care for the developer community.

View File

@ -4,7 +4,7 @@
<!-- Logo --> <!-- Logo -->
<div class="flex-shrink-0"> <div class="flex-shrink-0">
<a href="{{ url_for('web.index') }}" class="text-xl font-bold hover:text-indigo-400 transition-colors"> <a href="{{ url_for('web.index') }}" class="text-xl font-bold hover:text-indigo-400 transition-colors">
SmartTools CmdForge
</a> </a>
</div> </div>

View File

@ -54,10 +54,10 @@
<div class="mt-4"> <div class="mt-4">
<div class="flex items-center bg-gray-100 rounded px-3 py-2 group"> <div class="flex items-center bg-gray-100 rounded px-3 py-2 group">
<code class="text-xs text-gray-700 flex-1 truncate font-mono"> <code class="text-xs text-gray-700 flex-1 truncate font-mono">
smarttools install {{ tool.owner }}/{{ tool.name }} cmdforge install {{ tool.owner }}/{{ tool.name }}
</code> </code>
<button type="button" <button type="button"
onclick="copyToClipboard('smarttools install {{ tool.owner }}/{{ tool.name }}')" onclick="copyToClipboard('cmdforge install {{ tool.owner }}/{{ tool.name }}')"
class="ml-2 p-1 text-gray-400 hover:text-gray-600 opacity-0 group-hover:opacity-100 transition-opacity" class="ml-2 p-1 text-gray-400 hover:text-gray-600 opacity-0 group-hover:opacity-100 transition-opacity"
aria-label="Copy install command"> aria-label="Copy install command">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">

View File

@ -39,7 +39,7 @@
</a> </a>
</h3> </h3>
<p class="mt-2 text-sm text-gray-600 line-clamp-2"> <p class="mt-2 text-sm text-gray-600 line-clamp-2">
{{ tutorial.description or 'Learn how to use SmartTools effectively.' }} {{ tutorial.description or 'Learn how to use CmdForge effectively.' }}
</p> </p>
<a href="{{ href or '#' }}" <a href="{{ href or '#' }}"
class="mt-4 inline-flex items-center text-sm font-medium text-indigo-600 hover:text-indigo-800 transition-colors"> class="mt-4 inline-flex items-center text-sm font-medium text-indigo-600 hover:text-indigo-800 transition-colors">

View File

@ -1,7 +1,7 @@
{% extends "dashboard/base.html" %} {% extends "dashboard/base.html" %}
{% set active_page = 'overview' %} {% set active_page = 'overview' %}
{% block title %}Dashboard - SmartTools{% endblock %} {% block title %}Dashboard - CmdForge{% endblock %}
{% block dashboard_content %} {% block dashboard_content %}
<!-- Stats Cards --> <!-- Stats Cards -->

View File

@ -2,7 +2,7 @@
{% from "components/forms.html" import text_input, textarea, button_primary, form_errors, success_alert %} {% from "components/forms.html" import text_input, textarea, button_primary, form_errors, success_alert %}
{% set active_page = 'settings' %} {% set active_page = 'settings' %}
{% block title %}Settings - SmartTools Dashboard{% endblock %} {% block title %}Settings - CmdForge Dashboard{% endblock %}
{% block dashboard_header %} {% block dashboard_header %}
<h1 class="text-2xl font-bold text-gray-900">Settings</h1> <h1 class="text-2xl font-bold text-gray-900">Settings</h1>

View File

@ -1,7 +1,7 @@
{% extends "dashboard/base.html" %} {% extends "dashboard/base.html" %}
{% set active_page = 'tokens' %} {% set active_page = 'tokens' %}
{% block title %}API Tokens - SmartTools Dashboard{% endblock %} {% block title %}API Tokens - CmdForge Dashboard{% endblock %}
{% block dashboard_header %} {% block dashboard_header %}
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
@ -30,9 +30,9 @@
<div class="ml-3"> <div class="ml-3">
<h4 class="text-sm font-medium text-blue-800">About API Tokens</h4> <h4 class="text-sm font-medium text-blue-800">About API Tokens</h4>
<p class="mt-1 text-sm text-blue-700"> <p class="mt-1 text-sm text-blue-700">
API tokens are used to authenticate with the SmartTools registry from the CLI. API tokens are used to authenticate with the CmdForge registry from the CLI.
Use <code class="px-1 bg-blue-100 rounded">smarttools auth login</code> to authenticate, Use <code class="px-1 bg-blue-100 rounded">cmdforge auth login</code> to authenticate,
or set the <code class="px-1 bg-blue-100 rounded">SMARTTOOLS_TOKEN</code> environment variable. or set the <code class="px-1 bg-blue-100 rounded">CMDFORGE_TOKEN</code> environment variable.
</p> </p>
</div> </div>
</div> </div>
@ -215,7 +215,7 @@
<p class="mt-4 text-sm text-gray-600"> <p class="mt-4 text-sm text-gray-600">
To use this token, run: To use this token, run:
</p> </p>
<pre class="mt-2 bg-gray-900 text-gray-100 text-sm p-3 rounded-lg overflow-x-auto"><code>export SMARTTOOLS_TOKEN="<span id="token-in-export"></span>"</code></pre> <pre class="mt-2 bg-gray-900 text-gray-100 text-sm p-3 rounded-lg overflow-x-auto"><code>export CMDFORGE_TOKEN="<span id="token-in-export"></span>"</code></pre>
</div> </div>
<div class="bg-gray-50 px-6 py-4 rounded-b-lg flex justify-end"> <div class="bg-gray-50 px-6 py-4 rounded-b-lg flex justify-end">

View File

@ -1,7 +1,7 @@
{% extends "dashboard/base.html" %} {% extends "dashboard/base.html" %}
{% set active_page = 'tools' %} {% set active_page = 'tools' %}
{% block title %}My Tools - SmartTools Dashboard{% endblock %} {% block title %}My Tools - CmdForge Dashboard{% endblock %}
{% block dashboard_header %} {% block dashboard_header %}
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">

View File

@ -1,6 +1,6 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block title %}Page Not Found - SmartTools{% endblock %} {% block title %}Page Not Found - CmdForge{% endblock %}
{% block content %} {% block content %}
<div class="min-h-[60vh] flex items-center justify-center px-4"> <div class="min-h-[60vh] flex items-center justify-center px-4">

View File

@ -1,6 +1,6 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block title %}Server Error - SmartTools{% endblock %} {% block title %}Server Error - CmdForge{% endblock %}
{% block content %} {% block content %}
<div class="min-h-[60vh] flex items-center justify-center px-4"> <div class="min-h-[60vh] flex items-center justify-center px-4">
@ -15,7 +15,7 @@
class="w-full sm:w-auto inline-flex justify-center items-center px-6 py-3 text-base font-medium text-white bg-indigo-600 rounded-md hover:bg-indigo-700"> class="w-full sm:w-auto inline-flex justify-center items-center px-6 py-3 text-base font-medium text-white bg-indigo-600 rounded-md hover:bg-indigo-700">
Go Home Go Home
</a> </a>
<a href="https://github.com/your-org/smarttools/issues" <a href="https://github.com/your-org/cmdforge/issues"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
class="w-full sm:w-auto inline-flex justify-center items-center px-6 py-3 text-base font-medium text-gray-700 border border-gray-300 rounded-md hover:bg-gray-50"> class="w-full sm:w-auto inline-flex justify-center items-center px-6 py-3 text-base font-medium text-gray-700 border border-gray-300 rounded-md hover:bg-gray-50">

View File

@ -2,7 +2,7 @@
{% block title %}Community Forum{% endblock %} {% block title %}Community Forum{% endblock %}
{% block meta_description %}Join the SmartTools community. Ask questions, share your projects, and connect with other users.{% endblock %} {% block meta_description %}Join the CmdForge community. Ask questions, share your projects, and connect with other users.{% endblock %}
{% block content %} {% block content %}
<div class="bg-gray-50 min-h-screen"> <div class="bg-gray-50 min-h-screen">
@ -11,7 +11,7 @@
<div class="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 py-8"> <div class="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<h1 class="text-3xl font-bold text-gray-900">Community Forum</h1> <h1 class="text-3xl font-bold text-gray-900">Community Forum</h1>
<p class="mt-2 text-gray-600"> <p class="mt-2 text-gray-600">
Ask questions, share your projects, and connect with other SmartTools users. Ask questions, share your projects, and connect with other CmdForge users.
</p> </p>
<div class="mt-4 flex items-center gap-6 text-sm text-gray-500"> <div class="mt-4 flex items-center gap-6 text-sm text-gray-500">
<span>{{ stats.topics }} topics</span> <span>{{ stats.topics }} topics</span>
@ -119,7 +119,7 @@
</svg> </svg>
Browse Tools Browse Tools
</a> </a>
<a href="https://gitea.brrd.tech/rob/SmartTools/issues" <a href="https://gitea.brrd.tech/rob/CmdForge/issues"
target="_blank" rel="noopener" target="_blank" rel="noopener"
class="flex items-center text-sm text-gray-600 hover:text-indigo-600"> class="flex items-center text-sm text-gray-600 hover:text-indigo-600">
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">

View File

@ -1,14 +1,14 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block title %}About - SmartTools{% endblock %} {% block title %}About - CmdForge{% endblock %}
{% block meta_description %}Learn about SmartTools, the open-source platform for building custom AI-powered command-line tools.{% endblock %} {% block meta_description %}Learn about CmdForge, the open-source platform for building custom AI-powered command-line tools.{% endblock %}
{% block content %} {% block content %}
<div class="bg-white"> <div class="bg-white">
<!-- Hero --> <!-- Hero -->
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-16 text-center"> <div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-16 text-center">
<h1 class="text-4xl font-bold text-gray-900">About SmartTools</h1> <h1 class="text-4xl font-bold text-gray-900">About CmdForge</h1>
<p class="mt-6 text-xl text-gray-600"> <p class="mt-6 text-xl text-gray-600">
An open-source platform for building and sharing AI-powered command-line tools. An open-source platform for building and sharing AI-powered command-line tools.
</p> </p>
@ -20,7 +20,7 @@
<h2 class="text-2xl font-bold text-gray-900 mb-6">Our Mission</h2> <h2 class="text-2xl font-bold text-gray-900 mb-6">Our Mission</h2>
<div class="prose prose-lg prose-indigo max-w-none"> <div class="prose prose-lg prose-indigo max-w-none">
<p> <p>
SmartTools was created with a simple belief: powerful AI tools should be accessible to everyone, CmdForge was created with a simple belief: powerful AI tools should be accessible to everyone,
not just those with extensive programming knowledge or expensive API subscriptions. not just those with extensive programming knowledge or expensive API subscriptions.
</p> </p>
<p> <p>
@ -29,7 +29,7 @@
</p> </p>
<p> <p>
Our platform follows the Unix philosophy: simple, composable tools that do one thing well. Our platform follows the Unix philosophy: simple, composable tools that do one thing well.
With SmartTools, you can create custom AI commands using simple YAML configuration, With CmdForge, you can create custom AI commands using simple YAML configuration,
chain them together, and share them with the community. chain them together, and share them with the community.
</p> </p>
</div> </div>
@ -49,7 +49,7 @@
</div> </div>
<h3 class="text-lg font-semibold text-gray-900 mb-2">Open Source</h3> <h3 class="text-lg font-semibold text-gray-900 mb-2">Open Source</h3>
<p class="text-gray-600"> <p class="text-gray-600">
SmartTools is MIT licensed and open source. We believe in transparency and community ownership. CmdForge is MIT licensed and open source. We believe in transparency and community ownership.
</p> </p>
</div> </div>
@ -98,7 +98,7 @@
<h2 class="text-2xl font-bold text-gray-900 mb-6">Sustainability</h2> <h2 class="text-2xl font-bold text-gray-900 mb-6">Sustainability</h2>
<div class="prose prose-lg prose-indigo max-w-none"> <div class="prose prose-lg prose-indigo max-w-none">
<p> <p>
SmartTools is committed to long-term sustainability. Revenue from optional ads CmdForge is committed to long-term sustainability. Revenue from optional ads
and donations supports: and donations supports:
</p> </p>
<ul> <ul>
@ -121,9 +121,9 @@
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 text-center"> <div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
<h2 class="text-2xl font-bold text-gray-900 mb-6">Contribute</h2> <h2 class="text-2xl font-bold text-gray-900 mb-6">Contribute</h2>
<p class="text-lg text-gray-600 mb-8"> <p class="text-lg text-gray-600 mb-8">
SmartTools is open source and welcomes contributions of all kinds. CmdForge is open source and welcomes contributions of all kinds.
</p> </p>
<a href="https://github.com/your-org/smarttools" <a href="https://github.com/your-org/cmdforge"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
class="inline-flex items-center px-6 py-3 text-base font-medium text-white bg-gray-900 rounded-md hover:bg-gray-800"> class="inline-flex items-center px-6 py-3 text-base font-medium text-white bg-gray-900 rounded-md hover:bg-gray-800">

View File

@ -1,8 +1,8 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block title %}Community - SmartTools{% endblock %} {% block title %}Community - CmdForge{% endblock %}
{% block meta_description %}Connect with SmartTools - report issues, request features, and contribute to the project.{% endblock %} {% block meta_description %}Connect with CmdForge - report issues, request features, and contribute to the project.{% endblock %}
{% block content %} {% block content %}
<div class="bg-gray-50 min-h-screen"> <div class="bg-gray-50 min-h-screen">
@ -11,7 +11,7 @@
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-12 text-center"> <div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-12 text-center">
<h1 class="text-3xl font-bold text-gray-900">Community</h1> <h1 class="text-3xl font-bold text-gray-900">Community</h1>
<p class="mt-4 text-lg text-gray-600"> <p class="mt-4 text-lg text-gray-600">
SmartTools is open source. Get help, report issues, and contribute. CmdForge is open source. Get help, report issues, and contribute.
</p> </p>
</div> </div>
</div> </div>
@ -52,7 +52,7 @@
<p class="mt-2 text-sm text-gray-600"> <p class="mt-2 text-sm text-gray-600">
Browse the source, fork the project, and submit pull requests. Browse the source, fork the project, and submit pull requests.
</p> </p>
<a href="https://gitea.brrd.tech/rob/SmartTools" <a href="https://gitea.brrd.tech/rob/CmdForge"
target="_blank" rel="noopener" target="_blank" rel="noopener"
class="mt-4 inline-flex items-center text-sm font-medium text-indigo-600 hover:text-indigo-800"> class="mt-4 inline-flex items-center text-sm font-medium text-indigo-600 hover:text-indigo-800">
View Repository View Repository
@ -72,7 +72,7 @@
<p class="mt-2 text-sm text-gray-600"> <p class="mt-2 text-sm text-gray-600">
Found a bug? Have a feature request? Open an issue. Found a bug? Have a feature request? Open an issue.
</p> </p>
<a href="https://gitea.brrd.tech/rob/SmartTools/issues" <a href="https://gitea.brrd.tech/rob/CmdForge/issues"
target="_blank" rel="noopener" target="_blank" rel="noopener"
class="mt-4 inline-flex items-center text-sm font-medium text-indigo-600 hover:text-indigo-800"> class="mt-4 inline-flex items-center text-sm font-medium text-indigo-600 hover:text-indigo-800">
Open Issue Open Issue
@ -137,7 +137,7 @@
<div> <div>
<h3 class="font-semibold text-gray-900">Report Bugs</h3> <h3 class="font-semibold text-gray-900">Report Bugs</h3>
<p class="mt-1 text-sm text-gray-600"> <p class="mt-1 text-sm text-gray-600">
Help make SmartTools better by reporting issues with clear reproduction steps. Help make CmdForge better by reporting issues with clear reproduction steps.
</p> </p>
</div> </div>
</div> </div>
@ -163,7 +163,7 @@
class="inline-flex items-center px-4 py-2 text-sm font-medium text-white bg-indigo-600 rounded-md hover:bg-indigo-700"> class="inline-flex items-center px-4 py-2 text-sm font-medium text-white bg-indigo-600 rounded-md hover:bg-indigo-700">
Visit Forum Visit Forum
</a> </a>
<a href="https://gitea.brrd.tech/rob/SmartTools#installation" <a href="https://gitea.brrd.tech/rob/CmdForge#installation"
target="_blank" rel="noopener" target="_blank" rel="noopener"
class="inline-flex items-center px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50"> class="inline-flex items-center px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50">
Installation Installation

View File

@ -1,6 +1,6 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block title %}{{ title }} - SmartTools{% endblock %} {% block title %}{{ title }} - CmdForge{% endblock %}
{% block content %} {% block content %}
<section class="bg-white py-16"> <section class="bg-white py-16">

View File

@ -1,7 +1,7 @@
{% extends "base.html" %} {% extends "base.html" %}
{% from "components/callouts.html" import info, warning, tip %} {% from "components/callouts.html" import info, warning, tip %}
{% block title %}{{ page.title }} - SmartTools Docs{% endblock %} {% block title %}{{ page.title }} - CmdForge Docs{% endblock %}
{% block meta_description %}{{ page.description or page.title }}{% endblock %} {% block meta_description %}{{ page.description or page.title }}{% endblock %}
@ -124,7 +124,7 @@
<!-- Edit on GitHub --> <!-- Edit on GitHub -->
<div class="mt-6 text-center"> <div class="mt-6 text-center">
<a href="https://github.com/your-org/smarttools/edit/main/docs/{{ current_path }}.md" <a href="https://github.com/your-org/cmdforge/edit/main/docs/{{ current_path }}.md"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
class="inline-flex items-center text-sm text-gray-500 hover:text-gray-700"> class="inline-flex items-center text-sm text-gray-500 hover:text-gray-700">

View File

@ -1,17 +1,17 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block title %}Support SmartTools{% endblock %} {% block title %}Support CmdForge{% endblock %}
{% block meta_description %}Support SmartTools by contributing code, tools, or feedback.{% endblock %} {% block meta_description %}Support CmdForge by contributing code, tools, or feedback.{% endblock %}
{% block content %} {% block content %}
<div class="bg-gray-50 min-h-screen"> <div class="bg-gray-50 min-h-screen">
<!-- Hero --> <!-- Hero -->
<div class="bg-white border-b border-gray-200"> <div class="bg-white border-b border-gray-200">
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-12 text-center"> <div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-12 text-center">
<h1 class="text-3xl font-bold text-gray-900">Support SmartTools</h1> <h1 class="text-3xl font-bold text-gray-900">Support CmdForge</h1>
<p class="mt-4 text-lg text-gray-600"> <p class="mt-4 text-lg text-gray-600">
SmartTools is a passion project. The best way to support it is to use it and share what you build. CmdForge is a passion project. The best way to support it is to use it and share what you build.
</p> </p>
</div> </div>
</div> </div>
@ -38,7 +38,7 @@
</div> </div>
<h2 class="text-lg font-semibold text-gray-900">Spread the Word</h2> <h2 class="text-lg font-semibold text-gray-900">Spread the Word</h2>
<p class="mt-2 text-sm text-gray-600"> <p class="mt-2 text-sm text-gray-600">
Tell a friend or colleague who might find SmartTools useful. Tell a friend or colleague who might find CmdForge useful.
</p> </p>
</div> </div>
<div class="bg-white rounded-lg border border-gray-200 p-6"> <div class="bg-white rounded-lg border border-gray-200 p-6">
@ -58,10 +58,10 @@
<section class="bg-white rounded-lg border border-gray-200 p-8 text-center"> <section class="bg-white rounded-lg border border-gray-200 p-8 text-center">
<h2 class="text-2xl font-bold text-gray-900">Get Involved</h2> <h2 class="text-2xl font-bold text-gray-900">Get Involved</h2>
<p class="mt-3 text-gray-600 max-w-2xl mx-auto"> <p class="mt-3 text-gray-600 max-w-2xl mx-auto">
SmartTools is open source. The code, docs, and registry are all open for contributions. CmdForge is open source. The code, docs, and registry are all open for contributions.
</p> </p>
<div class="mt-6 flex flex-col sm:flex-row items-center justify-center gap-4"> <div class="mt-6 flex flex-col sm:flex-row items-center justify-center gap-4">
<a href="https://gitea.brrd.tech/rob/SmartTools" <a href="https://gitea.brrd.tech/rob/CmdForge"
target="_blank" rel="noopener" target="_blank" rel="noopener"
class="inline-flex items-center px-6 py-3 text-sm font-medium text-white bg-indigo-600 rounded-md hover:bg-indigo-700"> class="inline-flex items-center px-6 py-3 text-sm font-medium text-white bg-indigo-600 rounded-md hover:bg-indigo-700">
<svg class="w-5 h-5 mr-2" fill="currentColor" viewBox="0 0 24 24"> <svg class="w-5 h-5 mr-2" fill="currentColor" viewBox="0 0 24 24">
@ -79,7 +79,7 @@
<!-- Thank you --> <!-- Thank you -->
<section class="mt-12 text-center"> <section class="mt-12 text-center">
<p class="text-gray-500"> <p class="text-gray-500">
Thanks for using SmartTools! Thanks for using CmdForge!
</p> </p>
</section> </section>
</div> </div>

View File

@ -3,7 +3,7 @@
{% from "components/tutorial_card.html" import tutorial_card %} {% from "components/tutorial_card.html" import tutorial_card %}
{% from "components/contributor_card.html" import contributor_card %} {% from "components/contributor_card.html" import contributor_card %}
{% block title %}SmartTools - Build Custom AI Commands in YAML{% endblock %} {% block title %}CmdForge - Build Custom AI Commands in YAML{% endblock %}
{% block meta_description %}Create Unix-style pipeable AI tools with simple YAML configuration. Provider-agnostic, composable, and community-driven.{% endblock %} {% block meta_description %}Create Unix-style pipeable AI tools with simple YAML configuration. Provider-agnostic, composable, and community-driven.{% endblock %}
@ -21,7 +21,7 @@
<!-- Install Link --> <!-- Install Link -->
<div class="mt-10"> <div class="mt-10">
<a href="https://gitea.brrd.tech/rob/SmartTools#installation" <a href="https://gitea.brrd.tech/rob/CmdForge#installation"
target="_blank" target="_blank"
rel="noopener" rel="noopener"
class="inline-flex items-center gap-2 text-indigo-600 hover:text-indigo-800 font-medium transition-colors"> class="inline-flex items-center gap-2 text-indigo-600 hover:text-indigo-800 font-medium transition-colors">
@ -50,7 +50,7 @@
<section class="py-16 bg-gray-50"> <section class="py-16 bg-gray-50">
<div class="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8"> <div class="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
<h2 class="text-3xl font-bold text-gray-900 text-center mb-12"> <h2 class="text-3xl font-bold text-gray-900 text-center mb-12">
Why SmartTools? Why CmdForge?
</h2> </h2>
<div class="grid grid-cols-1 md:grid-cols-3 gap-8"> <div class="grid grid-cols-1 md:grid-cols-3 gap-8">
@ -144,7 +144,7 @@
<div class="grid grid-cols-1 md:grid-cols-3 gap-8"> <div class="grid grid-cols-1 md:grid-cols-3 gap-8">
{{ tutorial_card( {{ tutorial_card(
title="Basic Setup", title="Basic Setup",
description="Learn how to install SmartTools and configure your first AI provider.", description="Learn how to install CmdForge and configure your first AI provider.",
href=url_for('web.docs', path='getting-started'), href=url_for('web.docs', path='getting-started'),
step_number=1 step_number=1
) }} ) }}
@ -191,7 +191,7 @@
<p class="text-xs text-gray-500 mb-2">Advertisement</p> <p class="text-xs text-gray-500 mb-2">Advertisement</p>
<div id="footer-ad-zone" class="min-h-[90px] flex items-center justify-center"> <div id="footer-ad-zone" class="min-h-[90px] flex items-center justify-center">
<!-- Ad content loaded dynamically --> <!-- Ad content loaded dynamically -->
<p class="text-gray-400 text-sm">Support SmartTools Development</p> <p class="text-gray-400 text-sm">Support CmdForge Development</p>
</div> </div>
</div> </div>
</section> </section>

View File

@ -1,7 +1,7 @@
{% extends "base.html" %} {% extends "base.html" %}
{% from "components/forms.html" import text_input, button_primary, form_errors %} {% from "components/forms.html" import text_input, button_primary, form_errors %}
{% block title %}Sign In - SmartTools{% endblock %} {% block title %}Sign In - CmdForge{% endblock %}
{% block content %} {% block content %}
<div class="min-h-[70vh] flex items-center justify-center px-4 py-12"> <div class="min-h-[70vh] flex items-center justify-center px-4 py-12">
@ -12,7 +12,7 @@
<path d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"/> <path d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"/>
</svg> </svg>
</a> </a>
<h1 class="mt-4 text-2xl font-bold text-gray-900">Sign in to SmartTools</h1> <h1 class="mt-4 text-2xl font-bold text-gray-900">Sign in to CmdForge</h1>
<p class="mt-2 text-gray-600"> <p class="mt-2 text-gray-600">
Access your dashboard and manage your tools Access your dashboard and manage your tools
</p> </p>

View File

@ -1,8 +1,8 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block title %}Privacy Policy - SmartTools{% endblock %} {% block title %}Privacy Policy - CmdForge{% endblock %}
{% block meta_description %}SmartTools privacy policy. Learn how we collect, use, and protect your data.{% endblock %} {% block meta_description %}CmdForge privacy policy. Learn how we collect, use, and protect your data.{% endblock %}
{% block content %} {% block content %}
<div class="bg-white py-16"> <div class="bg-white py-16">
@ -13,7 +13,7 @@
<div class="prose prose-lg prose-indigo max-w-none"> <div class="prose prose-lg prose-indigo max-w-none">
<h2>Introduction</h2> <h2>Introduction</h2>
<p> <p>
SmartTools ("we", "our", or "us") respects your privacy and is committed to protecting CmdForge ("we", "our", or "us") respects your privacy and is committed to protecting
your personal data. This privacy policy explains how we collect, use, and safeguard your personal data. This privacy policy explains how we collect, use, and safeguard
your information when you use our website and services. your information when you use our website and services.
</p> </p>
@ -121,8 +121,8 @@
contact us at: contact us at:
</p> </p>
<ul> <ul>
<li>Email: privacy@smarttools.dev</li> <li>Email: privacy@cmdforge.dev</li>
<li>GitHub: <a href="https://github.com/your-org/smarttools/issues">Open an issue</a></li> <li>GitHub: <a href="https://github.com/your-org/cmdforge/issues">Open an issue</a></li>
</ul> </ul>
</div> </div>
</div> </div>

View File

@ -1,9 +1,9 @@
{% extends "base.html" %} {% extends "base.html" %}
{% from "components/tool_card.html" import tool_card %} {% from "components/tool_card.html" import tool_card %}
{% block title %}{{ publisher.display_name }} (@{{ publisher.slug }}) - SmartTools{% endblock %} {% block title %}{{ publisher.display_name }} (@{{ publisher.slug }}) - CmdForge{% endblock %}
{% block meta_description %}{{ publisher.bio or 'SmartTools publisher profile for ' ~ publisher.display_name }}{% endblock %} {% block meta_description %}{{ publisher.bio or 'CmdForge publisher profile for ' ~ publisher.display_name }}{% endblock %}
{% block content %} {% block content %}
<div class="bg-gray-50 min-h-screen"> <div class="bg-gray-50 min-h-screen">

View File

@ -1,7 +1,7 @@
{% extends "base.html" %} {% extends "base.html" %}
{% from "components/forms.html" import text_input, button_primary, form_errors, checkbox %} {% from "components/forms.html" import text_input, button_primary, form_errors, checkbox %}
{% block title %}Create Account - SmartTools{% endblock %} {% block title %}Create Account - CmdForge{% endblock %}
{% block content %} {% block content %}
<div class="min-h-[70vh] flex items-center justify-center px-4 py-12"> <div class="min-h-[70vh] flex items-center justify-center px-4 py-12">

View File

@ -1,9 +1,9 @@
{% extends "base.html" %} {% extends "base.html" %}
{% from "components/tool_card.html" import tool_card %} {% from "components/tool_card.html" import tool_card %}
{% block title %}Search: {{ query }} - SmartTools Registry{% endblock %} {% block title %}Search: {{ query }} - CmdForge Registry{% endblock %}
{% block meta_description %}Search results for "{{ query }}" in the SmartTools Registry.{% endblock %} {% block meta_description %}Search results for "{{ query }}" in the CmdForge Registry.{% endblock %}
{% block content %} {% block content %}
<div class="bg-gray-50 min-h-screen"> <div class="bg-gray-50 min-h-screen">

View File

@ -1,8 +1,8 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block title %}Terms of Service - SmartTools{% endblock %} {% block title %}Terms of Service - CmdForge{% endblock %}
{% block meta_description %}SmartTools terms of service. Read our terms and conditions for using the platform.{% endblock %} {% block meta_description %}CmdForge terms of service. Read our terms and conditions for using the platform.{% endblock %}
{% block content %} {% block content %}
<div class="bg-white py-16"> <div class="bg-white py-16">
@ -13,19 +13,19 @@
<div class="prose prose-lg prose-indigo max-w-none"> <div class="prose prose-lg prose-indigo max-w-none">
<h2>1. Acceptance of Terms</h2> <h2>1. Acceptance of Terms</h2>
<p> <p>
By accessing or using SmartTools ("the Service"), you agree to be bound by these By accessing or using CmdForge ("the Service"), you agree to be bound by these
Terms of Service ("Terms"). If you do not agree to these Terms, you may not use Terms of Service ("Terms"). If you do not agree to these Terms, you may not use
the Service. the Service.
</p> </p>
<h2>2. Description of Service</h2> <h2>2. Description of Service</h2>
<p> <p>
SmartTools is a platform for creating, publishing, and sharing AI-powered CmdForge is a platform for creating, publishing, and sharing AI-powered
command-line tools. The Service includes: command-line tools. The Service includes:
</p> </p>
<ul> <ul>
<li>The SmartTools CLI application</li> <li>The CmdForge CLI application</li>
<li>The SmartTools Registry (tool hosting and discovery)</li> <li>The CmdForge Registry (tool hosting and discovery)</li>
<li>Documentation and tutorials</li> <li>Documentation and tutorials</li>
<li>Community features</li> <li>Community features</li>
</ul> </ul>
@ -46,7 +46,7 @@
<h3>4.1 Your Content</h3> <h3>4.1 Your Content</h3>
<p> <p>
You retain ownership of tools and content you publish ("User Content"). By publishing You retain ownership of tools and content you publish ("User Content"). By publishing
to the Registry, you grant SmartTools a non-exclusive, worldwide license to host, to the Registry, you grant CmdForge a non-exclusive, worldwide license to host,
distribute, and display your User Content. distribute, and display your User Content.
</p> </p>
@ -80,22 +80,22 @@
<h2>6. API and CLI Usage</h2> <h2>6. API and CLI Usage</h2>
<p> <p>
Access to the SmartTools API and CLI is subject to rate limits. Excessive use Access to the CmdForge API and CLI is subject to rate limits. Excessive use
that impacts service availability for others may result in temporary or permanent that impacts service availability for others may result in temporary or permanent
restrictions. restrictions.
</p> </p>
<h2>7. Third-Party Services</h2> <h2>7. Third-Party Services</h2>
<p> <p>
SmartTools is designed to work with various AI providers and external services. CmdForge is designed to work with various AI providers and external services.
Your use of these third-party services is subject to their respective terms and Your use of these third-party services is subject to their respective terms and
conditions. We are not responsible for third-party services. conditions. We are not responsible for third-party services.
</p> </p>
<h2>8. Intellectual Property</h2> <h2>8. Intellectual Property</h2>
<p> <p>
The SmartTools software is open source and licensed under the MIT License. The CmdForge software is open source and licensed under the MIT License.
The SmartTools name, logo, and branding are trademarks of SmartTools. The CmdForge name, logo, and branding are trademarks of CmdForge.
</p> </p>
<h2>9. Disclaimer of Warranties</h2> <h2>9. Disclaimer of Warranties</h2>
@ -104,20 +104,20 @@
WE DO NOT WARRANT THAT THE SERVICE WILL BE UNINTERRUPTED, ERROR-FREE, OR SECURE. WE DO NOT WARRANT THAT THE SERVICE WILL BE UNINTERRUPTED, ERROR-FREE, OR SECURE.
</p> </p>
<p> <p>
Tools published by third parties are not endorsed by SmartTools. You use third-party Tools published by third parties are not endorsed by CmdForge. You use third-party
tools at your own risk. tools at your own risk.
</p> </p>
<h2>10. Limitation of Liability</h2> <h2>10. Limitation of Liability</h2>
<p> <p>
TO THE MAXIMUM EXTENT PERMITTED BY LAW, SMARTTOOLS SHALL NOT BE LIABLE FOR ANY TO THE MAXIMUM EXTENT PERMITTED BY LAW, CMDFORGE SHALL NOT BE LIABLE FOR ANY
INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, OR PUNITIVE DAMAGES ARISING FROM INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, OR PUNITIVE DAMAGES ARISING FROM
YOUR USE OF THE SERVICE. YOUR USE OF THE SERVICE.
</p> </p>
<h2>11. Indemnification</h2> <h2>11. Indemnification</h2>
<p> <p>
You agree to indemnify and hold harmless SmartTools and its contributors from You agree to indemnify and hold harmless CmdForge and its contributors from
any claims, damages, or expenses arising from your use of the Service or any claims, damages, or expenses arising from your use of the Service or
violation of these Terms. violation of these Terms.
</p> </p>
@ -140,7 +140,7 @@
<h2>14. Governing Law</h2> <h2>14. Governing Law</h2>
<p> <p>
These Terms are governed by the laws of the jurisdiction in which SmartTools These Terms are governed by the laws of the jurisdiction in which CmdForge
operates, without regard to conflict of law principles. operates, without regard to conflict of law principles.
</p> </p>
@ -149,8 +149,8 @@
For questions about these Terms, please contact us at: For questions about these Terms, please contact us at:
</p> </p>
<ul> <ul>
<li>Email: legal@smarttools.dev</li> <li>Email: legal@cmdforge.dev</li>
<li>GitHub: <a href="https://github.com/your-org/smarttools/issues">Open an issue</a></li> <li>GitHub: <a href="https://github.com/your-org/cmdforge/issues">Open an issue</a></li>
</ul> </ul>
</div> </div>
</div> </div>

Some files were not shown because too many files have changed in this diff Show More