npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

comfyforge

v1.2.0

Published

Generate ComfyUI configs and bake them into deployable Docker images.

Readme

ComfyForge

npm version License: MIT

CLI + web app to build a config.json for the ComfyUI Cloud Docker container and bake it into a Docker image ready to cold-start in seconds on RunPod, Vast.ai, Modal, and other GPU clouds.

Two ways to use it:

| Command | What it does | |---|---| | comfyforge init (default) | Interactive wizard — generates config.json from a workflow + a selection of models and workflows. | | comfyforge fetch <config> | Downloads every model + workflow from a config into a local directory using ComfyUI's layout. Reusable as a bake cache or as a sync target for a local ComfyUI install. | | comfyforge cache status <dir> | Inspects a local assets cache: sizes by category, .partial files, optional coverage vs a config. | | comfyforge bake <config> | Takes a config.json (file or URL) and runs docker buildx to create an image with everything pre-installed, with a deterministic tag derived from the config hash. Supports --assets-dir to reuse files from a previous fetch. |

There's also a web app (/web) — same UX, with a workflow dropzone, HuggingFace/Civitai pickers, a live config tree preview, and a "Bake tab" that generates a recipe zip (Dockerfile.bake + .env.example + README) so you can run docker buildx from your own terminal without installing anything.


Install

# Run directly with npx (no install required)
npx comfyforge --help

# Or install globally
npm install -g comfyforge
comfyforge --help

Prerequisite for bake: Docker with BuildKit (any recent Docker).


comfyforge init — generate the config

# Full wizard starting from a workflow
comfyforge init -w path/to/workflow.json

# Just extract nodes from the workflow, no wizard
comfyforge init -w workflow.json --no-interactive -o config.json

# Pure wizard (no workflow)
comfyforge init

The wizard:

  1. Shows the custom node repos extracted from the workflow for you to confirm/uncheck.
  2. Lets you add models by URL (HuggingFace, Civitai, direct link) with category and filename.
  3. Optionally adds workflows to be downloaded at boot.

Node mapping

  • If the node has properties.aux_id (format owner/repo) → uses it directly.
  • Otherwise, matches by pattern in the type (e.g. (rgthree)rgthree/rgthree-comfy).
  • ComfyUI core nodes are ignored.
  • To add new mappings: edit src/nodeMap.ts.

Output

{
  "nodes": [
    "https://github.com/kijai/ComfyUI-KJNodes",
    { "url": "https://github.com/city96/ComfyUI-GGUF", "ref": "v0.4.0" }
  ],
  "models": [
    { "category": "diffusion_models", "url": "https://...", "filename": "model.safetensors" }
  ],
  "workflows": []
}

Drop this into a Gist (or any public URL) and use it as CONFIG_URL at runtime — or pass it as input to bake.


comfyforge fetch — download assets locally

Downloads every models[] + workflows[] entry from a config into a local directory laid out exactly like ComfyUI's /workspace. Two main uses:

  1. Bake cache — prime a folder once, then run bake --assets-dir <folder> as many times as you want; assets already on disk are reused (no re-download inside the build).
  2. Sync a local ComfyUI install — point --out straight at your ComfyUI/ folder; models land in models/<category>/ and workflows land in user/default/workflows/ where the UI picks them up automatically.
# First time: download everything
export HF_TOKEN=...        # only if any model is gated
export CIVITAI_TOKEN=...   # required if config references civitai.com
comfyforge fetch ./my-config.json --out ~/comfy-cache

# Re-run later — only missing files are fetched
comfyforge fetch ./my-config.json --out ~/comfy-cache

# Just check what's present vs missing
comfyforge fetch ./my-config.json --out ~/comfy-cache --status

# Plan only (no downloads)
comfyforge fetch ./my-config.json --out ~/comfy-cache --dry-run

# Parallel downloads (default 1). Good for many small workflows/VAEs/LoRAs.
comfyforge fetch ./my-config.json --out ~/comfy-cache --concurrency 4

Layout produced

<out>/
  models/
    diffusion_models/<file>      # from { category: "diffusion_models", ... }
    vae/<file>
    loras/<file>
    ...
  user/
    default/
      workflows/<file>           # from workflows[]

Reuse rule

If a file already exists at the target path with the same filename and is non-empty, the fetch skips it — no hash check, no size check. The same rule applies inside bake --assets-dir, so the two commands stay consistent.

Flags

| Flag | What it does | |---|---| | -o, --out <path> | Required. Target directory (created if missing). | | --hf-token <v> / --civitai-token <v> | Tokens; also accepts HF_TOKEN / CIVITAI_TOKEN from env. | | -c, --concurrency <n> | Number of files to download in parallel (default 1). Larger values help when many small files dominate; large single files still bottleneck on the server. | | --dry-run | List what would be downloaded without fetching. | | --status | Print which items are present/missing in <out> and exit. | | --no-interactive | No prompts (CI). |

URL handling

The fetcher auto-rewrites two common URL mistakes so downloads succeed:

  • huggingface.co/.../blob/<ref>/....../resolve/<ref>/...
  • github.com/<user>/<repo>/blob/<ref>/<path>raw.githubusercontent.com/<user>/<repo>/<ref>/<path>

For model URLs, the fetcher also checks the response Content-Type and aborts with a clear error if the server returns HTML (typical sign of a webpage URL, an expired link, or a missing auth token).


comfyforge cache status — inspect a local cache

# What's in this cache directory?
comfyforge cache status ~/comfy-cache

# Cross-reference against a config: which assets are present, which are missing?
comfyforge cache status ~/comfy-cache --config ./my-config.json

Output includes:

  • File counts and total size per model category (diffusion_models, vae, loras, etc.)
  • Workflows count + size
  • A list of .partial files (interrupted downloads occupying disk space)
  • With --config: coverage percentage and the exact list of missing assets, matching what bake --assets-dir --strict would require.

comfyforge bake — bake the image

Takes the config.json, generates a Dockerfile.bake that inherits from the official base image (tcpassos/comfyui-cloud:latest), pre-downloads every node/model/workflow listed in the config inside the image, and runs docker buildx build --push (or --load with --no-push).

The tag is deterministic: cfg-<sha12>[-<name>]. Identical configs always produce the same tag → rebuilds are free.

Examples

# Bake + push to GHCR
comfyforge bake ./my-config.json \
  --image ghcr.io/your-user/comfy-flux \
  --name flux-dev

# Local bake (no push)
comfyforge bake ./my-config.json \
  --image docker.io/your-user/comfy-flux \
  --no-push

# Dry-run — only generates the Dockerfile.bake and prints the docker command, without running it
comfyforge bake ./my-config.json \
  --image ghcr.io/your-user/comfy-flux --dry-run --keep

# Bake from a URL (Gist, raw GitHub, etc.)
comfyforge bake https://gist.githubusercontent.com/.../config.json \
  --image ghcr.io/your-user/comfy-flux

# Reuse a local cache populated by `comfyforge fetch`
# (models/workflows already in the cache are NOT re-downloaded during the build)
comfyforge fetch ./my-config.json --out ~/comfy-cache
comfyforge bake  ./my-config.json --image ghcr.io/your-user/comfy-flux \
  --assets-dir ~/comfy-cache

# Strict mode — fail if anything is missing from the cache, no network fetches
comfyforge bake ./my-config.json --image ghcr.io/your-user/comfy-flux \
  --assets-dir ~/comfy-cache --strict

--keep preserves the temp directory with the generated recipe (useful for inspecting/customizing before running manually).

Flags

| Flag | What it does | |---|---| | -i, --image <repo> | Full repo without tag, e.g. ghcr.io/user/comfy-flux. | | -r, --registry <ghcr\|dockerhub\|custom> + -u, --user + --repo | Alternative to --image. | | -n, --name <name> | Friendly name (becomes the tag suffix and an image label). | | -b, --base <image> | Base image (default tcpassos/comfyui-cloud:latest). | | --no-push | Loads into local Docker instead of pushing. | | --dry-run | Only generates files and prints the command, without calling docker. | | --keep | Don't delete the recipe directory at the end. | | --hf-token <v> / --civitai-token <v> | Tokens; also accepts HF_TOKEN / CIVITAI_TOKEN from env. | | --no-interactive | No prompts (CI). | | --assets-dir <path> | Reuse pre-downloaded models/workflows from a local cache (typically created by comfyforge fetch). Files already present in the cache are copied into the image — the build only fetches what's missing. | | --strict | With --assets-dir, fail before invoking docker if any required asset is missing from the cache. No network downloads happen. Useful for air-gapped / reproducible builds. |

Secrets detection

When loading the config, bake detects:

  • URLs in huggingface.co/... → warns that gated repos require HF_TOKEN.
  • URLs in civitai.com/... → Civitai always requires CIVITAI_TOKEN.

In TTY (default), it only asks for the relevant tokens. In CI mode, it prints !! warnings before the build.

Tokens are passed via BuildKit secrets (--mount=type=secret), never copied into image layers.

Registry authentication

The CLI does not run docker login automatically — it assumes you're already logged in:

# GHCR
echo $GHCR_PAT | docker login ghcr.io -u <user> --password-stdin

# Docker Hub
docker login docker.io

Web app (/web)

cd web
npm install
npm run dev          # http://localhost:5173

Same feature set as the CLI:

  • Workflow dropzone → node extraction.
  • HuggingFace pickers (with auto-resolved filenames) and Civitai (with version selector).
  • Live config tree + volume estimate.
  • Bake tab: generates a "recipe zip" (Dockerfile.bake + bake.sh + .env.example + README) so you can run it locally without installing the CLI — or copies a one-liner npx comfyforge bake ... command if you'd rather use the CLI.

Extra features that need the backend (/api) running:

  • GitHub login — sign in to save private/public configs.
  • My library — personal collection of saved configs, with edit (name, description, tags, visibility).
  • Public gallery (/gallery) — search/filter community-shared configs by tag.
  • Permalinks (/u/:login/:slug) — every public/unlisted config gets a stable deploy-ready URL like https://api.comfyforge.app/c/u/<login>/<slug>.json that you can plug directly into CONFIG_URL on RunPod/Vast/Modal.

The web app and the CLI share the same deterministic hash algorithm (web/src/lib/configHash.ts and src/lib/configHash.ts) and the same Dockerfile templates, so the same config produces exactly the same tag through either path.


Backend (/api)

Optional Express + SQLite service that powers anonymous config sharing, GitHub-authenticated personal library, and the public gallery. The web app works without the backend (CLI-style features stay local); the backend only unlocks login/library/gallery.

Run locally

cd api
npm install
cp .env.example .env       # then edit (see below)
npm run dev                # http://localhost:3000 (tsx watch)

You should see:

comfyforge-api listening on :3000
  DATA_DIR        = ./data
  PUBLIC_BASE_URL = http://localhost:3000/c
  auth            = enabled

.env for local dev

PORT=3000
DATA_DIR=./data
PUBLIC_BASE_URL=http://localhost:3000/c
ALLOWED_ORIGIN=http://localhost:5173
FRONTEND_URL=http://localhost:5173
PUBLIC_API_URL=http://localhost:3000

# GitHub OAuth — optional. Without these, /me returns null
# and library/gallery write endpoints return 401, but the API still runs.
GITHUB_CLIENT_ID=
GITHUB_CLIENT_SECRET=
# COOKIE_DOMAIN=.comfyforge.app   # only in prod

| Var | Purpose | |---|---| | DATA_DIR | Folder where SQLite files live (auth.sqlite, library.sqlite, resolve-cache.sqlite, plus *.json configs). Use ./data in dev, a mounted volume in prod. | | PUBLIC_BASE_URL | Base URL printed back to clients when they upload an anonymous config. | | ALLOWED_ORIGIN | Must match the frontend origin exactly for CORS + cookies to work. Use * only if you don't need credentials. | | FRONTEND_URL / PUBLIC_API_URL | Used by the OAuth callback to know where to redirect and what redirect_uri to register with GitHub. | | GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRET | From a GitHub OAuth App. Callback URL must be ${PUBLIC_API_URL}/auth/github/callback. | | ADMIN_TOKEN | Optional bearer token for /resolve/misses admin endpoint. |

Setting up GitHub OAuth (for local login)

  1. https://github.com/settings/developers → New OAuth App
  2. Homepage URL: http://localhost:5173
  3. Authorization callback URL: http://localhost:3000/auth/github/callback
  4. Paste the Client ID + a generated Client Secret into api/.env.

Endpoints

| Method | Path | Auth | Purpose | |---|---|---|---| | GET | /me | optional | Current user or { user: null }. | | GET | /auth/github | — | Starts GitHub OAuth (sets cf_sess httpOnly cookie on callback). | | GET | /auth/github/callback | — | OAuth callback (do not call directly). | | POST | /auth/logout | required | Clears the session. | | GET | /library | required | List your saved configs. | | POST | /library | required | Save a new config ({ name, description?, visibility, tags?, payload }). | | GET | /library/:id | required (owner) | Get full config including payload. | | PATCH | /library/:id | required (owner) | Update metadata (name, description, visibility, tags). | | DELETE | /library/:id | required (owner) | Delete. | | GET | /gallery?q=&tag=&sort=recent\|popular&limit=&offset= | — | Public gallery listing. | | GET | /c/u/:login/:slug.json | — | Raw config payload (deploy URL — plug into CONFIG_URL). Increments view count. | | GET | /c/u/:login/:slug | — | Public metadata for the permalink page. | | POST | /configs | — | Anonymous one-shot upload (legacy flow, used by the CLI/web for ephemeral sharing). | | GET | /c/:filename | — | Fetch an anonymous config (legacy). | | GET | /resolve?repo=&filename= | — | Resolve HuggingFace filename patterns (cached). |

Production deploy (Railway)

The api/railway.toml is set up for Railway. Required in prod:

  • Mounted volume on DATA_DIR so the SQLite files survive deploys.
  • ALLOWED_ORIGIN=https://comfyforge.app (or your frontend domain).
  • COOKIE_DOMAIN=.comfyforge.app so the session cookie spans subdomains.
  • NODE_ENV=production so cookies go out with Secure.

How cold-start works

The base image tcpassos/comfyui-cloud:latest (source in comfyui-docker) supports two modes:

  1. Runtime: container boots, reads CONFIG_URL, downloads nodes/models on boot. Slow cold-start, zero pre-build.
  2. Baked: the CLI/web runs comfy-provision inside the build, pre-installing everything into /opt/preinstalled. At boot the entrypoint just does a quick merge. Cold-start in seconds.

The PROVISION_TARGET=/opt/preinstalled flag in Dockerfile.bake is what enables the baked mode.


Repo layout

comfyforge/
├── src/                    # CLI (init + bake)
│   ├── index.ts            # commander setup
│   ├── wizard.ts           # init flow
│   ├── bake.ts             # bake flow
│   └── lib/
│       ├── configHash.ts   # deterministic hash (node:crypto)
│       ├── bakeTemplates.ts
│       └── secretsDetect.ts
├── web/                    # React + Vite
│   └── src/lib/            # same libs, browser version (crypto.subtle)
└── api/                    # Express + SQLite — auth, library, gallery, permalinks
    └── src/                # GitHub OAuth, library CRUD, public gallery, HF resolver

Build from source

git clone https://github.com/tcpassos/comfyforge.git
cd comfyforge
npm install
npm run build              # CLI (tsc → dist/)
cd web && npm run build    # web (tsc + vite)

Roadmap

  • [x] Layer 0 — web app generates a recipe zip for local build
  • [x] Layer 1 — bake CLI that runs docker buildx directly
  • [ ] Layer 2 — "Bake on GitHub Actions" button (generated workflow + dispatch)
  • [ ] Layer 3 — ephemeral build pod on RunPod (direct uploads, no intermediate download)

License

MIT © tcpassos