pixelkiln 0.80.0 → 0.81.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +26 -18
- package/dist/cli.js.map +1 -1
- package/dist/client/gallery.css +42 -1
- package/dist/client/gallery.js +136 -5
- package/dist/index.cjs +26 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +26 -18
- package/dist/index.js.map +1 -1
- package/docs/CLI.md +13 -3
- package/package.json +1 -1
package/dist/client/gallery.css
CHANGED
|
@@ -84,7 +84,7 @@ section.project { border-bottom:1px solid var(--line-strong); background:var(--p
|
|
|
84
84
|
.card:hover { border-color:var(--line-strong); }
|
|
85
85
|
.card.active { border-color:var(--accent); box-shadow:0 0 0 2px color-mix(in srgb, var(--accent) 25%, transparent); }
|
|
86
86
|
.card.ghost { border-style:dashed; background:transparent; }
|
|
87
|
-
.cell { height:132px; display:grid; place-items:center; background-color:var(--stage-bg);
|
|
87
|
+
.cell { height:132px; flex:none; display:grid; place-items:center; background-color:var(--stage-bg);
|
|
88
88
|
background-image:var(--stage-pattern); background-size:12px 12px; background-position:0 0,6px 6px;
|
|
89
89
|
overflow:hidden; position:relative; padding:8px; }
|
|
90
90
|
.card.ghost .cell { background-image:none; background-color:var(--panel-deep); color:var(--dim); font-size:12px; }
|
|
@@ -484,3 +484,44 @@ td.col-on { background:rgba(255,107,53,.08); }
|
|
|
484
484
|
.dtabs .tablist button.on { color:var(--accent-soft); border-bottom-color:var(--accent); }
|
|
485
485
|
.dtabs .tabpanel[hidden] { display:none; }
|
|
486
486
|
.dtabs .tabpanel > section.meta:first-child { border-top:0; }
|
|
487
|
+
|
|
488
|
+
/* ---- View menu, card sizes, tag chips, shortcut sheet ---- */
|
|
489
|
+
.bar { flex-wrap:nowrap; }
|
|
490
|
+
.bar > button, .bar > .editing { white-space:nowrap; flex:none; }
|
|
491
|
+
.bar .search { flex:0 1 360px; min-width:180px; }
|
|
492
|
+
.menu { position:relative; }
|
|
493
|
+
.menu > summary { list-style:none; cursor:pointer; padding:6px 11px; border:1px solid var(--line); white-space:nowrap; }
|
|
494
|
+
.menu > summary::-webkit-details-marker { display:none; }
|
|
495
|
+
.menu > summary::after { content:' ▾'; color:var(--dim); font-size:11px; }
|
|
496
|
+
.menu[open] > summary { border-color:var(--accent); color:var(--accent-soft); }
|
|
497
|
+
.menu-panel { position:absolute; right:0; top:calc(100% + 6px); z-index:15; width:300px; display:grid; gap:10px;
|
|
498
|
+
padding:12px; background:var(--panel); border:1px solid var(--line-strong); box-shadow:0 10px 30px rgba(0,0,0,.45); }
|
|
499
|
+
.menu-row { display:grid; grid-template-columns:78px 1fr; align-items:center; gap:10px; font-size:12.5px; }
|
|
500
|
+
.menu-row > span:first-child { color:var(--dim); font:600 11.5px/1 var(--mono); }
|
|
501
|
+
.menu-row.check { display:flex; gap:8px; color:var(--text); }
|
|
502
|
+
.menu-row[hidden] { display:none; }
|
|
503
|
+
.menu-row select { width:100%; }
|
|
504
|
+
.seg { display:inline-flex; }
|
|
505
|
+
.seg button { padding:4px 12px; font:600 12px/1 var(--mono); }
|
|
506
|
+
.seg button + button { border-left:0; }
|
|
507
|
+
.seg button.on { background:var(--panel-deep); color:var(--accent-soft); border-color:var(--accent); }
|
|
508
|
+
#keys { width:32px; padding:6px 0; font:700 13px/1 var(--mono); }
|
|
509
|
+
body[data-size="s"] .grid { grid-template-columns:repeat(auto-fill, minmax(132px, 1fr)); gap:8px; }
|
|
510
|
+
body[data-size="s"] .cell { height:96px; }
|
|
511
|
+
/* A card not yet drawn holds this size (content-visibility), so it has to match the card size. */
|
|
512
|
+
body[data-size="s"] .card { contain-intrinsic-size:auto 132px auto 160px; }
|
|
513
|
+
body[data-size="l"] .card { contain-intrinsic-size:auto 260px auto 275px; }
|
|
514
|
+
body[data-size="s"] .cbody { padding:6px 8px; }
|
|
515
|
+
body[data-size="l"] .grid { grid-template-columns:repeat(auto-fill, minmax(260px, 1fr)); }
|
|
516
|
+
body[data-size="l"] .cell { height:210px; }
|
|
517
|
+
.chip.tag { font-family:var(--mono); }
|
|
518
|
+
.keys-sheet { background:var(--panel); border:1px solid var(--accent); width:min(620px, calc(100vw - 32px)); max-height:calc(100vh - 64px);
|
|
519
|
+
overflow-y:auto; padding:16px 18px; display:grid; gap:14px; }
|
|
520
|
+
.keys-head { display:flex; align-items:center; justify-content:space-between; }
|
|
521
|
+
.keys-sheet h3 { margin:0; font:650 14px/1.2 var(--mono); }
|
|
522
|
+
.keys-sheet h4 { margin:0 0 6px; font:650 12px/1 var(--mono); color:var(--accent-soft); }
|
|
523
|
+
.keys-sheet dl { display:grid; grid-template-columns:150px 1fr; gap:6px 16px; margin:0; font-size:13px; }
|
|
524
|
+
.keys-sheet dt { white-space:nowrap; }
|
|
525
|
+
.keys-sheet dd { margin:0; color:var(--dim); }
|
|
526
|
+
.keys-sheet kbd { font:600 11.5px/1 var(--mono); border:1px solid var(--line-strong); border-bottom-width:2px; padding:2px 6px; }
|
|
527
|
+
@media (max-width: 900px) { .bar { flex-wrap:wrap; } }
|
package/dist/client/gallery.js
CHANGED
|
@@ -47,16 +47,26 @@
|
|
|
47
47
|
onion: false,
|
|
48
48
|
selecting: false,
|
|
49
49
|
selected: /* @__PURE__ */ new Set(),
|
|
50
|
-
drawerTab: "overview"
|
|
50
|
+
drawerTab: "overview",
|
|
51
|
+
tags: /* @__PURE__ */ new Set(),
|
|
52
|
+
size: "m"
|
|
51
53
|
};
|
|
54
|
+
var CARD_SIZES = {
|
|
55
|
+
s: { box: [112, 80], tile: [48, 36] },
|
|
56
|
+
m: { box: [156, 116], tile: [66, 52] },
|
|
57
|
+
l: { box: [240, 190], tile: [108, 88] }
|
|
58
|
+
};
|
|
59
|
+
var declaredTags = (item) => item.asset && Array.isArray(item.asset.tags) ? item.asset.tags : [];
|
|
52
60
|
var PREFS_KEY = "pixelkiln.gallery.prefs";
|
|
53
|
-
var PREF_NAMES = ["playLoops", "backdrop", "notify", "onion", "drawerTab"];
|
|
61
|
+
var PREF_NAMES = ["playLoops", "backdrop", "notify", "onion", "drawerTab", "size"];
|
|
54
62
|
function loadPrefs() {
|
|
55
63
|
try {
|
|
56
64
|
const saved = JSON.parse(localStorage.getItem(PREFS_KEY) || "{}");
|
|
57
65
|
for (const name of PREF_NAMES) if (typeof saved[name] === typeof ui[name]) ui[name] = saved[name];
|
|
58
66
|
} catch {
|
|
59
67
|
}
|
|
68
|
+
if (!CARD_SIZES[ui.size]) ui.size = "m";
|
|
69
|
+
document.body.dataset.size = ui.size;
|
|
60
70
|
applyBackdrop();
|
|
61
71
|
}
|
|
62
72
|
function savePrefs() {
|
|
@@ -1197,6 +1207,7 @@
|
|
|
1197
1207
|
if (ui.providers.size && !ui.providers.has(item.provider)) return false;
|
|
1198
1208
|
if (ui.generators.size && !ui.generators.has(item.generator)) return false;
|
|
1199
1209
|
if (ui.projects.size && !ui.projects.has(item.project ?? "")) return false;
|
|
1210
|
+
if (ui.tags.size && !declaredTags(item).some((t) => ui.tags.has(t))) return false;
|
|
1200
1211
|
if (!q) return true;
|
|
1201
1212
|
const hay = [
|
|
1202
1213
|
item.id,
|
|
@@ -1304,7 +1315,19 @@
|
|
|
1304
1315
|
chips.append(el("span", "sep"));
|
|
1305
1316
|
for (const [k, v] of [...byGen].sort()) chips.append(chip(k, v, ui.generators, k));
|
|
1306
1317
|
}
|
|
1307
|
-
|
|
1318
|
+
const byTag = /* @__PURE__ */ new Map();
|
|
1319
|
+
for (const item of S.snap.items) for (const t2 of declaredTags(item)) byTag.set(t2, (byTag.get(t2) || 0) + 1);
|
|
1320
|
+
for (const t2 of ui.tags) if (!byTag.has(t2)) byTag.set(t2, 0);
|
|
1321
|
+
if (byTag.size) {
|
|
1322
|
+
chips.append(el("span", "sep"));
|
|
1323
|
+
for (const [k, v] of [...byTag].sort()) {
|
|
1324
|
+
const c = chip("#" + k, v, ui.tags, k);
|
|
1325
|
+
c.classList.add("tag");
|
|
1326
|
+
c.title = "Assets tagged “" + k + "” in the manifest";
|
|
1327
|
+
chips.append(c);
|
|
1328
|
+
}
|
|
1329
|
+
}
|
|
1330
|
+
if (ui.states.size || ui.providers.size || ui.generators.size || ui.projects.size || ui.tags.size || ui.q) {
|
|
1308
1331
|
const clear = el("button", "chip", "clear filters");
|
|
1309
1332
|
clear.type = "button";
|
|
1310
1333
|
clear.onclick = () => clearFilters();
|
|
@@ -1316,6 +1339,7 @@
|
|
|
1316
1339
|
ui.providers.clear();
|
|
1317
1340
|
ui.generators.clear();
|
|
1318
1341
|
ui.projects.clear();
|
|
1342
|
+
ui.tags.clear();
|
|
1319
1343
|
ui.q = "";
|
|
1320
1344
|
$("q").value = "";
|
|
1321
1345
|
render();
|
|
@@ -1337,7 +1361,7 @@
|
|
|
1337
1361
|
img2.src = o.url;
|
|
1338
1362
|
img2.alt = o.role || item.assetId;
|
|
1339
1363
|
img2.loading = "lazy";
|
|
1340
|
-
const s2 = displayScale(w, h,
|
|
1364
|
+
const s2 = displayScale(w, h, ...CARD_SIZES[ui.size].tile);
|
|
1341
1365
|
if (s2 >= 1) {
|
|
1342
1366
|
img2.width = w * s2;
|
|
1343
1367
|
img2.height = h * s2;
|
|
@@ -1352,7 +1376,7 @@
|
|
|
1352
1376
|
img.src = shown[0].url;
|
|
1353
1377
|
img.alt = item.assetId;
|
|
1354
1378
|
img.loading = "lazy";
|
|
1355
|
-
const s = displayScale(w, h,
|
|
1379
|
+
const s = displayScale(w, h, ...CARD_SIZES[ui.size].box);
|
|
1356
1380
|
if (s >= 1) {
|
|
1357
1381
|
img.width = w * s;
|
|
1358
1382
|
img.height = h * s;
|
|
@@ -4489,6 +4513,7 @@
|
|
|
4489
4513
|
ui.states = new Set(list("state"));
|
|
4490
4514
|
ui.providers = new Set(list("provider"));
|
|
4491
4515
|
ui.generators = new Set(list("generator"));
|
|
4516
|
+
ui.tags = new Set(list("tag"));
|
|
4492
4517
|
ui.projects = new Set(list("project"));
|
|
4493
4518
|
ui.compare = list("compare").slice(0, 4);
|
|
4494
4519
|
if (["key", "newest", "oldest", "cost", "size"].includes(params.get("sort") ?? "")) ui.sort = params.get("sort");
|
|
@@ -4500,6 +4525,7 @@
|
|
|
4500
4525
|
if (ui.states.size) params.set("state", [...ui.states].join(","));
|
|
4501
4526
|
if (ui.providers.size) params.set("provider", [...ui.providers].join(","));
|
|
4502
4527
|
if (ui.generators.size) params.set("generator", [...ui.generators].join(","));
|
|
4528
|
+
if (ui.tags.size) params.set("tag", [...ui.tags].join(","));
|
|
4503
4529
|
if (ui.projects.size) params.set("project", [...ui.projects].join(","));
|
|
4504
4530
|
if (ui.compare.length) params.set("compare", ui.compare.join(","));
|
|
4505
4531
|
if (ui.sort !== "key") params.set("sort", ui.sort);
|
|
@@ -5061,10 +5087,104 @@
|
|
|
5061
5087
|
setTimeout(() => baseId.focus(), 0);
|
|
5062
5088
|
}
|
|
5063
5089
|
|
|
5090
|
+
// src/gallery/client/src/keys.ts
|
|
5091
|
+
var GROUPS = [
|
|
5092
|
+
{
|
|
5093
|
+
title: "Anywhere",
|
|
5094
|
+
keys: [
|
|
5095
|
+
[["/"], "jump to search"],
|
|
5096
|
+
[["?"], "this list"],
|
|
5097
|
+
[["Esc"], "close whatever is open: a sheet, the record, the View menu, or select mode"]
|
|
5098
|
+
]
|
|
5099
|
+
},
|
|
5100
|
+
{
|
|
5101
|
+
title: "On the grid",
|
|
5102
|
+
keys: [
|
|
5103
|
+
[["click"], "open a record"],
|
|
5104
|
+
[["shift", "click"], "add it to a side-by-side comparison (up to four)"],
|
|
5105
|
+
[["ctrl/⌘", "click"], "select it; the bar at the bottom acts on the selection"],
|
|
5106
|
+
[["hover"], "play a loop"]
|
|
5107
|
+
]
|
|
5108
|
+
},
|
|
5109
|
+
{
|
|
5110
|
+
title: "With a record open",
|
|
5111
|
+
keys: [
|
|
5112
|
+
[["←", "→"], "step through the records in view"],
|
|
5113
|
+
[[",", "."], "step a loop one frame back or on"],
|
|
5114
|
+
[["space"], "play or pause a loop"],
|
|
5115
|
+
[["←", "→"], "switch tabs, once a tab has focus"]
|
|
5116
|
+
]
|
|
5117
|
+
},
|
|
5118
|
+
{
|
|
5119
|
+
title: "In the family view",
|
|
5120
|
+
keys: [
|
|
5121
|
+
[["drag"], "turn the sprite on the turntable"],
|
|
5122
|
+
[["←", "→"], "turn it a step, once the turntable has focus"]
|
|
5123
|
+
]
|
|
5124
|
+
}
|
|
5125
|
+
];
|
|
5126
|
+
function openShortcuts() {
|
|
5127
|
+
const host = $("dialog-host");
|
|
5128
|
+
host.textContent = "";
|
|
5129
|
+
const wrap = el("div", "dialog");
|
|
5130
|
+
wrap.onclick = (e) => {
|
|
5131
|
+
if (e.target === wrap) host.textContent = "";
|
|
5132
|
+
};
|
|
5133
|
+
const box = el("div", "keys-sheet");
|
|
5134
|
+
box.setAttribute("role", "dialog");
|
|
5135
|
+
box.setAttribute("aria-label", "Keyboard shortcuts");
|
|
5136
|
+
const head = el("div", "keys-head");
|
|
5137
|
+
head.append(el("h3", null, "Keyboard shortcuts"));
|
|
5138
|
+
const close = el("button", null, "Close");
|
|
5139
|
+
close.type = "button";
|
|
5140
|
+
close.onclick = () => {
|
|
5141
|
+
host.textContent = "";
|
|
5142
|
+
};
|
|
5143
|
+
head.append(close);
|
|
5144
|
+
box.append(head);
|
|
5145
|
+
for (const group of GROUPS) {
|
|
5146
|
+
const section2 = el("section");
|
|
5147
|
+
section2.append(el("h4", null, group.title));
|
|
5148
|
+
const dl = el("dl");
|
|
5149
|
+
for (const [keys, what] of group.keys) {
|
|
5150
|
+
const dt = el("dt");
|
|
5151
|
+
keys.forEach((k, i) => {
|
|
5152
|
+
if (i) dt.append(document.createTextNode(k === "click" ? "+" : " "));
|
|
5153
|
+
dt.append(el("kbd", null, k));
|
|
5154
|
+
});
|
|
5155
|
+
dl.append(dt, el("dd", null, what));
|
|
5156
|
+
}
|
|
5157
|
+
section2.append(dl);
|
|
5158
|
+
box.append(section2);
|
|
5159
|
+
}
|
|
5160
|
+
wrap.append(box);
|
|
5161
|
+
host.append(wrap);
|
|
5162
|
+
close.focus();
|
|
5163
|
+
}
|
|
5164
|
+
|
|
5064
5165
|
// src/gallery/client/src/main.ts
|
|
5065
5166
|
loadPrefs();
|
|
5066
5167
|
$("refresh").onclick = refresh;
|
|
5067
5168
|
$("select").onclick = () => setSelecting(!ui.selecting);
|
|
5169
|
+
$("keys").onclick = openShortcuts;
|
|
5170
|
+
var syncSize = () => {
|
|
5171
|
+
for (const b of $("size").querySelectorAll("button")) b.classList.toggle("on", b.dataset.size === ui.size);
|
|
5172
|
+
};
|
|
5173
|
+
for (const b of $("size").querySelectorAll("button")) {
|
|
5174
|
+
b.onclick = () => {
|
|
5175
|
+
if (!CARD_SIZES[b.dataset.size]) return;
|
|
5176
|
+
ui.size = b.dataset.size;
|
|
5177
|
+
document.body.dataset.size = ui.size;
|
|
5178
|
+
savePrefs();
|
|
5179
|
+
syncSize();
|
|
5180
|
+
render();
|
|
5181
|
+
};
|
|
5182
|
+
}
|
|
5183
|
+
syncSize();
|
|
5184
|
+
document.addEventListener("click", (e) => {
|
|
5185
|
+
const menu = $("view-menu");
|
|
5186
|
+
if (menu.open && !menu.contains(e.target)) menu.open = false;
|
|
5187
|
+
});
|
|
5068
5188
|
$("playloops").checked = ui.playLoops;
|
|
5069
5189
|
$("playloops").onchange = (e) => {
|
|
5070
5190
|
setPlayLoops(e.target.checked);
|
|
@@ -5109,7 +5229,18 @@
|
|
|
5109
5229
|
$("q").focus();
|
|
5110
5230
|
return;
|
|
5111
5231
|
}
|
|
5232
|
+
if (e.key === "?" && !typing) {
|
|
5233
|
+
e.preventDefault();
|
|
5234
|
+
openShortcuts();
|
|
5235
|
+
return;
|
|
5236
|
+
}
|
|
5112
5237
|
if (e.key === "Escape") {
|
|
5238
|
+
if ($("view-menu").open) {
|
|
5239
|
+
e.preventDefault();
|
|
5240
|
+
$("view-menu").open = false;
|
|
5241
|
+
$("view-menu").querySelector("summary").focus();
|
|
5242
|
+
return;
|
|
5243
|
+
}
|
|
5113
5244
|
if (typing && document.activeElement?.id === "q") {
|
|
5114
5245
|
document.activeElement.blur();
|
|
5115
5246
|
return;
|
package/dist/index.cjs
CHANGED
|
@@ -17063,26 +17063,35 @@ ${css}</style>
|
|
|
17063
17063
|
<span class="project" id="project"></span>
|
|
17064
17064
|
<span class="grow"></span>
|
|
17065
17065
|
<label class="search"><input id="q" type="search" placeholder="Search assets, prompts, ids, hashes" autocomplete="off"><kbd>/</kbd></label>
|
|
17066
|
-
<
|
|
17067
|
-
<
|
|
17068
|
-
<
|
|
17069
|
-
|
|
17070
|
-
|
|
17071
|
-
|
|
17072
|
-
|
|
17073
|
-
|
|
17074
|
-
|
|
17075
|
-
|
|
17076
|
-
|
|
17077
|
-
|
|
17066
|
+
<details class="menu" id="view-menu">
|
|
17067
|
+
<summary title="Sort, group, card size, backdrop, and playback">View</summary>
|
|
17068
|
+
<div class="menu-panel">
|
|
17069
|
+
<label class="menu-row"><span>Sort</span><select id="sort" aria-label="Sort">
|
|
17070
|
+
<option value="key">style / asset</option>
|
|
17071
|
+
<option value="newest">newest first</option>
|
|
17072
|
+
<option value="oldest">oldest first</option>
|
|
17073
|
+
<option value="cost">cost</option>
|
|
17074
|
+
<option value="size">size</option>
|
|
17075
|
+
</select></label>
|
|
17076
|
+
<label class="menu-row"><span>Group</span><select id="group" aria-label="Group">
|
|
17077
|
+
<option value="style">by style</option>
|
|
17078
|
+
<option value="family">by family</option>
|
|
17079
|
+
<option value="none">none</option>
|
|
17080
|
+
</select></label>
|
|
17081
|
+
<div class="menu-row"><span>Cards</span><span class="seg" id="size" role="group" aria-label="Card size">
|
|
17082
|
+
<button type="button" data-size="s" title="Small cards: more on screen">S</button><button type="button" data-size="m" title="Medium cards">M</button><button type="button" data-size="l" title="Large cards: sprites drawn bigger">L</button>
|
|
17083
|
+
</span></div>
|
|
17084
|
+
<div class="menu-row"><span>Backdrop</span><span id="backdrop-slot"></span></div>
|
|
17085
|
+
<label class="menu-row check" title="Play every loop on the grid; without this, a loop plays while the pointer is over it"><input id="playloops" type="checkbox"> Play every loop</label>
|
|
17086
|
+
<label class="menu-row check" title="Refresh every 5 seconds while this tab is visible"><input id="auto" type="checkbox"> Refresh every 5 seconds</label>
|
|
17087
|
+
<label class="menu-row check" id="notify-chip" hidden title="A system notification when a job finishes while this tab is in the background"><input id="notify" type="checkbox"> Notify when a job finishes</label>
|
|
17088
|
+
</div>
|
|
17089
|
+
</details>
|
|
17078
17090
|
<span id="editing" class="editing" hidden title="This gallery can write the manifest. It never contacts a provider.">editing</span>
|
|
17079
17091
|
<button id="select" type="button" title="Pick several records to generate, regenerate, compare, or tag together (or ctrl/\u2318-click a card)">Select</button>
|
|
17080
17092
|
<button id="studio" type="button" hidden title="Draft a new character: its style, base, loops, and portrait, priced as you go">+ New character</button>
|
|
17081
17093
|
<button id="refresh" type="button" title="Re-read the manifest, lockfile, and disk">Refresh</button>
|
|
17082
|
-
<
|
|
17083
|
-
<label class="chip" title="Play every loop on the grid; without this, a loop plays while the pointer is over it"><input id="playloops" type="checkbox"> play loops</label>
|
|
17084
|
-
<span id="backdrop-slot"></span>
|
|
17085
|
-
<label class="chip" id="notify-chip" hidden title="A system notification when a job finishes while this tab is in the background"><input id="notify" type="checkbox"> notify</label>
|
|
17094
|
+
<button id="keys" type="button" title="Keyboard shortcuts (?)" aria-label="Keyboard shortcuts">?</button>
|
|
17086
17095
|
</div>
|
|
17087
17096
|
<div class="totals" id="totals"></div>
|
|
17088
17097
|
<div class="chips" id="chips"></div>
|
|
@@ -17092,8 +17101,7 @@ ${css}</style>
|
|
|
17092
17101
|
<main id="root"></main>
|
|
17093
17102
|
<div id="selbar" class="selbar" hidden></div>
|
|
17094
17103
|
<footer>
|
|
17095
|
-
Click a sprite for its full record; <kbd>
|
|
17096
|
-
is open, <kbd>,</kbd>/<kbd>.</kbd> step a loop's frames and <kbd>space</kbd> plays it, <kbd>Esc</kbd> closes it, and <kbd>/</kbd> jumps to search. This page reads the manifest, lockfile,
|
|
17104
|
+
Click a sprite for its full record; press <kbd>?</kbd> for every keyboard shortcut. This page reads the manifest, lockfile,
|
|
17097
17105
|
and disk only. It never contacts a provider<span id="foot-edit"> and never writes anything</span><span id="foot-editing" hidden>.
|
|
17098
17106
|
Editing is on: saving rewrites the manifest and nothing else</span><span id="foot-gen" hidden>.
|
|
17099
17107
|
Generation is on under the session budget shown above; every run is the same submit, poll, and fetch as <code>pixelkiln gen</code></span>.
|