# comfy-resolve

A CLI dependency manager for [ComfyUI](https://github.com/comfyanonymous/ComfyUI) workflows.

ComfyUI workflow files reference models by filename only — no URLs, no sources. `comfy-resolve` fills that gap: it parses your workflow, hunts down every referenced model on HuggingFace and Civitai, and downloads them to the right folders in your ComfyUI install.

---

## Installation

```bash
pip install comfy-resolve
```

Or with pipx (keeps it isolated, recommended):

```bash
pipx install comfy-resolve
```

**Requires Python 3.10+**

---

## Quick Start

### Resolve a specific workflow

```bash
comfy-resolve resolve my_workflow.json
```

### Pick from your ComfyUI workflows folder

Run with no arguments and `comfy-resolve` will scan your ComfyUI install for workflows and let you pick:

```bash
comfy-resolve resolve
```

```
── Select a Workflow ─────────────────────────────────────
  #  Filename                    Size
  1  flux_portrait.json         12.4 KB
  2  sdxl_upscale.json           8.1 KB
  3  ltx2_inpaint.json         142.5 KB

Found 3 workflow(s) in C:\ComfyUI\user\default\workflows

Enter a number, a file path, or blank to abort.
Workflow:
```

### First run

The first time you run any command, you'll be asked for your ComfyUI installation path. Everything else is inferred automatically:

```
Welcome to comfy-resolve!
ComfyUI installation directory: C:/programs/ComfyUI
✓ Config written to ~/.config/comfy-resolve/config.toml
```

---

## How it works

### Resolution pipeline

For each asset in the workflow, `comfy-resolve` tries these steps in order, stopping at the first hit:

1. **Local filesystem** — scans your ComfyUI model directories for exact or fuzzy matches
2. **Cache** — previously confirmed resolutions are reused
3. **Config mappings** — static overrides you define in the config file
4. **HuggingFace** — queries the HF Hub API
5. **Civitai** — queries the Civitai API (public search, no token needed to find; token needed to download)
6. **Heuristic match** — fuzzy filename normalisation as a last resort

### Confidence levels

| Level | Meaning |
|-------|---------|
| ✓ HIGH | Exact filename match from local filesystem, cache, or known repo |
| ? MEDIUM | Fuzzy match above ~80% similarity |
| ! LOW | Heuristic guess — probably right, worth reviewing |
| ✗ UNKNOWN | No match found |

### Interactive review

After resolution, every asset is shown in a numbered table sorted worst-first. You can jump to any row by number — including HIGH confidence ones — to edit the source, change the download destination, or skip it entirely:

```
── Asset Resolution Review ──────────────────────────────────────────
 #  Asset                          Type    Source              Conf
 1  missing_model.safetensors      loras   UNRESOLVED          ✗ UNKNOWN
 2  some_lora_v1.safetensors       loras   Civitai: civ:12345  ! LOW
 3  clip_l.safetensors             text    HuggingFace: ...    ✓ HIGH
...

<number> edit  •  accept proceed as-is  •  skip all unknown/low  •  quit
```

### Pre-download review

Before any file is written to disk you get a final review with destinations shown, bulk actions, and per-asset overrides:

```
── Pre-Download Review ──────────────────────────────────────────────
 #  Asset                   Source                  Size    Dest        Action
 1  clip_l.safetensors      HuggingFace: comfy/...  246 MB  .../text_e  download
 2  my_lora.safetensors     Civitai: civ:99999      384 MB  .../loras   download
 3  local_model.safetensors Local: .../checkpoints  6.9 GB  —           already local

go  •  <number> edit  •  all bulk action  •  quit
```

---

## API keys

`comfy-resolve` works without any API keys for most public models. Keys unlock additional access:

| Key | Where to get it | What it unlocks |
|-----|----------------|-----------------|
| HuggingFace | [huggingface.co/settings/tokens](https://huggingface.co/settings/tokens) | Gated / private models |
| Civitai | [civitai.com/user/account](https://civitai.com/user/account) | Downloading from Civitai (searching is free) |

Set via environment variable (recommended):

```bash
# Linux / Mac
export COMFY_HF_TOKEN="hf_..."
export COMFY_CIVITAI_TOKEN="..."

# Windows PowerShell
$env:COMFY_HF_TOKEN="hf_..."
$env:COMFY_CIVITAI_TOKEN="..."
```

Or directly in the config file:

```toml
[api_keys]
huggingface = "hf_..."
civitai = "..."
```

---

## Configuration

**Location:**
- Linux / Mac: `~/.config/comfy-resolve/config.toml`
- Windows: `C:\Users\<you>\.config\comfy-resolve\config.toml`

```toml
comfyui_dir = "C:/programs/ComfyUI"

# Model paths are inferred from comfyui_dir automatically.
# Uncomment any line to override a specific path:
# [paths]
# checkpoints   = "D:/models/checkpoints"
# loras         = "D:/models/loras"
# vae           = "D:/models/vae"
# text_encoders = "D:/models/text_encoders"
# unet          = "D:/models/unet"

[api_keys]
huggingface = ""
civitai = ""

[download]
concurrent = 2      # parallel downloads
max_retries = 3

[resolution]
preferred_source = "huggingface"    # "huggingface" | "civitai" | "any"
auto_confidence_threshold = "high"  # used with --auto
```

---

## Commands

### `resolve`

```bash
comfy-resolve resolve [WORKFLOW] [OPTIONS]
```

| Option | Description |
|--------|-------------|
| `--auto` | Skip interactive prompts; use HIGH confidence resolutions only |
| `--auto-all` | Skip prompts; use all resolutions regardless of confidence |
| `--dry-run` | Show what would be downloaded without downloading anything |
| `--no-cache` | Ignore cached mappings and re-resolve everything fresh |
| `--download-dir PATH` | Override destination directory for all asset types |
| `--concurrent N` | Number of parallel downloads (1–16) |
| `--verbose` / `-v` | Show debug logs |

### `cache-list`

```bash
comfy-resolve cache-list
```

Show all cached asset→source mappings.

### `cache-clear`

```bash
comfy-resolve cache-clear [NAME]
```

Remove a specific cached mapping by filename, or all mappings if no name is given.

### `config-show`

```bash
comfy-resolve config-show
```

Print the active config with API keys redacted.

### `config-init`

```bash
comfy-resolve config-init
```

Re-run the first-time setup wizard.

---

## Supported asset types

| Type | Folder | Extensions |
|------|--------|------------|
| Checkpoints | `models/checkpoints` | `.safetensors`, `.ckpt` |
| LoRAs | `models/loras` | `.safetensors`, `.pt` |
| VAE | `models/vae` | `.safetensors`, `.pt` |
| Text encoders / CLIP | `models/text_encoders` | `.safetensors`, `.gguf` |
| UNet / diffusion models | `models/unet` | `.safetensors`, `.gguf` |
| ControlNet | `models/controlnet` | `.safetensors`, `.pth` |
| Upscale models | `models/upscale_models` | `.pth`, `.pt` |
| Embeddings | `models/embeddings` | `.pt`, `.bin` |
| IP-Adapter | `models/ipadapter` | `.safetensors`, `.bin` |
| GGUF quantized models | `models/unet` or `models/text_encoders` | `.gguf` |

GGUF routing is automatic: diffusion model GGUFs go to `unet`, text encoder GGUFs (T5, CLIP, Gemma, LLaMA, Qwen VL) go to `text_encoders`.

---

## Download features

- **Concurrent downloads** — configurable parallel transfers
- **Resume support** — picks up where it left off after interruption (Ctrl+C cleans up partial files)
- **Integrity verification** — SHA-256 checked when available; mismatches warn but never silently delete
- **Disk space check** — warns before starting if space is tight
- **Smart skipping** — files already present locally are never re-downloaded

---

## Troubleshooting

**"Gated model / access denied"**
Visit the model page on HuggingFace and request access, then retry.

**"Civitai token required to download"**
Searching Civitai is free, but downloading requires a token. Set `COMFY_CIVITAI_TOKEN` or add it to the config.

**SHA-256 mismatch warning**
The downloaded file's hash doesn't match what was expected — usually because the repo updated the file without renaming it. The file is kept (not deleted). Run `comfy-resolve cache-clear model.safetensors` then re-resolve with `--no-cache` if you want to try again.

**Downloads are slow**
```bash
comfy-resolve resolve workflow.json --concurrent 4
```

**Wrong model folder**
Override per-session with `--download-dir`, or set permanent path overrides in the `[paths]` section of the config.

---

## Development

```bash
git clone https://github.com/YOUR_USERNAME/comfy-resolve.git
cd comfy-resolve
python -m venv .venv
.venv\Scripts\activate      # Windows
source .venv/bin/activate   # Linux / Mac
pip install -e .

# Run tests
pytest tests/ -v

# Type check
mypy comfy_resolve/

# Lint
ruff check comfy_resolve/
```

---

## License

MIT — see [LICENSE](LICENSE) for details.

## Contributing

Issues and PRs welcome. The most useful contributions right now are additional node type mappings for custom node packs — if you find a node whose assets resolve to the wrong folder, open an issue with the node name and expected folder.

## Acknowledgements

Built for the [ComfyUI](https://github.com/comfyanonymous/ComfyUI) community.
Uses the [HuggingFace Hub](https://huggingface.co) and [Civitai](https://civitai.com) APIs.