Source profileQuality 94/100Review permissions

laurigates/claude-plugins/comfyui-plugin/skills/comfy-registry-lifecycle/SKILL.md

comfy-registry-lifecycle

Comfy Registry release pipeline: release-please + lockfile drift traps, the empty-web/dist publish bug, version status states, phantom versions, icon/banner generation. Use when debugging a pack's publish pipeline.

Source repository stars
53
Declared platforms
0
Static risk flags
2
Last source update
2026-08-24
Source checked
2026-08-25

Decision brief

What it does: where it fits

A ComfyUI custom-node pack's release flow: conventional commits → release-please bumps pyproject.toml + CHANGELOG.md → merge the release PR → the published GitHub release triggers publish.yml → Comfy-Org/publish-node-action publishes to registry.comfy.org. The failures below liv…

Best for

  • Use when debugging a pack's publish pipeline.

Not for

  • Tasks that require unconfirmed production actions or broad system permissions.
  • Environments where the pinned source and install steps cannot be inspected.

Compatibility matrix

Platform support, with evidence labels

PlatformStatusEvidenceWhat to check
CodexNot declaredNo explicit evidencePortability before use
Claude CodeNot declaredNo explicit evidencePortability before use
CursorNot declaredNo explicit evidencePortability before use
Gemini CLINot declaredNo explicit evidencePortability before use
Open the compatibility checker

Installation

Inspect first. Install second.

The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.

Source-detected install commandSource
npx skills add https://github.com/laurigates/claude-plugins --skill "comfyui-plugin/skills/comfy-registry-lifecycle"
Safe inspection promptEditorial

Inspect the Agent Skill "comfy-registry-lifecycle" from https://github.com/laurigates/claude-plugins/blob/5de06622d8def8c36f7f39d980300aaa15af4357/comfyui-plugin/skills/comfy-registry-lifecycle/SKILL.md at commit 5de06622d8def8c36f7f39d980300aaa15af4357. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.

Workflow

What the source asks the agent to do

  1. 01

    The security scan: what flags, what the reasons mean, how to shrink the surface

    Learned across an 11-pack flag epidemic (2026-06/07; appeal: Comfy-Org/registry-backend180, third-party confirmations in Comfy-Org/ComfyUI-Manager2927):

    Any finding flags the version — severity is irrelevant. A singleReasons are on the public API — behind an undocumented param.Known issue classes (from statusreason payloads):
  2. 02

    Standing feedback: the registry-health workflow

    A .github/workflows/registry-health.yml (runs after publish, daily, and on demand) that looks up the pyproject.toml version in the registry and fails + opens a registry-health issue when that version is Flagged, stuck Pending, missing, or outranked by a phantom — auto-closing wh…

    A .github/workflows/registry-health.yml (runs after publish, daily, and on demand) that looks up the pyproject.toml version in the registry and fails + opens a registry-health issue when that version is Flagged, stuck P…
  3. 03

    When to Use This Skill

    Review the “When to Use This Skill” section in the pinned source before continuing.

    Review and apply the “When to Use This Skill” source section.
  4. 04

    1. uv.lock self-version drifts — release-please has no native uv.lock support

    The lockfile records the workspace package's own version in its [[package]] entry. release-please's python release-type bumps pyproject.toml but not uv.lock (googleapis/release-please2561), so the lock's self-version silently trails pyproject.toml across releases. There is no uv…

    The lockfile records the workspace package's own version in its [[package]] entry. release-please's python release-type bumps pyproject.toml but not uv.lock (googleapis/release-please2561), so the lock's self-version si…Fix — a structured toml extra-files updater in release-please-config.json (the declarative equivalent of uv lock --upgrade-package, not a hand-edit):is the directory/package name. The toml updater parses the lock and sets only the matched version value at the JSONPath — everything else stays byte-stable. Note .name.value (release-please's TOML AST wraps scalar value…
  5. 05

    2. The registry "Updates" changelog — use native COMFYNODECHANGELOG, not a post-publish PUT

    comfy node publish sets the per-version changelog natively via the COMFYNODECHANGELOG env var (Comfy-Org/comfy-cli467, released in comfy-cli 1.11+), populating the registry's "Updates" section atomically at publish time.

    comfy node publish sets the per-version changelog natively via the COMFYNODECHANGELOG env var (Comfy-Org/comfy-cli467, released in comfy-cli 1.11+), populating the registry's "Updates" section atomically at publish time.Do not hand-roll a post-publish step that resolves the version UUID and PUTs to https://api.comfy.org/publishers/.../versions/{id}. A hand-rolled step that extracts nodeid/version via python3 -c 'import tomllib' fails o…Correct shape: a step before the publish-node-action step that flattens the release notes to plain text (the registry renders Updates as plain text) and exports it, so the action's comfy node publish reads it from the j…

Permission review

Static risk signals and limitations

Runs scripts

medium · line 131

The documentation asks the agent to run terminal commands or scripts.

bun install # regenerates bun.lock to resolve the new range

Runs scripts

medium · line 132

The documentation asks the agent to run terminal commands or scripts.

bun run build # rebuilds web/dist against the new dependency version

Network access

medium · line 198

The documentation includes network, browsing, or remote request actions.

d = json.load(urllib.request.urlopen(f"https://api.comfy.org/nodes/{nid}/versions"))

Network access

medium · line 467

The documentation includes network, browsing, or remote request actions.

curl -sI https://raw.githubusercontent.com/<owner>/<repo>/main/icon.png # 200 image/png

Evidence record

Why each signal appears

EvidenceSourceComputedTestedEditorial
SignalValueEvidence typeMeaning
Quality score94/100ComputedDocumentation, specificity, maintenance, and trust rules
Repository stars53SourceRepository attention, not individual Skill quality
Compatibility0 platformsSourceDeclared in the catalog source record
Usage guideautomated source guideEditorialGenerated or reviewed according to the visible evidence level

Pinned source

Provenance and original SKILL.md

Repository
laurigates/claude-plugins
Skill path
comfyui-plugin/skills/comfy-registry-lifecycle/SKILL.md
Commit
5de06622d8def8c36f7f39d980300aaa15af4357
License
MIT
Collected
2026-08-25
Default branch
main
View the original SKILL.md

comfy-registry-lifecycle

A ComfyUI custom-node pack's release flow: conventional commits → release-please bumps pyproject.toml + CHANGELOG.md → merge the release PR → the published GitHub release triggers publish.ymlComfy-Org/publish-node-action publishes to registry.comfy.org. The failures below live in this flow (or the CI that gates it) and are easy to ship without noticing, because the pipeline reports green while the registry artifact is broken.

When to Use This Skill

Use this skill when...Use instead when...
Setting up or debugging a pack's release-please -> publish.yml -> registry pipelineWriting the pack's frontend/backend code itself -> comfyui-node-authoring
A published node's frontend or artwork isn't showing up correctlySmoke-testing the pack in a running instance -> comfyui-pack-live-smoke

1. uv.lock self-version drifts — release-please has no native uv.lock support

The lockfile records the workspace package's own version in its [[package]] entry. release-please's python release-type bumps pyproject.toml but not uv.lock (googleapis/release-please#2561), so the lock's self-version silently trails pyproject.toml across releases. There is no uv/pyproject.toml setting to omit the project's own version from the lock, so the lock must be kept in sync explicitly.

Fix — a structured toml extra-files updater in release-please-config.json (the declarative equivalent of uv lock --upgrade-package, not a hand-edit):

"extra-files": [
  {
    "type": "toml",
    "path": "uv.lock",
    "jsonpath": "$.package[?(@.name.value=='<pack-name>')].version"
  }
]

<pack-name> is the directory/package name. The toml updater parses the lock and sets only the matched version value at the JSONPath — everything else stays byte-stable. Note .name.value (release-please's TOML AST wraps scalar values).

To repair an already-drifted lock once: uv lock regenerates it to match pyproject.toml (the only diff is the self-version line, plus occasional uv specifier normalization like >=1.40>=1.40.0).

New packs are born with it. comfyui-node-scaffold emits this updater in the pack's release-please-config.json, and scaffold.py --verify <pack> grades an existing pack's wiring as RELEASE_PLEASE_UVLOCK=wired|unwired| mistargeted (issue #2187). Packs scaffolded before that still need the manual add below.

Sweeps miss packs — check before the first release, not after. A pack created after a fix sweep can silently lack the updater. Before merging any pack's release PR — and when scaffolding or auditing a pack — confirm grep -c extra-files release-please-config.json ≥ 1 and that the release PR's changed files include uv.lock. Adding the updater to main while a release PR is open regenerates that PR to include the lock bump.

2. The registry "Updates" changelog — use native COMFY_NODE_CHANGELOG, not a post-publish PUT

comfy node publish sets the per-version changelog natively via the COMFY_NODE_CHANGELOG env var (Comfy-Org/comfy-cli#467, released in comfy-cli 1.11+), populating the registry's "Updates" section atomically at publish time.

Do not hand-roll a post-publish step that resolves the version UUID and PUTs to https://api.comfy.org/publishers/.../versions/{id}. A hand-rolled step that extracts node_id/version via python3 -c 'import tomllib' fails on every release with ModuleNotFoundError: No module named 'tomllib', because Comfy-Org/publish-node-action pins Python 3.10 and tomllib is 3.11+ stdlib. Under bash -e it dies before any || exit 0 guard — the node still publishes, but the Updates section is empty and the job shows red, which is easy to miss.

Correct shape: a step before the publish-node-action step that flattens the release notes to plain text (the registry renders Updates as plain text) and exports it, so the action's comfy node publish reads it from the job environment:

- name: Compute registry changelog from release notes
  if: github.event_name == 'release' && github.event.release.body != ''
  env:
    RELEASE_BODY: ${{ github.event.release.body }}   # via env, not inline interpolation
  run: |
    changelog=$(python3 <<'PY'
    # pure-`re` markdown→plaintext flatten (no tomllib); prints the changelog
    PY
    )
    {
      echo "COMFY_NODE_CHANGELOG<<__CHANGELOG_EOF__"
      echo "$changelog"
      echo "__CHANGELOG_EOF__"
    } >> "$GITHUB_ENV"

$GITHUB_ENV exports the var to all later steps in the job, including the composite publish-node-action run. No PUT, no UUID lookup, no tomllib.

3. Bumping a shared frontend-kit dependency: regenerate the lockfile and the built bundle together

For a TS-built pack that consumes a shared TypeScript package inlined at build time (bun build bundles the import into web/dist), bumping the version range in package.json looks like a one-line change but silently desyncs two other committed artifacts, and CI catches each with a different, non-obvious error:

  • bun.lock goes stale — its pinned resolution still satisfies the old range, so it isn't touched by hand-editing package.json. CI runs bun install --frozen-lockfile, which fails with error: No version matching "^X.Y.0" found for specifier "<pkg>" (but package exists) — a confusing message, since the version genuinely is published; the real problem is the lockfile's stale resolution.
  • web/dist goes stale — the committed bundle still contains the old inlined code. A "verify committed web/dist is up to date" CI gate (a git diff --exit-code -- web/dist after a fresh build) fails.

Both gates are correct — the footgun is that the fix requires two commands, and the second failure only surfaces after the first is fixed (the frozen-lockfile failure blocks the build step that would otherwise reveal the dist-drift):

bun install   # regenerates bun.lock to resolve the new range
bun run build # rebuilds web/dist against the new dependency version
git add bun.lock web/dist/index.js

Commit both in the same commit as the package.json bump — don't split them, and don't stop after fixing the lockfile install failure without also rebuilding web/dist.

Across a whole pack set, check for consistency (range equals locked version in every consumer):

for repo in <pack-glob>; do
  [ -f "$repo/package.json" ] || continue
  range=$(grep -o '"<shared-pkg>": *"[^"]*"' "$repo/package.json" | grep -o '\^[0-9.]*')
  locked=$(grep -o '<shared-pkg>@[0-9.]*' "$repo/bun.lock" 2>/dev/null | head -1)
  echo "$repo | range=$range | $locked"
done

The empty-web/dist publish trap

For TS-built packs, the registry tarball is supposed to force-ship the built frontend via [tool.comfy] includes = ["web/dist"]. The trap: a published tarball can contain web/dist/ as an empty directory — no index.js — while publish.yml reports green.

Root cause is the publish action, not the include:

  • Comfy-Org/publish-node-action@v1 (and tags 1.0.0 / 1.0.1) run an unconditional actions/checkout@v4 that wipes the git-ignored web/dist a prior bun run build step produced. None of the tagged releases have a skip_checkout input.
  • skip_checkout exists only on the action's main branch (added 2025-05-03, commit c742414d; no tagged release carries it).
  • comfy node publish then packs git-tracked files + includes; its zip_files walks an included dir's contents only if the dir exists at pack time — if absent it writes an empty-dir entry. A wiped web/dist → empty web/dist/ in the tarball.

Fix — pin the action to the commit that gates checkout on skip_checkout (no tag has it yet):

      - name: Publish Custom Node
        # @v1/1.0.x lack skip_checkout and wipe the built web/dist. Pin
        # the main commit that gates checkout on skip_checkout (no tag has it).
        uses: Comfy-Org/publish-node-action@d2366e7abb6ab16f3bb03e3520ae25c8cf749bc9  # v1.0.2-dev (main HEAD; skip_checkout not yet tagged)
        with:
          personal_access_token: ${{ secrets.REGISTRY_ACCESS_TOKEN }}
          skip_checkout: 'true'

skip_checkout: 'true' is silently ignored by @v1 — passing it without repinning does nothing, which is exactly what lets this hide for weeks.

Verify a publish actually shipped the frontend

Never trust a green publish.yml run — it succeeds even when the tarball is empty. Download the real artifact and inspect it:

python3 - <<'PY'
import json, urllib.request, zipfile, io
nid, ver = "<node-id>", "<version>"
d = json.load(urllib.request.urlopen(f"https://api.comfy.org/nodes/{nid}/versions"))
v = next(x for x in d if x["version"] == ver)
z = zipfile.ZipFile(io.BytesIO(urllib.request.urlopen(v["downloadUrl"]).read()))
print([n for n in z.namelist() if n.startswith("web/dist/") and n.endswith((".js",".css"))])
PY

Empty list ⇒ broken tarball. The downloadUrl (cdn.comfy.org/<owner>/<id>/<ver>/node.zip) is in each version object.

Version status: Pending vs Flagged vs Active

api.comfy.org/nodes/<id>/versions returns every version with a status:

StatusMeaningAction
NodeVersionStatusPendingheld while the automated security scan runsauto-transitions to Active, usually < a few hours — just wait
NodeVersionStatusActivescan passed; installablenone
NodeVersionStatusFlaggedscan flagged itstuck — does NOT auto-clear. Full reasons: GET /nodes/<id>/versions?include_status_reason=true (undocumented public param — see the security-scan section below). Republishing re-runs the scan; appeal via Comfy-Org if a false positive

comfy node install resolves to the highest-semver Active version. So while a fixed version is Pending, installs still serve the older (possibly broken) Active one. comfy node registry-install can fetch a Pending version directly.

Flag false-positives are real: an identical commit can flag one pack but not a structurally-identical sibling. Don't assume your code is the problem — get the scan reasons (email) first.

The security scan: what flags, what the reasons mean, how to shrink the surface

Learned across an 11-pack flag epidemic (2026-06/07; appeal: Comfy-Org/registry-backend#180, third-party confirmations in Comfy-Org/ComfyUI-Manager#2927):

  • Any finding flags the version — severity is irrelevant. A single info-severity yara match (e.g. os.environ.get(...) or a requests.get in an API client) produces Flagged, which blocks distribution. There is no self-service resolution path.
  • Reasons are on the public API — behind an undocumented param. GET api.comfy.org/nodes/<id>/versions?include_status_reason=true returns per-version status_reason JSON (issue_type, scanner, file_path, line, description, admin_tags); without the param the field is scrubbed. Scanner notifications post to the Comfy Org Discord SUPPORT/#security-review-council channel; the registry.comfy.org/admin/nodeversions links in them are staff-only (403) and the publisher dashboard shows nothing. Poll the API — no Discord access needed (the scaffold's registry-health.yml does this and writes the findings into its tracking issue).
  • Known issue classes (from status_reason payloads):
    • python_network_operations (yara_scan) — any urllib/requests/socket use in shipped .py, including dev scripts that should never have shipped. Siblings: python_environment_manipulation (os.environ), python_command_injection_risk (subprocess).
    • vendored_unknown (provenance_scan) — "Vendored file detected but upstream origin could not be identified". Fires on any bundler-built web/dist file, including bundles of the repo's own src/ with no third-party code at all (comfyui-touch-shim evidence, 2026-07) — not just inlined node_modules deps. Every TS-built pack hits this class on every publish until Comfy-Org can attribute bundler output; only the appeal path clears it.
  • Shrink the scan surface mechanically:
    • .comfyignore must exclude every dev-only path — and it silently rots: a scripts/ directory added after the ignore file was written shipped a urllib dev tool and flagged the version. Pair the ignore file with a tests/test_publish_hygiene.py that simulates the comfy-cli tarball (git-tracked − .comfyignore + [tool.comfy] includes, via pathspec) and fails on unclassified shipped paths or scanner-tripwire patterns in shipped Python. The scaffold now emits both.
    • Publish bundled first-party deps with real provenance: the shared kit must carry a LICENSE file and a license field in package.json (an unlicensed npm package is unclassifiable — that was true of comfy-modal-kit until comfy-modal-kit#17) plus npm provenance attestation. Open the built bundle with a bun build --banner comment attributing what is inlined.
    • Runtime code whose function is scanner-hostile (a manager pack doing registry lookups, installs, env feature-gates) cannot be trimmed — allowlist it in the hygiene test with a justification and cite it in the appeal.
  • Appeal via Discord first — it's processed faster. Post the re-review request in a persistent per-publisher thread (e.g. Publisher <name> — re-review) in the Comfy Org Discord SUPPORT/#security-review-council channel, not as a loose channel message: the channel is a firehose of automated flagged-release notifications, so a bare message is unfindable within hours and a multi-round appeal (a reply days later, the next release re-flagged) loses its history. Reuse the same thread for every appeal. Keep the message under the 2,000-char limit with no markdown tables — fitting a multi-pack appeal usually costs several trim passes, so put the version-ID table and per-finding detail in a GitHub issue on Comfy-Org/registry-backend as the durable record and have the Discord message link to it rather than duplicate it.
  • Then verify by publishing: a republish re-runs the scan, so the definitive test of any fix is the next release's verdict via api.comfy.org/nodes/<id>/versions?include_status_reason=true.

Phantom versions (higher semver, ahead of git)

A version published once from a stale local copy can sit in the registry ahead of git (e.g. 0.2.0 Active while git is at 0.1.7). Because install resolves to highest-semver Active, that phantom becomes the clean-install target and outranks every later fix below it. Two ways out:

  1. Release a version > the phantom (Release-As, below) — the fix must outrank it.
  2. Remove the phantom from the registry dashboard — then the next Active version wins.

Release-As is stripped by squash-merge

To force release-please to a specific version (e.g. to leapfrog a phantom), a commit needs a Release-As: X.Y.Z trailer. The trap: GitHub squash-merge rebuilds the commit body from the PR description, so the trailer only survives if it's a clean line in the PR description — a trailer that lives only in the branch commit, or sits inside backticks or mid-sentence, is dropped and release-please falls back to a plain patch bump. Reliable options:

  • "Rebase and merge" the trigger PR — preserves the commit message verbatim, trailer intact.
  • Or put Release-As: X.Y.Z as a plain last line of the PR description (no backticks) for squash.

Do not hand-edit .release-please-manifest.json / CHANGELOG.md to force a version — it conflicts with the automation.

Standing feedback: the registry-health workflow

A .github/workflows/registry-health.yml (runs after publish, daily, and on demand) that looks up the pyproject.toml version in the registry and fails + opens a registry-health issue when that version is Flagged, stuck Pending, missing, or outranked by a phantom — auto-closing when healthy — is the early-warning the publish pipeline lacks on its own. On Flagged it queries ?include_status_reason=true and writes the scan findings (issue type / scanner / file / description) into the issue body, so the security-scan verdict is readable without Discord. Worth adding to any new pack (the scaffold emits it).

Backport to the scaffold

If publish.yml is generated by a scaffold template (as it is for comfyui-node-scaffoldscaffold.py), fix the template in the same sweep as any live packs, or every newly-scaffolded pack inherits the same broken step.

Icons & banners

Without [tool.comfy] Icon, the registry shows a generic placeholder.

Icon design system

The exact spec every pack shares (canonical — the scaffold's icon.svg placeholder and every hand-drawn glyph target this):

  • 400×400 canvas, viewBox 0 0 400 400.
  • Dark inset tile, verbatim: <rect x="28" y="28" width="344" height="344" rx="76" fill="url(#tile)" stroke="#2a2a36" stroke-width="2"/> where #tile is a vertical gradient #1f1f2a#12121a (x1=0 y1=0 x2=0 y2=1). The 28 px inset is the family margin — not full-bleed.
  • One bespoke pictographic glyph, centred, filling the tile. No letters in final art — every sibling uses a pictogram; a letter is a placeholder only.
  • Glyph colour encodes the sub-family: #ffb02e (orange) for touch/interaction packs, #6ba6ff (blue) for info/gallery packs. Secondary accents (#ffd866, #6bff8e) appear sparingly. Keep tile, radius, stroke, and gradient identical across packs.

Framing gate (the consistency check). Because the tile is the outermost drawn element, a correctly-framed icon always trims to the same box — run it on every pack:

identify -format '%wx%h / %@\n' icon.png    # MUST be: 400x400 / 346x346+27+27

A 512x512 / 512x512+0+0 result is the classic drift: a full-bleed tile on the wrong canvas, which renders visibly larger and off-palette on the registry grid. This is exactly how comfyui-touch-shim shipped the raw 512×512 green-letter scaffold placeholder while the other 10 packs matched — the trim box is the one-line audit that catches it across the fleet:

for d in comfyui-*/; do printf '%-28s %s\n' "$d" "$(identify -format '%wx%h/%@' "$d/icon.png" 2>/dev/null)"; done

Rasterize SVG with cairosvg — NOT ImageMagick

ImageMagick's internal MSVG renderer silently drops stroke, fill="none", and gradients — only filled shapes render, so stroke-based glyphs come out half-missing and a gradient tile goes flat black. Use cairosvg:

uvx --from cairosvg cairosvg icon.svg -o icon.png -W 400 -H 400

magick/ImageMagick is fine for PNG compositing/montages — just never for SVG→PNG of stroke art. If neither rsvg-convert nor inkscape/resvg is available, cairosvg via uvx is the reliable fallback path.

Banners (21:9) — AI background + composited branding

Diffusion is the right tool for the background, the wrong tool for icons and text. Generate a clean background, then composite crisp branding on top. scripts/registry_banner_bg.py and registry_banner_compose.py (this skill's scripts/) implement this two-step pipeline against a running ComfyUI instance:

python3 scripts/registry_banner_bg.py \
  --accent "warm amber and orange" --seed 101 --out bg.png \
  --host "${COMFYUI_HOST:-127.0.0.1:8188}"

Generates a 1344×576 (exact 21:9) abstract on-brand texture with no text/letters/logo/symbols requested in the prompt.

python3 scripts/registry_banner_compose.py \
  --bg bg.png --icon icon.png --name "Display Name" \
  --tagline "Short tagline" --accent '#ffb02e' --out banner.png

Composites the icon + name wordmark + tagline with ImageMagick. Text stays sharp and correctly spelled this way — never trust a diffusion model to render pack names.

Wiring into the registry (pyproject.toml [tool.comfy])

  • Icon / Banner are URLs, not tarball paths. Use raw.githubusercontent off the default branch: Icon = "https://raw.githubusercontent.com/<owner>/<repo>/main/icon.png"
  • They 404 on the PR branch and resolve the instant the PR merges to main (icon + version land together). Keep the art files and the metadata change in the same PR.
  • Leave [tool.comfy] includes unchanged — the icon is fetched from the URL, not shipped in the publish tarball.

release-please owns the version — never hand-bump

Add Icon/Banner + art with a conventional-commit PR (fix: → patch, feat: → minor). Do not touch version. Squash-merge → release-please opens a release PR with the bump → merge that → it cuts the GitHub Release (which publishes).

publish.yml — trigger on the release event, not the pyproject path

A publish workflow triggering on push: paths: [pyproject.toml] re-fires on any pyproject edit and 400s with "node version already exists". Fix it to fire once per real release:

on:
  workflow_dispatch:
  release:
    types: [published]

release-please emits a published Release when its release PR merges → publish runs exactly once with the bumped version. Bonus: merging the icon PR itself no longer triggers a spurious publish.

Verify after merge

curl -sI https://raw.githubusercontent.com/<owner>/<repo>/main/icon.png   # 200 image/png
gh run list -R <owner>/<repo> --workflow=publish.yml -L1                  # release/success
curl -s https://api.comfy.org/nodes/<id>/versions                        # new version present

Agentic Optimizations

ContextCommand
Read scan verdictscurl -s "https://api.comfy.org/nodes/<id>/versions?include_status_reason=true" | jq -c '.[] | select(.status == "NodeVersionStatusFlagged") | {version, status_reason}'

Verify

#1/#2/lockfile issues: static-checkable (YAML + actionlint; uv lock diff is one line), but the changelog path is only exercised at real publish time. Definitive proof = the next release's publish job goes green with a populated Updates section.

publish action pin: the pack-set consistency check above returning range == locked for every consumer, plus a downloaded-tarball inspection showing a non-empty web/dist/.

Frequently asked questions

What to verify before installation and use

What does the comfy-registry-lifecycle source document cover?

A ComfyUI custom-node pack's release flow: conventional commits → release-please bumps pyproject.toml + CHANGELOG.md → merge the release PR → the published GitHub release triggers publish.yml → Comfy-Org/publish-node-action publishes to registry.comfy.org. The failures below liv…

How do I install comfy-registry-lifecycle?

The source record exposes this install command: npx skills add https://github.com/laurigates/claude-plugins --skill "comfyui-plugin/skills/comfy-registry-lifecycle". Inspect the command and pinned source before running it.

Which permission-related actions were detected?

Static rules flagged exec-script, network in the source; the page lists the matching lines and excerpts.

Alternatives

Compare before choosing