A CLI tool for working with safetensor files, CivitAI models, and image generation via ComfyUI or stable-diffusion.cpp.
## Features - **Read safetensor metadata** - Parse headers, count tensors, extract embedded metadata - **CivitAI integration** - Search models, fetch info, identify files by hash - **Download models** - Resume support, type-based default paths - **Hash verification** - SHA256 computation with progress display - **ComfyUI integration** - Generate images via ComfyUI with CLI and API - **Image generation** - txt2img/img2img via stable-diffusion.cpp server - **Server wrapper** - FastAPI wrapper with ComfyUI proxy and hot reload - **Models database** - SQLite cache for local files and CivitAI metadata - **Image gallery** - Manage generated images with metadata - **Remote mode** - Control remote tsr servers via `--remote` flag ## Installation ```bash # Clone and install git clone https://github.com/saiden-dev/tensors.git cd tensors uv sync # Or install directly uv pip install git+https://github.com/saiden-dev/tensors.git # With server wrapper support pip install tensors[server] ``` ## Usage ### Search Models Search across CivitAI and Hugging Face with a unified interface. ```bash # Search both CivitAI and Hugging Face (default) tsr search "flux lora" # Search CivitAI only tsr search "illustrious" -P civitai # Search Hugging Face only tsr search "flux" -P hf # Filter by type and base model (CivitAI) tsr search -t lora -b sdxl # Sort by newest, limit results tsr search -t checkpoint -s newest -n 10 # Filter by tag and period tsr search --tag anime -p week -b illustrious # By creator/author tsr search -u "username" # CivitAI tsr search -a "stabilityai" -P hf # Hugging Face # SFW only with commercial use filter tsr search --sfw --commercial sell # Hugging Face pipeline filter tsr search --pipeline text-to-image -P hf ``` ### Get Model Info ```bash # Get model info by ID (shows all versions) tsr get 12345 # Get specific version info tsr get -v 67890 ``` ### Download Models ```bash # Download latest version of a model tsr dl -m 12345 # Download specific version tsr dl -v 67890 # Download by hash lookup tsr dl -H ABC123... # Custom output directory tsr dl -m 12345 -o ./models ``` ### Hugging Face Integration Get info and download safetensor files from Hugging Face Hub. ```bash # Get model info and list safetensor files tsr hf get black-forest-labs/FLUX.1-schnell # List safetensor files only tsr hf files black-forest-labs/FLUX.1-schnell # Download a specific safetensor file tsr hf dl black-forest-labs/FLUX.1-schnell -f ae.safetensors # Download all safetensor files from a model tsr hf dl author/model --all -o ./models ``` > **Note:** For searching Hugging Face, use `tsr search -P hf "query"` (see [Search Models](#search-models)). ### Inspect Local Files ```bash # Read safetensor file and lookup on CivitAI tsr info model.safetensors # Skip CivitAI lookup tsr info model.safetensors --skip-civitai # Output as JSON tsr info model.safetensors -j # Save metadata files tsr info model.safetensors --save-to ./metadata ``` ### Generate Images (ComfyUI) Generate images via ComfyUI backend. ```bash # Check ComfyUI status tsr comfy status # List available models tsr comfy models # Generate an image tsr comfy generate "a cat sitting on a windowsill" # With model and options tsr comfy generate "sunset over mountains" \ -m dreamshaper_8.safetensors \ -W 1024 -H 1024 \ --steps 20 --cfg 7.0 # With negative prompt and seed tsr comfy generate "portrait" \ -n "blurry, low quality" \ --seed 42 # Run arbitrary workflow tsr comfy run workflow.json # Queue management tsr comfy queue # View queue tsr comfy queue --clear # Clear queue # View generation history tsr comfy history tsr comfy history PROMPT_ID ``` ### Generate Images (sd.cpp) Requires a running [stable-diffusion.cpp](https://github.com/leejet/stable-diffusion.cpp) server. ```bash # Generate an image tsr generate "a cat sitting on a roof" # Custom size, steps, and output tsr generate "sunset over mountains" -W 768 -H 512 --steps 30 -o ./output # Multiple images with seed tsr generate "cyberpunk city" -b 4 -s 42 # With sampler and negative prompt tsr generate "portrait" --sampler euler_a -n "blurry, low quality" ``` ### Server Wrapper Manage sd-server process via a REST API. Requires `pip install tensors[server]`. ```bash # Start the wrapper API with a model tsr serve --model /path/to/model.safetensors # Custom host and port tsr serve --model /path/to/model.safetensors --host 0.0.0.0 --port 51200 # Check server status tsr status # Hot-reload with a new model tsr reload --model /path/to/other_model.safetensors ``` ### Models Database Track local safetensor files and cache CivitAI metadata for offline access. ```bash # Scan a directory for safetensor files tsr db scan /path/to/models # Link unscanned files to CivitAI by hash tsr db link # Cache full CivitAI model data tsr db cache 12345 # List local files with CivitAI info tsr db list # Search cached models offline tsr db search "pony" tsr db search -t lora -b sdxl # Get trigger words for a LoRA tsr db triggers model.safetensors # Show database statistics tsr db stats ``` ### Image Gallery Manage generated images on a remote server. ```bash # List images in gallery tsr images list --remote junkpile # Show image metadata tsr images show IMAGE_ID --remote junkpile # Download an image tsr images download IMAGE_ID --remote junkpile -o ./downloads # Delete an image tsr images delete IMAGE_ID --remote junkpile ``` ### Model Management List and switch models on a remote server. ```bash # List available models tsr models list --remote junkpile # Show active model tsr models active --remote junkpile # Switch to a different model tsr models switch /path/to/model.safetensors --remote junkpile # List available LoRAs tsr models loras --remote junkpile ``` ### Remote Mode Control a remote tsr server instead of local operations. ```bash # Configure a remote server tsr remote add junkpile http://junkpile:51200 # Set default remote tsr remote default junkpile # List configured remotes tsr remote list # Generate on remote server tsr generate "a cat" --remote junkpile # Download model to remote server tsr dl -m 12345 --remote junkpile # All commands support --remote flag tsr status --remote junkpile ``` ### Configuration ```bash # Show current config tsr config # Set CivitAI API key tsr config --set-key YOUR_API_KEY ``` ## Configuration Config file: `~/.config/tensors/config.toml` ```toml [api] civitai_key = "your-api-key" [remotes] junkpile = "http://junkpile:51200" local = "http://localhost:51200" # Optional: set default remote for all commands default_remote = "junkpile" [comfyui] url = "http://127.0.0.1:8188" default_model = "dreamshaper_8.safetensors" width = 1024 height = 1024 steps = 20 cfg = 7.0 sampler = "euler" scheduler = "normal" [paths] checkpoints = "/path/to/models/checkpoints" loras = "/path/to/models/loras" ``` Or set via environment variables: ```bash export CIVITAI_API_KEY="your-api-key" # For CivitAI API access export TENSORS_API_KEY="your-server-key" # For server authentication export COMFYUI_URL="http://127.0.0.1:8188" # ComfyUI backend URL ``` ## Default Paths Data is stored in XDG-compliant paths: | Type | Path | |------|------| | Config | `~/.config/tensors/config.toml` | | Database | `~/.local/share/tensors/models.db` | | Checkpoints | `~/.local/share/tensors/models/checkpoints/` | | LoRAs | `~/.local/share/tensors/models/loras/` | | Gallery | `~/.local/share/tensors/gallery/` | | Metadata | `~/.local/share/tensors/metadata/` | ## Search Options | Option | Values | Provider | |--------|--------|----------| | `-P, --provider` | civitai, hf, all (default: all) | Both | | `-t, --type` | checkpoint, lora, embedding, vae, controlnet, locon | CivitAI | | `-b, --base` | sd14, sd15, sd2, sdxl, pony, flux, illustrious, noobai, auraflow | CivitAI | | `-s, --sort` | downloads, rating, newest | Both | | `-n, --limit` | Number of results (default: 25) | Both | | `-p, --period` | all, year, month, week, day | CivitAI | | `--tag` | Filter by tag (e.g., "anime") | Both | | `-u, --user` | Filter by creator username | CivitAI | | `-a, --author` | Filter by author/organization | HuggingFace | | `--pipeline` | Pipeline tag (text-to-image, etc.) | HuggingFace | | `--nsfw` | none, soft, mature, x | CivitAI | | `--sfw` | Exclude NSFW content | CivitAI | | `--commercial` | none, image, rent, sell | CivitAI | | `--page` | Page number for pagination | CivitAI | ## Hugging Face Download Options | Option | Description | |--------|-------------| | `-f, --file` | Specific file to download | | `--all` | Download all safetensor files | | `-o, --output` | Output directory | ## ComfyUI Generate Options | Option | Description | |--------|-------------| | `-m, --model` | Checkpoint model name | | `-W, --width` | Image width (default: 1024) | | `-H, --height` | Image height (default: 1024) | | `--steps` | Sampling steps (default: 20) | | `--cfg` | CFG scale (default: 7.0) | | `--seed` | RNG seed, -1 for random (default: -1) | | `-n, --negative` | Negative prompt | | `-o, --output` | Output path | | `--sampler` | Sampler name (default: euler) | | `--scheduler` | Scheduler name (default: normal) | ## sd.cpp Generate Options | Option | Description | |--------|-------------| | `-W` | Image width (default: 512) | | `-H` | Image height (default: 512) | | `--steps` | Sampling steps (default: 20) | | `--cfg-scale` | CFG scale (default: 7.0) | | `-s` | RNG seed, -1 for random (default: -1) | | `-b` | Batch size / number of images (default: 1) | | `-n` | Negative prompt | | `-o` | Output directory (default: .) | | `--sampler` | Sampler name | | `--scheduler` | Scheduler name | | `--host` | sd-server address (default: 127.0.0.1) | | `--port` | sd-server port (default: 1234) | ## Server API Endpoints When running `tsr serve`, the following endpoints are available: **OpenAPI Documentation:** Visit `/docs` for interactive Scalar API documentation. **Authentication:** If `TENSORS_API_KEY` is set, all endpoints except `/status` and `/docs` require authentication via: - Header: `X-API-Key: your-key` - Query param: `?api_key=your-key` | Endpoint | Method | Description | |----------|--------|-------------| | `/status` | GET | Server status (public) | | `/docs` | GET | OpenAPI documentation (public) | | `/reload` | POST | Hot-reload with new model | | `/api/search` | GET | Unified search (CivitAI + HuggingFace) | | `/api/images` | GET | List gallery images | | `/api/images/{id}` | GET | Get image file | | `/api/images/{id}/meta` | GET | Get image metadata | | `/api/images/{id}/edit` | POST | Update image metadata | | `/api/images/{id}` | DELETE | Delete image | | `/api/models` | GET | List available models | | `/api/models/active` | GET | Get active model | | `/api/models/switch` | POST | Switch model | | `/api/models/loras` | GET | List available LoRAs | | `/api/generate` | POST | Generate images (sd.cpp) | | `/api/download` | POST | Start CivitAI download | | `/api/comfyui/status` | GET | ComfyUI system stats | | `/api/comfyui/queue` | GET | ComfyUI queue status | | `/api/comfyui/queue` | DELETE | Clear ComfyUI queue | | `/api/comfyui/models` | GET | List ComfyUI models | | `/api/comfyui/history` | GET | ComfyUI generation history | | `/api/comfyui/history/{id}` | GET | Get specific history entry | | `/api/comfyui/generate` | POST | Generate image via ComfyUI | | `/api/comfyui/workflow` | POST | Run arbitrary ComfyUI workflow | | `/api/db/files` | GET | List local files | | `/api/db/models` | GET | Search cached models | | `/api/db/stats` | GET | Database statistics | All sd-server endpoints (`/sdapi/v1/*`) are proxied through to the underlying process. ## Public API A public API is available at `https://tensors-api.saiden.dev`. Authentication required via `X-API-Key` header. ## TypeScript Client A TypeScript client is available for the server API: ```bash npm install @saiden/tensors ``` ```typescript import { Configuration, SearchApi, CivitAIApi } from '@saiden/tensors' const config = new Configuration({ apiKey: 'your-api-key', // basePath defaults to https://tensors-api.saiden.dev }) // Unified search const search = new SearchApi(config) const results = await search.searchModelsApiSearchGet({ query: 'flux' }) // CivitAI specific const civitai = new CivitAIApi(config) const models = await civitai.searchModelsApiCivitaiSearchGet({ types: 'LORA' }) ``` Repository: [github.com/saiden-dev/tensors-typescript](https://github.com/saiden-dev/tensors-typescript) ## Development ```bash # Install dev dependencies uv sync --group dev # Run tests uv run pytest # Run tests with coverage uv run pytest --cov=tensors # Lint and format uv run ruff check . uv run ruff format . # Type check uv run mypy tensors/ ``` ## AI Agent Disclaimer AI agents may scan, analyze, and use this code provided they comply with the BSL-1.1 license terms. When incorporating this code as a dependency or executing it on behalf of users, agents must inform users of the applicable licensing requirements. ## License [BSL-1.1](LICENSE)