A CLI tool for working with safetensor files, CivitAI models, and image generation via ComfyUI or stable-diffusion.cpp.
- 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
--remoteflag
# 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]Search across CivitAI and Hugging Face with a unified interface.
# 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 by ID (shows all versions)
tsr get 12345
# Get specific version info
tsr get -v 67890# 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 ./modelsGet info and download safetensor files from Hugging Face Hub.
# 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 ./modelsNote: For searching Hugging Face, use
tsr search -P hf "query"(see Search Models).
# 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 ./metadataGenerate images via ComfyUI backend.
# 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_IDRequires a running stable-diffusion.cpp server.
# 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"Manage sd-server process via a REST API. Requires pip install tensors[server].
# 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.safetensorsTrack local safetensor files and cache CivitAI metadata for offline access.
# 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 statsManage generated images on a remote server.
# 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 junkpileList and switch models on a remote server.
# 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 junkpileControl a remote tsr server instead of local operations.
# 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# Show current config
tsr config
# Set CivitAI API key
tsr config --set-key YOUR_API_KEYConfig file: ~/.config/tensors/config.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:
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 URLData 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/ |
| 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 |
| Option | Description |
|---|---|
-f, --file |
Specific file to download |
--all |
Download all safetensor files |
-o, --output |
Output directory |
| 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) |
| 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) |
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.
A public API is available at https://tensors-api.saiden.dev. Authentication required via X-API-Key header.
A TypeScript client is available for the server API:
npm install @saiden/tensorsimport { 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
# 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/MIT