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
- OS:
- SmartTools version:
- CmdForge version:
- Provider:
- Docker or native install?

View File

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

View File

@ -1,7 +1,7 @@
# Repository Guidelines
## 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.
- `docs/` includes installation, provider setup, examples, and design notes.
- `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`.
## 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 tests/test.py::test_name` runs a focused test.
- `python -m smarttools.cli` runs the CLI module directly.
- `smarttools ui` launches the TUI (requires `urwid` or `python-newt`).
- `python -m cmdforge.cli` runs the CLI module directly.
- `cmdforge ui` launches the TUI (requires `urwid` or `python-newt`).
- `docker-compose build` builds the dev container image.
- `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.
## Security & Configuration Tips
- Provider credentials live in `~/.smarttools/providers.yaml`; avoid committing secrets.
- User tool configs live in `~/.smarttools/<toolname>/config.yaml` and should not be added to the repo.
- Provider credentials live in `~/.cmdforge/providers.yaml`; avoid committing secrets.
- 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
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
@ -19,29 +19,29 @@ pytest
pytest tests/test.py::test_name
# Run the CLI
python -m smarttools.cli
python -m cmdforge.cli
# Launch the UI
smarttools ui
cmdforge ui
```
## 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
- **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_urwid.py**: Full TUI implementation using urwid library
- **ui_snack.py**: Fallback TUI using python-newt/snack
### Key Paths
- **Tools storage**: `~/.smarttools/<toolname>/config.yaml`
- **Tools storage**: `~/.cmdforge/<toolname>/config.yaml`
- **Wrapper scripts**: `~/.local/bin/<toolname>` (auto-generated bash scripts)
- **Provider config**: `~/.smarttools/providers.yaml`
- **Provider config**: `~/.cmdforge/providers.yaml`
### Tool Structure
@ -67,7 +67,7 @@ Variable substitution is simple string replacement in `runner.py:substitute_vari
## 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
providers:
@ -81,9 +81,9 @@ The `mock` provider is built-in for testing without API calls.
## 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
- **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.)
- **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)
- **db.py**: SQLite schema and queries
@ -109,8 +109,8 @@ SmartTools includes a web interface and tool registry:
```bash
# Development
python -m smarttools.web.app
python -m cmdforge.web.app
# 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
# Build: docker build -t smarttools .
# Run: docker run -it --rm -v ~/.smarttools:/root/.smarttools smarttools
# CmdForge - AI-powered CLI command builder
# Build: docker build -t cmdforge .
# Run: docker run -it --rm -v ~/.cmdforge:/root/.cmdforge cmdforge
FROM python:3.12-slim
LABEL maintainer="rob"
LABEL description="SmartTools - Personal AI-powered CLI command builder"
LABEL description="CmdForge - Personal AI-powered CLI command builder"
# Install system dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
@ -34,24 +34,24 @@ COPY examples/ ./examples/
COPY docs/ ./docs/
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]"
# Create smarttools directory
RUN mkdir -p /root/.smarttools /root/.local/bin
# Create cmdforge directory
RUN mkdir -p /root/.cmdforge /root/.local/bin
# Install example tools
RUN python examples/install.py
# Generate CLI wrappers
RUN smarttools refresh
RUN cmdforge refresh
# Add local bin to PATH
ENV PATH="/root/.local/bin:${PATH}"
# Default command - show help
CMD ["smarttools", "--help"]
CMD ["cmdforge", "--help"]
# For interactive use:
# docker run -it --rm smarttools smarttools ui
# docker run -it --rm smarttools bash
# docker run -it --rm cmdforge cmdforge ui
# docker run -it --rm cmdforge bash

View File

@ -1,4 +1,4 @@
# SmartTools
# CmdForge
**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"}
```
## Why SmartTools?
## Why CmdForge?
- **Unix Philosophy** - Tools that do one thing well, composable with pipes
- **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)
See SmartTools in action without installing anything on your system:
See CmdForge in action without installing anything on your system:
```bash
# Pull the container
docker pull gitea.brrd.tech/rob/smarttools:latest
docker pull gitea.brrd.tech/rob/cmdforge:latest
# 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)
smarttools providers install # Select option 4, then 'y'
cmdforge providers install # Select option 4, then 'y'
source ~/.bashrc
# Try it! This explains the README using the free Big Pickle model
@ -55,21 +55,21 @@ For regular use, install natively:
```bash
# Clone and install
git clone https://gitea.brrd.tech/rob/SmartTools.git
cd SmartTools
git clone https://gitea.brrd.tech/rob/CmdForge.git
cd CmdForge
pip install -e .
# Ensure ~/.local/bin is in PATH
export PATH="$HOME/.local/bin:$PATH"
# Install an AI provider (interactive guide)
smarttools providers install
cmdforge providers install
# Launch the UI
smarttools ui
cmdforge ui
# Or create your first tool
smarttools create summarize
cmdforge create summarize
```
## Installation
@ -77,16 +77,16 @@ smarttools create summarize
### Native Install
```bash
git clone https://gitea.brrd.tech/rob/SmartTools.git
cd SmartTools
git clone https://gitea.brrd.tech/rob/CmdForge.git
cd CmdForge
pip install -e .
```
### With Development Dependencies
```bash
git clone https://gitea.brrd.tech/rob/SmartTools.git
cd SmartTools
git clone https://gitea.brrd.tech/rob/CmdForge.git
cd CmdForge
pip install -e ".[dev]"
```
@ -107,7 +107,7 @@ export PATH="$HOME/.local/bin:$PATH"
Then refresh wrapper scripts:
```bash
smarttools refresh
cmdforge refresh
```
## Usage
@ -115,7 +115,7 @@ smarttools refresh
### UI Mode (Recommended for Beginners)
```bash
smarttools ui
cmdforge ui
```
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
```bash
smarttools list # List all tools
smarttools create mytool # Create new tool
smarttools edit mytool # Edit in $EDITOR
smarttools delete mytool # Delete tool
smarttools run mytool # Run a tool
smarttools test mytool # Test with mock provider
smarttools refresh # Update executable wrappers
cmdforge list # List all tools
cmdforge create mytool # Create new tool
cmdforge edit mytool # Edit in $EDITOR
cmdforge delete mytool # Delete tool
cmdforge run mytool # Run a tool
cmdforge test mytool # Test with mock provider
cmdforge refresh # Update executable wrappers
```
### Running Tools
@ -155,10 +155,10 @@ cat file.txt | mytool --provider mock
### 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
# Chain SmartTools together
# Chain CmdForge together
cat error.log | log-errors | summarize | translate --lang Spanish
# Code review pipeline: focus on changes, review, then summarize
@ -208,7 +208,7 @@ translate-doc() {
## Example Tools
SmartTools comes with 28 pre-built examples you can install:
CmdForge comes with 28 pre-built examples you can install:
### Text Processing
@ -259,14 +259,14 @@ SmartTools comes with 28 pre-built examples you can install:
### Install Example Tools
```bash
# Run the example installer (from the SmartTools directory)
# Run the example installer (from the CmdForge directory)
python examples/install.py
smarttools refresh
cmdforge refresh
```
## 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 |
|----------|-------|----------|------|----------|
@ -281,7 +281,7 @@ See [docs/PROVIDERS.md](docs/PROVIDERS.md) for setup instructions.
## 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
name: summarize
@ -429,7 +429,7 @@ This lets you generate or modify Python code using AI directly within the tool b
## 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.
@ -444,15 +444,15 @@ SmartTools is built on **Unix philosophy**:
## Contributing
```bash
git clone https://gitea.brrd.tech/rob/smarttools.git
cd smarttools
git clone https://gitea.brrd.tech/rob/cmdforge.git
cd cmdforge
pip install -e ".[dev]"
pytest
```
## Support
If SmartTools saves you time, consider supporting the project:
If CmdForge saves you time, consider supporting the project:
**Bitcoin:** `3KeLqGv2Xo8jGYkqA1i68a6nXwgQnuJoza`
@ -470,16 +470,16 @@ Pull and run the pre-built image directly:
```bash
# Pull from registry
docker pull gitea.brrd.tech/rob/smarttools:latest
docker pull gitea.brrd.tech/rob/cmdforge:latest
# Run SmartTools
docker run -it --rm gitea.brrd.tech/rob/smarttools smarttools --help
# Run CmdForge
docker run -it --rm gitea.brrd.tech/rob/cmdforge cmdforge --help
# 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
docker run -it --rm gitea.brrd.tech/rob/smarttools bash
docker run -it --rm gitea.brrd.tech/rob/cmdforge bash
```
### Build from Source
@ -488,8 +488,8 @@ Alternatively, build the container yourself:
```bash
# Clone the repo
git clone https://gitea.brrd.tech/rob/SmartTools.git
cd SmartTools
git clone https://gitea.brrd.tech/rob/CmdForge.git
cd CmdForge
# Build the container
docker-compose build
@ -498,7 +498,7 @@ docker-compose build
docker-compose run --rm test
# Use the CLI
docker-compose run --rm cli smarttools list
docker-compose run --rm cli cmdforge list
# Interactive shell
docker-compose run --rm shell
@ -518,12 +518,12 @@ xhost +local:docker
docker run -it --rm \
-e DISPLAY=$DISPLAY \
-v /tmp/.X11-unix:/tmp/.X11-unix \
-v smarttools-data:/root/.smarttools \
-v cmdforge-data:/root/.cmdforge \
--network host \
gitea.brrd.tech/rob/smarttools bash
gitea.brrd.tech/rob/cmdforge bash
# Inside the container:
smarttools providers install
cmdforge providers install
```
**Using docker-compose (build from source):**
@ -533,14 +533,14 @@ xhost +local:docker
docker-compose run --rm setup
# Inside the container:
smarttools providers install
cmdforge providers install
```
**After installing a provider:**
```bash
# Test the provider works
smarttools providers test claude
cmdforge providers test claude
```
**Available Providers:**

View File

@ -1,9 +1,9 @@
# SmartTools - AI-powered CLI command builder
# CmdForge - AI-powered CLI command builder
#
# Quick Start:
# docker-compose build # Build the image
# 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.
@ -17,10 +17,10 @@ services:
build:
context: .
dockerfile: Dockerfile
image: smarttools:latest
image: cmdforge:latest
volumes:
- smarttools-data:/root/.smarttools
command: ["smarttools", "--help"]
- cmdforge-data:/root/.cmdforge
command: ["cmdforge", "--help"]
# ============================================================================
# Tests
@ -29,9 +29,9 @@ services:
build:
context: .
dockerfile: Dockerfile
image: smarttools:latest
image: cmdforge:latest
volumes:
- smarttools-data:/root/.smarttools
- cmdforge-data:/root/.cmdforge
command: ["pytest", "-v"]
# ============================================================================
@ -41,9 +41,9 @@ services:
build:
context: .
dockerfile: Dockerfile
image: smarttools:latest
image: cmdforge:latest
volumes:
- smarttools-data:/root/.smarttools
- cmdforge-data:/root/.cmdforge
command: ["/bin/bash"]
stdin_open: true
tty: true
@ -57,11 +57,11 @@ services:
build:
context: .
dockerfile: Dockerfile
image: smarttools:latest
image: cmdforge:latest
environment:
- DISPLAY=${DISPLAY:-:0}
volumes:
- smarttools-data:/root/.smarttools
- cmdforge-data:/root/.cmdforge
- /tmp/.X11-unix:/tmp/.X11-unix:ro
command: ["/bin/bash"]
stdin_open: true
@ -69,8 +69,8 @@ services:
network_mode: host
volumes:
smarttools-data:
# Persists ~/.smarttools between container runs
cmdforge-data:
# Persists ~/.cmdforge between container runs
# ==============================================================================
# Usage Examples
@ -83,8 +83,8 @@ volumes:
# docker-compose run --rm test
#
# Use CLI:
# docker-compose run --rm cli smarttools list
# docker-compose run --rm cli smarttools run hello-world
# docker-compose run --rm cli cmdforge list
# docker-compose run --rm cli cmdforge run hello-world
#
# Interactive shell:
# docker-compose run --rm shell
@ -93,5 +93,5 @@ volumes:
# xhost +local:docker
# docker-compose run --rm setup
# # Inside container:
# smarttools providers install # Interactive guide
# cmdforge providers install # Interactive guide
# # 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)
```bash
# Clone and install
git clone https://gitea.brrd.tech/rob/SmartTools.git
cd SmartTools
git clone https://gitea.brrd.tech/rob/CmdForge.git
cd CmdForge
pip install -e ".[dev]"
# Initialize database
cd src/smarttools/web
cd src/cmdforge/web
python -c "from app import create_app; create_app()"
# Run development server
@ -33,12 +33,12 @@ Access at `http://localhost:5050`
```bash
# Create application directory
sudo mkdir -p /opt/smarttools
sudo chown $USER:$USER /opt/smarttools
cd /opt/smarttools
sudo mkdir -p /opt/cmdforge
sudo chown $USER:$USER /opt/cmdforge
cd /opt/cmdforge
# Clone repository
git clone https://gitea.brrd.tech/rob/SmartTools.git .
git clone https://gitea.brrd.tech/rob/CmdForge.git .
# Create virtual environment
python3 -m venv venv
@ -51,7 +51,7 @@ pip install gunicorn
### 2. Configure Environment
Create `/opt/smarttools/.env`:
Create `/opt/cmdforge/.env`:
```bash
# Required
@ -60,40 +60,40 @@ SECRET_KEY=your-secret-key-here # Generate with: python -c "import secrets; pri
# Optional
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
```bash
cd /opt/smarttools/src/smarttools/web
cd /opt/cmdforge/src/cmdforge/web
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
Create `/etc/systemd/system/smarttools-web.service`:
Create `/etc/systemd/system/cmdforge-web.service`:
```ini
[Unit]
Description=SmartTools Registry Web Application
Description=CmdForge Registry Web Application
After=network.target
[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/opt/smarttools
Environment="PATH=/opt/smarttools/venv/bin"
EnvironmentFile=/opt/smarttools/.env
ExecStart=/opt/smarttools/venv/bin/gunicorn \
WorkingDirectory=/opt/cmdforge
Environment="PATH=/opt/cmdforge/venv/bin"
EnvironmentFile=/opt/cmdforge/.env
ExecStart=/opt/cmdforge/venv/bin/gunicorn \
--workers 4 \
--bind 127.0.0.1:5050 \
--access-logfile /var/log/smarttools/access.log \
--error-logfile /var/log/smarttools/error.log \
'smarttools.web.app:create_app()'
--access-logfile /var/log/cmdforge/access.log \
--error-logfile /var/log/cmdforge/error.log \
'cmdforge.web.app:create_app()'
Restart=always
RestartSec=5
@ -105,26 +105,26 @@ Enable and start:
```bash
# Create log directory
sudo mkdir -p /var/log/smarttools
sudo chown www-data:www-data /var/log/smarttools
sudo mkdir -p /var/log/cmdforge
sudo chown www-data:www-data /var/log/cmdforge
# Enable service
sudo systemctl daemon-reload
sudo systemctl enable smarttools-web
sudo systemctl start smarttools-web
sudo systemctl enable cmdforge-web
sudo systemctl start cmdforge-web
# Check status
sudo systemctl status smarttools-web
sudo systemctl status cmdforge-web
```
### 5. nginx Configuration
Create `/etc/nginx/sites-available/smarttools`:
Create `/etc/nginx/sites-available/cmdforge`:
```nginx
server {
listen 80;
server_name registry.smarttools.dev;
server_name cmdforge.brrd.tech;
# Redirect HTTP to HTTPS
return 301 https://$server_name$request_uri;
@ -132,11 +132,11 @@ server {
server {
listen 443 ssl http2;
server_name registry.smarttools.dev;
server_name cmdforge.brrd.tech;
# SSL certificates (use certbot for Let's Encrypt)
ssl_certificate /etc/letsencrypt/live/registry.smarttools.dev/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/registry.smarttools.dev/privkey.pem;
ssl_certificate /etc/letsencrypt/live/cmdforge.brrd.tech/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/cmdforge.brrd.tech/privkey.pem;
# SSL settings
ssl_protocols TLSv1.2 TLSv1.3;
@ -145,7 +145,7 @@ server {
# Static files (optional - Flask can serve these)
location /static/ {
alias /opt/smarttools/src/smarttools/web/static/;
alias /opt/cmdforge/src/cmdforge/web/static/;
expires 1d;
add_header Cache-Control "public, immutable";
}
@ -164,7 +164,7 @@ server {
Enable site:
```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 systemctl reload nginx
```
@ -173,7 +173,7 @@ sudo systemctl reload nginx
```bash
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d registry.smarttools.dev
sudo certbot --nginx -d cmdforge.brrd.tech
```
## Environment Variables
@ -184,16 +184,16 @@ sudo certbot --nginx -d registry.smarttools.dev
| `SECRET_KEY` | Yes | Secret key for sessions (32+ chars) |
| `SENTRY_DSN` | No | Sentry error monitoring DSN |
| `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
```bash
# 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
sqlite3 /opt/smarttools/data/smarttools.db ".backup '/backup/smarttools.db'"
sqlite3 /opt/cmdforge/data/cmdforge.db ".backup '/backup/cmdforge.db'"
```
## Monitoring
@ -202,11 +202,11 @@ sqlite3 /opt/smarttools/data/smarttools.db ".backup '/backup/smarttools.db'"
```bash
# Application logs
tail -f /var/log/smarttools/error.log
tail -f /var/log/smarttools/access.log
tail -f /var/log/cmdforge/error.log
tail -f /var/log/cmdforge/access.log
# systemd logs
journalctl -u smarttools-web -f
journalctl -u cmdforge-web -f
```
### Sentry Integration
@ -225,33 +225,33 @@ curl http://localhost:5050/api/v1/tools
```bash
# Check logs
journalctl -u smarttools-web -n 50
journalctl -u cmdforge-web -n 50
# Verify Python path
/opt/smarttools/venv/bin/python -c "import smarttools"
/opt/cmdforge/venv/bin/python -c "import cmdforge"
# Test gunicorn manually
cd /opt/smarttools
cd /opt/cmdforge
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
```bash
# Check database exists and is readable
ls -la /opt/smarttools/data/smarttools.db
ls -la /opt/cmdforge/data/cmdforge.db
# Verify permissions
chown www-data:www-data /opt/smarttools/data/
chown www-data:www-data /opt/smarttools/data/smarttools.db
chown www-data:www-data /opt/cmdforge/data/
chown www-data:www-data /opt/cmdforge/data/cmdforge.db
```
### Static files not loading
```bash
# Rebuild Tailwind CSS
cd /opt/smarttools
cd /opt/cmdforge
npm install
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
## 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:**
```bash
@ -17,7 +17,7 @@ sum -i text.txt -o summary.txt --max 512
### Tool = Directory + Config
```
~/.smarttools/
~/.cmdforge/
sum/
config.yaml
processed.py # Optional external code file
@ -128,8 +128,8 @@ sum --stdin
# No input (empty string) - useful for tools using only arguments
sum --max 100
# Or via smarttools run
smarttools run sum -i document.txt
# Or via cmdforge run
cmdforge run sum -i document.txt
```
### Input Handling
@ -158,17 +158,17 @@ smarttools run sum -i document.txt
```bash
# Launch the UI to manage tools
smarttools
cmdforge
# Or use CLI directly:
smarttools list # List all tools
smarttools create sum # Create new tool (basic)
smarttools edit sum # Edit tool config in $EDITOR
smarttools delete sum # Delete tool
smarttools test sum # Test with mock provider
smarttools run sum # Run tool for real
smarttools refresh # Refresh all wrapper scripts
smarttools ui # Launch interactive UI
cmdforge list # List all tools
cmdforge create sum # Create new tool (basic)
cmdforge edit sum # Edit tool config in $EDITOR
cmdforge delete sum # Delete tool
cmdforge test sum # Test with mock provider
cmdforge run sum # Run tool for real
cmdforge refresh # Refresh all wrapper scripts
cmdforge ui # Launch interactive UI
```
## Terminal UI
@ -179,7 +179,7 @@ A BIOS-style terminal UI using `urwid` with full mouse support.
```
┌──────────────────────────────────────┐
SmartTools Manager │
CmdForge Manager │
├──────────────────────────────────────┤
│ Tools: │
│ ┌────────────────────────────────┐ │
@ -256,7 +256,7 @@ The current section's title is highlighted with brackets: `[ Tool Info ]`
**Code Step Features:**
- **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)
- **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
```
smarttools/
cmdforge/
__init__.py
cli.py # Entry point, argument parsing
ui.py # UI dispatcher (chooses urwid/snack/dialog)
@ -278,7 +278,7 @@ smarttools/
### Provider System
Providers are defined in `~/.smarttools/providers.yaml`:
Providers are defined in `~/.cmdforge/providers.yaml`:
```yaml
providers:
@ -297,18 +297,18 @@ The provider command receives the prompt via stdin and outputs to stdout.
### Wrapper Scripts
When you save a tool, SmartTools creates a wrapper script in `~/.local/bin/`:
When you save a tool, CmdForge creates a wrapper script in `~/.local/bin/`:
```bash
#!/bin/bash
# SmartTools wrapper for 'sum'
# CmdForge wrapper for 'sum'
# 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.
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
@ -319,12 +319,12 @@ Tool names must:
## 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)
```bash
# Chain multiple SmartTools
# Chain multiple CmdForge
cat logs.txt | log-errors | summarize | translate --lang Japanese
# Mix with standard Unix tools
@ -389,7 +389,7 @@ Optional fallbacks:
## Example Workflow
1. Run `smarttools` to open UI
1. Run `cmdforge` to open UI
2. Select "Create" to create a new tool
3. Fill in: name, description, output template
4. Add arguments (e.g., `--max` with default `500`)

View File

@ -1,13 +1,13 @@
# 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
```bash
# Install all example tools (from the SmartTools directory)
# Install all example tools (from the CmdForge directory)
python examples/install.py
smarttools refresh
cmdforge refresh
```
## Text Processing Tools
@ -17,7 +17,7 @@ smarttools refresh
Condense long documents to key points.
```yaml
# ~/.smarttools/summarize/config.yaml
# ~/.cmdforge/summarize/config.yaml
name: summarize
description: Condense long documents to key points
arguments:
@ -963,7 +963,7 @@ output: "{result}"
## Pipeline Recipes
SmartTools chain together like Unix commands. Here are practical examples:
CmdForge chain together like Unix commands. Here are practical examples:
### Development Workflows

View File

@ -1,15 +1,15 @@
# Installation Guide
Complete installation instructions for SmartTools.
Complete installation instructions for CmdForge.
## Quick Install
```bash
git clone https://gitea.brrd.tech/rob/SmartTools.git
cd SmartTools
git clone https://gitea.brrd.tech/rob/CmdForge.git
cd CmdForge
pip install -e .
export PATH="$HOME/.local/bin:$PATH"
smarttools providers install
cmdforge providers install
```
## Detailed Installation
@ -32,11 +32,11 @@ brew install python@3.11
python3 --version # Should be 3.10 or higher
```
### Step 2: Install SmartTools
### Step 2: Install CmdForge
```bash
git clone https://gitea.brrd.tech/rob/SmartTools.git
cd SmartTools
git clone https://gitea.brrd.tech/rob/CmdForge.git
cd CmdForge
pip install -e .
```
@ -47,7 +47,7 @@ pip install -e ".[dev]"
### 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
@ -74,7 +74,7 @@ source ~/.bashrc # or restart terminal
You need at least one AI CLI tool. The easiest way is the interactive installer:
```bash
smarttools providers install
cmdforge providers install
```
This guides you through installing and authenticating providers.
@ -110,7 +110,7 @@ gemini # Opens browser for Google sign-in
```bash
curl -fsSL https://ollama.ai/install.sh | bash
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.
@ -118,17 +118,17 @@ See [PROVIDERS.md](PROVIDERS.md) for full provider setup instructions.
### Step 5: Verify Installation
```bash
# Check SmartTools is installed
smarttools --version
# Check CmdForge is installed
cmdforge --version
# List configured providers
smarttools providers list
cmdforge providers list
# Check which providers are available
smarttools providers check
cmdforge providers check
# 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
@ -136,7 +136,7 @@ echo "hello world" | smarttools run --provider mock
After installation or any Python environment change:
```bash
smarttools refresh
cmdforge refresh
```
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
python examples/install.py
smarttools refresh
cmdforge refresh
```
### 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.
## Troubleshooting
### "smarttools: command not found"
### "cmdforge: command not found"
PATH is not configured. Add to your shell config:
```bash
@ -168,14 +168,14 @@ export PATH="$HOME/.local/bin:$PATH"
### "Provider 'X' not found"
1. Check provider is installed: `which claude` or `which opencode`
2. Check provider is configured: `smarttools providers`
3. Add missing provider: `smarttools providers add`
2. Check provider is configured: `cmdforge providers`
3. Add missing provider: `cmdforge providers add`
### "Permission denied" on tool execution
Refresh wrapper scripts:
```bash
smarttools refresh
cmdforge refresh
```
### TUI doesn't start / looks broken
@ -187,28 +187,28 @@ pip install urwid
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:
```bash
smarttools refresh
cmdforge refresh
```
### 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
python3.11 -m pip install smarttools
python3.11 -m pip install cmdforge
```
## Uninstalling
```bash
# Remove package
pip uninstall smarttools
pip uninstall cmdforge
# Remove config and tools (optional)
rm -rf ~/.smarttools
rm -rf ~/.cmdforge
# Remove wrapper scripts (optional)
rm ~/.local/bin/{summarize,translate,fix-grammar,...}
@ -217,8 +217,8 @@ rm ~/.local/bin/{summarize,translate,fix-grammar,...}
## Upgrading
```bash
pip install --upgrade smarttools
smarttools refresh
pip install --upgrade cmdforge
cmdforge refresh
```
## Directory Structure
@ -226,7 +226,7 @@ smarttools refresh
After installation:
```
~/.smarttools/
~/.cmdforge/
├── providers.yaml # Provider configurations
├── summarize/
│ └── config.yaml # Tool config
@ -236,7 +236,7 @@ After installation:
└── ...
~/.local/bin/
├── smarttools # Main command
├── cmdforge # Main command
├── summarize # Tool wrapper script
├── translate # Tool wrapper script
└── ...
@ -246,4 +246,4 @@ After installation:
1. [Set up providers](PROVIDERS.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
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 |
|-----------|----------|---------|
| CLI | `src/smarttools/cli.py` | Main entry point for `smarttools` command |
| Registry API | `src/smarttools/registry/` | REST API for tool registry |
| Web UI | `src/smarttools/web/` | Flask web application |
| Tool Storage | `~/.smarttools/` | User's installed tools |
| Database | `data/smarttools.db` | SQLite with FTS5 search |
| CLI | `src/cmdforge/cli.py` | Main entry point for `cmdforge` command |
| Registry API | `src/cmdforge/registry/` | REST API for tool registry |
| Web UI | `src/cmdforge/web/` | Flask web application |
| Tool Storage | `~/.cmdforge/` | User's installed tools |
| Database | `data/cmdforge.db` | SQLite with FTS5 search |
## Architecture Diagrams
@ -31,7 +31,7 @@ See `docs/diagrams/` for visual representations:
## Source Code Structure
```
src/smarttools/
src/cmdforge/
├── cli.py # Entry point, subcommand routing
├── tool.py # Tool dataclasses, YAML loading
├── runner.py # Step execution engine
@ -68,7 +68,7 @@ src/smarttools/
## Database Schema
SQLite database at `data/smarttools.db`:
SQLite database at `data/cmdforge.db`:
| Table | Purpose |
|-------|---------|
@ -106,9 +106,9 @@ Base URL: `/api/v1/`
## Key Files to Know
### Configuration
- `~/.smarttools/providers.yaml` - AI provider configurations
- `~/.smarttools/config.yaml` - Global settings
- `~/.smarttools/<tool>/config.yaml` - Individual tool configs
- `~/.cmdforge/providers.yaml` - AI provider configurations
- `~/.cmdforge/config.yaml` - Global settings
- `~/.cmdforge/<tool>/config.yaml` - Individual tool configs
### Development
- `pyproject.toml` - Package configuration
@ -130,10 +130,10 @@ Base URL: `/api/v1/`
pip install -e ".[dev]"
# Run CLI
python -m smarttools.cli
python -m cmdforge.cli
# Run web server (development)
cd src/smarttools/web
cd src/cmdforge/web
flask run --port 5050
```
@ -141,7 +141,7 @@ flask run --port 5050
```bash
# 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:
# FLASK_ENV=production
@ -164,7 +164,7 @@ pytest
pytest tests/test_name.py::test_function
# Run with coverage
pytest --cov=smarttools
pytest --cov=cmdforge
```
## Design Documents

View File

@ -1,6 +1,6 @@
# 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
@ -139,7 +139,7 @@ echo "Hello" | gemini --model gemini-2.5-flash
The easiest way to install providers:
```bash
smarttools providers install
cmdforge providers install
```
This interactive guide:
@ -151,22 +151,22 @@ This interactive guide:
### List Providers
```bash
smarttools providers list
cmdforge providers list
```
### Check Availability
```bash
smarttools providers check
cmdforge providers check
```
### Add Custom Provider
```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
providers:
@ -242,9 +242,9 @@ cat file.txt | summarize --provider claude-opus
### "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>`
3. Add it: `smarttools providers add`
3. Add it: `cmdforge providers add`
### "Command 'X' not found"
@ -273,8 +273,8 @@ echo "Say hello" | claude -p
echo "Say hello" | ~/.opencode/bin/opencode run
```
If it works directly but not in SmartTools, check:
1. Provider command in `~/.smarttools/providers.yaml`
If it works directly but not in CmdForge, check:
1. Provider command in `~/.cmdforge/providers.yaml`
2. Environment variables are expanded correctly
## Cost Optimization

View File

@ -1,7 +1,7 @@
# SmartTools Registry Design
# CmdForge Registry Design
## 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
@ -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 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 |
| **Owner** | Immutable namespace slug identifying the publisher (e.g., `rob`, `alice`) |
| **Publisher** | A registered user who can publish tools to the registry |
| **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
- System overview: `discussions/diagrams/smarttools-registry_rob_1.puml`
- Data flows: `discussions/diagrams/smarttools-registry_rob_5.puml`
- System overview: `discussions/diagrams/cmdforge-registry_rob_1.puml`
- Data flows: `discussions/diagrams/cmdforge-registry_rob_5.puml`
## 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`
@ -166,7 +166,7 @@ tool = ToolSchema.parse(response['data']) # May fail on new fields
**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.
@ -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:
- Registry path: `tools/{owner}/{name}/config.yaml`
- API URL: `/tools/{owner}/{name}`
- Install: `smarttools registry install rob/summarize`
- Shorthand: `smarttools registry install summarize` resolves to the official namespace.
- Install: `cmdforge registry install rob/summarize`
- Shorthand: `cmdforge registry install summarize` resolves to the official namespace.
PR branches: `submit/{owner}/{name}/{version}`.
@ -227,7 +227,7 @@ tools/
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
name: summarize
version: "1.2.0"
@ -239,7 +239,7 @@ registry:
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)
2. Or explicitly define these fields in the Tool dataclass with defaults
3. Validate registry-specific fields only when publishing, not when running locally
@ -346,7 +346,7 @@ When resolving a version constraint:
### Prerelease Handling
- 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)
### Download Endpoint Version Selection
@ -401,14 +401,14 @@ Response (404):
## Tool Resolution 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)
2. **Global user**: `~/.smarttools/<owner>/<name>/config.yaml`
1. **Local project**: `./.cmdforge/<owner>/<name>/config.yaml` (or `./.cmdforge/<name>/` for unnamespaced)
2. **Global user**: `~/.cmdforge/<owner>/<name>/config.yaml`
3. **Registry**: Fetch from API, install to global, then run
4. **Error**: `Tool '<toolname>' not found`
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:
- `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`
- 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
When enabled (`auto_fetch_from_registry: true`), missing tools are automatically fetched:
@ -436,14 +436,14 @@ $ summarize < file.txt
```
Behavior details:
- Fetches latest stable version unless pinned in `smarttools.yaml`
- Installs to `~/.smarttools/<owner>/<name>/`
- Fetches latest stable version unless pinned in `cmdforge.yaml`
- Installs to `~/.cmdforge/<owner>/<name>/`
- Generates wrapper script in `~/.local/bin/`
- Subsequent runs use local copy (no re-fetch)
To disable (require explicit install):
```yaml
# ~/.smarttools/config.yaml
# ~/.cmdforge/config.yaml
auto_fetch_from_registry: false
```
@ -467,11 +467,11 @@ summarize < file.txt
# Explicit owner form (always works)
rob-summarize < file.txt
# Or via smarttools run
smarttools run rob/summarize < file.txt
# Or via cmdforge run
cmdforge run rob/summarize < file.txt
```
## Project Manifest (smarttools.yaml)
## Project Manifest (cmdforge.yaml)
Defines tool dependencies with optional runtime overrides:
```
name: my-ai-project
@ -487,7 +487,7 @@ overrides:
Overrides are applied at runtime and do not mutate installed tool configs.
## CLI Config and Tokens
Global config lives in `~/.smarttools/config.yaml`:
Global config lives in `~/.cmdforge/config.yaml`:
```yaml
registry:
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):**
1. Developer modifies tool locally
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`
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:
**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
3. Receives verification email (optional in v1, but track `verified` status)
4. Logs into dashboard at `/dashboard`
@ -690,7 +690,7 @@ Dashboard login uses session cookies (not tokens) for browser auth:
**Cookie settings:**
```python
SESSION_COOKIE_NAME = 'smarttools_session'
SESSION_COOKIE_NAME = 'cmdforge_session'
SESSION_COOKIE_HTTPONLY = True # Prevent JS access
SESSION_COOKIE_SECURE = True # HTTPS only in production
SESSION_COOKIE_SAMESITE = 'Lax' # CSRF protection
@ -844,7 +844,7 @@ CREATE TABLE tool_tags (
**CLI first-time publish flow:**
```bash
$ smarttools registry publish
$ cmdforge registry publish
No registry account configured.
@ -853,7 +853,7 @@ No registry account configured.
3. Enter your token below
Registry token: ********
Token saved to ~/.smarttools/config.yaml
Token saved to ~/.cmdforge/config.yaml
Validating tool...
✓ config.yaml is valid
@ -861,7 +861,7 @@ Validating tool...
✓ Version 1.0.0 not yet published
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.
```
@ -873,67 +873,67 @@ Full mapping of CLI commands to API calls:
```bash
# 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
# Browse tools (TUI)
$ smarttools registry browse [--category=<cat>]
$ cmdforge registry browse [--category=<cat>]
→ GET /api/v1/tools?category=<cat>&page=1
→ GET /api/v1/categories
# View tool details
$ smarttools registry info <owner/name>
$ cmdforge registry info <owner/name>
→ GET /api/v1/tools/<owner>/<name>
# 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
→ Writes to ~/.smarttools/<owner>/<name>/config.yaml
→ Writes to ~/.cmdforge/<owner>/<name>/config.yaml
→ Generates ~/.local/bin/<name> wrapper (or <owner>-<name> if collision)
# Uninstall a tool
$ smarttools registry uninstall <owner/name>
→ Removes ~/.smarttools/<owner>/<name>/
$ cmdforge registry uninstall <owner/name>
→ Removes ~/.cmdforge/<owner>/<name>/
→ Removes wrapper script
# Publish a tool
$ smarttools registry publish [path] [--dry-run]
$ cmdforge registry publish [path] [--dry-run]
→ POST /api/v1/tools (with registry token)
→ Returns PR URL
# List my published tools
$ smarttools registry my-tools
$ cmdforge registry my-tools
→ GET /api/v1/me/tools (with registry token)
# Update index cache
$ smarttools registry update
$ cmdforge registry update
→ GET /api/v1/index.json
→ Writes to ~/.smarttools/registry/index.json
→ Writes to ~/.cmdforge/registry/index.json
```
### Project Commands
```bash
# Install project dependencies from smarttools.yaml
$ smarttools install
→ Reads ./smarttools.yaml
# Install project dependencies from cmdforge.yaml
$ cmdforge install
→ Reads ./cmdforge.yaml
→ For each dependency:
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
$ smarttools add <owner/name> [--version=<constraint>]
→ Adds to ./smarttools.yaml dependencies
# Add a dependency to cmdforge.yaml
$ cmdforge add <owner/name> [--version=<constraint>]
→ Adds to ./cmdforge.yaml dependencies
→ Runs install for that tool
# Show project dependencies status
$ smarttools deps
→ Reads ./smarttools.yaml
$ cmdforge deps
→ Reads ./cmdforge.yaml
→ 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
@ -1081,7 +1081,7 @@ def sync_from_repo_atomic():
| Lock timeout | Skip this sync, next webhook will retry |
## Automated CI Validation
PRs are validated automatically using SmartTools (dogfooding):
PRs are validated automatically using CmdForge (dogfooding):
```
PR Submitted
@ -1121,16 +1121,16 @@ jobs:
- name: Validate schema
run: python scripts/validate_tool.py ${{ github.event.pull_request.head.sha }}
- name: Security scan
run: smarttools run security-scanner < changed_files.txt
run: cmdforge run security-scanner < changed_files.txt
- name: Check duplicates
run: smarttools run duplicate-detector < changed_files.txt
run: cmdforge run duplicate-detector < changed_files.txt
```
## 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
├── CONTRIBUTING.md # How to submit tools
├── LICENSE
@ -1236,7 +1236,7 @@ CLI generates a persistent anonymous ID on first run:
import uuid
import os
CONFIG_PATH = os.path.expanduser("~/.smarttools/config.yaml")
CONFIG_PATH = os.path.expanduser("~/.cmdforge/config.yaml")
def get_or_create_client_id():
config = load_config()
@ -1424,7 +1424,7 @@ def search_tools(q):
"name": "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
When `smarttools install` fails on a manifest:
When `cmdforge install` fails on a manifest:
```bash
$ smarttools install
$ cmdforge install
Error: Could not resolve all dependencies
@ -1511,7 +1511,7 @@ Suggestions:
| 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) |
| FTS5 index | Fall back to LIKE queries (slower but works) |
| Network | Use locally installed tools, skip registry features |
@ -1520,9 +1520,9 @@ Suggestions:
### 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
$ smarttools registry publish --dry-run
$ cmdforge registry publish --dry-run
Validating tool...
✓ config.yaml is valid
@ -1559,7 +1559,7 @@ Suggestions:
Long-running operations show progress:
```bash
$ smarttools install
$ cmdforge install
Installing project dependencies...
[1/3] rob/summarize@^1.0.0
@ -1579,24 +1579,24 @@ Installing project dependencies...
```
```bash
$ smarttools registry publish
$ cmdforge registry publish
Submitting rob/summarize@1.1.0...
Validating... done ✓
Uploading... 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.
```
### 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 ▼] │
├─────────────────────────────────────────────────────────────┤
│ │
@ -1634,9 +1634,9 @@ Your tool is pending review. You'll receive an email when it's approved.
### Project Initialization
```bash
$ smarttools init
$ cmdforge init
Creating smarttools.yaml...
Creating cmdforge.yaml...
Project name [my-project]: my-ai-project
Version [1.0.0]:
@ -1652,7 +1652,7 @@ Added rob/summarize@^1.2.0
Add tool (number, or Enter to finish):
✓ Created smarttools.yaml
✓ Created cmdforge.yaml
name: my-ai-project
version: "1.0.0"
@ -1660,7 +1660,7 @@ dependencies:
- name: rob/summarize
version: "^1.2.0"
Run 'smarttools install' to install dependencies.
Run 'cmdforge install' to install dependencies.
```
### Accessibility
@ -1676,7 +1676,7 @@ Run 'smarttools install' to install dependencies.
## Offline Cache
Cache registry index locally:
```
~/.smarttools/registry/index.json
~/.cmdforge/registry/index.json
```
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:**
```
registry.smarttools.dev (or gitea.brrd.tech/registry)
cmdforge.brrd.tech (or gitea.brrd.tech/registry)
├── / # Landing page
├── /tools # Browse all tools
├── /tools/{owner}/{name} # Tool detail page
@ -1843,9 +1843,9 @@ def render_readme_safe(readme_raw: str) -> str:
## Implementation Phases
### Phase 1: Foundation
- Define `smarttools.yaml` manifest format
- Define `cmdforge.yaml` manifest format
- 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
### Phase 2: Core Backend
@ -1856,22 +1856,22 @@ def render_readme_safe(readme_raw: str) -> str:
- Set up HMAC verification
### Phase 3: CLI Commands
- `smarttools registry search`
- `smarttools registry install`
- `smarttools registry info`
- `smarttools registry browse` (TUI)
- `cmdforge registry search`
- `cmdforge registry install`
- `cmdforge registry info`
- `cmdforge registry browse` (TUI)
- Local index caching
### Phase 4: Publishing
- Publisher registration (web UI)
- Token management
- `smarttools registry publish` command
- `cmdforge registry publish` command
- PR creation via Gitea API
- CI validation workflows
### Phase 5: Project Dependencies
- `smarttools install` (from manifest)
- `smarttools add` command
- `cmdforge install` (from manifest)
- `cmdforge add` command
- Runtime override application
- Dependency resolution

View File

@ -1,10 +1,10 @@
# SmartTools Web UI Design
# CmdForge Web UI Design
## 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
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
- Future hosting of AI models for users with less access to paid services
- Building a sustainable, community-first platform
@ -131,14 +131,14 @@ Use an 8px base grid for consistent spacing:
### 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)
```
┌─────────────────────────────────────────────────────────────────┐
│ [SmartTools] Docs Tutorials Registry Community About 🔍 │
│ [CmdForge] Docs Tutorials Registry Community About 🔍 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Build Custom AI Commands in YAML │
@ -147,7 +147,7 @@ Use an 8px base grid for consistent spacing:
│ provider. Provider-agnostic and composable. │
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ $ pip install smarttools && smarttools init │ [📋]│
│ │ $ pip install cmdforge && cmdforge init │ [📋]│
│ └──────────────────────────────────────────────────────┘ │
│ │
│ [Get Started] [View Tutorials] │
@ -158,7 +158,7 @@ Use an 8px base grid for consistent spacing:
**Content:**
- **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."
- **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)
- **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
- 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 │
│ │ │ │
@ -267,7 +267,7 @@ Use an 8px base grid for consistent spacing:
#### 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
```
┌─────────────────────────────────────────────────────────────────┐
SmartTools
CmdForge
│ ───────────────────────────────────────────────────────────── │
│ Docs | Registry | Community | About | Donate │
│ 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 │
│ │
│ ┌─────────────────────────────────┐ │
│ │ smarttools run owner/tool │ │
│ │ cmdforge run owner/tool │ │
│ └─────────────────────────────────┘ │
└───────────────────────────────────────┘
```
@ -637,7 +637,7 @@ Registry > owner > tool-name > v1.2.0
**Inline Code:**
```html
<code>smarttools run foo</code>
<code>cmdforge run foo</code>
```
- Background: Light gray (#F3F4F6)
- Font: Monospace
@ -1011,14 +1011,14 @@ Publisher dashboard uses auth endpoints:
Landing page:
```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="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:
```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}">
```
@ -1036,7 +1036,7 @@ Tool detail page:
"@type": "Person",
"name": "owner-name"
},
"downloadUrl": "https://registry.smarttools.dev/tools/owner/summarize",
"downloadUrl": "https://cmdforge.brrd.tech/tools/owner/summarize",
"softwareVersion": "1.2.0",
"aggregateRating": {
"@type": "AggregateRating",
@ -1051,12 +1051,12 @@ Tool detail page:
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "SmartTools",
"url": "https://smarttools.dev",
"logo": "https://smarttools.dev/logo.png",
"name": "CmdForge",
"url": "https://cmdforge.dev",
"logo": "https://cmdforge.dev/logo.png",
"sameAs": [
"https://github.com/your-org/smarttools",
"https://twitter.com/smarttools"
"https://github.com/your-org/cmdforge",
"https://twitter.com/cmdforge"
]
}
```
@ -1066,7 +1066,7 @@ Tool detail page:
{
"@context": "https://schema.org",
"@type": "TechArticle",
"headline": "Getting Started with SmartTools",
"headline": "Getting Started with CmdForge",
"author": {"@type": "Person", "name": "Author Name"},
"datePublished": "2025-01-15",
"dateModified": "2025-01-20"
@ -1077,18 +1077,18 @@ Tool detail page:
```html
<!-- 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:image" content="https://smarttools.dev/og-image.png">
<meta property="og:url" content="https://smarttools.dev">
<meta property="og:image" content="https://cmdforge.dev/og-image.png">
<meta property="og:url" content="https://cmdforge.dev">
<meta property="og:type" content="website">
<!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@smarttools">
<meta name="twitter:title" content="SmartTools">
<meta name="twitter:site" content="@cmdforge">
<meta name="twitter:title" content="CmdForge">
<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
@ -1104,12 +1104,12 @@ Auto-generate `sitemap.xml`:
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://smarttools.dev/</loc>
<loc>https://cmdforge.dev/</loc>
<priority>1.0</priority>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://smarttools.dev/tools</loc>
<loc>https://cmdforge.dev/tools</loc>
<priority>0.9</priority>
<changefreq>daily</changefreq>
</url>
@ -1129,7 +1129,7 @@ Disallow: /register
Disallow: /dashboard
Disallow: /api/
Sitemap: https://smarttools.dev/sitemap.xml
Sitemap: https://cmdforge.dev/sitemap.xml
```
### Canonical URLs
@ -1297,11 +1297,11 @@ The web UI consumes these existing API endpoints:
## Diagram References
- Landing page mockup: `discussions/diagrams/smarttools-registry_rob_6.svg`
- System overview: `discussions/diagrams/smarttools-registry_rob_1.puml`
- Data flows: `discussions/diagrams/smarttools-registry_rob_5.puml`
- Web UI strategy: `discussions/diagrams/smarttools-web-ui-strategy.puml`
- UI visual strategy: `discussions/diagrams/smarttools-web-ui-visual-strategy.puml`
- Landing page mockup: `discussions/diagrams/cmdforge-registry_rob_6.svg`
- System overview: `discussions/diagrams/cmdforge-registry_rob_1.puml`
- Data flows: `discussions/diagrams/cmdforge-registry_rob_5.puml`
- Web UI strategy: `discussions/diagrams/cmdforge-web-ui-strategy.puml`
- UI visual strategy: `discussions/diagrams/cmdforge-web-ui-visual-strategy.puml`
## Deployment Guide
@ -1315,8 +1315,8 @@ The web UI consumes these existing API endpoints:
```bash
# Clone the repository
git clone https://gitea.brrd.tech/rob/SmartTools.git
cd SmartTools
git clone https://gitea.brrd.tech/rob/CmdForge.git
cd CmdForge
# Create virtual environment
python3 -m venv venv
@ -1326,7 +1326,7 @@ source venv/bin/activate
pip install -e ".[registry]"
# Run the web server
python -m smarttools.web.app
python -m cmdforge.web.app
```
The server will start on `http://localhost:5000`.
@ -1337,47 +1337,47 @@ The server will start on `http://localhost:5000`.
```bash
# Required
export SMARTTOOLS_REGISTRY_DB=/path/to/registry.db
export CMDFORGE_REGISTRY_DB=/path/to/registry.db
export PORT=5050
# Optional
export SMARTTOOLS_ENV=production # Enables secure cookies
export SMARTTOOLS_SHOW_ADS=true # Enable ad placeholders
export CMDFORGE_ENV=production # Enables secure cookies
export CMDFORGE_SHOW_ADS=true # Enable ad placeholders
```
#### 2. Database Location
By default, the registry uses `~/.smarttools/registry.db`. For production:
By default, the registry uses `~/.cmdforge/registry.db`. For production:
```bash
# Create dedicated directory
mkdir -p /var/lib/smarttools
export SMARTTOOLS_REGISTRY_DB=/var/lib/smarttools/registry.db
mkdir -p /var/lib/cmdforge
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:
```bash
export SMARTTOOLS_REGISTRY_DB=/tmp/smarttools-registry/registry.db
export CMDFORGE_REGISTRY_DB=/tmp/cmdforge-registry/registry.db
```
#### 3. Running with systemd
Create `/etc/systemd/system/smarttools-registry.service`:
Create `/etc/systemd/system/cmdforge-registry.service`:
```ini
[Unit]
Description=SmartTools Registry Web Server
Description=CmdForge Registry Web Server
After=network.target
[Service]
Type=simple
User=smarttools
WorkingDirectory=/opt/smarttools
Environment=SMARTTOOLS_REGISTRY_DB=/var/lib/smarttools/registry.db
User=cmdforge
WorkingDirectory=/opt/cmdforge
Environment=CMDFORGE_REGISTRY_DB=/var/lib/cmdforge/registry.db
Environment=PORT=5050
Environment=SMARTTOOLS_ENV=production
ExecStart=/opt/smarttools/venv/bin/python -m smarttools.web.app
Environment=CMDFORGE_ENV=production
ExecStart=/opt/cmdforge/venv/bin/python -m cmdforge.web.app
Restart=always
RestartSec=5
@ -1387,8 +1387,8 @@ WantedBy=multi-user.target
```bash
sudo systemctl daemon-reload
sudo systemctl enable smarttools-registry
sudo systemctl start smarttools-registry
sudo systemctl enable cmdforge-registry
sudo systemctl start cmdforge-registry
```
#### 4. Reverse Proxy (nginx)
@ -1396,7 +1396,7 @@ sudo systemctl start smarttools-registry
```nginx
server {
listen 80;
server_name registry.smarttools.dev;
server_name cmdforge.brrd.tech;
location / {
proxy_pass http://127.0.0.1:5050;
@ -1407,7 +1407,7 @@ server {
}
location /static {
alias /opt/smarttools/src/smarttools/web/static;
alias /opt/cmdforge/src/cmdforge/web/static;
expires 1y;
add_header Cache-Control "public, immutable";
}
@ -1417,7 +1417,7 @@ server {
#### 5. SSL with Certbot
```bash
sudo certbot --nginx -d registry.smarttools.dev
sudo certbot --nginx -d cmdforge.brrd.tech
```
### Tailwind CSS Build
@ -1429,8 +1429,8 @@ The CSS is pre-built and committed. To rebuild after changes:
npm install
# Build for production
npx tailwindcss -i src/smarttools/web/static/css/input.css \
-o src/smarttools/web/static/css/main.css \
npx tailwindcss -i src/cmdforge/web/static/css/input.css \
-o src/cmdforge/web/static/css/main.css \
--minify
```
@ -1447,7 +1447,7 @@ curl http://localhost:5050/api/v1/tools
|-------|----------|
| `disk I/O error` | Move database to non-merged filesystem |
| 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 |
## Future Considerations (Phase 8+)

View File

@ -1,6 +1,6 @@
#!/usr/bin/env python3
"""
Install all SmartTools example tools.
Install all CmdForge example tools.
Usage:
python3 install.py # Install all tools
@ -9,7 +9,7 @@ Usage:
python3 install.py --category dev # Install category
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
@ -22,7 +22,7 @@ except ImportError:
print("PyYAML required. Install with: pip install pyyaml")
sys.exit(1)
TOOLS_DIR = Path.home() / ".smarttools"
TOOLS_DIR = Path.home() / ".cmdforge"
# All example tool configurations
TOOLS = {
@ -298,7 +298,7 @@ def list_tools():
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("--list", action="store_true", help="List available tools")
parser.add_argument("--category", "-c", choices=list(CATEGORIES.keys()), help="Install tools from category")
@ -335,7 +335,7 @@ def main():
installed += 1
print(f"\nInstalled {installed} tools.")
print("\nRun 'smarttools refresh' to create executable wrappers.")
print("\nRun 'cmdforge refresh' to create executable wrappers.")
if __name__ == "__main__":

View File

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

View File

@ -3,9 +3,9 @@ requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "smarttools"
name = "cmdforge"
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"
license = {text = "MIT"}
requires-python = ">=3.10"
@ -56,13 +56,13 @@ all = [
]
[project.scripts]
smarttools = "smarttools.cli:main"
cmdforge = "cmdforge.cli:main"
[project.urls]
Homepage = "https://gitea.brrd.tech/rob/smarttools"
Documentation = "https://gitea.brrd.tech/rob/smarttools#readme"
Repository = "https://gitea.brrd.tech/rob/smarttools.git"
Issues = "https://gitea.brrd.tech/rob/smarttools/issues"
Homepage = "https://cmdforge.brrd.tech"
Documentation = "https://cmdforge.brrd.tech/docs"
Repository = "https://gitea.brrd.tech/rob/CmdForge.git"
Issues = "https://gitea.brrd.tech/rob/CmdForge/issues"
[tool.setuptools.packages.find]
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
@ -17,13 +17,13 @@ def _add_src_to_path() -> None:
def _get_registry_url() -> str:
from smarttools.config import get_registry_url
from cmdforge.config import get_registry_url
return get_registry_url().rstrip("/")
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()

View File

@ -16,8 +16,8 @@ import yaml
# Allow running from repo root
sys.path.append(str(Path(__file__).resolve().parents[1] / "src"))
from smarttools.registry.db import connect_db, query_one
from smarttools.registry.sync import ensure_publisher, normalize_tags
from cmdforge.registry.db import connect_db, query_one
from cmdforge.registry.sync import ensure_publisher, normalize_tags
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.
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 sys
@ -18,7 +18,7 @@ from .config_commands import cmd_config
def main():
"""Main CLI entry point."""
parser = argparse.ArgumentParser(
prog="smarttools",
prog="cmdforge",
description="A lightweight personal tool builder for AI-powered CLI commands"
)
parser.add_argument("--version", action="version", version=f"%(prog)s {__version__}")
@ -179,7 +179,7 @@ def main():
p_deps.set_defaults(func=cmd_deps)
# '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)
# 'add' command
@ -190,7 +190,7 @@ def main():
p_add.set_defaults(func=cmd_add)
# '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("-v", "--version", help="Project version")
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):
"""Manage SmartTools configuration."""
"""Manage CmdForge configuration."""
if args.config_cmd == "show":
return _cmd_config_show(args)
elif args.config_cmd == "set-token":
@ -22,7 +22,7 @@ def cmd_config(args):
def _cmd_config_show(args):
"""Show current configuration."""
config = load_config()
print("SmartTools Configuration:")
print("CmdForge Configuration:")
print(f" Registry URL: {config.registry.url}")
print(f" Token: {'***' if config.registry.token else '(not set)'}")
print(f" Client ID: {config.client_id}")

View File

@ -13,12 +13,12 @@ from ..resolver import (
def cmd_deps(args):
"""Show project dependencies from smarttools.yaml."""
"""Show project dependencies from cmdforge.yaml."""
manifest = load_manifest()
if manifest is None:
print("No smarttools.yaml found in current project.")
print("Create one with: smarttools init")
print("No cmdforge.yaml found in current project.")
print("Create one with: cmdforge init")
return 1
print(f"Project: {manifest.name} v{manifest.version}")
@ -26,7 +26,7 @@ def cmd_deps(args):
if not manifest.dependencies:
print("No dependencies defined.")
print("Add one with: smarttools add <owner/name>")
print("Add one with: cmdforge add <owner/name>")
return 0
print(f"Dependencies ({len(manifest.dependencies)}):")
@ -52,14 +52,14 @@ def cmd_deps(args):
def cmd_install_deps(args):
"""Install dependencies from smarttools.yaml."""
"""Install dependencies from cmdforge.yaml."""
from ..registry_client import RegistryError
manifest = load_manifest()
if manifest is None:
print("No smarttools.yaml found in current project.")
print("Create one with: smarttools init")
print("No cmdforge.yaml found in current project.")
print("Create one with: cmdforge init")
return 1
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)
elif e.code == "CONNECTION_ERROR":
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:
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:
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
def cmd_init(args):
"""Initialize a new smarttools.yaml."""
"""Initialize a new cmdforge.yaml."""
manifest_path = Path.cwd() / MANIFEST_FILENAME
if manifest_path.exists() and not args.force:
@ -196,7 +196,7 @@ def cmd_init(args):
print(f"Created {MANIFEST_FILENAME}")
print()
print("Add dependencies with: smarttools add <owner/name>")
print("Install them with: smarttools install")
print("Add dependencies with: cmdforge add <owner/name>")
print("Install them with: cmdforge install")
return 0

View File

@ -48,7 +48,7 @@ PROVIDER_INSTALL_INFO = {
"cost": "FREE (runs entirely on your machine)",
"variants": [],
"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):
"""Interactive guide to install AI providers."""
print("=" * 60)
print("SmartTools Provider Installation Guide")
print("CmdForge Provider Installation Guide")
print("=" * 60)
print()
@ -185,9 +185,9 @@ def _cmd_providers_install(args):
print(f" 2. {info['setup']}")
if info.get('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:
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:
print()
print(f"Installation failed (exit code {result.returncode})")

View File

@ -86,7 +86,7 @@ def _cmd_registry_search(args):
return 1
except Exception as e:
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 0
@ -120,7 +120,7 @@ def _cmd_registry_install(args):
except RegistryError as e:
if e.code == "TOOL_NOT_FOUND":
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":
print(f"Error: {e.message}", file=sys.stderr)
if e.details and "available_versions" in e.details:
@ -191,12 +191,12 @@ def _cmd_registry_info(args):
if len(versions) > 5:
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:
if e.code == "TOOL_NOT_FOUND":
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":
print("Could not connect to the registry.", 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:
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
print(f"Your published tools ({len(tools)}):\n")
@ -393,7 +393,7 @@ def _cmd_registry_my_tools(args):
except RegistryError as e:
if e.code == "UNAUTHORIZED":
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("Don't have a token? Register at the registry website.", file=sys.stderr)
elif e.code == "CONNECTION_ERROR":
@ -418,8 +418,8 @@ def _cmd_registry_browse(args):
return run_registry_browser()
except ImportError:
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("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

View File

@ -16,7 +16,7 @@ def cmd_list(args):
if not tools:
print("No tools found.")
print("Create your first tool with: smarttools ui")
print("Create your first tool with: cmdforge ui")
return 0
print(f"Available tools ({len(tools)}):\n")
@ -76,7 +76,7 @@ def cmd_create(args):
path = save_tool(tool)
print(f"Created tool '{name}'")
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")
return 0
@ -326,7 +326,7 @@ echo "input" | {args.name}
# View README
if not readme_path.exists():
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
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
@ -12,7 +12,7 @@ import yaml
# Default configuration directory
CONFIG_DIR = Path.home() / ".smarttools"
CONFIG_DIR = Path.home() / ".cmdforge"
CONFIG_FILE = CONFIG_DIR / "config.yaml"
# Default registry URL (canonical base path)
@ -41,7 +41,7 @@ class RegistryConfig:
@dataclass
class Config:
"""Global SmartTools configuration."""
"""Global CmdForge configuration."""
registry: RegistryConfig = field(default_factory=RegistryConfig)
client_id: str = ""
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.
"""
@ -11,7 +11,7 @@ from typing import Optional, List, Dict
import yaml
MANIFEST_FILENAME = "smarttools.yaml"
MANIFEST_FILENAME = "cmdforge.yaml"
@dataclass
@ -76,7 +76,7 @@ class ToolOverride:
@dataclass
class Manifest:
"""Project manifest (smarttools.yaml)."""
"""Project manifest (cmdforge.yaml)."""
name: str = "my-project"
version: str = "1.0.0"
dependencies: List[Dependency] = field(default_factory=list)
@ -144,7 +144,7 @@ class Manifest:
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:
start_dir: Directory to start searching from (default: cwd)
@ -201,7 +201,7 @@ def save_manifest(manifest: Manifest, path: Optional[Path] = None) -> Path:
Args:
manifest: Manifest to save
path: Path to save to (default: ./smarttools.yaml)
path: Path to save to (default: ./cmdforge.yaml)
Returns:
Path where manifest was saved

View File

@ -12,7 +12,7 @@ import yaml
# Default providers config location
PROVIDERS_FILE = Path.home() / ".smarttools" / "providers.yaml"
PROVIDERS_FILE = Path.home() / ".cmdforge" / "providers.yaml"
@dataclass
@ -161,7 +161,7 @@ def call_provider(provider_name: str, prompt: str, timeout: int = 300) -> Provid
return ProviderResult(
text="",
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)
@ -181,7 +181,7 @@ def call_provider(provider_name: str, prompt: str, timeout: int = 300) -> Provid
return ProviderResult(
text="",
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:
@ -197,7 +197,7 @@ def call_provider(provider_name: str, prompt: str, timeout: int = 300) -> Provid
if result.returncode != 0:
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():
error_msg += "\n\nTo install AI providers, run: smarttools providers install"
error_msg += "\n\nTo install AI providers, run: cmdforge providers install"
return ProviderResult(
text="",
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" 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" 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 "")
return ProviderResult(
text="",
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)

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
@ -51,7 +51,7 @@ ALLOWED_SORT = {
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]$")
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()
password_hasher = PasswordHasher(memory_cost=65536, time_cost=3, parallelism=4)
@ -1517,7 +1517,7 @@ def create_app() -> Flask:
status=413,
details={"limit": MAX_BODY_BYTES},
)
secret = os.environ.get("SMARTTOOLS_REGISTRY_WEBHOOK_SECRET", "")
secret = os.environ.get("CMDFORGE_REGISTRY_WEBHOOK_SECRET", "")
if not secret:
return error_response("UNAUTHORIZED", "Webhook secret not configured", 401)
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:
default_path = Path.home() / ".smarttools" / "registry" / "registry.db"
return Path(os.environ.get("SMARTTOOLS_REGISTRY_DB", default_path))
default_path = Path.home() / ".cmdforge" / "registry" / "registry.db"
return Path(os.environ.get("CMDFORGE_REGISTRY_DB", default_path))
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:
default_dir = Path.home() / ".smarttools" / "registry" / "repo"
return Path(os.environ.get("SMARTTOOLS_REGISTRY_REPO_DIR", default_dir))
default_dir = Path.home() / ".cmdforge" / "registry" / "repo"
return Path(os.environ.get("CMDFORGE_REGISTRY_REPO_DIR", default_dir))
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:
return os.environ.get("SMARTTOOLS_REGISTRY_REPO_BRANCH", "main")
return os.environ.get("CMDFORGE_REGISTRY_REPO_BRANCH", "main")
def get_categories_cache_path() -> Path:
return Path(os.environ.get(
"SMARTTOOLS_REGISTRY_CATEGORIES_CACHE",
Path.home() / ".smarttools" / "registry" / "categories_cache.json",
"CMDFORGE_REGISTRY_CATEGORIES_CACHE",
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):
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):
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.
"""
@ -114,7 +114,7 @@ class DownloadResult:
class RegistryClient:
"""Client for interacting with the SmartTools registry API."""
"""Client for interacting with the CmdForge registry API."""
def __init__(
self,
@ -141,8 +141,8 @@ class RegistryClient:
# Session for connection pooling
self._session = requests.Session()
self._session.headers.update({
"User-Agent": "SmartTools-CLI/1.0",
"X-SmartTools-Client": "cli/1.0.0",
"User-Agent": "CmdForge-CLI/1.0",
"X-CmdForge-Client": "cli/1.0.0",
"Accept": "application/json"
})
@ -198,7 +198,7 @@ class RegistryClient:
if not self.token:
raise RegistryError(
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
)
headers.update(self._auth_headers())

View File

@ -1,8 +1,8 @@
"""Tool resolution with proper search order.
Implements the tool resolution order:
1. Local project: ./.smarttools/<owner>/<name>/config.yaml
2. Global user: ~/.smarttools/<owner>/<name>/config.yaml
1. Local project: ./.cmdforge/<owner>/<name>/config.yaml
2. Global user: ~/.cmdforge/<owner>/<name>/config.yaml
3. Registry: Fetch from API, install to global, then run
4. Error if not found
"""
@ -24,7 +24,7 @@ logger = logging.getLogger(__name__)
# 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
@ -436,9 +436,9 @@ class ToolResolver:
python_path = sys.executable
script = f"""#!/bin/bash
# SmartTools wrapper for '{owner}/{name}'
# CmdForge wrapper for '{owner}/{name}'
# 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)
@ -450,9 +450,9 @@ exec {python_path} -m smarttools.runner {owner}/{name} "$@"
"""Extract owner from existing wrapper script."""
try:
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
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:
return match.group(1)
return None

View File

@ -210,7 +210,7 @@ def create_argument_parser(tool: Tool) -> argparse.ArgumentParser:
"""
parser = argparse.ArgumentParser(
prog=tool.name,
description=tool.description or f"SmartTools: {tool.name}"
description=tool.description or f"CmdForge: {tool.name}"
)
# Universal flags
@ -244,7 +244,7 @@ def create_argument_parser(tool: Tool) -> argparse.ArgumentParser:
def main():
"""Entry point for tool execution via wrapper script."""
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)
tool_spec = sys.argv[1]

View File

@ -10,7 +10,7 @@ import yaml
# Default tools directory
TOOLS_DIR = Path.home() / ".smarttools"
TOOLS_DIR = Path.home() / ".cmdforge"
# Default bin directory for wrapper scripts
BIN_DIR = Path.home() / ".local" / "bin"
@ -106,7 +106,7 @@ DEFAULT_CATEGORIES = ["Text", "Developer", "Data", "Other"]
@dataclass
class Tool:
"""A SmartTools tool definition."""
"""A CmdForge tool definition."""
name: str
description: str = ""
category: str = "Other" # Tool category for organization
@ -275,13 +275,13 @@ def create_wrapper_script(name: str) -> Path:
bin_dir = get_bin_dir()
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
script = f"""#!/bin/bash
# SmartTools wrapper for '{name}'
# CmdForge wrapper for '{name}'
# Auto-generated - do not edit
exec {python_path} -m smarttools.runner {name} "$@"
exec {python_path} -m cmdforge.runner {name} "$@"
"""
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 sys
@ -762,7 +762,7 @@ def main_menu(dialog_prog: str):
"""Show the main menu."""
while True:
choice = show_menu(
"SmartTools Manager",
"CmdForge Manager",
[
("list", "List all tools"),
("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.
"""
@ -170,7 +170,7 @@ class AsyncOperation:
class RegistryBrowser:
"""TUI browser for the SmartTools Registry."""
"""TUI browser for the CmdForge Registry."""
def __init__(self):
self.client = get_client()
@ -195,7 +195,7 @@ class RegistryBrowser:
"""Build the main UI layout."""
# Header
self.header = urwid.AttrMap(
urwid.Text(" SmartTools Registry Browser ", align='center'),
urwid.Text(" CmdForge Registry Browser ", align='center'),
'header'
)
@ -344,7 +344,7 @@ Downloads: {downloads}
Tags: {', '.join(tags) if tags else 'None'}
Install command:
smarttools registry install {owner}/{name}
cmdforge registry install {owner}/{name}
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
# Ensure system packages are accessible
@ -15,8 +15,8 @@ from .tool import (
from .providers import Provider, load_providers, add_provider, delete_provider, get_provider
class SmartToolsUI:
"""BIOS-style UI for SmartTools."""
class CmdForgeUI:
"""BIOS-style UI for CmdForge."""
def __init__(self):
self.screen = None
@ -51,7 +51,7 @@ class SmartToolsUI:
for label, value in items:
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)
result = grid.runOnce()
@ -698,7 +698,7 @@ class SmartToolsUI:
def run_ui():
"""Entry point for the snack UI."""
ui = SmartToolsUI()
ui = CmdForgeUI()
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.
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.widgets import (
SelectableText, Button3D, Button3DCompact, ClickableButton,
@ -13,7 +13,7 @@ from .ui_urwid.widgets import (
)
__all__ = [
'run_ui', 'SmartToolsUI', 'PALETTE',
'run_ui', 'CmdForgeUI', 'PALETTE',
'SelectableText', 'Button3D', 'Button3DCompact', 'ClickableButton',
'SelectableToolItem', 'ToolListBox', 'TabCyclePile', 'TabPassEdit',
'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
from typing import Optional, Callable
@ -18,8 +18,8 @@ from .widgets import (
)
class SmartToolsUI:
"""Urwid-based UI for SmartTools with mouse support."""
class CmdForgeUI:
"""Urwid-based UI for CmdForge with mouse support."""
def __init__(self):
self.loop = None
@ -226,7 +226,7 @@ class SmartToolsUI:
], tab_positions=[0, 1, 5]) # Tool list, buttons row, exit button
# Header
header = urwid.Text(('header', ' SmartTools Manager '), align='center')
header = urwid.Text(('header', ' CmdForge Manager '), align='center')
# Footer
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():
"""Entry point for the urwid UI."""
ui = SmartToolsUI()
ui = CmdForgeUI()
ui.run()

View File

@ -1,4 +1,4 @@
"""Web UI blueprint for SmartTools."""
"""Web UI blueprint for CmdForge."""
import os
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
@ -19,13 +19,13 @@ if _sentry_dsn:
integrations=[FlaskIntegration()],
traces_sample_rate=float(os.environ.get("SENTRY_TRACES_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.
)
except ImportError:
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 .auth import login, register, logout
@ -44,10 +44,10 @@ def create_web_app() -> Flask:
app.register_blueprint(forum_bp)
# Session configuration
app.session_interface = SQLiteSessionInterface(cookie_name="smarttools_session")
app.config["SESSION_COOKIE_NAME"] = "smarttools_session"
app.config["SESSION_COOKIE_SECURE"] = os.environ.get("SMARTTOOLS_ENV") == "production"
app.config["SHOW_ADS"] = os.environ.get("SMARTTOOLS_SHOW_ADS", "").lower() == "true"
app.session_interface = SQLiteSessionInterface(cookie_name="cmdforge_session")
app.config["SESSION_COOKIE_NAME"] = "cmdforge_session"
app.config["SESSION_COOKIE_SECURE"] = os.environ.get("CMDFORGE_ENV") == "production"
app.config["SHOW_ADS"] = os.environ.get("CMDFORGE_SHOW_ADS", "").lower() == "true"
# CSRF token generator
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
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 = {
"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": """
<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>
<h2 id="what-is-smarttools">What is SmartTools?</h2>
<p>SmartTools is a lightweight personal tool builder that lets you:</p>
<h2 id="what-is-cmdforge">What is CmdForge?</h2>
<p>CmdForge is a lightweight personal tool builder that lets you:</p>
<ul>
<li><strong>Create custom CLI commands</strong> that call AI providers</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>
<p>Get up and running in under a minute:</p>
<pre><code class="language-bash"># Install SmartTools
pip install smarttools
<pre><code class="language-bash"># Install CmdForge
pip install cmdforge
# Create your first tool (choose your style)
smarttools ui # Visual builder with menus
smarttools create # CLI wizard
cmdforge ui # Visual builder with menus
cmdforge create # CLI wizard
# Or install a tool from the registry
smarttools registry install official/summarize
cmdforge registry install official/summarize
# Use it!
cat article.txt | summarize</code></pre>
<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="text-cyan-700"><code>smarttools 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>
<p class="text-cyan-700"><code>cmdforge ui</code> launches a visual builder with menus and forms.
<code>cmdforge create</code> uses a command-line wizard. Both create the same YAML config files.</p>
</div>
<h2 id="how-it-works">How It Works</h2>
@ -87,11 +87,11 @@ output: "{summary}"</code></pre>
<ul>
<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="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>
""",
"headings": [
("what-is-smarttools", "What is SmartTools?"),
("what-is-cmdforge", "What is CmdForge?"),
("quick-start", "Quick Start"),
("how-it-works", "How It Works"),
("next-steps", "Next Steps"),
@ -101,24 +101,24 @@ output: "{summary}"</code></pre>
"installation": {
"title": "Installation",
"description": "How to install SmartTools on your system",
"description": "How to install CmdForge on your system",
"parent": "getting-started",
"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>
<p>The simplest way to install SmartTools:</p>
<pre><code class="language-bash">pip install smarttools</code></pre>
<p>The simplest way to install CmdForge:</p>
<pre><code class="language-bash">pip install cmdforge</code></pre>
<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>
<pre><code class="language-bash">smarttools --version
smarttools --help</code></pre>
<pre><code class="language-bash">cmdforge --version
cmdforge --help</code></pre>
<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)
pip install claude-cli
@ -127,17 +127,17 @@ pip install claude-cli
pip install openai
# Configure your provider
smarttools config</code></pre>
cmdforge config</code></pre>
<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
export PATH="$HOME/.local/bin:$PATH"</code></pre>
<h2 id="development-install">Development Installation</h2>
<p>To contribute or modify SmartTools:</p>
<pre><code class="language-bash">git clone https://gitea.brrd.tech/rob/SmartTools.git
cd SmartTools
<p>To contribute or modify CmdForge:</p>
<pre><code class="language-bash">git clone https://gitea.brrd.tech/rob/CmdForge.git
cd CmdForge
pip install -e ".[dev]"</code></pre>
""",
"headings": [
@ -151,16 +151,16 @@ pip install -e ".[dev]"</code></pre>
"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",
"content": """
<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>
<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
version: "1.0.0"
description: Explain code or concepts in simple terms
@ -230,9 +230,9 @@ cat complex_algorithm.py | explain --level expert</code></pre>
"publishing": {
"title": "Publishing Tools",
"description": "Share your tools with the SmartTools community",
"description": "Share your tools with the CmdForge community",
"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>
<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>
<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
smarttools registry publish
cmdforge registry publish
# 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>
<p>Published versions are <strong>immutable</strong>. To update a tool:</p>
<ol>
<li>Make your changes</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>
<h2 id="best-practices">Best Practices</h2>
@ -294,11 +294,11 @@ smarttools registry publish --dry-run</code></pre>
"title": "AI Providers",
"description": "Configure different AI providers for your tools",
"content": """
<p class="lead">SmartTools works with any AI provider that has a CLI interface. Configure providers in
<code>~/.smarttools/providers.yaml</code>.</p>
<p class="lead">CmdForge works with any AI provider that has a CLI interface. Configure providers in
<code>~/.cmdforge/providers.yaml</code>.</p>
<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:
- name: claude
@ -397,9 +397,9 @@ providers:
"parallel-orchestration": {
"title": "Parallel Orchestration",
"description": "Run multiple SmartTools concurrently for faster workflows",
"description": "Run multiple CmdForge concurrently for faster workflows",
"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
is ideal for multi-agent workflows, parallel analysis, or any task where you need responses
from multiple AI providers simultaneously.</p>
@ -412,7 +412,7 @@ from multiple AI providers simultaneously.</p>
</ul>
<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
from concurrent.futures import ThreadPoolExecutor, as_completed
@ -604,11 +604,11 @@ def run_with_progress(tools: list[str], input_text: str):
</ul>
<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>
project. It implements:</p>
<ul>
<li>Multiple AI "participants" as SmartTools</li>
<li>Multiple AI "participants" as CmdForge</li>
<li>Parallel execution with live progress logging</li>
<li>Shared log files for real-time monitoring</li>
<li>Discussion workflows with voting and consensus</li>
@ -656,7 +656,7 @@ steps:
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
HELLO WORLD!!!</code></pre>
@ -1697,7 +1697,7 @@ loops, and more.</p>
<li>Using different AI models for different tasks</li>
<li>Building tools that adapt to their input</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>
</div>
@ -1912,7 +1912,7 @@ output: "{result}"</code></pre>
<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
version: "1.0.0"
@ -2087,7 +2087,7 @@ output: "{formatted}"</code></pre>
"title": "The Visual Builder",
"description": "Build tools without touching YAML using the terminal UI",
"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>
<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>
<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>
<div class="bg-gray-900 text-gray-100 rounded-lg p-4 my-6 font-mono text-sm">
<pre>
SmartTools Manager
CmdForge Manager
[ 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>
<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>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>
@ -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>
<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="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>
<tbody>
<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>
</tr>
<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
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 = """
@ -51,9 +51,9 @@ CREATE INDEX IF NOT EXISTS idx_forum_replies_topic ON forum_replies(topic_id);
"""
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),
("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),
("tutorials", "Tutorials & Guides", "Community-written guides and how-tos", "book", 5),
]

View File

@ -19,7 +19,7 @@ from flask import (
url_for,
)
from smarttools.registry.db import connect_db
from cmdforge.registry.db import connect_db
from .models import (
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
@ -8,7 +8,7 @@ from typing import Any, Dict, List, Optional, Tuple
from markupsafe import Markup, escape
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
@ -499,7 +499,7 @@ def docs(path: str):
else:
page = SimpleNamespace(
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>"),
headings=[],
parent=None,

View File

@ -7,7 +7,7 @@ from typing import List
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_cache = {"generated_at": None, "xml": ""}

View File

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

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
# and enable AI assistants to help solve SmartTools issues.
# and enable AI assistants to help solve CmdForge issues.
User-agent: *
Allow: /
@ -11,7 +11,7 @@ Allow: /tutorials/
Allow: /tools/
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
Allow: /
@ -42,6 +42,6 @@ Disallow: /api/v1/tokens
Allow: /api/
# 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!

View File

@ -3,14 +3,14 @@
<head>
<meta charset="UTF-8">
<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 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 %}
<!-- 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:type" content="website">
<meta property="og:url" content="{{ request.url }}">
@ -18,7 +18,7 @@
<!-- Twitter Card -->
<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 %}">
{% block twitter_extra %}{% endblock %}
@ -40,7 +40,7 @@
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "SmartTools",
"name": "CmdForge",
"url": "{{ request.host_url }}",
"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">
<!-- Brand -->
<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">
Build custom AI commands in YAML. Create Unix-style pipeable tools that work with any AI provider.
Provider-agnostic, composable, and community-driven.
</p>
<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">
<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"/>
</svg>
</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">
<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"/>
@ -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">
<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 class="text-gray-300 text-xs mt-2 sm:mt-0">
Made with care for the developer community.

View File

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

View File

@ -54,10 +54,10 @@
<div class="mt-4">
<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">
smarttools install {{ tool.owner }}/{{ tool.name }}
cmdforge install {{ tool.owner }}/{{ tool.name }}
</code>
<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"
aria-label="Copy install command">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">

View File

@ -39,7 +39,7 @@
</a>
</h3>
<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>
<a href="{{ href or '#' }}"
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" %}
{% set active_page = 'overview' %}
{% block title %}Dashboard - SmartTools{% endblock %}
{% block title %}Dashboard - CmdForge{% endblock %}
{% block dashboard_content %}
<!-- Stats Cards -->

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,6 @@
{% extends "base.html" %}
{% block title %}Server Error - SmartTools{% endblock %}
{% block title %}Server Error - CmdForge{% endblock %}
{% block content %}
<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">
Go Home
</a>
<a href="https://github.com/your-org/smarttools/issues"
<a href="https://github.com/your-org/cmdforge/issues"
target="_blank"
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">

View File

@ -2,7 +2,7 @@
{% 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 %}
<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">
<h1 class="text-3xl font-bold text-gray-900">Community Forum</h1>
<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>
<div class="mt-4 flex items-center gap-6 text-sm text-gray-500">
<span>{{ stats.topics }} topics</span>
@ -119,7 +119,7 @@
</svg>
Browse Tools
</a>
<a href="https://gitea.brrd.tech/rob/SmartTools/issues"
<a href="https://gitea.brrd.tech/rob/CmdForge/issues"
target="_blank" rel="noopener"
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">

View File

@ -1,14 +1,14 @@
{% 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 %}
<div class="bg-white">
<!-- Hero -->
<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">
An open-source platform for building and sharing AI-powered command-line tools.
</p>
@ -20,7 +20,7 @@
<h2 class="text-2xl font-bold text-gray-900 mb-6">Our Mission</h2>
<div class="prose prose-lg prose-indigo max-w-none">
<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.
</p>
<p>
@ -29,7 +29,7 @@
</p>
<p>
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.
</p>
</div>
@ -49,7 +49,7 @@
</div>
<h3 class="text-lg font-semibold text-gray-900 mb-2">Open Source</h3>
<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>
</div>
@ -98,7 +98,7 @@
<h2 class="text-2xl font-bold text-gray-900 mb-6">Sustainability</h2>
<div class="prose prose-lg prose-indigo max-w-none">
<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:
</p>
<ul>
@ -121,9 +121,9 @@
<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>
<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>
<a href="https://github.com/your-org/smarttools"
<a href="https://github.com/your-org/cmdforge"
target="_blank"
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">

View File

@ -1,8 +1,8 @@
{% 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 %}
<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">
<h1 class="text-3xl font-bold text-gray-900">Community</h1>
<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>
</div>
</div>
@ -52,7 +52,7 @@
<p class="mt-2 text-sm text-gray-600">
Browse the source, fork the project, and submit pull requests.
</p>
<a href="https://gitea.brrd.tech/rob/SmartTools"
<a href="https://gitea.brrd.tech/rob/CmdForge"
target="_blank" rel="noopener"
class="mt-4 inline-flex items-center text-sm font-medium text-indigo-600 hover:text-indigo-800">
View Repository
@ -72,7 +72,7 @@
<p class="mt-2 text-sm text-gray-600">
Found a bug? Have a feature request? Open an issue.
</p>
<a href="https://gitea.brrd.tech/rob/SmartTools/issues"
<a href="https://gitea.brrd.tech/rob/CmdForge/issues"
target="_blank" rel="noopener"
class="mt-4 inline-flex items-center text-sm font-medium text-indigo-600 hover:text-indigo-800">
Open Issue
@ -137,7 +137,7 @@
<div>
<h3 class="font-semibold text-gray-900">Report Bugs</h3>
<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>
</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">
Visit Forum
</a>
<a href="https://gitea.brrd.tech/rob/SmartTools#installation"
<a href="https://gitea.brrd.tech/rob/CmdForge#installation"
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">
Installation

View File

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

View File

@ -1,7 +1,7 @@
{% extends "base.html" %}
{% 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 %}
@ -124,7 +124,7 @@
<!-- Edit on GitHub -->
<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"
rel="noopener noreferrer"
class="inline-flex items-center text-sm text-gray-500 hover:text-gray-700">

View File

@ -1,17 +1,17 @@
{% 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 %}
<div class="bg-gray-50 min-h-screen">
<!-- Hero -->
<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">
<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">
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>
</div>
</div>
@ -38,7 +38,7 @@
</div>
<h2 class="text-lg font-semibold text-gray-900">Spread the Word</h2>
<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>
</div>
<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">
<h2 class="text-2xl font-bold text-gray-900">Get Involved</h2>
<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>
<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"
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">
@ -79,7 +79,7 @@
<!-- Thank you -->
<section class="mt-12 text-center">
<p class="text-gray-500">
Thanks for using SmartTools!
Thanks for using CmdForge!
</p>
</section>
</div>

View File

@ -3,7 +3,7 @@
{% from "components/tutorial_card.html" import tutorial_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 %}
@ -21,7 +21,7 @@
<!-- Install Link -->
<div class="mt-10">
<a href="https://gitea.brrd.tech/rob/SmartTools#installation"
<a href="https://gitea.brrd.tech/rob/CmdForge#installation"
target="_blank"
rel="noopener"
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">
<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">
Why SmartTools?
Why CmdForge?
</h2>
<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">
{{ tutorial_card(
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'),
step_number=1
) }}
@ -191,7 +191,7 @@
<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">
<!-- 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>
</section>

View File

@ -1,7 +1,7 @@
{% extends "base.html" %}
{% 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 %}
<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"/>
</svg>
</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">
Access your dashboard and manage your tools
</p>

View File

@ -1,8 +1,8 @@
{% 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 %}
<div class="bg-white py-16">
@ -13,7 +13,7 @@
<div class="prose prose-lg prose-indigo max-w-none">
<h2>Introduction</h2>
<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 information when you use our website and services.
</p>
@ -121,8 +121,8 @@
contact us at:
</p>
<ul>
<li>Email: privacy@smarttools.dev</li>
<li>GitHub: <a href="https://github.com/your-org/smarttools/issues">Open an issue</a></li>
<li>Email: privacy@cmdforge.dev</li>
<li>GitHub: <a href="https://github.com/your-org/cmdforge/issues">Open an issue</a></li>
</ul>
</div>
</div>

View File

@ -1,9 +1,9 @@
{% extends "base.html" %}
{% 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 %}
<div class="bg-gray-50 min-h-screen">

View File

@ -1,7 +1,7 @@
{% extends "base.html" %}
{% 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 %}
<div class="min-h-[70vh] flex items-center justify-center px-4 py-12">

View File

@ -1,9 +1,9 @@
{% extends "base.html" %}
{% 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 %}
<div class="bg-gray-50 min-h-screen">

View File

@ -1,8 +1,8 @@
{% 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 %}
<div class="bg-white py-16">
@ -13,19 +13,19 @@
<div class="prose prose-lg prose-indigo max-w-none">
<h2>1. Acceptance of Terms</h2>
<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
the Service.
</p>
<h2>2. Description of Service</h2>
<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:
</p>
<ul>
<li>The SmartTools CLI application</li>
<li>The SmartTools Registry (tool hosting and discovery)</li>
<li>The CmdForge CLI application</li>
<li>The CmdForge Registry (tool hosting and discovery)</li>
<li>Documentation and tutorials</li>
<li>Community features</li>
</ul>
@ -46,7 +46,7 @@
<h3>4.1 Your Content</h3>
<p>
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.
</p>
@ -80,22 +80,22 @@
<h2>6. API and CLI Usage</h2>
<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
restrictions.
</p>
<h2>7. Third-Party Services</h2>
<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
conditions. We are not responsible for third-party services.
</p>
<h2>8. Intellectual Property</h2>
<p>
The SmartTools software is open source and licensed under the MIT License.
The SmartTools name, logo, and branding are trademarks of SmartTools.
The CmdForge software is open source and licensed under the MIT License.
The CmdForge name, logo, and branding are trademarks of CmdForge.
</p>
<h2>9. Disclaimer of Warranties</h2>
@ -104,20 +104,20 @@
WE DO NOT WARRANT THAT THE SERVICE WILL BE UNINTERRUPTED, ERROR-FREE, OR SECURE.
</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.
</p>
<h2>10. Limitation of Liability</h2>
<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
YOUR USE OF THE SERVICE.
</p>
<h2>11. Indemnification</h2>
<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
violation of these Terms.
</p>
@ -140,7 +140,7 @@
<h2>14. Governing Law</h2>
<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.
</p>
@ -149,8 +149,8 @@
For questions about these Terms, please contact us at:
</p>
<ul>
<li>Email: legal@smarttools.dev</li>
<li>GitHub: <a href="https://github.com/your-org/smarttools/issues">Open an issue</a></li>
<li>Email: legal@cmdforge.dev</li>
<li>GitHub: <a href="https://github.com/your-org/cmdforge/issues">Open an issue</a></li>
</ul>
</div>
</div>

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