Metadata-Version: 2.5
Name: prosefmt
Version: 0.2.0
Summary: AI-powered text formatting for your terminal — fix grammar, rephrase, summarize, and more. CLI-first, cross-platform, works system-wide.
Project-URL: Homepage, https://github.com/digitronik/prosefmt
Project-URL: Repository, https://github.com/digitronik/prosefmt
Project-URL: Issues, https://github.com/digitronik/prosefmt/issues
Project-URL: Changelog, https://github.com/digitronik/prosefmt/releases
License-Expression: MIT
License-File: LICENSE
Keywords: ai,anthropic,cli,formatter,grammar,ollama,openai,prosefmt,rewriter,text
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: End Users/Desktop
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Text Processing
Classifier: Topic :: Text Processing :: Linguistic
Classifier: Topic :: Utilities
Requires-Python: >=3.11
Requires-Dist: click>=8.1
Requires-Dist: httpx>=0.27
Provides-Extra: dev
Requires-Dist: pre-commit>=4.0; extra == 'dev'
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
Requires-Dist: pytest-httpx>=0.30; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.4; extra == 'dev'
Description-Content-Type: text/markdown

# prosefmt

> Rewrite text in any app — press a hotkey, get polished prose back.

[![CI](https://github.com/digitronik/prosefmt/actions/workflows/ci.yml/badge.svg)](https://github.com/digitronik/prosefmt/actions/workflows/ci.yml)
[![PyPI](https://img.shields.io/pypi/v/prosefmt)](https://pypi.org/project/prosefmt/)
[![Python](https://img.shields.io/pypi/pyversions/prosefmt)](https://pypi.org/project/prosefmt/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)

<!-- TODO: Add demo.gif here — screen recording of: highlight text in a browser/Slack/email → press Mod+G → text rewrites in place -->

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
```

→ **[Jump to hotkey setup ↓](#system-wide-hotkeys)**

---

## Table of Contents

- [Why prosefmt?](#why-prosefmt)
- [Installation](#installation)
- [Setup Guide](#setup-guide)
  - [Step 1 — Install clipboard tools](#step-1--install-clipboard-tools)
  - [Step 2 — Choose an AI provider](#step-2--choose-an-ai-provider)
  - [Step 3 — Create your config](#step-3--create-your-config)
  - [Step 4 — Verify everything works](#step-4--verify-everything-works)
  - [Step 5 — Try it out](#step-5--try-it-out)
- [System-Wide Hotkeys](#system-wide-hotkeys)
- [Built-in Modes](#built-in-modes)
- [Custom Modes](#custom-modes)
- [Configuration Reference](#configuration-reference)
- [Commands](#commands)
- [Development](#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

```bash
# 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, …)**

```bash
# 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, …)**

```bash
# 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 prints `x11` or `wayland`.

**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.

```bash
# 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

```bash
export OPENAI_API_KEY="sk-..."
```

Add to your shell profile (`~/.bashrc`, `~/.zshrc`, or `~/.config/fish/config.fish`)
so it is always available:

```bash
echo 'export OPENAI_API_KEY="sk-..."' >> ~/.bashrc
```

#### Option C — Anthropic (Claude)

```bash
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)).

---

### Step 3 — Create your config

Run this once to create a ready-to-edit config file:

```bash
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:

```bash
# 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:

```toml
default_provider = "ollama"

[providers.ollama]
url   = "http://localhost:11434"
model = "qwen2.5:1.5b"
```

For OpenAI:

```toml
default_provider = "openai"

[providers.openai]
model = "gpt-4o-mini"    # API key comes from OPENAI_API_KEY env var
```

---

### Step 4 — Verify everything works

```bash
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

```bash
# 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](https://github.com/davatorium/rofi) if you do not have it already:

```bash
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`:

```bash
#!/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
```

```bash
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):

```bash
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`:

```bash
#!/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
```

```bash
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](https://www.hammerspoon.org) provides both the hotkey binding and a built-in
chooser for the mode picker. Add to `~/.hammerspoon/init.lua`:

```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:

```bash
/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`):

```powershell
# 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:

```ahk
; 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:

```toml
# ~/.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:

```bash
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

```toml
# ~/.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

```bash
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

[MIT](LICENSE)
