Skip to main content

🖼️ Limn

to limn: to depict or describe; to paint.

A small, privacy-first tool that turns a text description into an image. Type a prompt, get a picture — no account, minimal options, bring your own provider.

pip install limn

limn "a red bicycle against a brick wall" -o bike.png
  • Type a description → get an image. That's the whole thing.
  • No account, private by default. Your prompts and images are yours. The only network egress is the generation request to the provider you chose.
  • Bring your own provider — self-hosted (SwarmUI / any OpenAI-compatible endpoint) or a cloud key (Google Imagen, OpenAI / DALL·E). Swap with one setting.
  • Minimal by design. Prompt, size, count, seed. Want power? Install something bigger — Limn stays lean.

Quick start

Pick whichever provider you already have:

# Self-hosted SwarmUI (free, your GPU)
export SWARMUI_BASE_URL=https://image.example.org
export SWARMUI_TOKEN=...   # only if fronted by auth
limn "watercolour fox" --provider swarmui

# Any OpenAI-compatible /v1/images endpoint (LocalAI, ...)
export OPENAI_BASE_URL=http://localhost:8080/v1
limn "watercolour fox" --provider openai-compatible

# Google Imagen (cheap, ~$0.02/image on the Fast tier)
export GEMINI_API_KEY=...
limn "watercolour fox" --provider gemini

# OpenAI Images
export OPENAI_API_KEY=...
limn "watercolour fox" --provider openai

Then set your provider once so you never pass --provider again:

limn --init-config        # writes a commented ./limn.yaml template
mv limn.yaml ~/.limn.yaml # personal defaults, used everywhere

Usage

limn "a red bicycle against a brick wall" -o bike.png
limn "watercolour fox" --provider swarmui --size 1024x1024 --count 4 --seed 42
limn "pixel art, a fox" --lora pixel-art-xl:1.0 --cfg 5 --steps 30
limn --from prompts.txt -M           # batch a prompt list, with metadata sidecars
Option What
-p, --provider swarmui, openai-compatible, openai, gemini
-m, --model Model name (provider-specific)
-s, --size e.g. 1024x1024 (Imagen maps to the nearest aspect ratio)
-n, --count Number of images (1–10)
--seed Reproducibility, where the backend supports it (SwarmUI)
--negative Negative prompt, where supported (SwarmUI)
--lora LoRA as name[:weight], repeatable (SwarmUI; unknown names error)
--cfg, --steps, --sampler, --scheduler SDXL knobs (SwarmUI; others warn + ignore)
--from Read prompts from a file (one per line, - for stdin); each auto-named
-M, --metadata Write a <image>.json sidecar of the generation params
-o, --out Output file; default is a slug of the prompt, never overwritten
-c, --config Explicit config file

limn models asks your provider which models it offers (SwarmUI requires picking one — e.g. limn "a fox" -m juggernautXL_v9). The web UI and desktop Settings have a matching "fetch models" button.

Config

Layered, later wins: built-in defaults → ~/.limn.yaml (your provider + keys, set once) → ./limn.yaml → CLI flags. Secrets are referenced as ${VAR} so no plaintext keys live in files:

provider: swarmui
size: [1024, 1024]

providers:            # keep several configured; swap with `provider:`
  swarmui:
    base_url: https://image.example.org
    model: juggernautXL_v9
    api_key: "${SWARMUI_TOKEN}"      # bearer; or use username/password for Basic auth
  swarmui-basic:                     # a second server under its own label
    type: swarmui                    #   which provider class to use
    base_url: https://image2.example.org
    username: admin
    password: "${SWARMUI_PASS}"
  gemini:
    model: imagen-4.0-fast-generate-001

SwarmUI auth is auto-detected: username + password → HTTP Basic (for a reverse proxy in front of SwarmUI), otherwise api_keyBearer. A block's type: lets you run several servers of the same kind under distinct labels.

Web UI

pip install "limn[serve]"
limn serve                # opens http://127.0.0.1:5466/ in your browser

One page: type a prompt → Generate → the image appears → Save (to disk), Again (regenerate), or Delete. The session gallery lives in the server process's memory only — nothing touches disk until you click Save.

Binds 127.0.0.1 by default. Binding any other host requires a token (--token, or one is generated and printed); useful flags: --port, --out-dir, --no-browser.

Hosting a shared demo

limn serve --demo (or LIMN_DEMO=1) runs a friction-free public instance with guardrails instead of a token: 10 images/hour per IP, provider/model locked to the server config, one ≤1024px image per request, server-side Save disabled (visitors download instead), gallery entries expire after 15 min, and the page shows an "install locally" banner. See docs/demo-deploy.md.

Desktop app

A native app (Tauri) for people who don't live in a terminal: install, pick your provider in Settings (server URL / API key — bring your own), type, generate. First launch bootstraps a private Python runtime via uv (~a minute, no system Python needed); images save to Pictures/Limn. Installers for macOS / Windows / Linux are built by CI from desktop/ — grab them from the GitHub releases page. Builds are unsigned for now: on macOS right-click → Open the first time; on Windows "More info → Run anyway".

Roadmap

CLI, web UI (limn serve), hostable demo mode, and the desktop app — all four SPEC surfaces are in.

📄 See SPEC.md for the full specification.

Companion to slide-stream, which shares the same image-provider approach.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

limn-0.4.2.tar.gz (454.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

limn-0.4.2-py3-none-any.whl (31.8 kB view details)

Uploaded Python 3

File details

Details for the file limn-0.4.2.tar.gz.

File metadata

  • Download URL: limn-0.4.2.tar.gz
  • Upload date:
  • Size: 454.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.0

File hashes

Hashes for limn-0.4.2.tar.gz
Algorithm Hash digest
SHA256 1065a46d9b2d6cf524a50f4f8969805421ec7c54d72a46af4dabddd7122d2f87
MD5 ee7034eed16a1b475f5537d89699b629
BLAKE2b-256 845bc78d7dc395f782790bc10c76031aa8ea4c9b84f281c9b117f6f576ba780b

See more details on using hashes here.

File details

Details for the file limn-0.4.2-py3-none-any.whl.

File metadata

  • Download URL: limn-0.4.2-py3-none-any.whl
  • Upload date:
  • Size: 31.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.0

File hashes

Hashes for limn-0.4.2-py3-none-any.whl
Algorithm Hash digest
SHA256 268251b8dfc42f9bcfa2cc2939c4c52b53bf24d6ad58e699bd1203ca40bf40d5
MD5 a74b1365fc572dac19855daa7837814f
BLAKE2b-256 e3883857fed5529d831fd9d814ff7f94972bd560a33017482e9bc1181690483e

See more details on using hashes here.

Release history Release notifications | RSS feed

0.4.3

2 files

This release

0.4.2 This release

2 files

0.4.1

2 files

0.4.0

2 files

0.3.0

2 files

0.2.0

2 files

0.1.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page