Extensions/Majoor Project Settings
ComfyUI Extension

Majoor Project Settings

A custom node extension that adds project management functionality to ComfyUI.

By MajoorWaldi·Created 8 months ago·Updated 2 months ago· 0
MajoorWaldi/ComfyUI-Majoor-ProjectSettings
Nodes
On cloudLocal install
Stars0
Updated2 months ago
Readme

ComfyUI-Majoor-ProjectSettings 🚀

Project-aware outputs + workflow organization for ComfyUI — without adding any ComfyUI nodes.

This extension turns ComfyUI into a lightweight “mini pipeline”: you pick a project, it creates/maintains a clean folder structure under output/, auto-patches save/export nodes (paths + filename prefixes), and lets you save workflows inside the project (optionally mirrored to ComfyUI/workflows/).

Zero new nodes. Maximum order. Your future self will stop cursing your past self. (Maybe.)


Status & empty workflows

  • The Project Settings status bar watches your canvas and turns red when the current graph is empty while prompting you (via dialog) to create or assign a project instead of flooding toasts.
  • Toggle the MajoorPS: Black status when no project setting (in the MajoorPS settings category) if you'd rather keep a neutral indicator while you experiment without an active project.
  • MajoorPS: Legacy Ctrl+S hook is off by default because ComfyUI already owns Ctrl+S via Comfy.SaveWorkflow. Enable it only if you explicitly need the old capture-phase fallback.
  • MajoorPS: Prompt on empty workflow is off by default; the status badge remains passive unless you opt into modal prompts.

Key Features

  • Project management inside ComfyUI (create / select / list).
  • Project Health panel showing active folder, workflow assignment, output target, patchable save nodes, missing-model scan state, and workflow save state.
  • Topbar Project button, registered with the same ComfyUI button component pattern used by ComfyUI-Manager when available.
  • ComfyUI command palette integration for opening the panel, assigning the active project, saving workflows, scanning missing models, and patching save nodes.
  • Standardized folder structure per project under output/PROJECTS/<project>/....
  • Auto-patch “save/export” nodes:
    • sets a safe relative output folder (always under output/)
    • sets a filename prefix (project/asset/model/date driven)
    • supports many custom nodes via configurable “path widget” names.
  • Template-based output paths using tokens ({BASE}, {MEDIA}, {DATE}, {NAME}, {MODEL}, etc.).
  • Project-aware workflow save:
    • saves workflows into the project folder
    • optional mirror into ComfyUI/workflows/ for compatibility.
  • Project signature in workflow (graph.extra.mjr_project) to keep provenance.
  • Empty-graph guard: the status bar turns red when the current graph has no nodes and the extension will prompt you to create or switch to a project, and there is an optional MajoorPS: Black status when no project setting so you can work in a test mode without the warning color.
  • Safe path guardrails: blocks absolute paths, drive paths, .., and other escape attempts.
  • Model Utilities: Fix Missing Models inside the Project Settings panel (no top menu).
  • Model Utilities: Download Missing Models inside the Project Settings panel (recipes + direct URLs).
  • Advanced fingerprint cache (optional) for future hash-based model resolution.

Installation

Option A — Git (recommended)

  1. Go to your ComfyUI folder:
    • ComfyUI/custom_nodes/
  2. Clone:
    git clone https://github.com/MajoorWaldi/ComfyUI-Majoor-ProjectSettings.git
    
  3. Restart ComfyUI.

Option B — ZIP

  1. Unzip into:
    • ComfyUI/custom_nodes/ComfyUI-Majoor-ProjectSettings/
  2. Restart ComfyUI.

✅ The extension exposes a WEB_DIRECTORY (./web/js) and registers API routes on startup.


Frontend Development

The browser extension source is maintained in TypeScript under src/ and compiled to runtime JavaScript under web/js/, because ComfyUI loads custom-node frontend assets through WEB_DIRECTORY = "./web/js".

npm install
npm run build
npm run typecheck
npm run typecheck:strict
npm run test:frontend
  • Edit src/**/*.ts, not the generated web/js/**/*.js files.
  • Keep web/js/ committed so ComfyUI and ComfyUI-Manager can load the extension without a build step.
  • typecheck:strict is intentionally scoped to migrated modules while the large legacy UI is typed progressively.

UI Location

Depending on your ComfyUI version:

  • If sidebar tabs are supported, you’ll see a Project Settings tab.
  • Otherwise, the UI falls back to a floating panel.

The panel is split into Project, Model, and Workflow tabs. Project contains project health, output target creation, and patching options. Model contains model selection, registry search, and missing-model utilities. Workflow contains workflow assignment and project-aware workflow saving.

Recent ComfyUI frontends also get a compact Project button near the menu controls. It uses ComfyUI's ComfyButton / ComfyButtonGroup component pattern, matching ComfyUI-Manager's modern button integration, and falls back to the legacy .comfy-menu button location on older frontends.

ComfyUI Commands

The extension registers ComfyUI commands so recent ComfyUI frontends can expose them in the command palette and topbar menu:

  • MajoorPS: Open Project Settings
  • MajoorPS: Assign workflow to active project
  • MajoorPS: Save workflow to project
  • MajoorPS: Scan missing models
  • MajoorPS: Patch save nodes now

No default Ctrl+S keybinding is registered by this extension, because ComfyUI already uses it for Comfy.SaveWorkflow. The legacy capture-phase browser shortcut is disabled by default and remains available only through the MajoorPS: Legacy Ctrl+S hook setting.

Debugging logs 🐞

  • To enable verbose debug logs in the UI, set window.MJR_DEBUG = true in the browser dev console before interacting with the extension. When enabled, the UI will emit developer messages via console.debug().

Project Structure (Default)

Everything lives under:

output/
└─ PROJECTS/
   ├─ _INDEX/
   │  └─ projects.json
   └─ <PROJECT_FOLDER>/
      ├─ 00_META/
      │  └─ current.json
      ├─ 01_IN/
      │  ├─ REFS/
      │  └─ SOURCES/
      ├─ 02_OUT/
      │  ├─ IMAGES/
      │  ├─ VIDEOS/
      │  └─ OTHER/
      ├─ 03_WORKFLOWS/
      ├─ 04_PRESENTATION/
      └─ 05_DOCS/
  • projects.json stores your project index (last used, archived, etc.)
  • current.json stores the active project on disk (useful for external scripts/tools)

Environment Variables

The extension supports various environment variables for customization:

Security & Access Control

  • MJR_API_KEY: API key for authentication (if not set, only loopback/localhost access is allowed)
  • MJR_INSECURE_NO_AUTH=1: Disable authentication (NOT recommended in production)
  • MJR_DISABLE_CSRF=1: Disable CSRF protection (NOT recommended)
  • MJR_DISABLE_SAME_ORIGIN=1: Disable same-origin checks (NOT recommended)
  • MJR_TRUST_PROXY=1: Trust X-Forwarded-For headers for client IP detection

Download Settings

  • MJR_SKIP_EXISTING_FILES=1: Skip download if file already exists (default: 0 - overwrite mode enabled)
  • MJR_MODEL_DOWNLOAD_TIMEOUT: Download timeout in seconds (default: 300)
  • MJR_MODEL_DOWNLOAD_ALLOW_PRIVATE_IPS=1: Allow downloads from private IP addresses
  • MJR_MODEL_DOWNLOAD_ALLOWED_HOSTS: Comma-separated list of allowed download hosts

Rate Limiting & Performance

  • MJR_RATE_LIMIT_PER_MIN: Rate limit per minute per endpoint (default: 120)
  • MJR_JOB_CLEANUP_HOURS: Hours before cleaning up old download jobs (default: 1)

Example Configuration (Windows PowerShell)

# Enable overwrite mode for downloads (default behavior)
$env:MJR_SKIP_EXISTING_FILES="0"

# Or enable skip mode if you want to avoid re-downloading
$env:MJR_SKIP_EXISTING_FILES="1"

# Set custom download timeout (5 minutes)
$env:MJR_MODEL_DOWNLOAD_TIMEOUT="300"

Example Configuration (Linux/Mac)

# Enable overwrite mode for downloads (default behavior)
export MJR_SKIP_EXISTING_FILES=0

# Or enable skip mode if you want to avoid re-downloading
export MJR_SKIP_EXISTING_FILES=1

# Set custom download timeout (5 minutes)
export MJR_MODEL_DOWNLOAD_TIMEOUT=300

Note on file overwriting: By default (MJR_SKIP_EXISTING_FILES=0), the extension will overwrite existing model files when downloading. This ensures you always get the latest version and prevents issues with corrupted/incomplete downloads. Set MJR_SKIP_EXISTING_FILES=1 if you want to skip downloads when the file already exists.


Configuration: project_structure.json

You can customize the project directories and role mappings:

{
  "dirs": [
    "00_META",
    "01_IN/REFS",
    "01_IN/SOURCES",
    "02_OUT/IMAGES",
    "02_OUT/VIDEOS",
    "02_OUT/OTHER",
    "03_WORKFLOWS",
    "04_PRESENTATION",
    "05_DOCS"
  ],
  "roles": {
    "images": "02_OUT/IMAGES",
    "videos": "02_OUT/VIDEOS",
    "other": "02_OUT/OTHER",
    "workflows": "03_WORKFLOWS"
  }
}
  • dirs: physically created directories
  • roles: logical aliases used by the extension

Output Templates (Path Resolver)

The extension generates relative output paths (always safe under output/) using templates.

Common Tokens

Typical server/UI token set:

  • {BASE}: PROJECTS/<project_folder>
  • {MEDIA}: media subdir (e.g. 02_OUT/IMAGES)
  • {DATE}: YYMMDD (e.g. 251222)
  • {NAME}: normalized asset/shot name
  • {KIND}: kind label (asset/shot/etc., normalized)
  • {MODEL}: normalized model label (optionally uppercased from UI)

Example Template

{BASE}/{MEDIA}/{DATE}/{NAME}/{MODEL}

Example resolved output:

PROJECTS/MY_PROJECT/02_OUT/IMAGES/251222/AdrianCloseUp/FLUX_DEV

Node Patching (Save/Export Nodes)

The extension scans the current graph and patches “save-like” nodes:

  • detection: node type contains patterns like save, export, combine (implementation-specific)
  • patch targets:
    • filename_prefix
    • plus one recognized path widget (configurable list)

Supported Path Widget Names

Runtime-config endpoint:

  • GET /mjr_project/configpath_widgets

If your custom node uses a different widget name for its output folder/path:

  • add it to the server defaults (e.g. PATH_WIDGETS_DEFAULT in server/project_routes.py)
  • restart ComfyUI

Workflow Saving (Project-aware)

Endpoint:

  • POST /mjr_project/workflow/save

Behavior:

  • saves the workflow to:
    • PROJECTS/<project_folder>/<workflows_role>/<optional_subdir>/<workflow_name>.json
  • optionally mirrors to:
    • ComfyUI/workflows/

Returned fields usually include:

  • project_rel_path
  • workflow_rel_dir
  • comfy_workflow_rel
  • mirrored, mirror_error

Model Utilities: Fix Missing Models (Panel)

The Project Settings panel includes a "Fix Missing Models" button that scans the current graph for combo widgets whose selected model is no longer present in the available values. It proposes exact and near matches (fuzzy) and applies the selection back to the graph.

Behavior summary:

  • Missing detection is local (in-memory widgets, no API required).
  • Candidates are suggested via a server scan with exact + fuzzy matching.
  • Applied fixes update widget values and refresh the graph.

Model Utilities: Download Missing Models (Panel)

The Project Settings panel includes a "Download Missing Models" button that resolves missing model names to download recipes. You can paste direct URLs for missing items and optionally remember them for next time in: output/PROJECTS/_INDEX/model_sources.json

Rules:

  • Only direct http/https URLs are accepted.
  • Allowed extensions: .safetensors, .ckpt, .pt, .pth, .bin
  • Optional SHA256 verification if provided.
  • Hugging Face token can be provided via HUGGINGFACE_HUB_TOKEN or HF_TOKEN.
  • Default download size cap is 10GB per file; tune via MJR_MODEL_DOWNLOAD_MAX_BYTES or MJR_MODEL_DOWNLOAD_MAX_GB.
  • All public hosts are allowed by default for maximum compatibility. To restrict hosts, set MJR_MODEL_DOWNLOAD_ALLOW_ANY_HOST=0 / mjr_project.download_allow_any_host=false and configure MJR_MODEL_DOWNLOAD_ALLOWED_HOSTS (comma-separated list).
  • Private/local IPs are blocked by default (SSRF guard); override with MJR_MODEL_DOWNLOAD_BLOCK_PRIVATE_IPS=0 / mjr_project.download_block_private_ips=false.
  • POST endpoints enforce same-origin and CSRF token checks for browser requests.
  • Timeout can be tuned via MJR_MODEL_DOWNLOAD_TIMEOUT (seconds).
  • Online search endpoint is rate-limited per client IP via MJR_MODEL_SEARCH_RATE_PER_MIN (default: 30/min).

Endpoints:

  • POST /mjr_models/resolve_recipes
  • POST /mjr_models/save_recipes
  • POST /mjr_models/download
  • GET /mjr_models/download_status

Advanced: Fingerprint Cache

An optional cache can be built under: output/PROJECTS/_INDEX/model_fingerprints.json

The cache stores lightweight fingerprints (sha256 of first 1MB + last 1MB + size bytes). This enables future hash-based resolution when model filenames or paths change.

Endpoints:

  • GET /mjr_models/fingerprint_cache_status
  • POST /mjr_models/build_fingerprint_cache
  • POST /mjr_models/resolve_by_fingerprint

API Reference (High-Level)

Base URL: your ComfyUI host/port.

Set / Select a project

POST /mjr_project/set

{ "project_name": "My Cool Project" }

List projects

GET /mjr_project/list?include_archived=0|1

List available models (from ComfyUI)

GET /mjr_project/models

Get runtime config (includes path widgets)

GET /mjr_project/config

Resolve project by folder name

GET /mjr_project/resolve?folder=<project_folder>

Preview template resolution

POST /mjr_project/preview_template

{
  "template": "{BASE}/{MEDIA}/{DATE}/{NAME}/{MODEL}",
  "tokens": {
    "BASE": "PROJECTS/MY_PROJECT",
    "MEDIA": "02_OUT/IMAGES",
    "DATE": "251222",
    "NAME": "AdrianCloseUp",
    "MODEL": "FLUX_DEV"
  }
}

Create/validate a custom output dir + prefix (conceptual)

POST /mjr_project/create_custom_out

{
  "project_id": "...",
  "kind": "asset",
  "name": "AdrianCloseUp",
  "media": "images",
  "model": "Flux Dev",
  "model_upper": true,
  "date": "251222",
  "template": "{BASE}/{MEDIA}/{DATE}/{NAME}/{MODEL}"
}

Archive / Unarchive / Delete

  • POST /mjr_project/archive
  • POST /mjr_project/unarchive
  • POST /mjr_project/delete

“delete” is designed to be safe-by-default: it typically removes index entries and avoids dangerous disk nukes unless explicitly implemented.


Local UI State

The UI persists state in localStorage:

  • key: mjr_project_settings_state

So your settings survive browser refreshes and ComfyUI restarts (unless the browser decides it’s in a mood).


Repo Layout (Typical)

  • __init__.py
    • exposes WEB_DIRECTORY
    • imports server routes
  • server/
    • project_routes.py (AIOHTTP endpoints via PromptServer.instance.routes)
    • project_store.py (folder structure + safe path utils + index/current handling)
  • web/js/
    • majoor_project_settings.js (ComfyUI extension entry, UI, hooks)
    • state_manager.js (persistence/state)
    • ui_components.js (UI helpers)
    • mjr/ (api, graph scan, patching, dialogs, toasts, utilities)

Troubleshooting

“I don’t see the UI”

  • Confirm folder is inside:
    • ComfyUI/custom_nodes/ComfyUI-Majoor-ProjectSettings/
  • Restart ComfyUI (not just browser refresh).
  • Check browser console (F12): logs are usually prefixed with something like [mjr].

“My save nodes are not being patched”

  • The node may not expose:
    • filename_prefix, and/or
    • a recognized path widget name (output_path, folder, save_path, etc.)
  • Add your widget name to the server’s PATH_WIDGETS_DEFAULT and restart.

“Path rejected / invalid”

  • The server intentionally blocks:
    • absolute paths
    • drive paths (C:\...)
    • .. traversal
    • unsafe characters / escape attempts
  • This is by design: the extension is strict so it doesn’t become a foot-gun.

"Ctrl+S conflicts"

  • ComfyUI owns Ctrl+S through Comfy.SaveWorkflow; this extension does not register a default Ctrl+S keybinding.
  • Only enable MajoorPS: Legacy Ctrl+S hook if you accept that it can override core/browser save behavior.
  • Prefer capture-phase + stopping propagation (or disable your hotkey if exposed).

"Model download fails with permission error"

If model downloads succeed but fail when moving to the models folder:

Common causes:

  • Models folder is on a different drive with restricted permissions
  • Antivirus is blocking file creation
  • Another program has the models folder open
  • Insufficient disk space

Solutions:

  1. Check folder permissions: Right-click models folder → Properties → Security → Add write permissions
  2. Add models folder to antivirus exclusions
  3. Close any programs that might be accessing model files
  4. Run ComfyUI as administrator
  5. Check if you have enough disk space
  6. Change models directory to a location with proper permissions

Recovery: If download succeeded but move failed, the file is kept at:

ComfyUI/models/.mjr_tmp/{job_id}/{filename}

You can manually move this file to your models directory.

See docs/BUGFIX_WINDOWS_DOWNLOAD.md for detailed information.


Roadmap Ideas

  • Project dashboard (notes, tags, quick links)
  • More robust asset/shot detection from workflow metadata
  • Preset templates per media type (images/videos/comps)
  • Tight integration with an Asset/File Manager for a real pipeline feel

API Error Responses

All API endpoints return errors in the following standardized format:

{
  "ok": false,
  "error": "Error message describing what went wrong"
}

Common HTTP Status Codes

  • 400 Bad Request: Invalid input, validation error, or malformed request
  • 404 Not Found: Project ID, workflow, or resource not found
  • 409 Conflict: Resource already exists (when overwrite=false)
  • 415 Unsupported Media Type: Missing or invalid Content-Type header (must be application/json)
  • 500 Internal Server Error: Server-side error (file I/O, database issues)

Example Error Responses

// Missing required field
{
  "ok": false,
  "error": "project_name is required"
}

// Invalid characters in input
{
  "ok": false,
  "error": "project_name contains invalid characters (/ \\ : .. not allowed)"
}

// Resource not found
{
  "ok": false,
  "error": "project_id not found"
}

// Validation failure
{
  "ok": false,
  "error": "invalid date format: '999999' (expected YYMMDD, e.g., 251220 for today)"
}

License

No license file is currently included in this repository/folder. Until a license is added by the author, treat the code as unlicensed (i.e., no permission is granted for redistribution or modification beyond what applicable law allows).

If you are the author/maintainer: add a LICENSE file and update this section accordingly.


Credits

Built for the ComfyUI ecosystem with one goal: less chaos, more structure, and outputs that look like you meant it. 😄