prosefmt
Rewrite text in any app — press a hotkey, get polished prose back.
Highlight text in any application — browser, email, Slack, VS Code, anything — press your hotkey, and prosefmt silently rewrites it and pastes the result back. Grammar fixed, tone shifted, fully rephrased: all without leaving the app you are in.
It also works as a standard CLI tool that composes with pipes and scripts.
$ prosefmt fix "i can haz good grammer?"
I can have good grammar?
$ echo "this sentense has a typo" | prosefmt fix
This sentence has a typo.
$ prosefmt professional --clipboard # reads clipboard → rewrites → writes back
Table of Contents
- Why prosefmt?
- Installation
- Setup Guide
- System-Wide Hotkeys
- Built-in Modes
- Custom Modes
- Configuration Reference
- Commands
- Development
Why prosefmt?
Every existing tool in this space is a GUI desktop app — Electron, Tauri, or PyQt5. They are 100–200 MB, framework-dependent, and impossible to script.
prosefmt is a plain CLI tool: two Python dependencies, composes with pipes, works from hotkeys or scripts, and runs on every OS.
| prosefmt | GUI tools | |
|---|---|---|
| Size | ~2 Python deps | 100–200 MB runtime |
| Composability | Pipes, scripts, automation | GUI click-through only |
| Providers | Ollama, OpenAI, Anthropic, any OpenAI-compat | Varies |
| Custom modes | One line in a config file | Fork the source |
| Hotkey integration | Any window manager or OS shortcut | Their own UI |
Installation
# Recommended — installs as an isolated tool
uv tool install prosefmt
# Or with pip
pip install prosefmt
New to uv? Install it with:
curl -LsSf https://astral.sh/uv/install.sh | sh
Setup Guide
Follow these steps once after installing. This takes about 5 minutes.
Step 1 — Install clipboard tools
prosefmt uses your system clipboard to read and paste text. The tools needed depend on your OS. macOS and Windows users can skip this step — everything is built in.
Linux (X11 — most desktops: GNOME, KDE, i3, XFCE, …)
# Debian / Ubuntu / Mint / Pop!_OS
sudo apt install xclip xdotool
# Fedora / RHEL / CentOS / Rocky
sudo dnf install xclip xdotool
# Arch / Manjaro / EndeavourOS
sudo pacman -S xclip xdotool
# openSUSE
sudo zypper install xclip xdotool
Linux (Wayland — GNOME on Wayland, KDE Wayland, Sway, Hyprland, …)
# Debian / Ubuntu / Mint
sudo apt install wl-clipboard wtype
# Fedora / RHEL / CentOS
sudo dnf install wl-clipboard wtype
# Arch / Manjaro
sudo pacman -S wl-clipboard wtype
# openSUSE
sudo zypper install wl-clipboard wtype
Not sure if you are on X11 or Wayland? Run
echo $XDG_SESSION_TYPE— it printsx11orwayland.
macOS — nothing to install. pbcopy, pbpaste, and osascript are built in.
Windows — nothing to install. clip.exe and PowerShell are built in.
Step 2 — Choose an AI provider
Pick one. You can always add more later.
Option A — Ollama (local, free, fully private — recommended for first-time setup)
No API key needed. Runs entirely on your machine.
# 1. Install Ollama → https://ollama.com/download
# (macOS / Windows: download the installer; Linux: one-liner below)
curl -fsSL https://ollama.com/install.sh | sh
# 2. Pull a model (qwen2.5:1.5b is fast and small — great for CPU-only)
ollama pull qwen2.5:1.5b
# 3. Start the server (keep this running in the background)
ollama serve
Other good models to try: llama3.2:3b, mistral:7b, phi3:mini
Option B — OpenAI
export OPENAI_API_KEY="sk-..."
Add to your shell profile (~/.bashrc, ~/.zshrc, or ~/.config/fish/config.fish)
so it is always available:
echo 'export OPENAI_API_KEY="sk-..."' >> ~/.bashrc
Option C — Anthropic (Claude)
export ANTHROPIC_API_KEY="sk-ant-..."
Option D — Any OpenAI-compatible endpoint
Works with Groq, Together AI, LM Studio, vLLM, and any server that speaks the
/v1/chat/completions format. Configure the URL and model in your config file
(see Step 3).
Step 3 — Create your config
Run this once to create a ready-to-edit config file:
prosefmt config init
It also checks whether your clipboard tools from Step 1 are installed and tells you exactly what to run if anything is missing.
Open the file to set your default provider and model:
# Linux / macOS
nano ~/.config/prosefmt/config.toml # or: code, vim, whatever you prefer
# Windows
notepad %APPDATA%\prosefmt\config.toml
The minimum config for Ollama — the defaults already cover this, so you may not need to change anything:
default_provider = "ollama"
[providers.ollama]
url = "http://localhost:11434"
model = "qwen2.5:1.5b"
For OpenAI:
default_provider = "openai"
[providers.openai]
model = "gpt-4o-mini" # API key comes from OPENAI_API_KEY env var
Step 4 — Verify everything works
prosefmt check
Expected output:
✓ Clipboard tools installed
✓ Provider 'ollama' is reachable (model: qwen2.5:1.5b)
If anything is wrong, prosefmt check prints the exact command to fix it.
Step 5 — Try it out
# Pass text directly
prosefmt fix "me and him went to the store yesterday"
# Pipe from stdin
echo "this sentense has a typo" | prosefmt fix
# Read from clipboard and print the result
prosefmt fix --clipboard
# Read from clipboard, rewrite, and write the result back to clipboard
prosefmt professional --clipboard
# System-wide: read selected text from any app, rewrite, paste back in-place
prosefmt fix --system
System-Wide Hotkeys
The --system flag is what makes prosefmt useful beyond the terminal. Highlight any text, press
your hotkey, and the rewritten version is pasted back automatically — without touching the mouse
or switching windows.
Two bindings are recommended:
| Hotkey | Action |
|---|---|
Mod+G |
Fix grammar immediately — no prompt |
Mod+Shift+G |
Open a mode picker — choose fix / professional / casual / rephrase / … |
Linux — i3wm / Sway
Install rofi if you do not have it already:
sudo dnf install rofi # Fedora
sudo apt install rofi # Debian / Ubuntu
sudo pacman -S rofi # Arch
Create the mode picker script at ~/.config/prosefmt/prosefmt-menu.sh:
#!/bin/bash
set -euo pipefail
PROMPT=$'\uf044'" prosefmt"
choice=$(prosefmt list --names | rofi -dmenu -i -p "$PROMPT" -theme-str 'window {width: 28%;}')
[[ -z "$choice" ]] && exit 0
exec prosefmt "$choice" --system --notify
chmod +x ~/.config/prosefmt/prosefmt-menu.sh
Add to ~/.config/i3/config (or ~/.config/sway/config):
bindsym $mod+g exec --no-startup-id prosefmt fix --system --notify
bindsym $mod+Shift+g exec --no-startup-id ~/.config/prosefmt/prosefmt-menu.sh
Reload i3 with Mod+Shift+C.
Linux — Hyprland
Install wofi (Wayland-native picker) or rofi (also supports Wayland on modern builds):
sudo dnf install wofi # Fedora
sudo apt install wofi # Debian / Ubuntu
sudo pacman -S wofi # Arch
Create the mode picker script at ~/.config/prosefmt/prosefmt-menu.sh:
#!/bin/bash
set -euo pipefail
# Use wofi if available, otherwise fall back to rofi
if command -v wofi &>/dev/null; then
choice=$(prosefmt list --names | wofi --dmenu --prompt "prosefmt")
else
choice=$(prosefmt list --names | rofi -dmenu -i -p "prosefmt")
fi
[[ -z "$choice" ]] && exit 0
exec prosefmt "$choice" --system --notify
chmod +x ~/.config/prosefmt/prosefmt-menu.sh
Add to ~/.config/hypr/hyprland.conf:
bind = $mainMod, G, exec, prosefmt fix --system --notify
bind = $mainMod SHIFT, G, exec, ~/.config/prosefmt/prosefmt-menu.sh
Linux — GNOME / KDE (any desktop)
rofi works on GNOME and KDE too — install it and use the same script from the i3wm section above. Then add the shortcuts in Settings → Keyboard → Custom Shortcuts:
| Name | Command | Shortcut |
|---|---|---|
| prosefmt fix | prosefmt fix --system --notify |
Super+G |
| prosefmt mode picker | ~/.config/prosefmt/prosefmt-menu.sh |
Super+Shift+G |
macOS — Hammerspoon
Hammerspoon provides both the hotkey binding and a built-in
chooser for the mode picker. Add to ~/.hammerspoon/init.lua:
-- Grammar fix
hs.hotkey.bind({"cmd"}, "g", function()
hs.task.new("/usr/local/bin/prosefmt", nil, {"fix", "--system", "--notify"}):start()
end)
-- Mode picker — opens Hammerspoon's native chooser
hs.hotkey.bind({"cmd", "shift"}, "g", function()
hs.task.new("/usr/local/bin/prosefmt", function(_, stdout)
local choices = {}
for line in stdout:gmatch("[^\n]+") do
table.insert(choices, { text = line })
end
local chooser = hs.chooser.new(function(choice)
if choice then
hs.task.new("/usr/local/bin/prosefmt", nil,
{choice.text, "--system", "--notify"}):start()
end
end)
chooser:choices(choices)
chooser:show()
end, {"list", "--names"}):start()
end)
Reload the Hammerspoon config from the menu bar icon.
macOS — Automator / Shortcuts app
For a fix-only binding without Hammerspoon, create a Quick Action in Automator that runs:
/usr/local/bin/prosefmt fix --system --notify
Assign it a keyboard shortcut in System Settings → Keyboard → Keyboard Shortcuts → Services.
Windows — AutoHotkey v2
Create prosefmt-menu.ps1 anywhere on your system (for example %USERPROFILE%\prosefmt-menu.ps1):
# prosefmt-menu.ps1
$modes = (& prosefmt list --names) -split "`n" | Where-Object { $_ }
$mode = $modes | Out-GridView -Title "prosefmt — choose a mode" -PassThru
if ($mode) { & prosefmt $mode --system --notify }
Add to your AutoHotkey v2 script:
; prosefmt.ahk
#g:: Run "prosefmt fix --system --notify",, "Hide"
#+g:: Run 'powershell -WindowStyle Hidden -File "%USERPROFILE%\prosefmt-menu.ps1"',, "Hide"
Built-in Modes
| Mode | What it does |
|---|---|
fix |
Fix grammar, spelling, and punctuation only |
professional |
Rewrite in a polished workplace tone |
casual |
Rewrite in a friendly, conversational tone |
rephrase |
Improve clarity and flow without changing the meaning |
concise |
Same meaning, fewer words |
expand |
Add more detail and explanation |
summarize |
Condense to the key points |
email |
Format as a professional email with greeting and sign-off |
Run prosefmt list to see all modes including any custom ones you have added.
Custom Modes
Add any number of custom modes to your config file:
# ~/.config/prosefmt/config.toml
[modes.translate-spanish]
prompt = "Translate to Spanish. Keep technical terms in English."
label = "Translated to Spanish"
[modes.code-comments]
prompt = "Add clear, concise comments to this code. Do not change the code itself."
label = "Comments added"
preserve_structure = false
[modes.slack]
prompt = "Rewrite for Slack: brief, friendly, one or two sentences max. No formal sign-off."
label = "Slack-ready"
[modes.eli5]
prompt = "Explain this like I'm five — simple words, short sentences, no jargon."
label = "Simplified"
Use them exactly like built-in modes:
prosefmt translate-spanish "Good morning, how are you?"
prosefmt slack "Please review the pull request I opened for the authentication refactor."
Custom modes appear automatically in the mode picker — no changes to your hotkey scripts needed.
Configuration Reference
Config file location:
| OS | Path |
|---|---|
| Linux / macOS | ~/.config/prosefmt/config.toml |
| Linux (custom) | $XDG_CONFIG_HOME/prosefmt/config.toml |
| Windows | %APPDATA%\prosefmt\config.toml |
Run prosefmt config init to create it, prosefmt config show to see active values.
Full example
# ~/.config/prosefmt/config.toml
# Which provider to use by default
default_provider = "ollama"
# System prompt applied to every rewrite mode.
# Uncomment and edit to change the AI's base behaviour.
# system_prompt = "You are a text editor. Output ONLY the rewritten text — no preamble."
# ── Providers ────────────────────────────────────────────────────────────────
[providers.ollama]
url = "http://localhost:11434"
model = "qwen2.5:1.5b" # any model you have pulled
[providers.openai]
# API key: set OPENAI_API_KEY or PROSEFMT_OPENAI_API_KEY in your environment
model = "gpt-4o-mini"
[providers.anthropic]
# API key: set ANTHROPIC_API_KEY or PROSEFMT_ANTHROPIC_API_KEY in your environment
model = "claude-haiku-4-5-20251001"
# Any OpenAI-compatible endpoint: Groq, Together AI, LM Studio, vLLM, etc.
# [providers.openai-compat]
# url = "https://api.groq.com/openai/v1"
# model = "llama-3.3-70b-versatile"
# API key: set PROSEFMT_COMPAT_API_KEY in your environment
API keys — environment variables
Never put API keys in the config file. Set them as environment variables instead:
| Provider | Environment variable |
|---|---|
| OpenAI | PROSEFMT_OPENAI_API_KEY or OPENAI_API_KEY |
| Anthropic | PROSEFMT_ANTHROPIC_API_KEY or ANTHROPIC_API_KEY |
| OpenAI-compat | PROSEFMT_COMPAT_API_KEY |
Add them to your shell profile (~/.bashrc, ~/.zshrc, ~/.config/fish/config.fish) so they
load automatically in every session.
Commands
prosefmt <mode> [TEXT] Rewrite TEXT (or stdin if omitted)
prosefmt <mode> --clipboard Read from clipboard, print result (also writes back)
prosefmt <mode> --system Read selected text, rewrite, paste back in-place
prosefmt <mode> --provider P Override the AI provider for this run
prosefmt <mode> --model M Override the model for this run
prosefmt <mode> --notify Show a desktop notification when done
prosefmt list List all available modes (human-readable)
prosefmt list --names Mode names only — used by hotkey picker scripts
prosefmt undo Restore the original text from the last rewrite
prosefmt check Check clipboard tools and provider connectivity
prosefmt config init Create ~/.config/prosefmt/config.toml
prosefmt config show Show the active configuration
prosefmt --version Show version
prosefmt --help Show help
Development
git clone https://github.com/digitronik/prosefmt.git
cd prosefmt
uv sync --extra dev
# Git hooks (ruff + file hygiene) — uses .pre-commit-config.yaml
uv run pre-commit install
uv run pre-commit run --all-files # once, to verify hooks
# Run tests
uv run pytest -v
Contributions welcome — open an issue or pull request on GitHub.
License
Metadata
Release files for prosefmt 0.2.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 | Provenance | |
|---|---|---|---|---|
| prosefmt-0.2.0.tar.gz | 57.2 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| prosefmt-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 81.8 kB
Release files / prosefmt-0.2.0.tar.gz
| Download URL | prosefmt-0.2.0.tar.gz |
|---|---|
| Size | 57.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
771e6cb5630f5688de767b5d91a4bc325a306ea7e0a975fa366dd31a0470b6a4
|
|
BLAKE2b-256 checksum How to use checksums |
1434033d42f803cc173714b04f8f0888a090db122e38bf2f901bd785e3eb694b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
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 Oct 23, 2026.
Transparency logRelease files / prosefmt-0.2.0-py3-none-any.whl
| Download URL | prosefmt-0.2.0-py3-none-any.whl |
|---|---|
| Size | 24.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b486417f0eacc11c24690787b4a879cffd7968b0d6569bad020a7ff353153da3
|
|
BLAKE2b-256 checksum How to use checksums |
6daaa2edd807ffe009e2ba49668c833c077b78344a95999e261ae99bece99a6c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
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 Oct 23, 2026.
Transparency logSecurity for prosefmt 0.2.0
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.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for prosefmt-0.2.0.tar.gz
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 Oct 23, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.