RSSAmplifier

Blog

Manuel de la Peña

Recent content on Manuel de la Peña

mdelapenya.xyzRSS feed ↗80 posts

Latest posts

Understanding Testcontainers: Session IDs

I am a core maintainer of testcontainers-go . This is the eighth post in a series on the library. The previous seven covered the API shape, wait strategies, lifecycle hooks, the module system, networks, and two applied module posts that used LocalStack to test a Lambda and Toxiproxy to test network resilience. This one goes back to internals. It also pays off a pointer I left earlier. In the…

Code Is a Cache

Every time we change a file in a repository, we are changing the worldview of every agent working in that repo. That sentence sounds abstract until you sit with it. A file is not just code the machine runs. It is context the agents read to understand what the project is, what it values, how it behaves. When an agent opens your codebase, the files are what it knows. Change a file and you change…

Understanding Testcontainers: Testing Network Resilience with Toxiproxy

I am a core maintainer of testcontainers-go . This is the seventh post in a series on the library. The previous six covered the core from the inside: the API shape, wait strategies, lifecycle hooks, the module system, networks, and then an applied module post that used LocalStack to test a Lambda. This one goes somewhere different. Instead of testing that a feature works, we test that the…

Understanding Testcontainers: Testing AWS Lambdas Locally with LocalStack

I am a core maintainer of testcontainers-go . This is the sixth post in a series on the library. The previous five read the core from the inside: the API shape, wait strategies, lifecycle hooks, the module system, networks. This one changes direction. I take one module off the shelf, the LocalStack module, and use it to write a test that would be painful to write any other way. Everything here…

Understanding Testcontainers: Networks

I am a core maintainer of testcontainers-go . This is the fifth post in a series on the library’s internals: how the API is shaped, how containers wait until they are ready, how the module system layers on top of the core, how cleanup works. Each part stands on its own. Each part is written by reading the source directly, so every claim in the post traces back to a file and a line.

A Year of testcontainers-go on Docker Hub

I am a core maintainer of testcontainers-go and a Docker employee. That overlap is what makes this post possible. As the maintainer I know exactly how the library identifies itself when it talks to a Docker daemon. As a Docker employee I can look at the Docker Hub pull metrics filtered by that identifier. Together they produce a measurable trail. This post is short. It covers the two images…

Understanding Testcontainers: The Module Layer

I am a core maintainer of testcontainers-go . The third post in this series closed pointing at the module layer. modules/postgres.Run , modules/redis.Run , modules/kafka.Run , and the rest of them are not standalone constructions. They are thin wrappers around the same Run we have been tracing for three posts. Today there are 65 of them in the repository, and I went looking to see how consistent…

Understanding Testcontainers: The Lifecycle Hook System

I am a core maintainer of testcontainers-go . The second post in this series closed on a teaser: the wait strategy is just a PostStarts lifecycle hook. So is the streamer that routes container logs to your consumers. So is the file copier that puts your test fixtures inside the container. So is the friendly emoji-decorated logger that announces “🐳 Creating container” and “✅…

Understanding Testcontainers: The Wait Strategy Taxonomy

I am a core maintainer of testcontainers-go . The first post in this series ended on a teaser: how the library decides a container is “ready” after it has started, which turns out to be a surprisingly different question from “is it running”. The first half of that distinction is easy. Running means Docker says the container is running, no more, no less. The second half is…

Testing Helm charts with sk8s and testcontainers-go

Originally written by Enin Kaduk , also published his personal blog: https://www.blueprismo.com/posts/2026/sk8s_testcontainers/ Intro If you ship Kubernetes workloads, you eventually want tests that go beyond helm template and YAML linting. You want to know that the chart actually installs, that the security context matches your intended least privilege, that probes succeed, that pods become Ready…

Understanding Testcontainers: From GenericContainer to Functional Options

I am a core maintainer of testcontainers-go . This post opens a series on the library’s internals: how the API is shaped, how containers wait until they are ready, how the module system layers on top of the core, how cleanup works. Each part stands on its own. Each part is written by reading the source directly, so every claim in the post traces back to the code.

I Sent a Message on Telegram. A Pull Request Appeared on GitHub.

I typed a message in Telegram. Something like: “I want to write a post about the setup we just built for writing blogs from Telegram.” I sent it to TheBlog, one of the topics in my personal AI group. Twenty minutes later, the agent sent me a link. A pull request existed on GitHub with a draft of this post, a branch, a conventional commit, and a structured PR description. I had not…

Haciendo webs ultraligeras

En el año 2000 me matriculé en un curso de creación de páginas web. Duraba 300 horas. Trescientas horas para aprender a escribir HTML. Hoy, más de 25 años después, construí un fan site completo con Next.js, TypeScript y Vercel en un par de días, con un agente de IA haciendo la mayor parte del trabajo. Este post no es nostalgia. Es un mapa de cómo ha cambiado el oficio, y por qué los…

A Virtual Agent Team at Docker: How the Coding Agent Sandboxes Team Uses a Fleet of Agents to Ship Faster

This post was originally published on the Docker Blog on May 1, 2026. I work on Coding Agent Sandboxes, aka “sbx” at Docker. The project provides secure, microVM-based isolation for running AI coding agents like Claude Code, Gemini, Codex, Docker Agent and Kiro. Agents get full autonomy inside a sandbox (their own Docker daemon, network, filesystem) without touching your host system.…

My PR Has a Lawyer, a Nurse, a Detective, and a Scribe

Every PR I open goes through four people. The scribe writes the description. The lawyer handles the review. The detective investigates CI failures. The nurse watches the build until it merges. None of them are people. They are Claude Code skills, each designed as a role with judgment, not a command that executes. This is how they work and why the “role not command” distinction matters…

A Personal AI That Reads My Bills

There is a Synology NAS in my home office that already runs Plex, holds photo backups, and hosts a handful of Docker containers. Adding “personal AI assistant” to the workload was, in cost terms, free. The real question was: what would I use it for? The answer turned out to be my bills. Mercadona grocery receipts, Iberdrola electricity invoices, BBVA bank statements, Amazon orders. All…

My Daily Workflow with biomelab

I have biomelab open all day. It’s the first thing I launch in the morning and the last thing I close. Every repo I work on, every worktree, every agent session, every PR: all visible in one terminal dashboard. I never touch main. I never work without a worktree. And I never start Claude without knowing exactly which branch it’s on. This is what my daily workflow looks like.

Por qué construí un visor de trenes en tiempo real

En enero de 2026, iba con mi familia en un tren a Barcelona. Las noticias del accidente de Adamuz llevaban días en todos los medios. Nuestra línea, Madrid-Barcelona, acumulaba retrasos por reducción de velocidad en varios tramos largos del recorrido debido a problemas en la infraestructura. Quería saber dónde estaba mi tren, cuánto retraso llevaba, y qué estaba pasando en la red. No había forma…

Building a Real App Inside a Docker Sandbox

I started renfe-maps in January using GitHub Copilot’s agent mode directly on GitHub. I opened issues, Copilot opened PRs, I merged them. The first PR scaffolded the entire app in one shot: GoFiber backend, React frontend, everything wired up. The second added documentation. A third tried to add GCP deployment with Terraform; I closed it without merging. It worked for bootstrapping, but the…

Tokens Are the New AWS Account

Ten years ago, if your company didn’t give you an AWS account, you were stuck spinning up servers under your desk. The companies that got it understood that giving engineers cloud access wasn’t a cost. It was a multiplier. The rest fell behind. Today the same thing is happening with AI tokens. And most companies haven’t noticed yet. The AWS Account Test Around 2014, cloud access…

The Seventh Tip: Testing Is What Makes Swarming Safe

Steve Yegge and Gene Kim published six tips for coding with agents while in Sydney for Vibe Coding workshops. The tips are excellent. Every one of them maps to something I have experienced building this blog, its infrastructure, and the tools around it. I agree with all six. But there is a seventh tip missing. Yegge describes how to review agent work (the Rule of Five) and how to manage parallel…

Quality Assurance vs Quality Assistance

QA has always meant one thing. Now it means two. I spent years building Testcontainers, a library whose entire purpose is deterministic integration tests. Set up a real database in a container, run your assertions, tear it down. Pass or fail. Green or red. That’s Quality Assurance: the gate model. It works when you control the volume of code flowing through the gate. Then I built an…

Dream QA: The Manifesto I Wrote in 2019

In 2019 I was QA Team Lead at Liferay Cloud . I wrote a manifesto for my team that redefined what we meant by QA. I gave two talks about it under the title “Dream QA”: the first at EURODOG (European DevOps Group) in Madrid, and the second at JCCM (Junta de Comunidades de Castilla-La Mancha, the government of the region where I live in Spain). It wasn’t a process document. It was…

From /loop to CI: Ralph and the Level 6 Pattern

The Level 5 post ended with a promise: “Agent teams and /batch are where the automation goes next. When agent teams stabilize, the ‘four Warp panels’ setup becomes ‘one command that spawns a coordinated team.’ That’s Level 6: agents that don’t need my laptop at all.” Ralph is my answer to that. Not an agent team (those are still experimental). Not a…

Skills Are Roles, Not Commands

I kept calling them commands. /blog-editor , /deploy , /fix-issue . Imperative verbs. Do this thing. But the more I used them, the more I realized the mental model was wrong. A skill isn’t a command. It’s a role. A command says “run deploy.” A skill says “you are the deployment engineer. Here’s your process, your constraints, and your tools.” One executes…

Level 5 in Practice: Four Agents, Four Worktrees, One Developer

I described Level 5 in the six levels post: multiple agents in parallel, each on its own worktree, the IDE for reviews only. That was the theory. Here’s what a Wednesday morning actually looks like. Four Warp panels. Four git worktrees. Four Claude Code sessions. Each one working on a different task. And each one running its own /loop command, autonomously monitoring CI, merging from main,…

gwaim: The Tool That Level 5 Needed

The Manual Pain The Level 5 workflow was a workflow that worked. Four git worktrees, four Warp panels, four Claude Code sessions. Each one on its own branch, its own task, its own /loop . The throughput was real. Three merged PRs by lunch instead of one. But the setup was all manual. git worktree add ../sandbox-fix-auth fix/auth-bypass . Repeat four times. Open four terminals. Navigate to each…

My Agentic Coding Stack: Why the IDE Matters Less Than You Think

In the previous post I described six levels of AI-assisted development, from no AI to fully autonomous agents. Each level changes which tools matter and which ones become irrelevant. This post is what my stack looks like at Level 4: one coding agent in the terminal, the IDE as a review surface. Why I Left Cursor’s Chat Behind I moved to Cursor specifically for Level 3. The inline chat was…

The Six Levels of AI-Assisted Development

I moved from VS Code to Cursor for the AI chat. Then I moved the AI chat to the terminal. Now I’m not sure I need Cursor at all. That shift wasn’t random. It followed a pattern I’ve been thinking about: a maturity model for how developers adopt AI tools. Each level changes which tools matter in your stack, and which ones become irrelevant. Understanding where you are on the curve…

Subscriptions: From Idea to Testcontainers Module

I went from one post a month to publishing every other day. The friction post explains how. The writing problem was solved. But a new problem appeared. I had no idea if anyone was reading. This post is the full arc: why I added subscriptions, how I built them on a static site with no backend, and how the testing journey led me to create an open-source Testcontainers module for Resend.

Choosing a Terminal for Agentic Development

A colleague recommended Warp. “Try it,” he said. “It’s good for the kind of work we do.” I’d been on Terminal.app for years. Running Claude Code sessions, supervising agents, iterating on prompts: that part was only about a year old. It worked. But I’d never stopped to ask whether it was working well . So I started exploring Warp, and somewhere along the…

Coding Agents as Exploratory Testers

I needed to test a CLI tool across three platforms. I’ve been down this road before. I’ve used Aruba in Ruby to wrap CLI interactions in Cucumber scenarios, termtest in Go to drive pseudo-terminals programmatically, and Tcl/Expect to automate interactive prompts. Each one works, but they all share the same limitation: they’re scripts. They check that command X produces output Y .…

Choosing the Smallest LLM That Won't Completely Fail You (Part IV): Observability with OpenTelemetry and Grafana

In Part 1 we set up SLMs with Docker Model Runner. In Part 2 we built the benchmarking framework with Go. In Part 3 we added automated quality evaluation and tool calling benchmarks. The framework now produces all the data you need. But 160 scenarios with 10+ metrics each means 1,600+ data points in console output. Patterns that are obvious in a chart are invisible in a wall of text.

I Removed the Friction. Now I Write Every Other Day.

I used to need a full afternoon to write a blog post. Not because the writing took that long, but because I needed a long, uninterrupted block of time. Find the right topic, set up the front matter, write the draft, check the links, fix the cross-references, write the social copy. If I got interrupted halfway through, I’d lose context and the post would sit half-finished for days. Sometimes…

Choosing the Smallest LLM That Won't Completely Fail You (Part III): Evaluator Agent and Tool Calling

In Part 1 we covered what SLMs are and how to run them locally with Docker Model Runner. In Part 2 we built a benchmarking framework with Go that runs 160 scenarios and reports latency, throughput, and success rates. But there’s a gap. Latency and token counts tell you how fast a model responds. They don’t tell you how good the response is. If a model answers in 200ms but the answer is…

Choosing the Smallest LLM That Won't Completely Fail You (Part II): Benchmarking with Go

In Part 1 I showed how to run Small Language Models locally with Docker Model Runner. You can pull a 727 MB model and chat with it on your laptop. Great. But which model should you actually pick for your project? MMLU scores and Hugging Face leaderboards give you a general sense of model quality, but they don’t test your prompts, with your tasks, at your temperature settings. The only way to…

Choosing the Smallest LLM That Won't Completely Fail You (Part I): SLMs and Docker Model Runner

I recently gave a talk at ContainerDays London 2026 called “Choosing the Smallest LLM That Won’t Completely Fail You.” The title was a bit funny, but the question behind it is dead serious: when you’re building AI-powered software, do you really need a model with hundreds of billions of parameters for every single task? The short answer is no. And in this four-part series,…

Spec-Driven Development: Is This the New BDD?

Write specifications first, let something else handle the implementation. We’ve been chasing this dream for thirty years, UML, CASE tools, Model-Driven Architecture. Now AI agents are making us chase it again. I got that déjà vu reading Birgitta Böckeler’s “Understanding Spec-Driven-Development: Kiro, spec-kit, and Tessl” , shared with me by Kevin Wittek . She explores…

Parallel Coding Agents with Docker Sandboxes and Git Worktrees

Coding agents are powerful. They can refactor modules, write tests, fix bugs, and scaffold entire features. But running them directly on your host means giving them access to your system: your files, your packages, your running containers. Now imagine running multiple agents in parallel on the same repository checkout. That’s a recipe for conflicts, corrupted state, and a bad afternoon.…

Coding with AI Agents: Like Driving a Tesla on Autopilot

I’ve been coding with AI agents for the past year, and recently something clicked: the experience is remarkably similar to driving my Tesla with Autopilot engaged. Not Full Self-Driving (Supervised), just the basic Autopilot, the Level 2 driver-assistance system that handles steering and adaptive cruise control while you remain fully responsible for the vehicle. The analogy isn’t…

A Tale of Two Diagnostics: AI vs. Traditional Troubleshooting

The Setup I recently bought an electric car and had a home charger installed. Installation went smoothly, the technician finished up, and we were ready for the moment of truth: the first charge. The car detected the charger. The app showed it was connected. Everything looked perfect. Then the car’s screen displayed: “External charging equipment not supplying energy. Check power source…

From Hours to Minutes: How Dotfiles Changed My Laptop Migration Strategy

The Problem: The Dreaded Laptop Switch We’ve all been there. You get a shiny new MacBook, and instead of diving into work, you spend the next day (or week) trying to remember: Which Homebrew packages did I have installed? What were my bash/zsh aliases again? How did I configure my Git settings? Where are my SSH keys? What VSCode extensions was I using? Which version of Node, Go, Java, and…

Refactoring 60 Go Modules with an AI Coding Agent: A Senior Developer's Experience

This post is about a real refactoring experience using AI coding agents on production code. No hype, no hand-waving—just what actually happened, what worked, what didn’t, and what I learned. The Challenge The Testcontainers for Go project needed a major refactoring: migrate all 60 modules from using testcontainers.GenericContainer() to the new testcontainers.Run() API. Each module represents…

ContainerDays 2025, my experience

No AI has been harmed in the making of this post. Well, just a bit for completing sentences. But that’s ok nowaday, right? This post serves as a record of my first experience at the ContainerDays conference, which took place in Hamburg, Germany, from September 10th to 12th. Back in April, a community member from the Testcontainers community asked me if I would be interested in presenting at…

Effortless Self-Signed TLS Certificates in Go with tlscert

“Ever struggled with wiring up self-signed TLS certs for your Go tests and dev servers? tlscert solves that with a clean API—no TLS boilerplate, just a few lines of code.” Why tlscert? When working on Go projects, especially during local development or integration testing , it’s common to need self-signed certificates. Unfortunately, generating them usually means dealing with complex crypto APIs…

License Matters: A Hands-On Guide to Merging MIT Code into an Apache 2.0 Codebase with Full OSS Respect

Open source isn’t just about code — it’s about trust, stewardship, and honoring the people and principles that built the foundations we stand on. When working on a recent SDK project, I faced a common but delicate challenge: merging an existing MIT-licensed repository into a new Apache 2.0 codebase. Rather than rush through it, I took the opportunity to do it right — preserving history, respecting…

Fiber v3 + Testcontainers: Production-like Local Dev with Air

With the upcoming v3 release, Fiber is introducing a powerful new abstraction: Services . These provide a standardized way to start and manage backing services like databases, queues, and cloud emulators, enabling you to manage backing services directly as part of your app’s lifecycle, with no extra orchestration required. Even more exciting is the new contrib module that connects Services…

Creating a Responsive Image Gallery Shortcode in Hugo

In this tutorial, I’ll walk you through creating a responsive image gallery shortcode for Hugo that includes a modal view for full-size images. This solution provides a clean, grid-based layout with thumbnail images that expand to full size when clicked. Features Responsive grid layout Thumbnail generation with Hugo’s image processing Modal view for full-size images Keyboard navigation…

GopherCon Singapore 2025

GopherCon Singapore 2025 Since I joined AtomicJar back in 2022, one of my first goals was to be accepted in a Gophercon to share the benefits of using Testcontainers for Go. I tried with the EU conference twice in 2024 (Greece and Berlin), the US (Chicago), and the Israel one, always being rejected. I asked for feedback by email but the organisation team from Europe seemed very busy with the…

5th DevTools Day Bengaluru (Collabnix Docker Community)

5th DevTools Day Bengaluru (Collabnix Docker Community) Back in October I met Ajeet Raina at Devoxx Belgium, and from there, while we were returning back to the hotel and sharing that I had submitted a CfP to Gophercon Singapore, Ajeet told me: “ if you are accepted, you must stop in Bangalore, because it’s on your way to SG, and share that knowledge to the huge community that lives in the city.…