A One-Click Polish Script for Your Writing
Turning a tiny Python script into a seamless everyday tool with the OpenAI API.
There are days when I write more words than I read. Notes, emails, drafts, snippets of text for projects — most of them written quickly, with little care for grammar or flow. I usually know what I want to say, but the words land rough on the page. Fixing them later feels tedious, and most of the time I just don’t bother.
For a while I tried bigger tools: grammar checkers in the browser, or AI‑powered writing assistants. They all worked - technically - but they came with friction. Extra clicks. Extra windows. Extra features I didn’t need. What I really wanted was a single action: take the text I just wrote, clean it up, keep my meaning intact, and hand it back to me.

Starting with the simplest thing possible
The easiest way I found to start was with Python. I already had an API key for OpenAI and knew how to make a basic request. The missing piece was just gluing it together: grab the text from the clipboard, send it to the API, and put the polished version back into the clipboard.
No UI, no extra prompts — just in, out.
The first version was barely thirty lines of code. It does three things:
- Reads whatever text is in my clipboard.
- Sends it to the OpenAI API with a simple system prompt.
- Copies the improved text back into the clipboard.
If there’s nothing in the clipboard, it exits politely. If something goes wrong, it prints the error. That’s it. I call the script from the terminal with a single command — I named mine polish.
The code itself is short enough to understand at a glance. I won’t paste it here (Substack doesn’t handle code well), but you can take a look at it in the GitHub repository.
Why not just use a bigger tool?
Because I wanted something I wouldn’t notice. No UI. No new writing environment. I already my editor (neovim) and note‑taking system I like and use. This script works everywhere: email clients, Slack, Obsidian, even a plain text box in a browser.
The benefit of such a small tool is that you end up using it all the time. It doesn’t feel like “opening an app” or “switching modes.” It’s just there when you need it — like undo or copy‑paste.
And when something is this frictionless, it becomes part of your muscle memory. That’s when tools stop feeling like “tools” and start feeling like part of the system.
From CLI to hotkey
The command‑line version was fine for a while. I’d copy text, switch to the terminal, run polish, and paste the result. Three steps. Not bad, but still enough friction to skip it when I was in a hurry — or if I wasn’t already working inside a terminal (for example, when writing an email).
I wanted something that felt like magic: highlight text, press a single key combination, and watch it instantly improve. No windows flashing, no context switch. Just better text, right where I left it.
That led me to Hammerspoon.
A hammer and a spoon
Hammerspoon is an open‑source macOS tool for desktop automation. It sits quietly in the background and lets you script macOS itself using Lua. With it, you can listen for system events, manipulate windows, control hardware, and — crucially for this project — intercept keyboard shortcuts.
What impressed me is how straightforward it feels. The API is minimal and well‑documented, and the integration with macOS is deep enough that you can automate almost anything without hacks. Although Hammerspoon is already around for years, it just caught my attention recently. This little polish script felt like the first touch point.
Installing Hammerspoon
The easiest way to install it is via Homebrew:
brew install hammerspoon
After installation, launch the app once so macOS can ask for the necessary permissions (accessibility, clipboard, etc.).
By default, Hammerspoon looks for its configuration file at ~/.hammerspoon/init.lua. I like to keep my dotfiles under ~/.config, so I tell it to look there instead:
defaults write org.hammerspoon.Hammerspoon MJConfigFile “~/.config/hammerspoon/init.lua”
From then on, any Lua code in that file will run when Hammerspoon starts.
Rewriting the script in Lua
Porting the Python prototype to Lua was simple. The logic is identical:
- Get the current clipboard text.
- Send it to the OpenAI API (with proper authentication).
- Take the returned text and copy it back to the clipboard.
Hammerspoon provides functions for both clipboard handling (hs.pasteboard) and HTTP requests (hs.http). Binding it to a global hotkey is one line:
hs.hotkey.bind({"cmd", "alt"}, "P", function()
-- polish logic here
end)
I chose ⌘⌥P because it’s easy to hit with one hand and unlikely to clash with other apps.
Why Hammerspoon over Shortcuts?
I first experimented with Apple Shortcuts. It works, technically: you can grab the clipboard, call the OpenAI API, and paste the result back. But the process is awkward. The JSON handling is clunky, debugging is painful, and the whole system feels opaque.
Hammerspoon, by contrast, is a real scripting environment. The code is readable, debuggable, and lives in a plain text file under version control. It’s faster, too - no spinning wheels or modal dialogs.
Most importantly, it’s fun. Writing tiny Lua snippets to automate your computer feels like customizing a toolbelt. Once I had the polish script working, I immediately thought of five other things I wanted to automate.
Living with it
I’ve been using the Hammerspoon version for some days now. The change in habit is subtle but real: I polish text constantly, not just when I’m writing something “important”. A quick reply, a comment on GitHub, a paragraph in a blog draft - if it takes me one keystroke, why wouldn’t I?
It doesn’t make my writing perfect. It doesn’t replace editing. But it clears the roughest edges in seconds and gives me a cleaner starting point. And because it’s mine, I know exactly what it does and how it behaves. There are no surprises, no subscriptions, no “pro plans.”
A pattern worth repeating
This project is a good reminder of a pattern I keep returning to:
- Start with a tiny, personal need.
- Build the simplest thing that works, even if it’s rough.
- Use it in your daily life.
- Iterate, polish, integrate — only if it’s worth it.
The process is the same whether I’m making a note‑taking workflow, a physical “thing” in my shop, or a small automation script: start minimal, live with it, see where it leads.
The idea of small tools isn’t new — and it certainly wasn’t invented by me. The philosophy goes back to the early UNIX days in the 1970s: small is beautiful, and small is simple.
Share – code & conversation
The code for this tool lives on GitHub
Clone it, fork it, change it to your needs.
And if you enjoyed this article, consider subscribing.