HN Local Image
Generates a daily AI art piece based on the top stories currently on Hacker News, using 100% local Apple Silicon hardware.
This is a local-first reimagining of the original concept, allowing you to generate "front page" artwork without relying on external cloud APIs (except for fetching the headlines themselves).
Releases
See RELEASE_NOTES.md for version history and detailed release information.
Inspiration & Credits
This project was heavily inspired by and built upon the concepts of three fantastic projects:
- hn_dailyimage: The original Go-based project that conceived the idea of turning Hacker News headlines into art using Gemini, including the clever post-processing for e-ink displays.
- MFlux: A stellar line-by-line MLX port of generative image models. MFlux provides the high-performance local image generation engine that makes running this entirely on a Mac possible.
- mlx-vlm: Prince Canuma's MLX-based vision-language model package. mlx-vlm powers the local text model that analyzes the headlines and crafts the image prompts.
Features
- 100% Local Inference: Uses MLX to run both the text model (for prompt analysis) and the image model (for generation) directly on your Mac.
- Multiple Image Models: Supports
z-image-turbo(default), FLUX.2 Klein, Ernie Image Turbo, and Ideogram 4 FP8. Ideogram 4 uses its native JSON-caption format and preset sampler for better quality. - Multiple Styles: Choose from various artistic directions (e.g.,
editorial,story_scene,story_blueprint,story_desk,story_frontpage,original). - Target Profiles: Output full-color, high-resolution PNGs for the
web, or heavily processed, dithered 1-bit monochrome images optimized foreinkdisplays. - Terminal Preview: Automatically previews the generated image directly in your terminal if you are using Kitty or Ghostty.
Styles Gallery
All of the examples below are generated with --target eink: a 1-bit, dithered 800×480 monochrome image optimized for e-ink displays.
| Style | E-ink Example |
|---|---|
Editorial--style editorial |
|
Story Scene--style story_scene |
|
Story Blueprint--style story_blueprint |
|
Story Desk--style story_desk |
|
Story Frontpage--style story_frontpage |
|
Original--style original |
Model Comparison
Different models interpret prompts in unique ways. Below are examples of how each available model visualizes the same Hacker News headlines (using the --watermark flag to identify models):
| Model | Example (with watermark) |
|---|---|
| Z-Image Turbo (fastest, ~9 steps) | |
| FLUX.2 Klein 4B (balanced, ~4 steps) | |
| FLUX.2 Klein 9B (higher quality, ~4 steps) | |
| Ernie Image Turbo (fast, ~4 steps) | |
| Ideogram 4 FP8 (turbo preset, ~12 steps) |
Use the --watermark flag to add model identification when comparing outputs:
hn-local-image compare --watermark --style editorial
High-Resolution Color Output
The default target is web, which produces full-color, high-resolution 1280×768 PNGs. The same six styles, generated with the default z-image-turbo model:
| Style | Color Example |
|---|---|
Editorial--style editorial |
|
Story Scene--style story_scene |
|
Story Blueprint--style story_blueprint |
|
Story Desk--style story_desk |
|
Story Frontpage--style story_frontpage |
|
Original--style original |
Requirements
- An Apple Silicon Mac (M1/M2/M3/M4)
- Python 3.12+
Installation
Recommended: Install via PyPI with uv
uv is the fastest Python package installer and highly recommended for running this tool.
Run directly without installing:
uvx hn-local-image
Install for persistent use:
uv tool install hn-local-image
hn-local-image
Alternative: Install from source
Clone the repository and run the application using uv:
git clone https://github.com/ivanfioravanti/hn_local_image.git
cd hn_local_image
uv run will automatically manage the virtual environment and dependencies for you.
Alternative: Install with pip
pip install hn-local-image
hn-local-image
Optional: Install the Codex agent skill
This repository includes a Codex skill that teaches agents how to use the
published hn-local-image package. To make it available in Codex from the
published package, run:
uvx hn-local-image install-skill
By default, this installs to ${CODEX_HOME:-$HOME/.codex}/skills/hn-local-image.
Use --skills-dir for a custom skills root, or --force to overwrite an
existing install. If you already installed the CLI persistently with
uv tool install hn-local-image, hn-local-image install-skill works too.
For local skill development from a repo checkout, symlink it instead so changes in this repo are picked up immediately:
mkdir -p "${CODEX_HOME:-$HOME/.codex}/skills"
ln -sfn "$(pwd)/hn_local_image_assets/skills/hn-local-image" "${CODEX_HOME:-$HOME/.codex}/skills/hn-local-image"
After installing, ask Codex to use $hn-local-image for Hacker News headline
artwork, e-ink output, model comparisons, or headless upload automation.
Usage
If installed via PyPI, run the command directly:
hn-local-image [OPTIONS]
If running from source, use uv run:
uv run main.py [OPTIONS]
Examples
Default (Editorial style, Web output, Z-Image Turbo):
uv run main.py
Generate an e-ink optimized image:
uv run main.py --target eink
Use a different style and the FLUX.2 Klein 9B image model:
uv run main.py --style story_blueprint --image-model flux2-klein-9b
Use a different local text model for prompt generation:
uv run main.py --model-name "mlx-community/Llama-3.2-8B-Instruct-4bit"
Options
--style: The artistic style to use (e.g.,editorial,story_scene,story_blueprint,story_desk,story_frontpage,original). Default iseditorial.--target: The output processing mode (weboreink). Default isweb.--image-model: The image generation model to use (z-image-turbo,flux2-klein-4b,flux2-klein-9b,ernie-image-turbo, orideogram-4-fp8). Default isz-image-turbo.--watermark: Add a model name watermark to the bottom-right corner of the generated image for easy identification when comparing models.--model-name: The Hugging Face repo ID of the MLX text model to use for prompt generation. Default ismlx-community/gemma-4-e4b-it-8bit.--output-dir: Directory to save the generated images and JSON sidecars. Default isgenerated/.--headless: Run without interaction.--headless-upload: Automatically upload the generated image as a binary payload to a URL. Requires configuring theWEBHOOK_URLvariable in a.envor.env.examplefile.
Before each image model loads, the CLI prints available system memory and a model-specific recommendation. This is advisory; Ideogram 4 FP8 has the highest memory demand.
Environment Variables
You can configure the application's default behavior without passing CLI flags by setting the following environment variables in a .env file in the project root:
# Example .env.example file format:
WEBHOOK_URL=https://your-webhook-endpoint.com/upload
# Optional Overrides
PROMPT_MODE=editorial # Equivalent to --style
TARGET_MODE=eink # Equivalent to --target
OUTPUT_DIR=generated # Equivalent to --output-dir
HN_URL=https://news.ycombinator.com/ # Override the default HN url
Comparing Image Models
The compare command generates images with all available image models using the same prompt and seed, making it easy to compare quality and speed side by side.
Compare a single style:
uv run main.py compare --style editorial
Compare a selected subset of image models:
uv run main.py compare --style editorial --image-model z-image-turbo --image-model ideogram-4-fp8
Compare all styles in one run (shared headlines and seed):
uv run main.py compare --all-styles
Compare with e-ink target:
uv run main.py compare --all-styles --target eink
This produces a generated/compare/<timestamp>/ directory with one subfolder per style, each containing:
- One
.pngper image model (z-image-turbo.png,flux2-klein-4b.png,flux2-klein-9b.png,ernie-image-turbo.png,ideogram-4-fp8.png) - A
comparison-grid.pngcontact sheet with every generated image, model watermark, and generation time. Ideogram is promoted to the top row, with the remaining models arranged below. - A
comparison.jsonsidecar with prompt details, seed, and per-model timing - A root
comparison.jsonaggregating all styles (when using--all-styles)
Webhooks / Headless Uploads
If you pass the --headless-upload flag, the application will automatically read the WEBHOOK_URL environment variable and perform an HTTP POST request sending the raw PNG bytes of the generated image (with Content-Type: image/png).
uv run main.py --target eink --headless-upload
This is heavily modeled after the original hn_dailyimage application to make pushing images to devices like e-ink displays seamless via Cron jobs.
Output
The script will save two files in the output directory (default: generated/):
- The generated
.pngimage. - A
.jsonsidecar file containing metadata about the generation, including the time, models used, headlines parsed, and the specific prompt used to generate the image.
License
MIT License. See LICENSE for more details.
Metadata
Release files for hn-local-image 0.4.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| hn_local_image-0.4.0.tar.gz | 24.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| hn_local_image-0.4.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 51.1 kB
Release files / hn_local_image-0.4.0.tar.gz
| Download URL | hn_local_image-0.4.0.tar.gz |
|---|---|
| Size | 24.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ca966ab42c671b26fd8acfe28ccc87612a5fbc50b14ce4be00a60288b43d91b4
|
|
BLAKE2b-256 checksum How to use checksums |
0317b600890d758d47b03e74faecfb21887576a6e913f4c8a5d06bf521b7a678
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 15, 2026.
Transparency logRelease files / hn_local_image-0.4.0-py3-none-any.whl
| Download URL | hn_local_image-0.4.0-py3-none-any.whl |
|---|---|
| Size | 26.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
77ce72046916a074a6dd8223e1d8f002463dcfe841e30480690fada4dcb13844
|
|
BLAKE2b-256 checksum How to use checksums |
35e4a7d1acf88b1cb996c5fa96c65ba6db598fa3c7b8712aade320de0719b8f4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 15, 2026.
Transparency log