{"_id":"11img","name":"11img","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"11img","version":"0.1.0","description":"Identity & permanence layer over the ElevenLabs image API: reference coercion, asset auto-promotion, generation chaining, a content-addressed batch cache, and a CLI.","type":"module","license":"MIT","author":{"name":"Bernardo Castro","email":"me@bernardocastro.dev"},"homepage":"https://github.com/bernatch22/11img#readme","repository":{"type":"git","url":"git+https://github.com/bernatch22/11img.git"},"bugs":{"url":"https://github.com/bernatch22/11img/issues"},"keywords":["elevenlabs","image-generation","gpt-image","gemini","seedream","cli","text-to-image","reference-images"],"engines":{"node":">=20"},"main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"bin":{"11img":"dist/cli/main.js"},"publishConfig":{"access":"public"},"scripts":{"build":"tsc -p tsconfig.json","typecheck":"tsc -p tsconfig.json --noEmit","dev":"tsc -p tsconfig.json --watch","prepublishOnly":"npm run build"},"dependencies":{"@elevenlabs/elevenlabs-js":"^2.64.0"},"devDependencies":{"@types/node":"^22.10.0","typescript":"^5.7.0"},"gitHead":"2ae40f21bb0804a275e7991d9b654461fcaec6f0","_id":"11img@0.1.0","_nodeVersion":"24.14.0","_npmVersion":"11.9.0","dist":{"integrity":"sha512-5wuRyR5RAW855J/u9Oo+vJqnJmR/l3fWY+8y928Cx1CSwMLBsgh8y9Qg4EiS9ED5NUkf5tZRkJ6Eia4/Y1fVpg==","shasum":"3c83ad7c41e4fa5588bcfb851f5159a4a86c7f3a","tarball":"https://registry.npmjs.org/11img/-/11img-0.1.0.tgz","fileCount":40,"unpackedSize":110581,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCtWwK3Qoa4QJWtqsxC2Lc8bfXwoVfMFxAvjFuqJq7glgIgCBp7tvy7uouNBXlCV9sYsbBl4PQs/Znd577cvGBVc44="}]},"_npmUser":{"name":"bernatch22","email":"bernatchx22@gmail.com"},"directories":{},"maintainers":[{"name":"bernatch22","email":"bernatchx22@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/11img_0.1.0_1786869362821_0.8222721482496167"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-16T08:36:02.662Z","0.1.0":"2026-08-16T08:36:02.961Z","modified":"2026-08-16T08:36:03.147Z"},"maintainers":[{"name":"bernatch22","email":"bernatchx22@gmail.com"}],"description":"Identity & permanence layer over the ElevenLabs image API: reference coercion, asset auto-promotion, generation chaining, a content-addressed batch cache, and a CLI.","homepage":"https://github.com/bernatch22/11img#readme","keywords":["elevenlabs","image-generation","gpt-image","gemini","seedream","cli","text-to-image","reference-images"],"repository":{"type":"git","url":"git+https://github.com/bernatch22/11img.git"},"author":{"name":"Bernardo Castro","email":"me@bernardocastro.dev"},"bugs":{"url":"https://github.com/bernatch22/11img/issues"},"license":"MIT","readme":"# 11img\n\nIdentity & permanence layer over the ElevenLabs image API (`/v1/flows/image`),\nbuilt on top of the official `@elevenlabs/elevenlabs-js` SDK — not instead of it.\n\nThe official SDK is a faithful, generated wire layer. What it does not give you,\nand what nothing else on npm or GitHub gives you either, is here.\n\n## Why\n\nThe image API has three sharp edges that every consumer re-implements by hand:\n\n1. **References are a tagged union you must build yourself** — `{type:\"asset\"}`,\n   `{type:\"generation\"}`, `{type:\"inline_base64\"}`.\n2. **Inline references are ephemeral.** The API's own type documentation says an\n   inline image \"is stored as an ephemeral asset with no guaranteed retention:\n   it may be deleted at any time after the generation completes.\"\n3. **There is no seed on the GPT and Gemini models** (only Seedream has one), so\n   visual consistency across a set of images cannot come from a seed.\n\n11img answers all three: references coerce from anything, reused bytes are\nauto-promoted to persistent assets, and consistency comes from chaining a prior\ngeneration in as a reference.\n\n## Features\n\n- **Reference coercion** — `'./hero.png' | 'https://…' | Buffer | 'gen_…' | 'asset:…' | '@name' | Generation`\n  all become valid wire references.\n- **Auto-promotion** — the second time the same local bytes are used, 11img\n  uploads them once as a persistent asset (`11img:<hash>`) and sends\n  `{type:\"asset\"}` from then on. Measured: a 1.1M-character base64 payload\n  disappears from every subsequent request.\n- **Named refs** — `refs add hero ./hero.png`, then `@hero` anywhere.\n  Recoverable on another machine with `refs sync`.\n- **The `Generation` entity** — signed `contentUrl`s expire; `url()` re-fetches\n  when stale, `save()`/`buffer()` always download fresh. Persist `gen.id`,\n  never the URL.\n- **Sessions** — each turn chains the previous output in as a reference, which\n  is what preserves identity in the absence of a seed. `fork()` branches from\n  any point in the history.\n- **Batch with a content-addressed cache** — the key is a hash of the exact wire\n  request. Output *bytes* are cached, so a dead URL never costs you a frame, and\n  interrupted runs journal their pending ids and resume without re-charging.\n- **Pre-flight validation** — a runtime model registry rejects `background` on\n  gpt-image-2, `mask` on Gemini, `seed` outside Seedream, an unsupported aspect\n  ratio… *before* a single credit is spent, with an actionable hint.\n\n## Requirements\n\n- Node ≥ 20.\n- `ELEVENLABS_API_KEY` from a **paid workspace (Pro or above)**. The free tier\n  covers the web UI only; every image endpoint — including `GET /v1/assets` and\n  the generation list — answers `402 paid_plan_required`,\n  *\"This endpoint requires a Pro plan or above.\"*\n\n## SDK\n\n```ts\nimport { ImgClient } from '11img';\n\nconst img = new ImgClient({ model: 'gpt-image-2', residency: 'eu' });\n\n// one-liner\nconst hero = await img.generate({\n  prompt: 'goalkeeper diving, cinematic',\n  aspectRatio: '16:9',\n  resolution: '2K',\n});\nawait hero.save('out/hero.png');\n\n// references of any shape\nawait img.generate({\n  prompt: 'same player, far post header',\n  refs: ['@hero', './kit-away.png', hero],\n});\n\n// iterative thread — each turn chains the previous output\nconst s = img.session({ defaults: { aspectRatio: '1:1' } });\nconst v1 = await s.gen('a minimal geometric owl logo, black on white');\nconst v2 = await s.gen('the same owl logo, now with a thin circular border');\nconst v3 = await s.fork(v1).gen('the same owl logo, in a rounded square badge');\n\n// fire-and-forget, for a web backend\nconst job = await img.submit({ prompt: '…', webhook: 'all' });\nawait db.save(job.id);                  // later: await img.result(id).wait()\n\n// batch — cached, resumable, bounded concurrency\nconst frames = await img.batch(\n  scenarios.map(sc => ({\n    key: sc.name,\n    prompt: sc.description,\n    refs: ['@hero'],\n    aspectRatio: '16:9',\n  })),\n  { concurrency: 4, onProgress: p => console.error(`${p.done}/${p.total}`) },\n);\n```\n\n## CLI\n\n```bash\n11img \"a goalkeeper diving, cinematic\"                # → out/…png (path on stdout)\n11img gen -p \"same, far post\" -r @hero -r ./kit.png --ar 16:9 --res 2K -q high\n11img models                                          # the real API enum + capabilities\n11img refs add hero ./hero.png                        # named persistent reference\n11img refs ls | rm <name> | sync\n11img batch frames.json -c 4                          # manifest = array of BatchItem\n11img get <gen_id> -o .                               # rescue any generation by id\n11img ls --status failed\n11img gen -p \"…\" --dry-run                            # exact wire request, 0 credits\n```\n\nstdout carries only paths (or JSON with `--json`); progress and errors go to\nstderr, so `11img \"…\" | pbcopy` just works.\n\n## Models\n\nNine models, from the real API enum — `11img models` prints them with their\ncapabilities. Highlights:\n\n| model | refs | mask | seed | resolution | notes |\n|---|---|---|---|---|---|\n| `gpt-image-2` | ≤10 | yes | no | 1K/2K/4K | default; 15 aspect ratios; no `background` |\n| `gpt-image-1.5` | ≤10 | yes | no | — | has `background`; **sunset 2026-12-01** |\n| `gpt-image-1` | ≤10 | yes | no | — | **sunset 2026-10-23** |\n| `gemini-3-pro-image` | ≤10 | no | no | 1K/2K/4K | |\n| `gemini-3.1-flash-image` | ≤10 | no | no | 512/1K/2K/4K | widest ratios (up to 8:1) |\n| `bytedance-seedream-5-*` | ≤10 | no | **yes** | 1K–3K | not available in the US |\n\nThe models shown in the ElevenCreative web UI (Nano Banana, FLUX, Krea, Runway,\nKling, Seedream 4.x) are **not** in the API enum.\n\n## State\n\nEverything lives in `.11img/` per project: `refs.json` (named + auto-promoted\nrefs) and `cache/` (batch outputs + resume journal). The API key is **only** ever\nread from `ELEVENLABS_API_KEY` — never written to disk.\n\n## Verified against the live API\n\nExercised end to end on 2026-08-16 against a paid workspace:\n\n- generation, download, and the `402` path on a free key;\n- an asset reference reproducing the source logo exactly inside a new composition;\n- session chaining preserving identity across turns without a seed;\n- auto-promotion: inline on first use → asset on the second → same asset on the third;\n- batch cache: 26.5s cold → 1.0s warm at zero credits, and editing 1 of 2 items\n  regenerating exactly 1.\n\nTwo places where the live API differs from its documentation:\n\n- The generation **list** response carries `id`, `status`, `content_url` and\n  `content_mime_type` only — **not** `model_id`, even though `model_id` is a\n  valid filter parameter.\n- Signed URLs are issued with `X-Goog-Expires=7200` (2 hours), not the ~1 hour\n  the docs state. 11img refreshes at 50 minutes, which is safe either way.\n\n## Ground truth\n\nModel capabilities in `src/models/registry.ts` are derived by hand from the\nrequest types of `@elevenlabs/elevenlabs-js@2.64.0`. When bumping that\ndependency, re-diff the specs against the new `api/types/*Request.d.ts`.\n\n## License\n\nMIT\n","readmeFilename":"README.md","_rev":"1-86ba295dff73a2fb0fae6cb10dc60654"}