Skip to main content

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:

  1. 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.
  2. 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.
  3. 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 for eink displays.
  • Terminal Preview: Automatically previews the generated image directly in your terminal if you are using Kitty or Ghostty.

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
Editorial Style
Story Scene
--style story_scene
Story Scene Style
Story Blueprint
--style story_blueprint
Story Blueprint Style
Story Desk
--style story_desk
Story Desk Style
Story Frontpage
--style story_frontpage
Story Frontpage Style
Original
--style original
Original Style

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) Z-Image Turbo
FLUX.2 Klein 4B (balanced, ~4 steps) FLUX2 Klein 4B
FLUX.2 Klein 9B (higher quality, ~4 steps) FLUX2 Klein 9B
Ernie Image Turbo (fast, ~4 steps) Ernie Image Turbo
Ideogram 4 FP8 (turbo preset, ~12 steps) Ideogram 4 FP8

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
Editorial Color
Story Scene
--style story_scene
Story Scene Color
Story Blueprint
--style story_blueprint
Story Blueprint Color
Story Desk
--style story_desk
Story Desk Color
Story Frontpage
--style story_frontpage
Story Frontpage Color
Original
--style original
Original Color

Requirements

  • An Apple Silicon Mac (M1/M2/M3/M4)
  • Python 3.12+

Installation

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 is editorial.
  • --target: The output processing mode (web or eink). Default is web.
  • --image-model: The image generation model to use (z-image-turbo, flux2-klein-4b, flux2-klein-9b, ernie-image-turbo, or ideogram-4-fp8). Default is z-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 is mlx-community/gemma-4-e4b-it-8bit.
  • --output-dir: Directory to save the generated images and JSON sidecars. Default is generated/.
  • --headless: Run without interaction.
  • --headless-upload: Automatically upload the generated image as a binary payload to a URL. Requires configuring the WEBHOOK_URL variable in a .env or .env.example file.

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 .png per 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.png contact 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.json sidecar with prompt details, seed, and per-model timing
  • A root comparison.json aggregating 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/):

  1. The generated .png image.
  2. A .json sidecar 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)

Source distribution for hn-local-image 0.4.0
File Size Uploaded
hn_local_image-0.4.0.tar.gz 24.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for hn-local-image 0.4.0
File Interpreter ABI Platform
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 log

Release 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

Release history Release notifications | RSS feed

This release

0.4.0 This release

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page