Repository navigation
Releases: Artificial-Humanity/Lucida
Release list
v1.3.0
Lucida v1.3.0 — a Lemonade image provider Lucida can now generate and edit images through a Lemonade server (--provider lemonade, or LUCIDA_IMAGE_PROVIDERS). The lane is free and unmarked. It is never inferred from a model id. Also in this release: review fixes to the canary and tests, to file writes, to money paths, and to what Lucida tells a caller. Changes a user may notice: - The minimum Rust version is 1.86. - A capitalised model id that would be inferred to BFL is refused (exit 2). - Only png, jpg, jpeg, webp and mp4 count as output formats.
v1.2.0
Lucida v1.2.0 — Runway renders images
Runway was video-only here while it sells image generation. It now
renders images with its own two models.
feat runway images — gen4_image (from text) and gen4_image_turbo
(from up to three reference images), a seed, and sixteen pixel
ratios, where the pair is also the output size. The output carries
a signed C2PA manifest and no pixel watermark was found.
feat `lucida models --provider runway` lists image and video models,
each half labelled; google shows its Veo aliases the same way.
fix runway video refused `--aspect 16:9`. A ratio is now accepted on
both runway lanes wherever an offered pixel pair has its shape.
fix `--provider runway` no longer reaches models Runway resells from
other companies; they are refused by name.
fix `lucida update` recognises a copy cargo installed under
CARGO_INSTALL_ROOT or install.root, and rebuilds it with cargo
instead of overwriting it.
v1.1.1
Lucida v1.1.1 — `lucida update` keeps a cargo install where cargo put it
Three fixes above v1.1.0, all in how `lucida update` treats a copy that
cargo installed.
fix a copy installed from crates.io is updated from crates.io. It was
rebuilt from git, which worked and quietly turned it into a git
install. The source is read from cargo's own install record.
fix the reinstall goes into the copy's own cargo home. It went
wherever cargo was configured to install today, so a changed
CARGO_INSTALL_ROOT or install.root could leave the copy on PATH
old while reporting success.
fix a cargo home behind a symlink, and Windows' canonical paths, are
recognised, so such a copy is no longer overwritten as though it
were a download.
The first release whose crate the release workflow is set to publish to
crates.io, by trusted publishing, from the same commit as the binaries.
v1.1.0
Lucida v1.1.0 — the macOS binary is signed, and defaults answer a ren…
v1.0.1
Lucida v1.0.1 — packaging metadata, so the crate and the tag are one …
v1.0.0
Lucida v1.0.0 — video became a substitution, and the tests grew a sec…
v0.10.0
v0.10.0 — dependable unattended use The 2026-08-09 product review's second tranche, closing its third and last structural finding. Tool calls run off the MCP read loop and a cancellation is honoured; renders are recorded so a paid one can be found again; cost is stated before it is spent and a budget can refuse it; four outcomes have four exit codes with --json throughout; and a weekly canary asks the providers whether they still speak our protocol.
v0.9.2
v0.9.2 — the 2026-08-09 product review's first tranche Keep the existing promises. Two of the review's three structural findings close: mistyped MCP arguments are refused rather than silently dropped, and a paid Veo render can no longer be lost from the CLI. Plus connect timeouts everywhere, atomic image writes, self-dating shutdown notices, and a description that matches the tool.
v0.9.1
The guarantee v0.9.0 shipped, now visible
v0.9.0 gave comfyui a mask that binds — every pixel outside it comes back byte-identical, measured at 0.00/255. Then it told you otherwise.
Eight surfaces describe masking, and only README.md was updated. --help said "openai only, and advisory". lucida models printed advisory for both providers. The MCP schema said "ADVISORY, not binding — composite over the original if untouched pixels matter". And so did image_providers — the one place an agent is told to believe over anything it remembers.
So the release's headline feature was invisible from the surface most people read first, and an agent following the schema would carefully re-composite a render that had already come back exact.
The fix is not eight corrections. Whether a mask binds is a value now, not prose. Every surface that reports it is generated from that value, so they cannot disagree again — including the error for asking a provider that cannot mask, which now points at the one whose mask actually guarantees something:
$ lucida generate "a field" --mask region.png --provider google
error: `google` does not accept a mask, so `--mask` cannot be honoured.
Use one of: comfyui and openai. What a mask guarantees differs between them, and
that difference is usually the reason to prefer one:
On comfyui the mask is binding: Lucida composites the render back through the
mask, so pixels outside it come back unchanged — measured at 0.00/255, which
leaves nothing for the caller to composite. On openai the mask is advisory: the
change is concentrated but not confined, and the rest of the picture is
regenerated too — composite over the original yourself if untouched pixels
matter.lucida models reports the same distinction per provider (accepted, binding — pixels outside it come back unchanged, against accepted, advisory — the change is concentrated, not confined), and so does image_providers.
Two surfaces genuinely cannot be generated: a clap help string has to be a literal, and the shipped skill is a snapshot by design. Those now name no provider and claim no semantics at all — only where the live answer is. Tests enforce it, including one that reads the --mask help back out of the parser and rejects any provider name or either semantics word in it.
Windows could not hold an API key
lucida config --set had nowhere to write on stock Windows. The search for a config file read only HOME, which PowerShell, cmd and a GUI-launched Claude do not set — so the list of places to look came back empty. The one mechanism that exists for a client inheriting no shell environment was the one that failed, on the platform where launching without a shell is normal.
Windows has a release asset, a one-line installer, self-update and its own CI lane. It could not store a credential.
It survived because of how it was tested: the Windows CI job runs the smoke script under bash, and git-bash sets HOME. The check named "the config file is read with no environment" passed in an environment no native Windows user has.
%USERPROFILE% is now read alongside HOME, and %APPDATA%\lucida\config.env joins the search path. Separately, lucida setup can now find Claude Code there at all — it looked for a file called claude, which does not exist when the executable is claude.exe or claude.cmd, so it reported finding nothing while claude ran fine in the same terminal. It consults PATHEXT now, the list the shell itself uses.
Smaller, and worth having
- Config files are replaced by rename rather than truncated in place. A crash or a full disk mid-write could previously destroy
config.env— possibly the only copy of an API key — or the Claude desktop config, which holds other servers' registrations. The replacement is also locked to its owner before it becomes visible, closing the window where a freshly written key was briefly world-readable. lucida setupno longer panics on a desktop config whosemcpServersis not an object. It says what is there and leaves the file untouched.- The daily update check keeps its timestamp in
%LOCALAPPDATA%on Windows, rather than a.cachedotfile borrowed from another platform. - Nothing changes for existing installs beyond this. There are no new parameters, no removed ones, and no provider changed what it can be asked for.
Method
The failure was not that someone wrote "advisory" and forgot to update it. Capabilities.mask was a bool, so the advisory/binding distinction could not be generated — and the moment the two providers diverged, every mention of it became hand-maintained prose in eight places, none of them in the path of the commit that diverged them.
This repository already had the answer. Provenance has been an enum with a describe() since it was added, and every surface reporting it stayed correct through five providers, because there was never a second copy to keep in sync.
A capability that varies has to be a variant. Otherwise the variation lives in sentences, and sentences do not have a compiler.
v0.9.0
A mask that binds
--mask now works on comfyui, and it means something stronger there than anywhere else: every pixel outside the mask comes back byte-identical.
$ lucida edit scene.png "a field of sunflowers here" --mask region.png --provider comfyuiMeasured rather than claimed, against a two-tone source with the left half masked:
| change inside mask | change outside | ||
|---|---|---|---|
| Inpaint conditioning alone | 128.03/255 | 23.84/255 | advisory, 5.4× |
| Plus in-graph compositing | 127.47/255 | 0.00/255 | binding |
| Through the release binary | 123.82/255 | 0.00 mean, 0.00 max | binding |
This is the one thing the local lane can do that no hosted provider here can, and the reason is structural rather than clever: Lucida builds the ComfyUI graph. OpenAI's mask concentrates change without confining it — the README has always said so, and told callers to composite the result themselves. A local graph can do that compositing before it returns, so you get a guarantee instead of a caveat.
The same mask file works on both providers. Transparent pixels are the region that changes, on openai and comfyui alike — verified against a live server rather than assumed, because guessing wrong inverts every mask and still renders happily.
No new model needed
The roadmap said local inpainting required a Flux.1 Fill checkpoint. It doesn't — Flux.2 does it through InpaintModelConditioning, which one probe settled. That would otherwise have cost a 24 GB download and forced a licence decision that remains open.
Worth stating as a method: it was a claim about a model, and claims about models are testable.