KLDH262
Local-first desktop library for AI-generated images — indexes in place, never moves a file.
The problem
A folder of ten thousand AI generations named 00042_.png is write-only memory. KLDH262 indexes those folders in place — never moving or copying a file — by reading the generation metadata that ComfyUI, Automatic1111, and Civitai embed in each image: prompt, negative prompt, seed, steps, sampler, checkpoint, and the full LoRA stack.
All derived data — tags, ratings, characters, albums — lives in one JSON catalogue outside the image folders. No account, no server, no telemetry.
Hand-rolled binary parsers
The metadata layer reads PNG tEXt/iTXt/zTXt chunks directly, walks ComfyUI's node graph backward from the sampler through the LoRA chain to the checkpoint, and parses A1111 parameter blocks from both PNG text and EXIF. On a real mixed library it recovers a full generation record for roughly 96% of files.
/**
* Walks a PNG's chunk list and pulls out IHDR dimensions plus every text
* chunk. Both generators stash their parameters here: ComfyUI writes the
* node graph as `prompt`, A1111 writes its parameter string as `parameters`.
*/
function readPng(buf: Buffer): { w: number; h: number; texts: PngText[] } | null {
if (buf.length < 8 || buf.readUInt32BE(0) !== 0x89504e47) return null;
const texts: PngText[] = [];
let w = 0, h = 0, off = 8;
while (off + 8 <= buf.length) {
const len = buf.readUInt32BE(off);
const type = buf.toString('ascii', off + 4, off + 8);
const start = off + 8;
const end = start + len;
if (end > buf.length) break;
if (type === 'IHDR') {
w = buf.readUInt32BE(start);
h = buf.readUInt32BE(start + 4);
} else if (type === 'tEXt') {
const data = buf.subarray(start, end);
const nul = data.indexOf(0);
if (nul > 0) {
texts.push({
keyword: data.toString('latin1', 0, nul),
text: data.toString('latin1', nul + 1),
});
}
} else if (type === 'iTXt') {
/* keyword \0 compressed? \0 langTag \0 translated \0 text —
malformed chunks are skipped rather than failing the file */
// …
}
off = end + 4; // skip CRC
}
return { w, h, texts };
}Small ML, no cloud
Two features most apps would ship as API calls are computed locally. A naive-Bayes-style 18+ classifier learns from the user's own labels — combining prompt terms, LoRA identity, and a skin-chroma histogram — and deliberately under-calls, because a human confirms each batch. "Find more like these" builds a TF-IDF centroid over prompt terms, LoRA overlap, and color composition, on the argument that for synthetic images the generation record is a stronger signal than any face embedding.
Duplicate detection uses two distinct perceptual hashes for two distinct questions: a 64-bit difference hash for "is this the same picture" and a color signature for "does this look alike".
Engineering discipline
The renderer has no filesystem or network access at all: 51 named IPC channels, media served over a custom protocol addressed by ID so no path ever crosses the boundary, and API tokens encrypted via the OS keychain. State lives in a 1,000-line pure reducer handling 107 action types with no Date.now() or Math.random() inside — React StrictMode's double-invoke is a true no-op.
Zero native modules — image decoding, thumbnailing, and hashing all go through Chromium — so CI builds installers for Windows, Linux, and macOS from one codebase with nothing to compile.
— capture coming soon —
— capture coming soon —
Built with
Every technology this project runs on, and the job it does here. Each one links to the other projects it appears in.