Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
185 commits
Select commit Hold shift + click to select a range
68bed80
feat(updater): default to startup install + installer UI on Windows (…
Kosinkadink Jun 13, 2026
badf68e
chore: bump version to 1.0.19 (#1098)
cloud-code-bot[bot] Jun 13, 2026
e56f94b
chore: bump version to 1.0.20 (#1100)
cloud-code-bot[bot] Jun 13, 2026
eb05abe
Feat/titlebar theme match and version pill (#1102)
MaanilVerma Jun 15, 2026
336a1e4
fix(adopt): fail clearly when adoption can't source ComfyUI + replace…
Kosinkadink Jun 15, 2026
d74e912
fix(telemetry): never identify the anonymous installation_id (restore…
deepme987 Jun 16, 2026
e05f696
feat(telemetry): enable GeoIP for country cohorts (country only, no s…
deepme987 Jun 16, 2026
e3eae4f
feat(chooser): redesign install card for density + recency (#1111)
MaanilVerma Jun 16, 2026
77ffdb6
feat(downloads): serve "View All Downloads" as a title-bar popup (#1123)
MaanilVerma Jun 16, 2026
f26e941
fix(standalone): show nightly version for Latest on GitHub install ca…
Kosinkadink Jun 16, 2026
95448e9
fix(terminal): activate the right env for git/portable Console (#1099…
Kosinkadink Jun 16, 2026
a9ef971
fix(settings): don't default local installs to the Terminal tab (#1120)
Kosinkadink Jun 16, 2026
1c7c861
refactor(titlebar): tighten reset-zoom gate + drop redundant e2e case…
deepme987 Jun 17, 2026
56ae2f5
fix(launch): show host only in cloud "Connecting…" status (#1134)
MaanilVerma Jun 17, 2026
36cf7f4
feat(install): ship starter-template picker unconditionally (drop A/B…
deepme987 Jun 17, 2026
9a37613
fix(titlebar): relabel hamburger "New Window" → "Open Dashboard" (#1136)
deepme987 Jun 17, 2026
2f78c27
Clean up unique browser partitions on delete + drive-aware data defau…
Kosinkadink Jun 17, 2026
1917483
fix(operations): surface full substep output on failure (#1106) (#1110)
Kosinkadink Jun 17, 2026
11c136d
chore: bump version to 1.0.21 (#1138)
cloud-code-bot[bot] Jun 17, 2026
0ebb8be
chore: bump version to 1.0.22 (#1139)
cloud-code-bot[bot] Jun 17, 2026
93ec36d
ci: add team-gated Cursor review (thin caller for github-workflows) (…
mattmillerai Jun 17, 2026
c684b68
feat(telemetry): instrument the install -> boot -> canvas funnel (#1132)
deepme987 Jun 18, 2026
2573585
fix(telemetry): address CodeRabbit review from #1132 (#1145)
deepme987 Jun 18, 2026
39842e0
feat(telemetry): installation_id super-property + install.completed (…
deepme987 Jun 18, 2026
fd8cc41
feat: signal enable_telemetry to ComfyUI on opted-in standalone insta…
Kosinkadink Jun 18, 2026
84d9d1f
Use frontend-owned Comfy Desktop bridge types (#1112)
benceruleanlu Jun 19, 2026
5190403
Expose ComfyUI telemetry bridge (#1069)
benceruleanlu Jun 19, 2026
9eb3e98
chore: bump version to 1.0.23 (#1152)
cloud-code-bot[bot] Jun 19, 2026
e8e9cfc
feat(telemetry): boot_completed + boot_id for a per-attempt boot-succ…
deepme987 Jun 22, 2026
8695096
chore: bump version to 1.0.24 (#1157)
cloud-code-bot[bot] Jun 22, 2026
5ec84a0
ci: add CLA Assistant workflow (#1160)
alexisrolland Jun 22, 2026
1107756
fix(updater): reject non-newer update offers to stop reinstall loop (…
Kosinkadink Jun 23, 2026
ea1880c
fix(updater): don't auto-install Desktop updates when the setting is …
Kosinkadink Jun 23, 2026
0209f5d
Decode native-crash exit codes (0xC0000005), capture the failing impo…
Kosinkadink Jun 23, 2026
325d14f
fix: keep tracked instances when folder is inaccessible (#1155) (#1163)
Kosinkadink Jun 23, 2026
ee93831
feat(telemetry): real compute GPU + AMD/Intel drivers + ComfyUI model…
Kosinkadink Jun 23, 2026
db03387
chore: bump version to 1.0.25-rc.1 (#1171)
cloud-code-bot[bot] Jun 23, 2026
1d84dd8
chore: bump version to 1.0.25-rc.2 (#1172)
cloud-code-bot[bot] Jun 23, 2026
7870110
chore: bump version to 1.0.25-rc.3 (#1174)
cloud-code-bot[bot] Jun 23, 2026
89091e3
fix(telemetry): parse ComfyUI Desktop [LEVEL]-prefixed logs (hardware…
Kosinkadink Jun 24, 2026
58052b0
chore: bump version to 1.0.25-rc.4 (#1176)
cloud-code-bot[bot] Jun 24, 2026
d93bb3a
feat(telemetry): loaded model-class usage, full GPU/AMD/Intel/DirectM…
Kosinkadink Jun 25, 2026
dab65fc
GTM-104 Add Windows download token attribution bridge (#1149)
benceruleanlu Jun 25, 2026
273a338
chore: bump version to 1.0.25 (#1188)
cloud-code-bot[bot] Jun 25, 2026
6ebea42
GTM-104 fix NSIS build: inline dt_ token scan instead of StrFunc (#1190)
Kosinkadink Jun 25, 2026
ca54c59
chore: bump version to 1.0.26 (#1192)
cloud-code-bot[bot] Jun 25, 2026
7518baf
chore: bump version to 1.0.27 (#1193)
cloud-code-bot[bot] Jun 25, 2026
9f6b16c
feat(templates): live-curated & category segmented starter-template p…
MaanilVerma Jun 25, 2026
dcae6a2
Refactor/926 state driven instance navigation (#973)
MaanilVerma Jun 26, 2026
e5cd6eb
Strip ANSI color codes from plain-text ComfyUI logs (#1197)
Kosinkadink Jun 26, 2026
a8627df
feat(terminal): enable frontend terminal + logs injection on Portable…
Kosinkadink Jun 26, 2026
588b072
feat(diagnostics): persistent global app log + native crash capture (…
Kosinkadink Jun 26, 2026
dd0a7b7
Mention snapshot-undo path in ComfyUI update confirm modal (#1201)
Kosinkadink Jun 28, 2026
22dab80
fix(settings): use shared folder glyph in global Storage tab (#1202)
Kosinkadink Jun 28, 2026
ba8f3d6
fix(context-menu): add Save/Copy Image entries on right-click (#1200)
Kosinkadink Jun 28, 2026
bfdae71
Make Add Existing Install detect standalone/portable in nested ComfyU…
Kosinkadink Jun 28, 2026
f597a04
feat(terminal): OS-aware copy/paste shortcuts + desktop right-click m…
Kosinkadink Jun 29, 2026
22d5073
fix(templates): make picker thumbnail prefetch actually warm the cach…
MaanilVerma Jun 29, 2026
dc5bb4b
feat(storage): migrate remaining path displays to clickable StorageDi…
Kosinkadink Jun 29, 2026
bdaf244
fix(templates): show starter-template downloads in the downloads draw…
Kosinkadink Jun 29, 2026
5394475
chore: bump version to 1.0.28 (#1217)
cloud-code-bot[bot] Jun 29, 2026
b97b423
Enhance CLA workflow with author allowlist logic (#1221)
alexisrolland Jul 4, 2026
88b0342
feat(telemetry): tag events with client + deployment platform axes (#…
benceruleanlu Jul 9, 2026
375af8d
fix(naming): stop duplicate-suffix compounding + report instance name…
Kosinkadink Jul 9, 2026
a5f9437
Fix author login extraction in CLA workflow (#1241)
alexisrolland Jul 10, 2026
cb9a46c
Telemetry: standardize error events (matched error, class, normalized…
Kosinkadink Jul 10, 2026
45e30a9
fix(theme): force dark theme regardless of setting or OS appearance (…
Kosinkadink Jul 10, 2026
5b3f7d9
feat(telemetry): track global settings as durable properties (#1220, …
Kosinkadink Jul 11, 2026
8df736d
Add init dev script (#1244)
Kosinkadink Jul 11, 2026
4fc9712
i18n: startup arg categories + error messages; remove dead legacy arg…
Kosinkadink Jul 11, 2026
2b8b411
Telemetry: instrument the onboarding-complete to installation_started…
Kosinkadink Jul 11, 2026
3b562da
fix(update): prevent inconsistent ComfyUI source after git checkout f…
Kosinkadink Jul 14, 2026
9eecd3d
ci: bump cursor-review to github-workflows@df507e6 (#1232)
cloud-code-bot[bot] Jul 14, 2026
ccc3360
fix(snapshots): keep newest snapshot accurate after failed/rolled-bac…
Kosinkadink Jul 14, 2026
bd1e234
chore: bump version to 1.0.29 (#1252)
cloud-code-bot[bot] Jul 14, 2026
a3c5979
feat(auth): sign in via cloud login page with short-lived desktop log…
benceruleanlu Jul 16, 2026
0a96853
chore: bump version to 1.0.30-rc.1 (#1273)
cloud-code-bot[bot] Jul 16, 2026
ebaa998
ci: bump cursor-review to github-workflows@3ea5dce (#1270)
cloud-code-bot[bot] Jul 17, 2026
3ab9a19
Revert "feat(auth): sign in via cloud login page with short-lived des…
deepme987 Jul 17, 2026
b9cb529
fix(adopt): restore Legacy Desktop settings from workspace (#1281)
Kosinkadink Jul 18, 2026
d7a2722
feat: always-visible settings scrollbar and downloaded-model badge on…
MaanilVerma Jul 20, 2026
fed483d
feat: open gated model access pages in the Comfy session (#1275)
jaeone94 Jul 20, 2026
fce1dfd
Define e2e/lifecycle test taxonomy, inventory specs, and run lifecycl…
Kosinkadink Jul 24, 2026
25d77cb
feat: share GPU tier classifier via IPC (#1289)
benceruleanlu Jul 24, 2026
bcc0d55
feat: per-install ComfyUI-Manager security level + network mode in St…
Kosinkadink Jul 24, 2026
100de27
Run CI and CLA checks for merge groups (#1312)
benceruleanlu Jul 24, 2026
0ba02b6
fix: Restart during boot does nothing - cancel the in-flight launch, …
Kosinkadink Jul 25, 2026
d09611f
feat: recommend Cloud on first use for low-GPU hardware (#1299)
mariana953 Jul 27, 2026
f0c4ab9
refactor: extract model download path helpers (#1302)
benceruleanlu Jul 28, 2026
5e5f772
fix(templates): reposition the downloaded and recommended badges on s…
mariana953 Jul 28, 2026
e64c33e
chore: bump version to 1.0.30 (#1328)
cloud-code-bot[bot] Jul 28, 2026
2fd3b82
feat(auth): add desktop login-code flow (#1303)
benceruleanlu Jul 28, 2026
ff5cf97
Add trusted PyTorch stack switching and reliable v2 snapshot torch re…
Kosinkadink Jul 28, 2026
bc136c3
chore: bump version to 1.0.31 (#1332)
cloud-code-bot[bot] Jul 28, 2026
d7951e7
docs: clean up AGENTS.md (#1324)
benceruleanlu Jul 29, 2026
2e038a3
ci: bump cursor-review to github-workflows@ece4c3e (#1286)
cloud-code-bot[bot] Jul 29, 2026
f9c9671
feat(chooser): surface the cloud free-runs pill on the dashboard (#1336)
deepme987 Jul 29, 2026
da54d47
fix: refresh PyTorch stack catalog on boot even when release cache is…
Kosinkadink Jul 29, 2026
e76e15f
fix: preserve remote output subfolders (#1277)
Kosinkadink Jul 29, 2026
07dc6ea
feat(telemetry): add anonymous identity core (#1304)
benceruleanlu Jul 29, 2026
fee272d
feat(installer): carry website anonymous identity (#1305)
benceruleanlu Jul 29, 2026
b6ccfc4
feat(templates): offer API-node starter templates in the install pick…
MaanilVerma Jul 29, 2026
470269f
feat(telemetry): add Firebase auth consensus (#1306)
benceruleanlu Jul 29, 2026
a15a85c
chore: bump version to 1.0.32-rc.1 (#1344)
cloud-code-bot[bot] Jul 29, 2026
982309f
Harden Desktop error telemetry and diagnostics (#1271)
Kosinkadink Jul 30, 2026
e85beca
chore: make pnpm format:check pass and enforce it in CI (#1342)
benceruleanlu Jul 30, 2026
85e28b7
chore: relicense from MIT to AGPL-3.0-or-later + commercial (dual lic…
yoland68 Jul 30, 2026
69544d7
ci: enroll in AGENTS.md integrity check and add CLAUDE.md shims (#1348)
claude[bot] Jul 30, 2026
b24ceae
chore: add deepme987, Kosinkadink to AGENTS.md CODEOWNERS (#1349)
claude[bot] Jul 30, 2026
bd14760
chore: bump version to 1.0.32 (#1350)
cloud-code-bot[bot] Jul 30, 2026
17e1c01
fix(auth): reduce login-code return latency (#1353)
benceruleanlu Jul 31, 2026
ff36c04
chore: bump version to 1.0.33 (#1354)
cloud-code-bot[bot] Jul 31, 2026
69bd7f5
Accept 30-minute desktop login codes (#1356)
benceruleanlu Jul 31, 2026
381c0f7
fix(auth): route main-process auth HTTP through proxy-aware net.fetch…
benceruleanlu Jul 31, 2026
05f5516
chore: bump version to 1.0.34 (#1360)
cloud-code-bot[bot] Jul 31, 2026
d495ea8
fix(chooser): relabel the cloud pill 5 FREE RUNS -> TRY FREE (#1363)
deepme987 Jul 31, 2026
ef0d1e4
fix: isolate hosted terminal access (#1365)
Kosinkadink Aug 2, 2026
37c4ea6
chore: bump version to 1.0.35 (#1366)
cloud-code-bot[bot] Aug 2, 2026
e6cd5e3
feat(templates): lead with video and swap in the open-source MiniMax …
MaanilVerma Aug 5, 2026
64aa54f
chore: bump version to 1.0.36 (#1372)
cloud-code-bot[bot] Aug 5, 2026
d5fc0c4
feat(telemetry): remove the comfy.desktop.comfyui.model_usage event (…
benceruleanlu Aug 5, 2026
0174b1e
Remove duplicate per-execution telemetry events (#1369)
benceruleanlu Aug 5, 2026
88632d0
Remove the Desktop cloud capacity flag (#1374)
benceruleanlu Aug 5, 2026
81bcae5
fix(billing): open credits checkout in the system browser (#1380)
deepme987 Aug 7, 2026
31d9c73
chore: bump version to 1.0.37 (#1381)
cloud-code-bot[bot] Aug 7, 2026
f447f0c
feat(templates): swap in Seedance 2.5 as the video API-node starter (…
deepme987 Aug 9, 2026
856366d
chore: bump version to 1.0.38 (#1387)
cloud-code-bot[bot] Aug 9, 2026
90ce5a5
Storage controls: additive model dirs, split shared input/output, uni…
Kosinkadink Aug 12, 2026
bf30592
Fix startup update reinstall loop with a durable attempt marker (#1378)
Kosinkadink Aug 12, 2026
5b0e660
Add preference for multiple-instance warnings (#1394)
Kosinkadink Aug 12, 2026
f0585a1
feat(telemetry): report storage drive hardware for install and model …
Kosinkadink Aug 12, 2026
f145eb8
fix: quarantine telemetry writes while Firebase consensus is pending …
benceruleanlu Aug 13, 2026
5d4c7d1
fix: resolve Firebase auth consensus per committed frame (#1400)
benceruleanlu Aug 13, 2026
ae0e32d
fix: stage login attribution from the verified auth flows (#1401)
benceruleanlu Aug 13, 2026
08e6425
Route starter-template model downloads through the managed download s…
Kosinkadink Aug 13, 2026
ce92770
Add spelling suggestions to native context menus (#1407)
Kosinkadink Aug 14, 2026
31d6ca5
Add hardware acceleration toggle and reorganize Desktop Settings (#1409)
Kosinkadink Aug 15, 2026
8f11b71
Merge comfy-builder into main (#1404)
shrimbly Aug 15, 2026
78ab53f
Fix select dropdown viewport clipping (#1413)
Kosinkadink Aug 15, 2026
1ff443a
chore: bump version to 1.0.39 (#1415)
cloud-code-bot[bot] Aug 15, 2026
5df76f8
feat(cloud): offer Cloud during the install wait and from the dashboa…
MaanilVerma Aug 18, 2026
8522717
feat(telemetry): restore hourly model usage summaries (#1417)
benceruleanlu Aug 19, 2026
032e9b8
test: handle watchdog rejections before timers fire (#1424)
Kosinkadink Aug 20, 2026
db24416
feat(install): live output showcase during the install wait (#1426)
MaanilVerma Aug 20, 2026
fbe9f33
chore: bump version to 1.0.40-rc.1 (#1428)
cloud-code-bot[bot] Aug 20, 2026
f26ea50
feat(templates): serve the starter-template list from R2 (#1427)
MaanilVerma Aug 20, 2026
879b44a
Fix startup argument refresh after ComfyUI updates (#1430)
Kosinkadink Aug 21, 2026
6c29614
chore: bump version to 1.0.40 (#1431)
cloud-code-bot[bot] Aug 21, 2026
64de59a
chore: raise todesktop uploadSizeLimit to 60 MB (#1437)
deepme987 Aug 21, 2026
10f7eee
fix(install): show the loader scene for any op, not just installs (#1…
MaanilVerma Aug 21, 2026
e721713
fix: fail CLA allowlist step on API errors (#1439)
alexisrolland Aug 21, 2026
e798106
feat(comfybuilder): the client calls the build API and the copy says …
james00012 Aug 22, 2026
1aef81a
chore: bump version to 1.0.41 (#1444)
cloud-code-bot[bot] Aug 22, 2026
0234ecd
feat(mcp): Local MCP desktop distribution surface (banner + setup mod…
MaanilVerma Aug 25, 2026
4a915fe
chore: bump version to 1.0.42 (#1451)
cloud-code-bot[bot] Aug 25, 2026
b3fac43
fix(onboarding): no default starter workflow, move Skip to the right …
claude[bot] Aug 25, 2026
d2ae6fc
fix(install): use relative paths for scene video assets (#1454)
MaanilVerma Aug 26, 2026
0d389bc
chore: bump version to 1.0.43 (#1459)
cloud-code-bot[bot] Aug 26, 2026
5fc6026
feat(bridge-types): own and publish the frontend bridge contract (#1416)
benceruleanlu Aug 26, 2026
fd7e607
fix(mcp): await the flag fetch before the sidebar gate decides (#1460)
MaanilVerma Aug 26, 2026
542509f
fix(install): keep the progress loader clear of the footer (#1461)
MaanilVerma Aug 26, 2026
18e57d0
fix(install/mcp): kill the loader black flash, MCP cold video, and ov…
MaanilVerma Aug 26, 2026
f24b006
chore: bump version to 1.0.44 (#1463)
cloud-code-bot[bot] Aug 26, 2026
2908735
ci(release): comment ToDesktop build link + downloads on the release …
deepme987 Aug 26, 2026
9eaef5d
feat(announcement): MiniMax license announcement modal (draft copy, p…
deepme987 Aug 28, 2026
c498f16
chore: bump version to 1.0.45 (#1468)
cloud-code-bot[bot] Aug 28, 2026
51184ac
feat(announcement): add commercial-license bullet to the MiniMax H3 m…
deepme987 Aug 28, 2026
539df07
chore: bump version to 1.0.46 (#1470)
cloud-code-bot[bot] Aug 28, 2026
c7acad3
feat(updater): correlate update telemetry across launches (#1471)
christian-byrne Aug 29, 2026
073b969
Add workspace controls, local instance promotion, and managed install…
Kosinkadink Aug 29, 2026
836a341
Require code and test breakdowns in PR descriptions (#1411)
Kosinkadink Aug 29, 2026
0ae8f81
Fix startup update loop when the staged installer is corrupt or still…
Kosinkadink Aug 31, 2026
b0498cb
Show download progress for auto-installed update downloads (#1474)
Kosinkadink Aug 31, 2026
61e5e3b
chore: bump version to 1.0.47-rc.1 (#1477)
cloud-code-bot[bot] Aug 31, 2026
5dccce4
Add native Windows ARM64 (RTX Spark) support to the install path (#1481)
benceruleanlu Sep 4, 2026
fbf470e
chore: bump version to 1.0.47-rc.2 (#1482)
cloud-code-bot[bot] Sep 4, 2026
a3924a8
fix(release): raise upload limit and bump to 1.0.47-rc.3 (#1483)
benceruleanlu Sep 4, 2026
6151310
fix(release): align Windows target resource paths (#1484)
benceruleanlu Sep 4, 2026
fd95041
feat(templates): update starter templates from a PR, no app release (…
MaanilVerma Sep 4, 2026
36f9039
content(templates): swap image slots 3 and 4 (#1492)
MaanilVerma Sep 4, 2026
90e5fc3
feat(announcement): swap the launch modal to Comfy Cloud nodes (#1480)
deepme987 Sep 8, 2026
b9b50cd
chore: bump version to 1.0.47 (#1500)
cloud-code-bot[bot] Sep 8, 2026
90470f2
test: clean up PanelApp scopes between tests (#1511)
benceruleanlu Sep 9, 2026
3304521
fix(linux): reject x64 runtimes on ARM64 (#1486)
benceruleanlu Sep 9, 2026
966a35e
Merge branch 'main' into adopt-extra-model-paths-install-scoped
morgroth123-commits Sep 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
141 changes: 141 additions & 0 deletions .claude/skills/starter-templates/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
---
name: starter-templates
description: Change which starter templates the desktop install picker offers. Use when someone wants to swap, add, feature or refresh a starter template, or asks what the picker shows after install.
argument-hint: '[what you want to change]'
allowed-tools: Bash(node scripts/starter-templates.mjs *) Bash(git checkout *) Bash(git switch *) Bash(git add *) Bash(git commit *) Bash(git push *) Bash(gh pr create *) Read
---

# Starter templates

Change the starter templates the desktop installer offers, then open a PR.

The picker shows 4 templates in each of 4 tabs: `video`, `image`, `3d`, `audio`.
The list is `assets/starter-templates.json`, which desktop reads from R2 at boot,
so a merged change reaches users on their next launch with no app release.

## Rules

**Never edit the JSON directly.** Every command below regenerates the display
fields from the live template index. Hand-editing puts stale titles and sizes in
front of users and fails CI.

**Only ever pass template ids.** Titles, descriptions, sizes and thumbnails are
derived. If the user supplies them, ignore them and let the script fill them in.

**Confirm the id before writing.** Run `list` first and show the user the
matching titles. Ids differ by one character (`video_minimax_h3_t2v` vs
`..._i2v`), so never infer one from a product name.

**Never work around a rejection.** Read the message, fix the input, and tell the
user what was wrong. Do not edit the JSON to get past it.

## Steps

### 1. Find the id

```bash
node scripts/starter-templates.mjs list --modality video --free
```

`--modality` is `video`, `image`, `3d` or `audio`. `--free` or `--paid` narrows
it. Report the handful of relevant matches with titles and sizes, then confirm.

### 2. Make the change

Pick the command from what the user is changing.

Swap the featured (auto-selected) pick:

```bash
node scripts/starter-templates.mjs set --modality video --id <id> --recommended
```

Swap the paid API-node pick:

```bash
node scripts/starter-templates.mjs set --modality video --id <id> --paid
```

Swap one specific card, leaving the others alone:

```bash
node scripts/starter-templates.mjs set --modality video --id <new_id> --replaces <old_id>
```

Rebuild every tab at once, for a seasonal refresh. Four ids per tab, `*` marks
the featured card, `$` marks the paid one. Single-quote each list so the shell
leaves `$` alone:

```bash
node scripts/starter-templates.mjs replace \
--video '*id_a,$api_id,id_c,id_d' \
--image '*id_a,$api_id,id_c,id_d' \
--3d '*id_a,$api_id,id_c,id_d' \
--audio '*id_a,$api_id,id_c,id_d'
```

Refresh titles and sizes for the ids already in the list, changing nothing else:

```bash
node scripts/starter-templates.mjs regenerate
```

Each tab holds 4 slots, so `set` replaces rather than appends. The script
validates before writing, so a refusal leaves the file untouched.

The spec pins the slot rule, not the exact order: every tab keeps its
recommended pick in slot 1 and its paid card in slot 2, while slots 3 and 4
may reorder freely. So a plain swap of the two free cards needs no spec
change. The `TABS` fixture in `scripts/starter-templates.spec.mjs` only feeds
the negative `replace` cases — its own order is never compared against the
file — so leave it alone unless you add or drop an id there.

### 3. Open a PR

```bash
git switch -c templates/<short-description>
git add assets/starter-templates.json
git commit -m "content(templates): <what changed and why>"
git push -u origin HEAD
gh pr create --title "content(templates): <what changed>" --body "<what and why>"
```

Name the old and new template in the PR body, and why it changed. A swap,
feature or paid change touches only `assets/starter-templates.json`. Add
`scripts/starter-templates.spec.mjs` to the commit only if you introduced or
removed an id that the `TABS` fixture references. Nothing else should change;
if `git status` shows more, you edited the JSON by hand instead of running the
script.

### 4. Report back

Tell the user which template replaced which, and that it reaches users on their
next app launch once the PR merges. Nothing ships before then.

## What the script refuses

These fail silently in the app, so they fail here instead.

- Exactly 4 templates per tab.
- Exactly 1 featured per tab, and it must be free.
- Exactly 1 paid (API-node) template per tab.
- Every id must exist in the live template index.
- No duplicate ids anywhere, including across tabs.
- Ids and text within the app's length caps.

## If something fails

`is not in the template index` — the id is wrong or was renamed upstream. Run
`list` for that modality and pick from the output.

`cannot be both --recommended and paid` — the featured card must be free. Ask
which the user meant.

`needs exactly 1 paid template` — a tab lost or gained its API-node card. Use
`--replaces` to swap like for like.

`could not read the template index` — the live index is unreachable. This is
network, not input. Retry rather than changing the request.

First run in a fresh clone: see [setup.md](setup.md). Needs Node 22 and
`gh auth login`, no build step.
67 changes: 67 additions & 0 deletions .claude/skills/starter-templates/setup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# First-time setup

Everything below is one-time. After it, changing a template is one sentence to
Claude.

## What you need

**Node 22+** — check with `node --version`. If it's missing or older, install
from [nodejs.org](https://nodejs.org) (take the LTS build).

**The repo:**

```bash
git clone https://github.com/Comfy-Org/Comfy-Desktop.git
cd Comfy-Desktop
```

You do **not** need to install dependencies or build the app. The template
script runs on Node alone.

**GitHub CLI**, so Claude can open the PR for you:

```bash
gh auth login
```

Pick GitHub.com, HTTPS, and authenticate in the browser.

## Check it works

```bash
node scripts/starter-templates.mjs validate
```

Expected:

```
✓ 16 templates, 4 per tab, rules hold
```

If you see that, you are done.

## Using it

Open Claude Code in the repo folder and ask in plain English:

> swap the recommended video template to Wan 2.2

Claude finds the id, makes the change, validates it, and opens a PR for review.
You can also run `/starter-templates` to invoke it directly.

You never edit JSON by hand. You only ever choose which template goes where.

## If something goes wrong

**`node: command not found`** — Node is not installed, or the terminal needs
reopening after installing it.

**`could not read the template index`** — no internet, or GitHub is blocked.
The script reads the live template list from raw.githubusercontent.com.

**`"<id>" is not in the template index`** — that template id does not exist
upstream. Run `node scripts/starter-templates.mjs list --modality video` to see
what is available.

**Anything else** — paste the error into Claude Code. The messages are written
to say what to do next.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
* text=auto eol=lf
*.sh text eol=lf
6 changes: 6 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Agent instructions
**/AGENTS.md @benceruleanlu @deepme987 @Kosinkadink
# Root-anchored rule so the top-level AGENTS.md has an explicit DRI (a bare
# `**/`-prefixed pattern doesn't match a repo-root file in every CODEOWNERS
# reader).
/AGENTS.md @benceruleanlu @deepme987 @Kosinkadink
109 changes: 109 additions & 0 deletions .github/scripts/check-gcs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#!/usr/bin/env bash
# Reports what the mirror service account can do. Uses the JSON API with the
# token `google-github-actions/auth` exports, rather than the gcloud CLI.
set -uo pipefail

BUCKET=comfy-desktop-public
PREFIX=standalone-environments
KEY="$PREFIX/.credential-check-${GITHUB_RUN_ID:-local}.json"

say() {
echo "$1"
[ -n "${GITHUB_STEP_SUMMARY:-}" ] && echo "$1" >> "$GITHUB_STEP_SUMMARY"
return 0
}

say "### GCS mirror"

TMP=$(mktemp -d)
trap 'rm -rf "$TMP"' EXIT

CREDS="${GOOGLE_APPLICATION_CREDENTIALS:-}"
if [ -z "$CREDS" ] || [ ! -f "$CREDS" ]; then
say "- **No credentials were exported by the auth step.**"
exit 1
fi
say "- Service account: \`$(jq -r '.client_email // "unknown"' "$CREDS")\`"
say "- Project: \`$(jq -r '.project_id // "unknown"' "$CREDS")\`"

# Mint an access token from the service-account key.
TOKEN=$(python3 - "$CREDS" <<'PY'
import base64, json, sys, time, urllib.parse, urllib.request
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding

key = json.load(open(sys.argv[1]))
b64 = lambda d: base64.urlsafe_b64encode(d).rstrip(b'=')
now = int(time.time())
claim = {
"iss": key["client_email"],
"scope": "https://www.googleapis.com/auth/devstorage.read_write",
"aud": key["token_uri"],
"iat": now,
"exp": now + 300,
}
signing_input = b64(json.dumps({"alg": "RS256", "typ": "JWT"}).encode()) + b"." + b64(json.dumps(claim).encode())
signature = serialization.load_pem_private_key(key["private_key"].encode(), password=None).sign(
signing_input, padding.PKCS1v15(), hashes.SHA256()
)
assertion = (signing_input + b"." + b64(signature)).decode()
body = urllib.parse.urlencode({
"grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
"assertion": assertion,
}).encode()
try:
with urllib.request.urlopen(urllib.request.Request(key["token_uri"], data=body), timeout=30) as r:
print(json.load(r)["access_token"])
except Exception as e:
print("", end="")
sys.stderr.write(f"token exchange failed: {e}\n")
PY
)

if [ -z "$TOKEN" ]; then
say "- **Could not mint an access token from the key.** It may be disabled or malformed."
exit 1
fi
say "- Minted an access token"

read_code=$(curl -sS --connect-timeout 10 --max-time 30 -o /dev/null -w '%{http_code}' \
"https://storage.googleapis.com/storage/v1/b/$BUCKET/o/$(printf %s "$PREFIX/starter-templates.json" | jq -sRr @uri)" \
-H "Authorization: Bearer $TOKEN")
say "- Read the published file: HTTP $read_code (404 just means it is not there yet)"

echo '{"check":true}' > "$TMP/check.json"
write_code=$(curl -sS --connect-timeout 10 --max-time 30 -o "$TMP/gcs-write.json" -w '%{http_code}' -X POST \
"https://storage.googleapis.com/upload/storage/v1/b/$BUCKET/o?uploadType=media&name=$(printf %s "$KEY" | jq -sRr @uri)" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
--data-binary @"$TMP/check.json")
say "- Write a throwaway object: HTTP $write_code"

if [ "$write_code" = "200" ]; then
# Publishing overwrites an existing object, which a create-only credential
# cannot do, so prove overwrite rather than just create.
again=$(curl -sS --connect-timeout 10 --max-time 30 -o /dev/null -w '%{http_code}' -X POST \
"https://storage.googleapis.com/upload/storage/v1/b/$BUCKET/o?uploadType=media&name=$(printf %s "$KEY" | jq -sRr @uri)" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
--data-binary @"$TMP/check.json")
say "- Overwrite the same object: HTTP $again"

del=$(curl -sS --connect-timeout 10 --max-time 30 -o /dev/null -w '%{http_code}' -X DELETE \
"https://storage.googleapis.com/storage/v1/b/$BUCKET/o/$(printf %s "$KEY" | jq -sRr @uri)" \
-H "Authorization: Bearer $TOKEN")
say "- Delete the throwaway object: HTTP $del"

if [ "$again" != "200" ]; then
say "- **Create works but overwrite does not, so publishing would fail.**"
say "- Ask for: Storage Object Admin on \`$BUCKET\`, not just object create."
exit 1
fi
if [ "$del" != "204" ] && [ "$del" != "200" ]; then
say "- Left \`$KEY\` behind; the credential cannot delete."
fi
say "- **Mirror is ready to publish.**"
exit 0
fi

say "- Refused: \`$(jq -c '.error.message' "$TMP/gcs-write.json" 2>/dev/null || cat "$TMP/gcs-write.json")\`"
say "- **Ask for: Storage Object Admin on \`$BUCKET\` for this service account.**"
exit 1
Loading
Loading