Skip to main content

Lazyread local-first listening library runtime

Project description

Lazyread

Lazyread turns URLs and Markdown into a private local listening library: readable article typography, natural on-device narration, exact word highlighting, complete-track preloading, progress, telemetry, and mobile controls in one durable app.

It is an early public release for Apple Silicon Macs. Text extraction and the web library are lightweight; natural narration uses MLX, Qwen3-TTS 1.7B CustomVoice, and Qwen3 ForcedAligner. Article content and finished audio stay on the Mac. URL extraction still accesses the source website.

Prerequisites are macOS 14 or newer, Node.js 20.19+, FFmpeg 6+, and UV 0.5+. lazyread doctor reports exact versions and Homebrew repair commands before setup changes anything. These small system tools are not installed silently; Defuddle, Python/MLX packages, and models are installed into app-owned storage.

Quick start

Lazyread is published on PyPI and runs directly through UVX:

uvx lazyread doctor
uvx lazyread setup

The product, command, Python module, repository, skill, and PyPI distribution are all named lazyread.

setup first prints the compatibility and storage disclosure. The confirmed command installs pinned dependencies under ~/Library/Application Support/Lazyread and downloads about 5.4 GB of speech/alignment models:

uvx lazyread setup --yes
uvx lazyread install-skills
uvx lazyread serve --detach

Restart the agent host after installing skills, then invoke:

$lazyread https://example.com/article

The companion skill reviews Defuddle extraction before submitting the source. The browser also has a baseline URL/Markdown form at http://127.0.0.1:4242/library.

Private Tailscale access

Add a single tailnet-only listener without touching other Serve routes:

uvx lazyread expose --https-port 7447

Lazyread never enables Funnel and never resets the machine's Tailscale Serve configuration. The Tailscale listener trusts the tailnet: every principal allowed to reach the Mac by its tailnet ACL can use the complete library API, including deletion. Use it only on a personal tailnet or restrict the device/port with Tailscale ACLs. A future public multi-user release will add per-user pairing.

What is persisted

The library lives under ~/Library/Application Support/Lazyread unless LAZYREAD_HOME is set. SQLite holds catalog/job state; article folders hold source Markdown, display and speech projections, FLAC/WAV audio, timings, and telemetry. Delete moves an article to trash; purge is separate. Model and chunk storage are reported independently.

The server survives independently of the heavy narration worker. Jobs run serially, persisted progress is replayed over SSE, interrupted work is recoverable, and the MLX process exits when its queue item finishes so it does not retain unified memory while idle.

Current pinned speech stack

Verified 14 July 2026 against the official upstream repositories:

  • MLX-Audio 64e8416c303fb3b3463dab8eb4ebd78c55a87c1a
  • Qwen3-TTS 1.7B CustomVoice 52f4770fd9726457eae3d3b6aa92047a25a10776
  • Qwen3 ForcedAligner 0e1a68e91d815300c7c9754b2a7639378b23db15
  • Defuddle 0.19.1

Revisions are immutable for reproducibility. A release update verifies and advances them; normal article creation does not silently upgrade the environment.

Development

To test the unreleased repository version through UVX instead of the PyPI release:

uvx --from git+https://github.com/JayFarei/lazyread lazyread --help
uv sync --extra test
uv run --extra test pytest
uvx ruff check src tests

cd web
npm ci
npm test
npm run build
npm audit --omit=dev

Run the full app with deterministic silent narration for UI/integration work:

LAZYREAD_HOME=/tmp/lazyread-dev LAZYREAD_WORKER=fake \
  PYTHONPATH=src uv run lazyread serve --port 4246

The architecture and measured 10,068-word scientific-paper production run are documented in design/. Maintainer release steps are documented in RELEASING.md.

License

MIT. See THIRD_PARTY_NOTICES.md for bundled skill attribution.

Project details


Download files

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

Source Distribution

lazyread-0.1.1.tar.gz (100.5 kB view details)

Uploaded Source

Built Distribution

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

lazyread-0.1.1-py3-none-any.whl (96.1 kB view details)

Uploaded Python 3

File details

Details for the file lazyread-0.1.1.tar.gz.

File metadata

  • Download URL: lazyread-0.1.1.tar.gz
  • Upload date:
  • Size: 100.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for lazyread-0.1.1.tar.gz
Algorithm Hash digest
SHA256 c18eac9c9af92d85bdb164fe4d1b8a404d411063991db87240280fd5f0ffb0cb
MD5 3e01342b530d769a286005ff80562fa0
BLAKE2b-256 cef8776e48cae573e8cdc6e2b3b9fcd2cf6d817b60adcd27f9f77ca2fa67110f

See more details on using hashes here.

File details

Details for the file lazyread-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: lazyread-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 96.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for lazyread-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 bf1330a4a9d2409b57a26add8acd8e21ec4bca93bb7ca1414f44fc66795a09e2
MD5 b7921b0a6af4dff4918500fd5a51b98d
BLAKE2b-256 50d28ba6132f94d76f823761717ddbcb335d4e03858caafce40b4e2b13e02ba5

See more details on using hashes here.

Supported by

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