Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
989067d
fix(workflow): write property_download_intent models to pyproject.toml
akatz-ai Jan 23, 2026
1e34d36
feat(extension): add workflow load hooks to intercept missing resources
akatz-ai Jan 23, 2026
07c4cde
test: add failing tests for analyze-json endpoint (cgm-z5o.1)
akatz-ai Jan 23, 2026
e5f25b8
feat(api): add /v2/comfygit/workflow/analyze-json endpoint (cgm-z5o.1)
akatz-ai Jan 23, 2026
9e36228
fix: move inline imports to module level for analyze-json endpoint
akatz-ai Jan 23, 2026
91545d2
Merge: extension-track
akatz-ai Jan 23, 2026
850f41a
style: fix line length in analyze-json endpoint
akatz-ai Jan 23, 2026
803c4db
fix: use temp file for analyze-json endpoint (core lib doesn't suppor…
akatz-ai Jan 23, 2026
ab64b79
feat(ui): add MissingResourcesPopup component for workflow load inter…
akatz-ai Jan 23, 2026
893697a
fix: add defensive checks for missing analysis properties
akatz-ai Jan 23, 2026
af56b47
feat(ui): wire up missing resources flow with event-based architecture
akatz-ai Jan 23, 2026
bde7415
fix: remove unused currentWorkflow variable in MissingResourcesPopup
akatz-ai Jan 23, 2026
2c9b85a
fix: suppress ComfyUI built-in missing nodes/models popups
akatz-ai Jan 23, 2026
bf038bb
feat(ui): add actionable install/download buttons to MissingResources…
akatz-ai Jan 23, 2026
4bd5c38
feat(ui): add restart notification after node installation
akatz-ai Jan 23, 2026
0a9a612
fix(ui): improve MissingResourcesPopup visibility and dismiss behavior
akatz-ai Jan 23, 2026
3450097
fix(api): normalize match_confidence scores in search-nodes endpoint
akatz-ai Jan 24, 2026
4e55541
feat(ui): add auto-advance after resolution selection
akatz-ai Jan 24, 2026
808fcb5
fix: add missing auto-advance to submitManualEntry
akatz-ai Jan 24, 2026
5204a77
Merge: frontend-track
akatz-ai Jan 24, 2026
035bcff
fix: use editable comfygit-core install for development
akatz-ai Jan 24, 2026
ec731ce
feat(popup): route node installs through Manager queue API
akatz-ai Jan 24, 2026
ad0598a
fix(popup): pass repository and version to Manager queue API
akatz-ai Jan 24, 2026
074ea18
fix: use fallback UUID generator for non-secure contexts
akatz-ai Jan 24, 2026
81b5059
feat(popup): simplify missing dependencies popup to global setting
akatz-ai Jan 26, 2026
bca30d7
test: add failing tests for is-saved workflow detection endpoint
akatz-ai Jan 27, 2026
f8361b0
feat: add is-saved workflow detection endpoint and frontend integration
akatz-ai Jan 27, 2026
6b34d21
fix: self-review corrections for is-saved-detection
akatz-ai Jan 27, 2026
6f6a21f
fix(test): add missing mock attributes for package_data in workflow t…
akatz-ai Jan 27, 2026
7e85700
feat(popup): add session-based suppression by workflow ID
akatz-ai Jan 27, 2026
896e268
fix(popup): add workflow ID to suppression set when is-saved check pa…
akatz-ai Jan 27, 2026
5d390ca
feat: add HuggingFace URL parser utility and types
akatz-ai Jan 28, 2026
fd58291
test: add failing tests for HuggingFace endpoints (cgm-0qc)
akatz-ai Jan 28, 2026
b4cf764
feat: add HuggingFace repo-info and subdirectories endpoints (cgm-0qc)
akatz-ai Jan 28, 2026
5a45c32
Merge: backend-track
akatz-ai Jan 28, 2026
cab3e3b
fix(test): correct mock kind values in HuggingFace endpoint tests
akatz-ai Jan 28, 2026
952329f
feat: add HuggingFace service methods to useComfyGitService (cgm-huc)
akatz-ai Jan 28, 2026
bea7a5b
feat: add HuggingFaceRepoModal.vue component (cgm-ft3)
akatz-ai Jan 28, 2026
c3dacd0
fix: set loading=false on invalid URL early return
akatz-ai Jan 28, 2026
493ce99
feat: wire HuggingFace detection into ModelIndexSection download moda…
akatz-ai Jan 28, 2026
75467b8
feat: add CivitaiTab placeholder component (cgm-e11)
akatz-ai Jan 28, 2026
ac21264
test: add failing tests for HuggingFace search endpoint
akatz-ai Jan 28, 2026
509f370
feat: add DirectUrlTab component for unified modal (cgm-ryx)
akatz-ai Jan 28, 2026
39dd374
feat: add HuggingFace search endpoint
akatz-ai Jan 28, 2026
970b7d5
fix: add validation for limit parameter in HuggingFace search
akatz-ai Jan 28, 2026
92ab43b
feat(frontend): add HuggingFace search types and service method
akatz-ai Jan 28, 2026
64be12b
Merge: types-track
akatz-ai Jan 28, 2026
f2004b0
Merge: direct-tab-track
akatz-ai Jan 28, 2026
93599f9
Merge: civitai-tab-track
akatz-ai Jan 28, 2026
1ee4173
feat(frontend): add HfFileBrowser component for HuggingFace file brow…
akatz-ai Jan 28, 2026
d7a28c4
feat(frontend): add HuggingFaceTab component for search and browse or…
akatz-ai Jan 28, 2026
c972679
feat(frontend): add ModelDownloadModal unified modal shell
akatz-ai Jan 28, 2026
972559e
test: add failing tests for ModelDownloadModal integration in ModelIn…
akatz-ai Jan 28, 2026
9657d1b
feat: integrate ModelDownloadModal in ModelIndexSection
akatz-ai Jan 28, 2026
ae57429
build: rebuild frontend with ModelDownloadModal integration
akatz-ai Jan 28, 2026
58e32d1
cleanup: delete unused HuggingFaceRepoModal component
akatz-ai Jan 28, 2026
8e98ed2
chore: delete unused HuggingFaceRepoModal component
akatz-ai Jan 28, 2026
b48e128
Merge: sprint integration
akatz-ai Jan 28, 2026
be17103
fix: audit fixes for unified download modal
akatz-ai Jan 28, 2026
0e11c77
chore: gitignore playwright test artifacts
akatz-ai Jan 28, 2026
356602e
chore: add dev tooling and documentation
akatz-ai Jan 28, 2026
55f35f0
chore: bump version to 0.0.17
akatz-ai Jan 28, 2026
523a016
feat: add Show All modal for missing resources
akatz-ai Jan 28, 2026
5a9a926
refactor(popup): improve Show All UX with inline clickable row
akatz-ai Jan 28, 2026
27bcb1f
fix(server): add missing fields to Manager queue WebSocket events
akatz-ai Jan 28, 2026
8a20fa5
chore: update uv.lock with corrected paths and dependencies
akatz-ai Jan 28, 2026
38d3630
fix(popup): fix WebSocket event listeners not receiving install compl…
akatz-ai Jan 28, 2026
a51ff73
feat(ui): improve download modal UX and add custom dropdown component
akatz-ai Jan 29, 2026
ccf162f
feat(ui): add BranchDetailModal for improved branch management UX
akatz-ai Jan 29, 2026
ff15649
feat(ui): add download button to env models + remember panel view
akatz-ai Jan 29, 2026
bd07243
feat(ui): auto-detect download destination from HF file paths
akatz-ai Jan 29, 2026
ce32f2c
fix(ui): fix race condition in download destination auto-detect
akatz-ai Jan 29, 2026
6f4482d
feat(ui): add configurable keyboard shortcuts for panel and commit
akatz-ai Jan 29, 2026
b1c38f6
docs: add keyboard shortcuts to README
akatz-ai Jan 29, 2026
73250c4
test: add failing tests for HF token masking and config API
akatz-ai Jan 29, 2026
8329219
feat: add HF token support to config API with security masking
akatz-ai Jan 29, 2026
3be32f7
fix: add debug logging to import preview endpoint
akatz-ai Jan 30, 2026
48660c0
feat(ui): add HuggingFace token input to workspace settings
akatz-ai Jan 30, 2026
fd3240d
feat(ui): create TokenConfigModal component for inline token management
akatz-ai Jan 30, 2026
1b301c2
feat(ui): integrate TokenConfigModal into HuggingFaceTab
akatz-ai Jan 30, 2026
65ce0e8
fix: prevent null reference error in isAuthError computed
akatz-ai Jan 30, 2026
aa007df
build: rebuild frontend after HF integration merge
akatz-ai Jan 30, 2026
956da88
fix: use client-side ID polling to detect saved workflows in popup
akatz-ai Jan 30, 2026
843c81d
test: add failing tests for crash-retry
akatz-ai Jan 30, 2026
99cbf27
feat: add general crash retry with delay to orchestrator
akatz-ai Jan 30, 2026
da934a7
test: add failing tests for environment detail endpoint
akatz-ai Jan 30, 2026
04f7c16
feat: add per-environment detail API endpoint
akatz-ai Jan 30, 2026
6f5cee6
feat: add collapsible workflow/node/model lists to environment detail…
akatz-ai Jan 30, 2026
610bc51
Merge: frontend-track
akatz-ai Jan 30, 2026
2876ba7
fix: use detail endpoint counts in environment details modal
akatz-ai Jan 30, 2026
1cb8c00
feat: show environment creation date in details modal
akatz-ai Jan 30, 2026
179150a
fix: reset panel tab to status on browser refresh
akatz-ai Jan 30, 2026
c320409
test: add failing tests for backend-commits push preview
akatz-ai Jan 30, 2026
4cb0b1b
fix: replace Unicode info icon with inline SVG in PushModal
akatz-ai Jan 30, 2026
3a32f31
fix: populate outgoing commits in push preview endpoint
akatz-ai Jan 30, 2026
64a41c1
Merge: backend-commits-track
akatz-ai Jan 30, 2026
72beccc
test: add failing tests for pull-commits-track
akatz-ai Jan 30, 2026
5282689
feat: populate incoming commits in pull preview endpoint
akatz-ai Jan 30, 2026
33f1d56
fix: remove editable comfygit-core source from pyproject.toml
akatz-ai Feb 2, 2026
6cdaf1b
chore: bump comfygit-core dependency to 0.3.14
akatz-ai Feb 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .claude/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# MEOW-generated hooks - do not commit
settings.json
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ logs/
.coverage
htmlcov/
tests/output/
playwright-report/
test-results/

# Frontend (Node.js/Vue)
frontend/node_modules/
Expand All @@ -75,3 +77,4 @@ web/.meow/
.browserflow/
node_modules/
packages/
legacy/
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,15 @@ New to ComfyGit? The setup wizard guides you through creating your first workspa

<img width="1596" height="965" alt="Screenshot 2025-12-08 185458" src="https://github.com/user-attachments/assets/b46e00d6-e13c-4320-b4cc-a1d575e4f0f9" />

### Keyboard Shortcuts

| Shortcut | Action |
|----------|--------|
| `Alt+Shift+L` | Open ComfyGit Panel |
| `Alt+Shift+K` | Quick Commit |

Customize these in ComfyUI's **Settings → Keyboard Shortcuts**.

---

## Getting Started
Expand Down
360 changes: 360 additions & 0 deletions docs/huggingface-hub-guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,360 @@
# HuggingFace Hub Python Library - Quick Reference

Concise guide for finding, downloading, and authenticating with HuggingFace Hub.

## Installation

```bash
pip install huggingface_hub
# or
uv add huggingface_hub
```

## Authentication

### Methods (choose one)

```python
# 1. Environment variable (recommended for scripts)
# Set HF_TOKEN=hf_xxx in environment

# 2. Login once (persists token to ~/.cache/huggingface/token)
from huggingface_hub import login
login(token="hf_xxx") # or login() for interactive prompt

# 3. Pass token directly to functions
hf_hub_download(..., token="hf_xxx")

# 4. HfApi client with token
from huggingface_hub import HfApi
api = HfApi(token="hf_xxx")
```

### Token precedence
1. Explicit `token=` parameter
2. `HF_TOKEN` environment variable
3. Stored token at `~/.cache/huggingface/token`

### Other auth functions
```python
from huggingface_hub import logout, auth_switch, auth_list
logout() # Remove stored token
auth_list() # List stored tokens
auth_switch("token_name") # Switch between tokens
```

## Finding Models

### List models with filters

```python
from huggingface_hub import list_models, HfApi

# Basic listing
models = list_models()

# With filters
models = list_models(
filter="text-generation", # Task/tag filter
author="meta-llama", # Filter by author
search="llama", # Search in name
library_name="transformers", # Filter by library
pipeline_tag="text-generation", # Filter by pipeline
sort="downloads", # Sort: downloads, likes, trending_score, created_at
limit=10, # Max results
token="hf_xxx", # For private models
)

# Iterate results
for model in models:
print(f"{model.id}: {model.downloads} downloads")
```

### Get model info

```python
from huggingface_hub import model_info

info = model_info("meta-llama/Llama-2-7b", token="hf_xxx")
print(info.id, info.sha, info.downloads, info.pipeline_tag)
print(info.siblings) # List of files in repo
```

### Check if model/file exists

```python
from huggingface_hub import repo_exists, file_exists

repo_exists("meta-llama/Llama-2-7b") # True/False
file_exists("meta-llama/Llama-2-7b", "config.json") # True/False
```

### List files in repo

```python
from huggingface_hub import list_repo_files

files = list_repo_files("meta-llama/Llama-2-7b", token="hf_xxx")
```

## Downloading

### Download single file

```python
from huggingface_hub import hf_hub_download

# To cache (default: ~/.cache/huggingface/hub)
path = hf_hub_download(
repo_id="meta-llama/Llama-2-7b",
filename="config.json",
token="hf_xxx",
)

# To specific folder (replicates repo structure)
path = hf_hub_download(
repo_id="meta-llama/Llama-2-7b",
filename="config.json",
local_dir="/path/to/models/llama2", # Key param!
token="hf_xxx",
)

# File in subfolder
path = hf_hub_download(
repo_id="stabilityai/stable-diffusion-xl-base-1.0",
filename="model_index.json",
subfolder="scheduler",
local_dir="/models/sdxl",
)

# Specific revision (branch, tag, or commit hash)
path = hf_hub_download(
repo_id="meta-llama/Llama-2-7b",
filename="config.json",
revision="main", # or "v1.0" or commit hash
)

# Force re-download
path = hf_hub_download(..., force_download=True)

# Use only cached files (offline mode)
path = hf_hub_download(..., local_files_only=True)
```

### Download entire repo (snapshot)

```python
from huggingface_hub import snapshot_download

# To cache
path = snapshot_download(
repo_id="meta-llama/Llama-2-7b",
token="hf_xxx",
)

# To specific folder
path = snapshot_download(
repo_id="meta-llama/Llama-2-7b",
local_dir="/path/to/models/llama2", # Key param!
token="hf_xxx",
)

# Filter files with patterns (glob syntax)
path = snapshot_download(
repo_id="meta-llama/Llama-2-7b",
allow_patterns=["*.safetensors", "*.json"], # Only these
ignore_patterns=["*.bin", "*.h5"], # Skip these
local_dir="/models/llama2",
)

# Download specific revision
path = snapshot_download(
repo_id="meta-llama/Llama-2-7b",
revision="main",
local_dir="/models/llama2",
)

# Parallel downloads (default: 8 workers)
path = snapshot_download(..., max_workers=16)
```

### Dry run (check what would download)

```python
# Single file
info = hf_hub_download(
repo_id="meta-llama/Llama-2-7b",
filename="config.json",
dry_run=True,
)
print(info.file_size, info.is_cached, info.will_download)

# Full repo
infos = snapshot_download(
repo_id="meta-llama/Llama-2-7b",
dry_run=True,
)
for info in infos:
print(f"{info.filename}: {info.file_size} bytes, cached={info.is_cached}")
```

## Download Locations

### Key parameters

| Parameter | Behavior |
|-----------|----------|
| `local_dir` | Download to this folder, replicating repo structure. Creates `.cache/huggingface/` inside for metadata. |
| `cache_dir` | Use this as cache location instead of default. Files stored with content-addressed naming. |
| (neither) | Uses default cache: `~/.cache/huggingface/hub` |

### Environment variables

```bash
HF_HOME=~/.cache/huggingface # Base dir for all HF data
HF_HUB_CACHE=$HF_HOME/hub # Where repos are cached
HF_TOKEN=hf_xxx # Auth token
HF_HUB_OFFLINE=1 # Force offline mode
HF_HUB_DISABLE_PROGRESS_BARS=1 # No progress bars
```

## Repo Types

For datasets or spaces, add `repo_type`:

```python
# Download dataset
snapshot_download(
repo_id="squad",
repo_type="dataset",
local_dir="/data/squad",
)

# Download space
snapshot_download(
repo_id="gradio/hello_world",
repo_type="space",
local_dir="/spaces/hello",
)

# List datasets
list_datasets(filter="text-classification")

# Dataset info
dataset_info("squad")
```

## HfApi Client

For multiple operations, use the client:

```python
from huggingface_hub import HfApi

api = HfApi(token="hf_xxx")

# All methods available
api.list_models(author="meta-llama")
api.model_info("meta-llama/Llama-2-7b")
api.hf_hub_download(...)
api.snapshot_download(...)
api.list_repo_files(...)
api.repo_exists(...)
api.file_exists(...)
api.whoami() # Get current user info
```

## Common Patterns

### Download model to specific folder

```python
from huggingface_hub import snapshot_download
import os

def download_model(repo_id: str, dest_dir: str, token: str = None):
"""Download a model to a specific directory."""
return snapshot_download(
repo_id=repo_id,
local_dir=dest_dir,
token=token or os.getenv("HF_TOKEN"),
allow_patterns=["*.safetensors", "*.json", "*.txt"],
ignore_patterns=["*.bin", "*.h5", "*.ckpt"],
)

# Usage
path = download_model("meta-llama/Llama-2-7b", "/models/llama2")
```

### Check size before downloading

```python
from huggingface_hub import snapshot_download

infos = snapshot_download(
repo_id="meta-llama/Llama-2-7b",
dry_run=True,
allow_patterns=["*.safetensors"],
)
total_size = sum(f.file_size for f in infos if f.will_download)
print(f"Will download: {total_size / 1e9:.2f} GB")
```

### Download with progress callback

```python
from huggingface_hub import snapshot_download
from tqdm import tqdm

class CustomTqdm(tqdm):
def __init__(self, *args, **kwargs):
kwargs.setdefault('unit', 'B')
kwargs.setdefault('unit_scale', True)
super().__init__(*args, **kwargs)

path = snapshot_download(
repo_id="meta-llama/Llama-2-7b",
local_dir="/models/llama2",
tqdm_class=CustomTqdm,
)
```

## Error Handling

```python
from huggingface_hub import hf_hub_download
from huggingface_hub.errors import (
RepositoryNotFoundError,
RevisionNotFoundError,
EntryNotFoundError,
GatedRepoError,
)

try:
path = hf_hub_download("meta-llama/Llama-2-7b", "config.json")
except RepositoryNotFoundError:
print("Repo doesn't exist or is private")
except GatedRepoError:
print("Need to accept license at huggingface.co")
except RevisionNotFoundError:
print("Branch/tag/commit not found")
except EntryNotFoundError:
print("File not found in repo")
```

## Gated Models

Some models require accepting terms on the website first:

1. Go to model page (e.g., https://huggingface.co/meta-llama/Llama-2-7b)
2. Accept the license/terms
3. Download with authenticated token

```python
# After accepting terms on website
path = hf_hub_download(
repo_id="meta-llama/Llama-2-7b",
filename="config.json",
token="hf_xxx", # Required for gated models
)
```
Loading
Loading