The idea is simple:
- highlight text where you’re writing
- press a hotkey
- get an AI paraphrase in a small popup
- insert it back with one click
The goal is to remove the “copy - open AI tool - paste - rewrite - paste back” loop for small edits.This post is about how I wired it up, what worked technically, and what didn’t.
Constraints I designed for
From the beginning I tried to design under a few constraints:
- One hotkey - one main action
- Stay inside the current app (no browser, no big side panel)
- Minimal UI: single suggestion, one click to insert
- Latency “feels instant” or it doesn’t get used
Whenever I broke these constraints (added extra choices, prompts, etc.), usage dropped in dogfooding.High-level architecture
Rough breakdown:
Desktop client that:
- listens for a global hotkey
- grabs the current text selection
- sends it to an API
- displays the returned paraphrase in a small overlay near the selection
Backend API that: - accepts the selected text + some minimal context
- calls an LLM
- applies a fixed prompt (“make this clearer, keep tone/voice as much as possible”)
- returns a single suggestion (no multi-choice for now)
No fancy infra yet, just trying to keep the path from “key press” to “returned text” as short as possible.Text capture and insertion
The surprisingly tricky part wasn’t the LLM, it was:
- reliably capturing the selected text
- not messing up the user’s clipboard
- inserting the rewritten text back without breaking formatting
The first version literally abused the clipboard: \ save clipboard
\ copy selection
\ send to backend
\ replace selection by pasting the result
\ restore clipboard
This worked… until it didn’t: \ some apps ignore simulated keypresses
\ sometimes the clipboard got overwritten by other things in between
\ it felt fragile and “hacky”
I’m slowly moving toward more app-aware integrations (where possible) while still keeping a generic fallback.Latency and UX
Latency matters more than I expected. Rough buckets:
1) < 500 ms - feels instant, people are happy
2) 1–2 seconds - acceptable if the suggestion is clearly better
3) > 3 seconds - people regret pressing the hotkey and use it less
A few tiny UX things helped: - show a small “loading” state immediately near the selection
- render the popup instantly (skeleton state), then fill it when the response arrives
- on failure, show a short, honest message instead of silently doing nothing
If you’re building AI tools, this won’t surprise you, but it’s different when you watch your own users hesitate after a few slow responses.Things that went wrong
I overbuilt customization early:
- tone dropdowns
- multiple modes (“shorter”, “longer”, “more formal”)
- extra toggles
People ignored them, or got decision fatigue.I underestimated how many edge cases there are with selection/insertion across different apps.
I didn’t log enough in the first builds, so I had to retrofit telemetry to understand actual usage.
If you’re curious, the current early version is here: [https://rephrazo-ai.app/](https://rephrazo-ai.app/)