Files
ComfyUI-Lora-Manager/docs/metadata-json-schema.md
T
Will Miao b90d60f043 fix(sidecars): carry the identity map through a sidecar root move
A model root that moved earlier is mirrored under a pinned name derived
from its old path. If anything resolved against the new sidecar path before
the relocation ran, the destination got a map naming the mirror after the
*current* path. migrate_root's keep-newer transfer then dropped the source
map, so the moved metadata stayed orphaned under the pinned component while
reads followed the new name and rebuilt defaults — losing favorites, notes
and tags a second time.

The identity map is now relocated by relocate_root_map() instead of the
generic transfer: entries recorded under the old sidecar root win for the
roots they describe, destination-only entries are preserved, and the cache
is dropped so the next resolution reloads the merged map. A merge that
cannot be written is reported as a migration error rather than silently
stranding the moved metadata.

Reported by the Codex review on #1131.
2026-09-28 21:25:48 +08:00

18 KiB

metadata.json Schema Documentation

This document defines the complete schema for .metadata.json files used by Lora Manager. These sidecar files store model metadata alongside model files (LoRA, Checkpoint, Embedding).

Overview

  • File naming: <model_name>.metadata.json (e.g., my_lora.safetensors → my_lora.metadata.json)
  • Format: JSON with UTF-8 encoding
  • Purpose: Store model metadata, tags, descriptions, preview images, and Civitai/CivArchive integration data
  • Extensibility: Unknown fields are preserved via _unknown_fields mechanism for forward compatibility

Storage Location (Alongside vs Centralized)

By default, .metadata.json sidecars and preview images live alongside their model files. An optional centralized mode stores them under a single root directory instead. Two settings control this (Settings → Library → Sidecar Storage):

Setting Values Default
sidecar_storage_mode "alongside" | "centralized" "alongside"
sidecar_storage_path Absolute path string; empty = <settings dir>/sidecars ""

In centralized mode, sidecars and previews mirror each model root's directory structure:

<sidecar_root>/<root_component>/<rel_dir>/<name>.metadata.json
  • <rel_dir> is the model's directory relative to the model root containing the file; the longest matching root wins, so nested roots mirror under the most specific root.
  • <root_component> identifies the model root and survives the root being moved or renamed. It starts as the deterministic <sanitized basename>-<path digest> — so mirrors created by older builds, and mirrors left behind by a relocated sidecar root, still resolve — and is then pinned in <sidecar_root>/.lm-sidecar-roots.json alongside the root's last known path and a few sample subdirectories. Two roots sharing a basename (e.g. /mnt/a/loras and /mnt/b/loras) always get distinct components and never collide. Each path component is sanitized to filesystem-safe characters.
  • Moving or renaming a model root does not strand its sidecars. On the next run the mirror identity is re-anchored to the root's new path (matched by basename and recorded sample directories), so favorites, notes, tags and usage tips keep resolving. An existing hash-named mirror from an older build is adopted as-is on first use.
  • If an identity cannot be re-anchored unambiguously (e.g. two same-named candidate roots), nothing is guessed: the mirror stays on disk untouched and surfaces as an orphan in Doctor → Centralized Sidecars (and in the log). Restoring the original root path re-links it automatically.
  • .civitai.info files always stay next to the model file, in both modes.
  • Changing the mode does not move existing files automatically — run the migration (POST /api/lm/sidecars/migrate with {"direction": "to_centralized" | "to_alongside"}, or the "Migrate Sidecars Now" button in settings). The migration covers excluded (hidden) models too, so un-excluding one later never strands its sidecar in the old layout. The result payload includes a sidecar_root field with the resolved centralized root, and the settings UI shows the outcome counters plus an "Open Folder" shortcut.
  • Changing sidecar_storage_path while centralized likewise needs a root relocation: {"direction": "relocate_root", "old_root": "<previous path>"} moves the whole mirror tree to the new root (the settings UI offers this automatically). The identity map travels with the tree, and its entries win over any map the destination acquired beforehand — so a mirror that was re-anchored earlier keeps its name even if something resolved against the new path before the relocation ran.
  • The settings UI always shows the resolved effective storage root (via the sidecar_storage_root* fields in GET /api/lm/settings), with POST /api/lm/sidecars/open-location opening it in the file manager. When the resolved root lies inside the plugin installation folder (portable settings mode), the UI warns: reinstalling or clean-updating the plugin would delete the sidecars, so an explicit path outside the installation folder is recommended. The repo .gitignore excludes the portable-mode default (/sidecars/).
  • All sidecar/preview path derivation goes through the helpers in py/utils/sidecar_paths.py; never construct paths inline. In the default alongside mode these helpers do no extra I/O at all — the identity map is only loaded and reconciled when centralized storage is actually in use.

Base Fields (All Model Types)

These fields are present in all model metadata files.

Field Type Required Auto-Updated Description
file_name string ✅ Yes ✅ Yes Filename without extension (e.g., "my_lora")
model_name string ✅ Yes ❌ No Display name of the model. Default: file_name if no other source
file_path string ✅ Yes ✅ Yes Full absolute path to the model file (normalized with / separators)
size integer ✅ Yes ❌ No File size in bytes. Set at: Initial scan or download completion. Does not change thereafter.
modified float ✅ Yes ❌ No Import timestamp — Unix timestamp when the model was first imported/added to the system. Used for "Date Added" sorting. Does not change after initial creation.
sha256 string ⚠️ Conditional ✅ Yes SHA256 hash of the model file (lowercase). LoRA: Required. Checkpoint: May be empty when hash_status="pending" (lazy hash calculation)
base_model string ❌ No ❌ No Base model type. Examples: "SD 1.5", "SDXL 1.0", "SDXL Lightning", "Flux.1 D", "Flux.1 S", "Flux.1 Krea", "Illustrious", "Pony", "AuraFlow", "Kolors", "ZImageTurbo", "Wan Video", etc. Default: "Unknown" or ""
preview_url string ❌ No ✅ Yes Path to preview image file
preview_nsfw_level integer ❌ No ❌ No NSFW level using bitmask values from Civitai: 1 (PG), 2 (PG13), 4 (R), 8 (X), 16 (XXX), 32 (Blocked). Default: 0 (none)
notes string ❌ No ❌ No User-defined notes
from_civitai boolean ❌ No (default: true) ❌ No Whether the model originated from Civitai
civitai object ❌ No ⚠️ Partial Civitai/CivArchive API data and user-defined fields
tags array[string] ❌ No ⚠️ Partial Model tags (merged from API and user input)
modelDescription string ❌ No ⚠️ Partial Full model description (from API or user)
civitai_deleted boolean ❌ No (default: false) ❌ No Whether the model was deleted from Civitai
favorite boolean ❌ No (default: false) ❌ No Whether the model is marked as favorite
exclude boolean ❌ No (default: false) ❌ No Whether to exclude from cache/scanning. User can set from false to true (currently no UI to revert)
db_checked boolean ❌ No (default: false) ❌ No Whether checked against archive database
skip_metadata_refresh boolean ❌ No (default: false) ❌ No Skip this model during bulk metadata refresh
metadata_source string|null ❌ No ✅ Yes Last provider that supplied metadata (see below)
last_checked_at float ❌ No (default: 0) ✅ Yes Unix timestamp of last metadata check
hash_status string ❌ No (default: "completed") ✅ Yes Hash calculation status: "pending", "calculating", "completed", "failed"
autov3 string|null ❌ No ✅ Yes CivitAI AutoV3 hash (first 12 chars, lowercase hex) sourced from the safetensors embedded metadata (sshs_model_hash / modelspec.hash_sha256). Absent = not yet checked (may be backfilled later); null = checked but unavailable (header has no recognized hash); 12-char hex string = value

Model-Specific Fields

LoRA Models

LoRA models do not have a model_type field in metadata.json. The type is inferred from context or civitai.type (e.g., "LoRA", "LoCon", "DoRA").

Field Type Required Auto-Updated Description
usage_tips string (JSON) ❌ No (default: "{}") ❌ No JSON string containing recommended usage parameters

usage_tips JSON structure:

{
  "strength_min": 0.3,
  "strength_max": 0.8,
  "strength_range": "0.3-0.8",
  "strength": 0.6,
  "clip_strength": 0.5,
  "clip_skip": 2
}
Key Type Description
strength_min number Minimum recommended model strength
strength_max number Maximum recommended model strength
strength_range string Human-readable strength range
strength number Single recommended strength value
clip_strength number Recommended CLIP/embedding strength
clip_skip integer Recommended CLIP skip value

Checkpoint Models

Field Type Required Auto-Updated Description
model_type string ❌ No (default: "checkpoint") ❌ No Model type: "checkpoint", "diffusion_model"

Embedding Models

Field Type Required Auto-Updated Description
model_type string ❌ No (default: "embedding") ❌ No Model type: "embedding"

The civitai Field Structure

The civitai object stores the complete Civitai/CivArchive API response. Lora Manager preserves all fields from the API for future compatibility and extracts specific fields for use in the application.

Version-Level Fields (Civitai API)

Fields Used by Lora Manager:

Field Type Description
id integer Version ID
modelId integer Parent model ID
name string Version name (e.g., "v1.0", "v2.0-pruned")
nsfwLevel integer NSFW level (bitmask: 1=PG, 2=PG13, 4=R, 8=X, 16=XXX, 32=Blocked)
baseModel string Base model (e.g., "SDXL 1.0", "Flux.1 D", "Illustrious", "Pony")
trainedWords array[string] Trigger words for the model
type string Model type ("LoRA", "Checkpoint", "TextualInversion")
earlyAccessEndsAt string|null Early access end date (used for update notifications)
description string Version description (HTML)
model object Parent model object (see Model-Level Fields below)
creator object Creator information (see Creator Fields below)
files array[object] File list with hashes, sizes, download URLs (used for metadata extraction)
images array[object] Image list with metadata, prompts, NSFW levels (used for preview/examples)

Fields Stored but Not Currently Used:

Field Type Description
createdAt string (ISO 8601) Creation timestamp
updatedAt string (ISO 8601) Last update timestamp
status string Version status (e.g., "Published", "Draft")
publishedAt string (ISO 8601) Publication timestamp
baseModelType string Base model type (e.g., "Standard", "Inpaint", "Refiner")
earlyAccessConfig object Early access configuration
uploadType string Upload type ("Created", "FineTuned", etc.)
usageControl string Usage control setting
air string Artifact ID (URN format: urn:air:sdxl:lora:civitai:122359@135867)
stats object Download count, ratings, thumbs up count
videos array[object] Video list
downloadUrl string Direct download URL
trainingStatus string|null Training status (for on-site training)
trainingDetails object|null Training configuration

Model-Level Fields (civitai.model.*)

Fields Used by Lora Manager:

Field Type Description
name string Model name
type string Model type ("LoRA", "Checkpoint", "TextualInversion")
description string Model description (HTML, used for modelDescription)
tags array[string] Model tags (used for tags field)
allowNoCredit boolean License: allow use without credit
allowCommercialUse array[string] License: allowed commercial uses. Values: "Image" (sell generated images), "Video" (sell generated videos), "RentCivit" (rent on Civitai), "Rent" (rent elsewhere)
allowDerivatives boolean License: allow derivatives
allowDifferentLicense boolean License: allow different license

Fields Stored but Not Currently Used:

Field Type Description
nsfw boolean Model NSFW flag
poi boolean Person of Interest flag

Creator Fields (civitai.creator.*)

Both fields are used by Lora Manager:

Field Type Description
username string Creator username (used for author display and search)
image string Creator avatar URL (used for display)

Model Type Field (Top-Level, Outside civitai)

Field Type Values Description
model_type string "checkpoint", "diffusion_model", "embedding" Stored in metadata.json for Checkpoint and Embedding models. Note: LoRA models do not have this field; type is inferred from civitai.type or context.

User-Defined Fields (Within civitai)

For models not from Civitai or user-added data:

Field Type Description
trainedWords array[string] Trigger words — manually added by user
customImages array[object] Custom example images added by user

customImages Structure

Each custom image entry has the following structure:

{
  "url": "",
  "id": "short_id",
  "nsfwLevel": 0,
  "width": 832,
  "height": 1216,
  "type": "image",
  "meta": {
    "prompt": "...",
    "negativePrompt": "...",
    "steps": 20,
    "cfgScale": 7,
    "seed": 123456
  },
  "hasMeta": true,
  "hasPositivePrompt": true
}
Field Type Description
url string Empty for local custom images
id string Short ID or filename
nsfwLevel integer NSFW level (bitmask)
width integer Image width in pixels
height integer Image height in pixels
type string "image" or "video"
meta object|null Generation metadata (prompt, seed, etc.) extracted from image
hasMeta boolean Whether metadata is available
hasPositivePrompt boolean Whether a positive prompt is available

Minimal Non-Civitai Example

{
  "civitai": {
    "trainedWords": ["my_trigger_word"]
  }
}

Non-Civitai Example Without Trigger Words

{
  "civitai": {}
}

Example: User-Added Custom Images

{
  "civitai": {
    "trainedWords": ["custom_style"],
    "customImages": [
      {
        "url": "",
        "id": "example_1",
        "nsfwLevel": 0,
        "width": 832,
        "height": 1216,
        "type": "image",
        "meta": {
          "prompt": "example prompt",
          "seed": 12345
        },
        "hasMeta": true,
        "hasPositivePrompt": true
      }
    ]
  }
}

Metadata Source Values

The metadata_source field indicates which provider last updated the metadata:

Value Source
"civitai_api" Civitai API
"civarchive" CivArchive API
"archive_db" Metadata Archive Database
null No external source (user-defined only)

Auto-Update Behavior

Fields Updated During Scanning

These fields are automatically synchronized with the filesystem:

  • file_name — Updated if actual filename differs
  • file_path — Normalized and updated if path changes
  • preview_url — Updated if preview file is moved/removed
  • sha256 — Updated during hash calculation (when hash_status="pending")
  • hash_status — Updated during hash calculation
  • autov3 — Set when metadata is first created (from safetensors header); may be backfilled later for entries where it is absent
  • last_checked_at — Timestamp of scan
  • metadata_source — Set based on metadata provider

Fields Set Once (Immutable After Import)

These fields are set when the model is first imported/scanned and never change thereafter:

  • modified — Import timestamp (used for "Date Added" sorting)
  • size — File size at time of import/download

User-Editable Fields

These fields can be edited by users at any time through the Lora Manager UI or by manually editing the metadata.json file:

  • model_name — Display name
  • tags — Model tags
  • modelDescription — Model description
  • notes — User notes
  • favorite — Favorite flag
  • exclude — Exclude from scanning (user can set false→true, currently no UI to revert)
  • skip_metadata_refresh — Skip during bulk refresh
  • civitai.trainedWords — Trigger words
  • civitai.customImages — Custom example images
  • usage_tips — Usage recommendations (LoRA only)

Field Reference by Behavior

Required Fields (Must Always Exist)

  • file_name
  • model_name (defaults to file_name if not provided)
  • file_path
  • size
  • modified
  • sha256 (LoRA: always required; Checkpoint: may be empty when hash_status="pending")

Optional Fields with Defaults

Field Default
base_model "Unknown" or ""
preview_nsfw_level 0
from_civitai true
civitai {}
tags []
modelDescription ""
notes ""
civitai_deleted false
favorite false
exclude false
db_checked false
skip_metadata_refresh false
metadata_source null
last_checked_at 0
hash_status "completed"
autov3 absent (not checked) or null (checked, no value)
usage_tips "{}" (LoRA only)
model_type "checkpoint" or "embedding" (not present in LoRA models)

Version History

Version Date Changes
1.1 2026-08 Added autov3 field (CivitAI AutoV3 hash with three-state semantics)
1.0 2026-03 Initial schema documentation

See Also