Skip to main content

Lexo logo

Lexo

PyPI version Python versions CI License: AGPL-3.0

Lexo stands for Local EXtraction and OCR: a local-first desktop document OCR tool. It turns PDFs and images into clean, editable text, with strong support for Burmese (Myanmar script) using free, high-accuracy Google Docs OCR.

Everything runs on your machine. The only network call is the optional OCR provider, which uses your own Google account, so there is nothing to pay for. Lexo is built especially for Myanmar OCR work: scanned books, old Burmese PDFs, dataset preparation, EPUB production, and other workflows where general-purpose Latin-first OCR tools often fall short. Other non-Latin languages can work too by passing the appropriate Google Docs OCR language hint.

Features

  • Myanmar-first OCR workflow: Burmese is the default OCR language hint, with Unicode normalization and bundled Myanmar font support for reliable review.
  • Free Google Docs OCR from your own account: no paid OCR API, no per-page service fee, and no large local OCR model download.
  • Batch-friendly processing: open a PDF or a set of images, tune pages once, and process many pages through the same desktop workflow.
  • Error recovery for long OCR runs: transient page failures are retried automatically, and failed pages can be retried without re-running the whole document.
  • PDF operations: extract page ranges, split, crop, rotate, merge, and split two-up spreads into separate pages.
  • Visual crop and split editor in the GUI: drag a crop box on the rendered page to remove headers and page numbers, and split scanned two-up spreads. Works on a PDF or a batch of images.
  • Smart OCR routing: digital PDFs use their embedded text layer (instant and lossless); only scanned pages are OCR'd.
  • OCR via Google Docs OCR: free, high-accuracy (especially for Burmese), run on your own Google account. Other non-Latin scripts can also work with the right --lang value. Providers are pluggable behind a single interface.
  • Burmese-aware text handling: NFC normalization and zero-width-space-safe cleaning.
  • Proofread before you export: the desktop app shows each page beside an editable text pane.
  • Exports: plain text (the default), Markdown (with YAML frontmatter), and JSONL (for NLP and LLM workflows).
  • A desktop GUI and a scriptable CLI, both driving the same engine.

Install

Lexo is a Python package. With uv:

uv tool install lexo            # the `lexo` CLI and `lexo gui`

Without uv, use any standard Python installer:

pipx install lexo
# or
python -m pip install lexo

Everything is included in the one install. There are no separate system dependencies to set up.

Quick start

# Launch the desktop app
lexo gui

# Digital PDF: extract the embedded text, instantly (plain text by default)
lexo extract report.pdf -o report.txt

# Scanned PDF or image: OCR it (Burmese by default) with your Google account
lexo login
lexo ocr scan.pdf --lang my -o scan.txt

# PDF operations
lexo pdf extract book.pdf --pages "1-3,7,10-" -o subset.pdf
lexo pdf split book.pdf --every 10
lexo pdf crop book.pdf --top 8 --bottom 8 -o trimmed.pdf

Run lexo --help (or lexo pdf --help) for the full command list.

Video walkthroughs

Short walkthroughs (~1 min each) covering setup and common Burmese OCR workflows.

OCR processing time depends on your network speed and Google Drive's response time. Lexo retries each page automatically on transient failures. If any pages still fail, a "Retry Failed Pages" button appears so you can re-run just those.

1 - Install with uv and one-time Google Cloud setup

Everything needed before the first OCR run: install Lexo with uv tool install lexo → create a Google Cloud project → enable the Drive API → configure the OAuth consent screen → create and download credentials.json → place it in the config directory → run lexo login to sign in.

https://github.com/user-attachments/assets/92d86684-ebaa-438a-a6dd-880d49943405

2 - Main OCR workflow: scanned Burmese PDF (GUI)

Full GUI walkthrough for a scanned Burmese PDF: open the file → use the visual editor to split two-up spreads and crop headers/margins → run Google Docs OCR → review the per-page text → export to plain text.

https://github.com/user-attachments/assets/b247cdc5-0421-4400-bc6c-f4dc35268268

3 - Legacy Windows font PDF: getting real Burmese text with Google OCR (GUI)

Some Burmese documents were created with old non-Unicode Windows fonts such as Win Innwa or Win Myanmar. These fonts render Burmese glyphs by mapping them onto ASCII codepoints, so the PDF actually stores English characters internally - the font is what makes them look Burmese on screen. When you run text extraction on such a file, you get those raw ASCII characters back, which is technically correct but not useful as Burmese text. This video shows how to recognise this case in the GUI and switch to Google Docs OCR instead, which reads the page visually and returns proper Unicode Burmese.

https://github.com/user-attachments/assets/9cd60cbc-6a2b-4925-b076-89e97346e391

Commands

Command Purpose
lexo extract <pdf> Extract the embedded text layer of a digital PDF
lexo ocr <pdf|image> OCR a scanned document (--lang, --force-ocr)
lexo pdf info|extract|split|crop|rotate|merge|split-spread PDF operations
lexo login / lexo logout Sign in to / out of Google (token stored in the OS keychain)
lexo gui Launch the desktop app
lexo info Show the version and where Lexo stores its data
lexo check-update Check PyPI for a newer release

All output formats are available via --format text|markdown|jsonl.

Google Docs OCR setup (one-time)

OCR uses Google Docs OCR, which is free and runs on your own Google account. You bring your own OAuth client credentials (credentials.json). It is a one-time setup:

  1. Create or pick a Google Cloud project at the Google Cloud Console.
  2. Enable the Google Drive API: APIs & Services -> Library -> search "Google Drive API" -> Enable.
  3. Configure the OAuth consent screen: APIs & Services -> OAuth consent screen -> User type External -> add an app name and your email, then add your own Google account under Test users.
  4. Create the OAuth client: APIs & Services -> Credentials -> Create credentials -> OAuth client ID -> Application type Desktop app -> Create -> Download JSON, and rename the file to credentials.json.
  5. Place credentials.json where Lexo looks for it (first match wins):
    • the path in the LEXO_GOOGLE_CREDENTIALS environment variable, or
    • your Lexo config directory (run lexo info to see it), or
    • the current working directory.
  6. Sign in: run lexo login (or in the GUI, Account -> Sign in with Google). A browser opens; approve access. The token is saved in your OS keychain, and credentials.json is only read during login.

Notes:

  • Lexo requests only the least-privilege drive.file scope, so it can touch only the temporary files it creates while running OCR.
  • While the OAuth app stays in Testing status, Google expires the sign-in roughly every 7 days, so you may need to run lexo login again periodically.
  • Sign out any time with lexo logout (or Account -> Sign out); this removes the stored token.

Burmese notes

  • The OCR language hint defaults to my; override with --lang.
  • Other non-Latin languages may work through Google Docs OCR when you pass the matching language hint.
  • Extracted text is normalized to Unicode NFC and zero-width spaces are preserved.
  • A Myanmar Unicode font (Noto Sans Myanmar, SIL Open Font License) is bundled so Burmese renders in the GUI regardless of installed system fonts. The license travels with it as OFL.txt.

Lexo exists because many OCR tools are strongest on Latin-script documents. Local engines such as Tesseract and PaddleOCR can be useful, but Myanmar accuracy, setup size, and reliability vary a lot in practice. Lexo uses Google Docs OCR as the practical free path today, while keeping the OCR provider boundary open for better future options.

Future direction

Lexo focuses on turning scanned or legacy Burmese documents into editable text. Document intelligence features such as layout-aware extraction, table structure, and semantic field detection are not built in yet. If a reliable free approach becomes available, they are natural next steps.

Tech stack

Area Tools
Language Python 3.11+
CLI Typer
Desktop GUI PySide6 (Qt)
PDF engine PyMuPDF
Images Pillow
OCR Google Docs OCR via the Google Drive API (google-api-python-client + google-auth)
Credentials keyring (OS keychain)
Settings pydantic-settings (env-var config)
Logging structlog
Paths platformdirs
Build & packaging uv + Hatchling
Quality Ruff, mypy, pytest
CI/CD GitHub Actions, PyPI Trusted Publishing

Development

uv sync
uv run ruff check src tests
uv run mypy src/lexo
uv run pytest

Design notes live in docs/ARCHITECTURE.md.

Contributing

Bug reports, documentation fixes, and focused pull requests are welcome. Please see CONTRIBUTING.md for setup notes, recommended checks, and privacy guidance before attaching sample PDFs or images.

License

AGPL-3.0, to align with PyMuPDF. See LICENSE.

Download files

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

Source Distribution

lexo-0.3.1.tar.gz (449.5 kB view details)

Uploaded Source

Built Distribution

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

lexo-0.3.1-py3-none-any.whl (464.0 kB view details)

Uploaded Python 3

File details

Details for the file lexo-0.3.1.tar.gz.

File metadata

  • Download URL: lexo-0.3.1.tar.gz
  • Upload date:
  • Size: 449.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for lexo-0.3.1.tar.gz
Algorithm Hash digest
SHA256 0b24dcbffe0546cc624a79ebb5cf14f876e7b75a949edc90bac9075642d4ca23
MD5 6fc3620524db5678f4509f6e8d2e5328
BLAKE2b-256 c881b64f1ad2435e3a7fbdcc81ea42fc8ed2e1efb759df15019901e9c39ddd6e

See more details on using hashes here.

Provenance

The following attestation bundles were made for lexo-0.3.1.tar.gz:

Publisher: release.yml on PhilixTheExplorer/lexo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file lexo-0.3.1-py3-none-any.whl.

File metadata

  • Download URL: lexo-0.3.1-py3-none-any.whl
  • Upload date:
  • Size: 464.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for lexo-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 ccf04e8201ad96ee73362ff746d2f46ae4ea360fc6d57b81e2c635ea07728286
MD5 c8f5280e5ff48171baee89b8419c47a9
BLAKE2b-256 1b023e089f4783ec512a53f5915fd5c7af3f8066db605a7868a3f059cea5d9b8

See more details on using hashes here.

Provenance

The following attestation bundles were made for lexo-0.3.1-py3-none-any.whl:

Publisher: release.yml on PhilixTheExplorer/lexo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.4.1

2 files

0.4.0

2 files

This release

0.3.1 This release

2 files

0.3.0

2 files

0.2.1

2 files

0.2.0

2 files

0.1.1

2 files

0.1.0

2 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