Pinned Tweet
I got tired of constant tool switching, so I built PostPilot.
An all-in-one local devtool with:
• API client
• DB client
• Data inspector
Built for workflows where you keep jumping between tools, copying IDs, and losing focus.
My first changelog for PostPilot - "another" API client.
I've been building PostPilot for almost 2 years.
Building a dev tool is hard. Correctness matters more than speed. It's not about shipping fast.
No one wants to debug an API issue, only to find out the tool itself is the problem.
Agent skills will soon become another maintenance liability alongside code.
Clean code principles apply to Markdown too.
Write skills you can maintain.
ASCII diagrams are SOOO powerful for understanding your code flow.
Especially now that we're generating so much code.
A tiny way complexity enters a codebase: adding logic in consumers to compensate for an upstream mistake.
Example:
Producer stores:
status = COMPLETED_AND_EXPORTED
But the domain really means:
status = COMPLETED
exportState = EXPORTED
A consumer can translate between them, and everything works.
But as more consumers appear, that logic starts to spread.
Prefer fixing the root cause.
Each branch is cheap. The accumulated mental model isn't.
The more I learn about AI harnesses, the more impressive they become.
A useful way I think about their anatomy:
AI HARNESS
┌────────────────────┐
│ Instructions ───┐ │
│ Context ─────┤ │
│ Memory ─────┤ │
│ Retrieval ─────┼─► MODEL │
│ Tools ◄──────┤ │ │
│ │ ▼ │
│ Orchestration │
│ Guardrails │
│ Evals / Observability │
└────────────────────┘
The model is only one part.
A lot of the magic is in the engineering around it.
And I think that's where developers can get much more out of AI too:
Better context.
Better tools.
Better guardrails.
Better evals.
Don't just use a better model.
Build a better environment around it.
Another supply chain attack.
Another reminder that software engineering is an always-on job.
It's not just about writing code anymore.
It's about constantly watching what your code depends on.
Not having any users means you don't need to deal with refunds and chargebacks.
Stay positive, builders 😂
Building WebSocket support in PostPilot this weekend.
AI helped move fast. but it also added backward-compatibility code for a schema I'd changed minutes earlier.
Good reminder: AI can generate code faster than it can justify it.
The real job is still deciding what should exist.
How do you keep AI-assisted changes proportional to the problem?
Weekend build log: WebSocket support in PostPilot.
Added a saved message composer with Text/JSON mode. Then caught an AI-generated "migration" for an intermediate format that had never shipped.
Deleted it.
Small lesson: AI is great at implementation, but it will happily turn a simple feature into future maintenance if you don't keep asking: "Do we actually need this?"
I thought Agent Skills worked like function calls.
That wrong mental model wasted hours.
🗒️I was contributing a shared Skill library for my team's workflow, where agents could use other Skills to accomplish more complex tasks.
Naturally, AI started generating instructions like:
> Call Skill A with File B
> Wait for Output C
> Pass it to Skill D
It looked perfectly reasonable.
Until I went back to the docs.
That's when I realized Skills aren't function calls.
They're instructions loaded into Agent's context.
Agent doesn't call a Skill with param.
It reads it, then decides what to do next.
That one mental model change completely changed how I write Skills, and how I ask AI to generate them.
I added to my skill-creator / writing-great-skill these rules:
1. Skills are loaded as context/instructions, not invoked like functions.
2. After reading a Skill, Agent should decide its own next steps based on the Skill's guidance.
3. Don't write Skills that expect explicit parameters or return values. Write them as instructions Agent follows while working on the current task.
Before:
Call Skill A with input X, Y, Z. Expect output C.
After:
Invoke Skill A to do task B.
Java's functional interfaces are surprisingly hard to remember.
💡 Here's the cheat sheet I wish I had:
Predicate<T> T -> boolean
Function<T,R> T -> R
Consumer<T> T -> void
Supplier<T> () -> T
UnaryOperator<T> T -> T
BinaryOperator<T> (T,T) -> T
BiFunction<T,U,R> (T,U) -> R
BiConsumer<T,U> (T,U) -> void
BiPredicate<T,U> (T,U) -> boolean
🎯 Mental model:
• Predicate → asks a question ✅
• Function → transforms 🔄
• Consumer → does something ⚡
• Supplier → creates/provides 📦
• Operator → same type in, same type out ♻️
Once I remembered those 5 concepts, the rest became much easier.
Been working on PostPilot, my local-first API + DB client, and finally shipped SSE support today 🎞️.
This ended up taking much longer than I expected.
Streaming responses aren't difficult to receive.
Making them pleasant to debug is.
Instead of showing a blank loading screen, PostPilot now:
• automatically detects text/event-stream
• displays events live with timestamps and event types
• lets you stop the stream without losing previous events
Small feature, but one I'm genuinely happy with.
Curious: what's the most annoying part of working with SSE or streaming APIs?
Also shipped a bunch of DB client fixes and OpenAPI import improvements in this release.
I wrote up the full breakdown on r/webdev if you'd like to check it out: reddit.com/r/webdev/comments…
If you find it useful, an upvote would really help get it in front of more developers. 🙏
Project: postpilot.dev
Changelog: postpilot.dev/changelog
Most AI founders fear one thing:
💣Waking up to find Anthropic just launched your product.
That's exactly what happened to Viktor, an AI startup building an "AI Employee" for enterprise teams.
Anthropic recently introduced Claude Tag, an AI teammate for Slack that looked surprisingly familiar.
So what did Viktor do?
They bought the Google Ads keyword "Claude Tag."
Anthropic had just spent millions educating the market about AI Employees.
Viktor simply showed up when people searched.
According to their CEO, they only lost a handful of customers while gaining hundreds of new signups from the increased attention.
---------------------------------
But the story made me think about something even more interesting.
Viktor's takeaway was:
"Rent the intelligence. Own the context."
I think there's an even broader lesson for AI builders today.
Rent the intelligence. Build the harness.
Because the harness is what owns the context.
We're entering the era of Harness Engineering.
Think about it.
An AI product isn't just a model anymore.
Agent = Model + Harness
The model provides intelligence.
The harness turns that intelligence into a useful product.
The harness includes things like:
• Context management
• Memory
• Prompt orchestration
• Tool calling
• MCP / external integrations
• Permissions
• Human approval
• UI/UX
• Workflows
• Observability
This is why companies built on the same foundation model can still look completely different.
Claude Code is a harness.
Cursor is a harness.
Perplexity is a harness.
GitHub Copilot is a harness.
The foundation model may change every few months.
Claude is ahead today.
GPT might be ahead tomorrow.
Gemini, DeepSeek, or an open-weight model could lead next year.
But if your product is only "Claude wrapped with a button", you're competing with Anthropic.
If your value comes from your harness - your workflows, integrations, context, and user experience - you have something much harder to replace.
Maybe that's why we're seeing a new engineering discipline emerge.
Not prompt engineering.
Harness Engineering.
The model gets smarter every month.
Your harness is what customers stay for.
AI had all my docs.
It had the right context.
We still almost shipped the wrong implementation.
Here's what happened. 👇
🧾I'm building PostPilot, an all-in-one API client, DB client, and data inspector (think Postman).
We hit a bug: SSE streams were auto-closing after 2 minutes because of reqwest's built-in timeout.
So I asked AI to fix it.
💬Me: "SSE stream closes after 2 min. It's the reqwest timeout."
🤖AI: Removes reqwest's timeout and applies a tokio timeout only to the header phase. The stream body now has no timeout.
💬Me: "Looks good. Ship it?"
🤖AI: "Yes. Timeout now only applies to the header phase, so SSE streams can run indefinitely."
Technically correct.
We almost shipped it.
⚠️Then I stopped and asked one more question.
💬Me: "Wait... what do developers expect when they set Request Timeout = 5s for a normal request?"
🤖AI: "...they expect the entire request - headers and body - to finish within 5 seconds. Like Postman."
💬Me: "So our fix is wrong for non-SSE requests?"
🤖AI: "Yes. Let me fix that."
One question.
Completely different implementation.
The fact that PostPilot is an API client was already in my docs.
AI had that information.
But having a fact in context isn't the same as knowing when it should influence a design decision.
AI didn't make the connection:
"API client" → "check timeout behavior against API client conventions."
Until I explicitly asked.
Facts have weight. Commands have direction. They're not the same thing.
🎯 Takeaway:
When AI has all your context, it still needs you to bridge fact → judgment.
The more I use AI for coding, the less I think the real skill is prompting.
The real skill is noticing when something feels off...
...and asking the one question that changes the entire solution.
In a distributed system:
"Reacting to state changes" is powerful.
For short flows, it feels right:
CartUpdated event ⚡
→ recalculate total
→ update shipping fee
The UI doesn't need to call "Recalculate Total". The system simply keeps derived data up to date.
⚠️ But it gets blurry when events start driving a user decision flow:
CartUpdated event ⚡
→ shipping service finds options
→ emits ShippingOptionsFound event ⚡
→ UI shows options
→ user selects one
→ UI saves shippingOptionId
→ CartUpdated event fires again ⚡
→ fulfillment service detects shippingOptionId changed
→ creates shipment
→ reserves inventory
Now the business flow is split across state changes and hidden listeners.
The problem isn't events.
The problem is using state changes as hidden commands.
🎯 My rule of thumb:
- Use events for derived side effects.
- Use explicit commands when the user is making a business decision.
What event-driven pattern have you seen become more complex than it needed to be?
Today I learned why it's called a radio button.
The name doesn't come from software.
It comes from old car/home radios.
📻 Those radios had physical preset buttons. When you pressed one station, that button stayed down while the previously selected one popped back up.
🔘 Exactly how HTML radio buttons work today.
One option in.
The others out.
Sometimes UI components carry decades of history.


















