Why is replying so much harder than reading?
You scroll past a post, you have a reaction, and then you stare at the empty reply box for thirty seconds and move on. I did that every day.
So in August 2024 I built a Chrome extension that drafts the reply for you, right in the reply box, in a tone you pick. It’s called ReplyKit now. It started as a weekend hack for X and grew into a small product on three networks, with a free tier, a paid plan and a mobile web app.
The model turned out to be the easy part.
Version 1: bring your own key
The first version only worked on X. You got a button under each post, a few tones, and a field in the popup to paste your own API key, which the extension encrypted and stored locally.
That was fine for me and for anyone comfortable creating an API key. There aren’t many of those.
In July 2025, version 2 added a provider picker: OpenAI, Claude, Gemini or a local model. More choice, same problem. Everyone still needed a key.
Version 3: no keys at all
In 2026 I moved generation behind my own backend, and then made that the only path.
Today the extension has no API keys anywhere. Every request goes through a proxy on this site, which picks the model by plan: Claude Haiku on the free tiers, Claude Sonnet on Pro.
The plans:
- •Anonymous: 3 replies a day, no setup.
- •Free account: 5 a day after a one-tap email sign-in.
- •Pro: €6.99 a month, unlimited, with the better model.
Did dropping the key setup help? Less than I expected on installs, more on usage. In the three months before the switch, ReplyKit got about 13 installs a week. In the three months after, about 15. The share of store visitors who installed didn’t move, around 60% both times.
What changed was how many people kept using it. Weekly users averaged about 26 before the switch and about 40 after. I shipped other things in that window too, a lower free limit and a prompt overhaul, so I wouldn’t give the hosted backend all the credit. But people who never had to find an API key were a lot more likely to come back.
How the extension is built
ReplyKit is a Manifest V3 extension in plain TypeScript, with no UI framework. Three pieces do the work.
A content script gets injected into X, LinkedIn and Reddit. It builds the reply panel, reads the post you’re replying to, and writes the draft into the composer.
A service worker runs in the background. It’s the only part that makes network calls, which keeps each site’s security policy out of the way.
Then there are the platform adapters, one per site, behind a single interface. Each adapter knows how to find the reply box and the post button, insert text, and pull context like the parent posts and the character limit.
Generation streams. The service worker reads the server’s streaming response and forwards each chunk to the tab, so you watch the reply type itself into the box.
Everything outside the adapters is platform-agnostic, so fixing a broken site, or adding a new one, means touching one file.
The hardest part: other people’s editors
You’d think putting text into a text box was a solved problem. On X, it isn’t.
X’s composer is a rich-text editor with its own internal state. If you just set the text in the page, the box looks filled, but X’s editor has no idea.
The only reliable trick I found is to fake a paste: build a clipboard event with the text and dispatch it on the editor. That updates X’s state and keeps the line breaks. There are two fallbacks for when the paste doesn’t take.
Threads were worse. To add a second post to a thread, you click the “+” button. Calling .click() on it does nothing, because X’s toolbar buttons listen for mouse-down and pointer-down, not click. So the extension fires the whole pointer sequence.
The “+” also shows up late, so the code checks for it every 150ms for up to 5 seconds. It finds the button by the shape of its plus icon rather than a test ID or a label, because the icon survives renames and language changes.
Site selectors are by far the most fragile part of the codebase. When X ships a redesign, ReplyKit breaks. I haven’t found a way around that, only fast fixes and good tests.
Quotas you can trust
Free tiers attract abuse, so the server is the only source of truth for usage. The extension shows counters, but they’re display-only.
Each request runs one Postgres function that checks the token, checks the quota and bumps the counter atomically, with row locking, so concurrent requests can’t sneak past the limit. If the AI call fails afterwards, the counter gets rolled back, and an error never costs you a reply.
Anonymous trial tokens are capped at 10 per IP address per 24 hours. That’s generous on purpose, because whole offices and universities share one IP.
One bug taught me something. When the anonymous allowance ran out, users saw a “Can’t reach ReplyKit” error. The client picked which error card to show by searching the error text for the word “network”, and the quota message reads “Trial limit reached for this network…”. Now errors are routed by their structure, never by their wording.
Prompting: polish, don’t invent
Most of the iteration went into prompts, and most of that was removing the tells that make a reply sound AI-written.
Every platform’s prompt shares one block of style rules: no em dashes, a ban list of words and phrases, rules about sentence rhythm, and an instruction to always reply in the language of the post.
The most useful discovery was about blank posts. Ask Claude to “write a post about something interesting” and it hedges. Hand it a rough draft to polish and it does a good job, reliably. So when you start from an empty composer, ReplyKit first builds a draft scaffold from a random pairing of a subject and an angle, then asks the model to finish it.
Beyond the desktop
People reply on their phones too, and phones don’t run extensions. So ReplyKit also ships as an installable web app on this site. On Android you can share a post straight into it from the share sheet and get a reply to paste back.
Installs are nothing crazy, but they’re growing slowly. Over the last twelve months the Chrome Web Store counted 641 installs, roughly 50 a month, and weekly users went from 13 to about 60. A bit under half the people who open the store page end up installing it.
Since I started logging in May, people have opened 251 anonymous trials and ReplyKit has written 539 replies and posts, about 85% of them for X. LinkedIn and Reddit are still small. 37 people have created an account. Three have paid for Pro, and one still does. Not a business yet, but people use it.
What I’d tell you
- •Remove setup before you add features. Nobody wants to create an API key.
- •Put every network call in one place, and let the server be the only judge of quotas.
- •Expect the sites you integrate with to break you. Keep their DOM behind adapters.
- •Never route errors by matching their text.