💬 Commit message: Update 2026-02-15 23:19:02, 1 files, 116 lines
📁 Files changed: 1 📝 Lines changed: 116 • CLAUDE.md
This commit is contained in:
@@ -4,7 +4,44 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|||||||
|
|
||||||
## Project Overview
|
## Project Overview
|
||||||
|
|
||||||
`tensors` is a Python CLI tool (`tsr`) for reading safetensor file metadata and interacting with the CivitAI API (search, fetch, download models). Built with Typer, Rich, and httpx.
|
`tensors` is a Python CLI + FastAPI server for:
|
||||||
|
- Reading safetensor file metadata
|
||||||
|
- Searching CivitAI and HuggingFace models
|
||||||
|
- Managing a local model database (SQLModel ORM)
|
||||||
|
- Image gallery management
|
||||||
|
- Model downloads with resume support
|
||||||
|
|
||||||
|
Built with: Typer, Rich, FastAPI, httpx, SQLModel.
|
||||||
|
|
||||||
|
## Deployment
|
||||||
|
|
||||||
|
### Production (junkpile server)
|
||||||
|
|
||||||
|
| Service | Port | URL | Status |
|
||||||
|
|---------|------|-----|--------|
|
||||||
|
| tensors API | 51200 | https://tensors-api.saiden.dev | `systemctl status tensors` |
|
||||||
|
| ComfyUI | 8188 | internal only | `systemctl status comfyui` |
|
||||||
|
|
||||||
|
**Note:** ComfyUI runs separately - no integration with tensors yet.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Deploy to junkpile
|
||||||
|
/deploy # or: ssh junkpile "cd /opt/tensors && git pull && pip install -e '.[server]' && systemctl restart tensors"
|
||||||
|
|
||||||
|
# Check status
|
||||||
|
curl https://tensors-api.saiden.dev/status
|
||||||
|
ssh junkpile "systemctl status tensors"
|
||||||
|
ssh junkpile "journalctl -u tensors -f" # logs
|
||||||
|
```
|
||||||
|
|
||||||
|
### TypeScript Client
|
||||||
|
|
||||||
|
Package: `@saiden/tensors` (GitHub: saiden-dev/tensors-typescript)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Regenerate client after API changes
|
||||||
|
ruby ~/.claude/scripts/commands/tensors/generate_client.rb
|
||||||
|
```
|
||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
|
|
||||||
@@ -21,29 +58,88 @@ just test # pytest with coverage
|
|||||||
just fix # auto-fix lint + format
|
just fix # auto-fix lint + format
|
||||||
just types # mypy only
|
just types # mypy only
|
||||||
|
|
||||||
|
# Run server locally
|
||||||
|
uv run tsr serve --port 8000
|
||||||
|
|
||||||
# Run a single test
|
# Run a single test
|
||||||
uv run pytest tests/test_tensors.py::TestClassName::test_name -v
|
uv run pytest tests/test_tensors.py::TestClassName::test_name -v
|
||||||
```
|
```
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||
Five modules with clean separation:
|
### CLI (`tsr`)
|
||||||
|
|
||||||
- **`cli.py`** — Typer CLI with commands: `info`, `search`, `get`, `dl`, `config`. Legacy mode auto-converts bare `tsr file.safetensors` to `tsr info`.
|
Entry point: `tsr = "tensors:main"` (pyproject.toml)
|
||||||
- **`api.py`** — CivitAI REST API wrapper using httpx. Search, fetch model/version/by-hash, download with resume support and Rich progress bars.
|
|
||||||
- **`config.py`** — XDG-compliant paths (`~/.config/tensors/config.toml`, `~/.local/share/tensors/`). Enums with `to_api()` methods for CivitAI parameter mapping. API key resolution: env var → config file → legacy `~/.sftrc`.
|
|
||||||
- **`safetensor.py`** — Binary safetensor header parsing (8-byte u64 LE header size → JSON metadata). SHA256 streaming hash computation.
|
|
||||||
- **`display.py`** — Rich table formatting for all output types. All major commands support `--json` output.
|
|
||||||
|
|
||||||
Entry point: `tsr = "tensors:main"` (pyproject.toml `[project.scripts]`).
|
Commands: `info`, `search`, `get`, `dl`, `config`, `serve`
|
||||||
|
|
||||||
|
### Modules
|
||||||
|
|
||||||
|
| Module | Purpose |
|
||||||
|
|--------|---------|
|
||||||
|
| `cli.py` | Typer CLI commands |
|
||||||
|
| `api.py` | CivitAI REST API wrapper (httpx) |
|
||||||
|
| `hf.py` | HuggingFace Hub integration |
|
||||||
|
| `config.py` | XDG paths, enums, API key resolution |
|
||||||
|
| `safetensor.py` | Binary header parsing, SHA256 |
|
||||||
|
| `display.py` | Rich table formatting |
|
||||||
|
| `models.py` | SQLModel ORM (17 tables) |
|
||||||
|
| `db.py` | Database operations |
|
||||||
|
|
||||||
|
### Server (`/api/*`)
|
||||||
|
|
||||||
|
| Endpoint | Description |
|
||||||
|
|----------|-------------|
|
||||||
|
| `/api/search` | Unified CivitAI + HuggingFace search |
|
||||||
|
| `/api/civitai/model/{id}` | CivitAI model info |
|
||||||
|
| `/api/db/*` | Local database CRUD |
|
||||||
|
| `/api/images/*` | Gallery management |
|
||||||
|
| `/api/download/*` | Model downloads |
|
||||||
|
|
||||||
|
Auth: `X-API-Key` header (configured via `TENSORS_API_KEY` env var)
|
||||||
|
|
||||||
|
### Database
|
||||||
|
|
||||||
|
SQLite with SQLModel ORM. Tables:
|
||||||
|
- Local files: `local_files`, `safetensor_metadata`
|
||||||
|
- CivitAI cache: `models`, `model_versions`, `creators`, `tags`, `version_files`, `file_hashes`, `trained_words`, `version_images`, `image_generation_params`, `image_resources`
|
||||||
|
- HuggingFace cache: `hf_models`, `hf_model_tags`, `hf_safetensor_files`
|
||||||
|
|
||||||
## Code Standards
|
## Code Standards
|
||||||
|
|
||||||
- Python 3.12+, strict mypy, line length 130
|
- Python 3.12+, strict mypy, line length 130
|
||||||
- Ruff with extended rule set (E, W, F, I, B, C4, UP, ARG, SIM, TCH, PTH, PL, RUF)
|
- Ruff with extended rule set (E, W, F, I, B, C4, UP, ARG, SIM, TCH, PTH, PL, RUF)
|
||||||
- PLR0913 (too many arguments) is intentionally ignored for CLI commands
|
- PLR0913 (too many arguments) is intentionally ignored for CLI commands
|
||||||
- Tests use respx for HTTP mocking and a `temp_safetensor` fixture from conftest.py
|
- Tests use respx for HTTP mocking and pytest fixtures from conftest.py
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Full test suite
|
||||||
|
just test
|
||||||
|
|
||||||
|
# Specific test file
|
||||||
|
uv run pytest tests/test_db.py -v
|
||||||
|
|
||||||
|
# Test with coverage
|
||||||
|
uv run pytest --cov=tensors --cov-report=term-missing
|
||||||
|
|
||||||
|
# Test API endpoints locally
|
||||||
|
uv run tsr serve --port 8000 &
|
||||||
|
curl http://localhost:8000/status
|
||||||
|
curl -H "X-API-Key: test" http://localhost:8000/api/db/stats
|
||||||
|
```
|
||||||
|
|
||||||
## Release
|
## Release
|
||||||
|
|
||||||
Tags trigger PyPI publish: `git tag v0.1.x && git push origin v0.1.x`. See RELEASE.md for binary builds (Nuitka).
|
Tags trigger PyPI publish: `git tag v0.1.x && git push origin v0.1.x`
|
||||||
|
|
||||||
|
## TODO: ComfyUI Integration
|
||||||
|
|
||||||
|
ComfyUI is running on junkpile (port 8188) but NOT integrated with tensors.
|
||||||
|
|
||||||
|
Needed:
|
||||||
|
- [ ] Add `/api/generate` endpoint that proxies to ComfyUI
|
||||||
|
- [ ] Workflow template management
|
||||||
|
- [ ] Queue job → poll for completion → return image
|
||||||
|
- [ ] Config: `[comfyui] url = "http://127.0.0.1:8188"`
|
||||||
|
|||||||
Reference in New Issue
Block a user