dimiro1's notes

I recently got criticised for my tech choices on a few projects. The criticism wasn’t necessarily wrong, but it missed something crucial: context.

It’s easy to look at a project from the outside and think “why didn’t they use X?” or “this would be better with Y.” But when you’re not inside the constraints, when you don’t know the timeline, the team size, the actual problem being solved, or what success looks like, those judgments often miss the point.

Every project has its own shape

Here’s what I’ve learned building things at startups: each project needs you to look at it from different angles. A rule engine for transforming invoices has completely different constraints than a real-time AI agent or a B2B dropshipping platform.

What worked yesterday might not work today. The “right” technology isn’t absolute. It’s right for this problem, this team, this moment.

Sometimes that means choosing Go because you can deploy a single binary and move fast. Sometimes it means Clojure because the problem is about data transformation and you need the flexibility to let business analysts modify rules. Sometimes it means boring, proven tech because you need to ship tomorrow, not in three months.

Good developers adapt

The developers I respect most aren’t attached to a single stack. They can be effective in any reasonable environment. They learn what they need to learn. They make things work.

If you can only be productive in one language or one framework, that’s a limitation worth examining. The ability to assess a problem and choose appropriate tools, even unfamiliar ones, is more valuable than deep expertise in whatever’s currently popular.

Don’t let the market choose your stack

There’s a tempting trap: choosing technology mainly because it’s easy to hire for.

Yes, hiring matters. But don’t let it be your primary decision. Good developers can pick up new technologies. If you’re the kind of person who learns what’s needed, finding work won’t be your problem.

Context is everything

When someone criticizes your technical choices without understanding your constraints, it says more about them than about your decisions. People feel uncomfortable with what they don’t understand. They stick to what’s familiar.

That’s fine. Use PHP, JavaScript, Clojure, Rust, whatever makes sense for your situation. Maybe you’re experimenting and learning. Maybe you’re moving fast and need something you know. Maybe the problem really calls for specific capabilities.

The important thing is to solve the problem with the right balance for your situation: performance, developer happiness, maintainability, time to market, team capability. These trade-offs change with every project.

Understanding this, really understanding it, is what separates experienced builders from people who just have opinions about technology.

I was looking for a modern way to quickly find and replace text from the terminal, and I stumbled upon a Rust tool called amber. It's quite interesting, especially for quick replacements.

Amber provides two commands: ambs for search and ambr for replacement (as you can guess from the suffixes).

Leia mais...

This is part 3 of a series on building a terminal agent from scratch.

Previous parts: – Part 1: Building an Agent from Scratch – Part 2: The Conversation Loop

The complete source code is available on GitHub: https://github.com/dimiro1/agent-from-scratch/tree/main/03

In this part, we'll add markdown rendering to our terminal agent. LLMs return responses in markdown, so we need a way to display formatted text bold, italic, headers, code, and more, all using ANSI escape codes.

Leia mais...

This is part 2 of a series on building a fully functional terminal agent from scratch.

You can find the part 1 of this series in the following page: https://dimiro1.dev/building-an-agent-from-scratch

The complete source code is available in my GitHub: https://github.com/dimiro1/agent-from-scratch/tree/main/02

In this second part, we'll implement the conversation loop so we can have real back-and-forth conversations with the LLM. The agent will remember our past messages from the same conversation, making interactions feel natural and contextual.

Read more...

The other day I overheard two “vibe coders” talking about their project: “No, we need to build the backend first, and then the frontend will communicate like this and that...” Listening to them, I was reminded that the hardest part of software development isn't actually writing code. It's managing complexity.

There's currently an explosion of coding agents available. Some are deeply integrated into text editors like GitHub Copilot in VS Code or the flexible ones in the Zed editor. My favorites are the ones I can run directly in my terminal, such as Anthropic's Claude Code and Google's Gemini CLI. Excellent open-source projects exist too—Crush from Charm is one that comes to mind.

My goal is to create a series of posts where I build a fully functional terminal coding agent completely from scratch. I'll use minimal libraries and focus on teaching how a coding agent actually works. This isn't complex software, and I want to demystify that.

Read more...

Phoenix is a web framework written in Elixir. It's great for solo developers or small teams.

Phoenix LiveView lets you build interactive interfaces without writing JavaScript. Everything runs on the server. This is really useful when you need to ship fast.

The idea is similar to React, but it all happens server side. Phoenix handles the render loop:

  • Receive Event
  • Change State
  • Render State

Loop phoenix framework

Read more...

I just learned that we can use dbg/2 (https://hexdocs.pm/elixir/1.19.0/debugging.html#dbg-2) to debug expressions in Elixir. It's quite useful when used with the pipe operator – unlike IO.inspect, it automatically shows each step in the pipeline.

Read more...

Since I've been learning Clojure for the past few weeks, I decided to try to use clojure.spec library to generate tests. With spec, I essentially just need to define the shape of my data, and with this meta-information the library will dynamically generate all the tests.

Read more...

In Clojure, the let macro can be implemented in an elegant way using just what the language provides out of the box.

Read more...

Enter your email to subscribe to updates.