This file provides guidance for agentic coding assistants working in this repository.
# Install dependencies
pip install -r requirements.txt
pip install -r requirements-dev.txt
# Run standalone server (port 8188 by default)
python standalone.py --port 8188
# Run all backend tests
pytest
# Run specific test file
pytest tests/test_recipes.py
# Run specific test function
pytest tests/test_recipes.py::test_function_name
# Run backend tests with coverage
COVERAGE_FILE=coverage/backend/.coverage pytest \
--cov=py --cov=standalone \
--cov-report=term-missing \
--cov-report=html:coverage/backend/html \
--cov-report=xml:coverage/backend/coverage.xmlnpm install
npm test # Run all tests (JS + Vue)
npm run test:js # Run JS tests only
npm run test:watch # Watch mode
npm run test:coverage # Generate coverage reportcd vue-widgets
npm install
npm run dev # Build in watch mode
npm run build # Build production bundle
npm run typecheck # Run TypeScript type checking
npm test # Run Vue widget tests
npm run test:watch # Watch mode
npm run test:coverage # Generate coverage report- Use
from __future__ import annotationsfor forward references - Group imports: standard library, third-party, local (blank line separated)
- Absolute imports within
py/:from ..services import X - PEP 8 with 4-space indentation, type hints required
- Files:
snake_case.py, Classes:PascalCase, Functions/vars:snake_case - Constants:
UPPER_SNAKE_CASE, Private:_protected,__mangled
- Use
logging.getLogger(__name__), define custom exceptions inpy/services/errors.py async deffor I/O,@pytest.mark.asynciofor async tests- Singleton with
asyncio.Lock: seeModelScanner.get_instance() - Return
aiohttp.web.json_responseorweb.Response
pytestwith--import-mode=importlib- Fixtures in
tests/conftest.py, usetmp_path_factoryfor isolation - Mark tests needing real paths:
@pytest.mark.no_settings_dir_isolation - Mock ComfyUI dependencies via conftest patterns
- ES modules:
import { app } from "../../scripts/app.js"for ComfyUI - Vue:
import { ref, computed } from 'vue', type imports:import type { Foo } - Export named functions:
export function foo() {}
- camelCase for functions/vars/props, PascalCase for classes
- Constants:
UPPER_SNAKE_CASE, Files:snake_case.jsorkebab-case.js - 2-space indentation preferred (follow existing file conventions)
- Vue Single File Components:
<script setup lang="ts">preferred
- ComfyUI:
app.registerExtension(),node.addDOMWidget(name, type, element, options) - Event handlers via
addEventListeneror widget callbacks - Shared utilities:
web/comfyui/utils.js
- Use composition API:
useXxxState(widget), return reactive refs and methods - Guard restoration loops with flag:
let isRestoring = false - Build config from state:
const buildConfig = (): Config => { ... }
ServiceRegistrysingleton for DI, services useget_instance()classmethod- Separate scanners (discovery) from services (business logic)
- Handlers in
py/routes/handlers/are pure functions with deps as params
BaseModelServicebase for LoRA, Checkpoint, EmbeddingModelScannerfor file discovery, hash deduplicationPersistentModelCache(SQLite) for persistence- Route registrars:
ModelRouteRegistrar, endpoints:/loras/*,/checkpoints/*,/embeddings/* - WebSocket via
WebSocketManagerfor real-time updates
- Base:
py/recipes/base.py, Enrichment:RecipeEnrichmentService - Parsers:
py/recipes/parsers/
- ALWAYS use English for comments (per copilot-instructions.md)
- Dual mode: ComfyUI plugin (folder_paths) vs standalone (settings.json)
- Detection:
os.environ.get("LORA_MANAGER_STANDALONE", "0") == "1" - Run
python scripts/sync_translation_keys.pyafter adding UI strings tolocales/en.json - Symlinks require normalized paths
- Location:
./static/and./templates/ - Tech: Vanilla JS + CSS, served by standalone server
- Tests via npm in root directory
- Location:
./web/comfyui/(Vanilla JS) +./vue-widgets/(Vue) - Primary styles:
./web/comfyui/lm_styles.css(NOT./static/css/) - Vue builds to
./web/comfyui/vue-widgets/, typecheck viavue-tsc