Blue Pencil
Text

Blue Pencil

The Blue Pencil app is a proofreader that runs on your own model: type or paste into the top field and the checked version fills in below as you write — spelling, grammar, punctuation and capitalization corrected, the wording left alone. Every correction is marked in pencil blue; hover one to see what it replaced. Copy takes the corrected text, Accept puts it back into the top field, Clear empties it to start over (undo brings the text back). Click the model name in the status bar for the options: which backend the check runs on — the Ollama endpoint, or the ChatGPT subscription signed in under Configuration → OpenAI — a model of that backend just for this app (the ChatGPT list is what the subscription serves, gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, …), how hard it thinks (Max by default — the best reading of the passage is worth the wait; Ollama's Off is fastest, but some models then think out loud in the answer; a level a ChatGPT model rejects runs at its default), and whether changes are marked at all.

Drafts are listed down the window's left, the way a Claude Code or Codex window lists its sessions: one row per draft, newest first, titled by its first line. Click a row to open that draft; New starts another beside it. The pencil keeps working on the drafts you are not looking at — the open one first, then the rest — and while the window shows one draft, a pulsing green dot marks another still being checked and a black dot one it finished, waiting for you; hover a row for which. A row's contextual menu opens with when the draft was started, in grey, then starts a new draft, copies the row's text or its checked text, or deletes the draft after a dialog. An empty draft is dropped the moment you leave it, so the list never fills with blank rows — on a phone, where the column is a strip of tabs above the fields, Clear and then any other row is how a draft goes. Dragging the line between the list and the fields sets the list's width. Every draft is kept, checked paragraphs included: reload the window, or open it on another desk sharing this node, and the column comes back as it was without asking the model again; which draft is open is this browser's own. With a draft open on two desks at once, the text belongs to the desk you type in: a check that finishes on the other desk adds its corrections and never changes your words, and text that does arrive from another desk waits for a word still being composed (an IME, a phone keyboard) and leaves the caret where it was.

The check runs on the Ollama endpoint in Configuration (ollama.base_url, ollama.model) unless the options point it at ChatGPT, so with a local model nothing you write leaves this machine; on ChatGPT the passage goes to OpenAI. Text is checked a paragraph at a time and only the paragraph you touched is re-checked, which keeps long documents cheap. A draft open on two desks of this node — or in the Hub composer too — still costs one model call a paragraph: the desk you type in asks first, the others join its answer as it streams, and a paragraph edited mid-check has its call cancelled once every desk has let go of it.

A working Blue Pencil also proofreads the Hub app's composer, in place: blue rules under what it would change and a floating menu to accept them (see The Hub). It runs on the settings chosen here.

Any app can ask that model a question the same way: POST /v1/chat/complete with {"system": …, "prompt": …} streams the answer as newline-delimited JSON — {"delta": …} lines, then {"done": true} — and optional model, effort and Ollama options (temperature, seed, …) fields override the configuration for that one call. "provider": "openai" runs it on the ChatGPT subscription instead (openai.model, openai.effort, and the sign-in under Configuration → OpenAI). With "share": true, identical calls are one model call: whoever asks while another asker's call is running reads that answer from its start, the call ends when the last asker hangs up, and a finished answer is kept ten minutes for whoever asks next — those read "shared": true on the done line. Leave it off when every call should sample afresh.

Contents