OpenRead is a personal reading app for plain text and markdown documents.
You can upload a file or paste text directly, open it in a focused reading view, highlight words or phrases, and translate selected passages inline or from the explanation pane.
- Upload
.txtand.mdfiles - Paste text directly into the library screen
- Store documents locally in SQLite
- Open each document at its own reloadable URL
- Highlight text selections in the reader
- Translate through Groq, an OpenAI-compatible API, or a Codex subscription
- Navigate and select text with Vim-style keyboard controls
- Adjust reader font, size, width, and highlight color
- Persist reader preferences across reloads
- Build the frontend and server into one executable
The reader starts in Normal mode. The current word is marked with a small underline.
| Key | Action |
|---|---|
h / l, b / w |
Previous or next word |
j / k |
Move down or up a visual line |
v |
Enter or leave Visual mode |
Enter |
Translate the current word or Visual selection |
x |
Remove the translation under the cursor |
[ / ], Ctrl+u / Ctrl+d |
Previous or next page |
g / G |
Start or end of the document |
s |
Reader settings |
? |
Show all keyboard controls |
Esc |
Return to Normal mode and close overlays |
OpenRead reads ~/.config/openread/config.json. If the file is missing or incomplete, starting OpenRead in a terminal opens a small setup screen and then launches the server. Run openread --setup at any time to change providers or credentials and exit without starting the server.
The setup screen hides API-token input and stores named provider profiles in config.json. Use the profile menu to select the active provider, add another, edit credentials, or delete one. The file is replaced atomically with owner-only 0600 permissions. Native Codex OAuth access and refresh tokens are stored in the same private file.
{
"active_provider": "fast-translations",
"providers": [
{
"name": "fast-translations",
"type": "codex",
"model": "gpt-5.6-luna"
},
{
"name": "groq-backup",
"type": "groq",
"model": "llama-3.1-8b-instant",
"token": "gsk_..."
}
]
}Existing flat single-provider configuration files are accepted and converted when setup next saves the file.
Groq uses its fixed API URL, so a Groq profile only needs the token and optional model.
Use openai for OpenAI or another server implementing /chat/completions. Its profile stores the model, token, and base_url, which can be the API root or the complete chat completions URL.
Run setup and select Codex subscription:
./openread --setupOpenRead starts a PKCE-protected callback on localhost, opens ChatGPT sign-in in your browser, and stores the resulting credentials in that Codex profile. No Codex CLI installation is required.
OpenRead refreshes expired credentials automatically and saves rotated refresh tokens before continuing. Browser callbacks use localhost ports 1455 or 1457.
Warning
ChatGPT subscription access uses the current open-source Codex OAuth flow and the internal chatgpt.com/backend-api/codex response endpoint. OpenAI does not document this as a stable third-party API, so a future Codex service change may require an OpenRead update. The OpenAI-compatible provider remains the stable option for API-key usage.
--setup is the only configuration flag. Use it to add, edit, delete, or select the active provider:
./openread --setupProvider credentials, models, and the active selection are read exclusively from ~/.config/openread/config.json. Environment-variable and command-line provisioning are not supported.
cd backend
go mod tidy
go run .The backend runs on http://localhost:8080.
cd frontend
npm install
npm run devThe frontend runs on http://localhost:5173.
Vite proxies /api requests to the Go server during development.
Build the frontend and embed it into the Go executable:
make build
./openreadOpen http://localhost:8080. The resulting openread file contains the Vue application and the Go API server; only the SQLite database in the user data directory remains external.
Run ./openread --setup on the host first. Compose supplies ~/.config/openread/config.json to the container as a read-only Docker secret.
The supplied Compose configuration is intended for Groq and OpenAI-compatible providers. Native Codex OAuth must be able to persist rotated refresh tokens, so Codex users should run the standalone binary or replace the Docker secret with a private writable configuration mount.
docker compose up --build- OpenRead:
http://localhost:8080
The production image contains the same single executable and runs one service.
docker compose -f docker-compose.dev.yml up --buildThis development setup uses:
- Vite for frontend hot reload
- Air for Go rebuilds
- bind mounts for
frontend/andbackend/ - named volumes for SQLite data and dependency caches
- On Linux, the local backend stores SQLite in
$XDG_DATA_HOME/openread/openread.db, or~/.local/share/openread/openread.dbwhenXDG_DATA_HOMEis unset - Docker stores SQLite data in the
backend-datavolume
- The backend fails on startup when the selected provider is missing required credentials or settings
- Reader routes use hash URLs such as
#/documents/12so reloading a document stays on that document