I Built a Fake Linear So My Agents Could Fail in Private ๐ซ
Hey tech adventurers! ๐
Confession: I'm building a tool where agents pick up Linear issues, do the work, and open PRs. It's called Paws. And testing that against a real Linear workspace is a great way to teach your coworkers what an agent sounds like at 3am. ๐
So I did the reasonable thing and built my own Linear. Locally. In a few hours. Like a normal person.
Mocks lie, and agents believe them ๐คฅ
The usual move is to mock the API. Stub issue.update, return some JSON, call it a day.
Except agent workflows don't really live in single calls. They live in the stuff between calls. A webhook shows up twice. A delivery fails and retries an hour later. An OAuth token rotates mid-session. A human answers the agent's question in a comment thread. Mocks happily skip all of that, and then production finds it for you.
I didn't want a fake that agrees with me. I wanted one that argues back.
Meet Finear ๐
Finear is a local, Linear-compatible server for integration tests. Bun, SQLite, done.
The part I'm weirdly proud of: it runs the unchanged @linear/sdk against real GraphQL. My code doesn't know it's being lied to. It just points apiUrl somewhere else.
What's actually in there:
- Issues, projects, sub-issues, labels, threaded comments ๐
- OAuth consent, PKCE, refresh rotation, revocation ๐
- Signed, durable webhooks with retries ๐ฌ
- Agent delegation, sessions, activities, and the human prompts in between ๐ค
- Deterministic fixtures and a reset button ๐งฝ
I can fast-forward time now โฐ
Real webhook retries wait a minute, then an hour, then six hours. Waiting six hours to watch a test fail is not a personality I want.
So Finear has a virtual clock. Advance it, and due retries fire in order, instantly. Inspect every delivery and every attempt. Reset the whole world when you're done.
It's the closest I'll ever get to time travel, and I used it to debug webhooks. ๐ซ
The agent part ๐
This is why it exists. Delegate an issue to an app and Finear creates an agent session. The agent can post thoughts, take actions, ask the human a question, and finish with a response or an error. The questions and answers show up as normal comment threads, like you'd expect.
That's exactly the loop Paws lives in. Now I can break it as many times as I want, on my laptop, without a single "hey, why is a bot commenting on my issue?" DM.
The fine print ๐งพ
Finear is a test harness, not a Linear replacement. It binds to 127.0.0.1 on purpose, and it isn't affiliated with Linear in any way. Please don't run your team on it. I'm begging you.
How to set it up lives in the README. This post is just me admitting I built a whole issue tracker so my agents could fail in private.
P.S. If your integration tests mostly test your mocks, I'm not judging. I was there two weeks ago. ๐