Coding Agents Need Deterministic Feedback: A Case for Phoenix

Introduction Let me preemptively acknowledge the fact that anyone who reads this probably has some level of LLM fatigue from social media. This article is about maximizing the potential benefit from LLM usage in the context of software engineering, which I (as one might infer from the title), in my humble opinion, have been fairly successful at. I will share the ideas with which I have found success, and I will leave the reader to determine their virtues and vices. ...

December 7, 2025 · 9 min · Kristoffer Opsahl

Using dd to write an .iso to a USB drive

dd is one of those commands for which I have to look up proper usage every usage because I use it regularly but not often. As such, this is a public note-to-self, which may or may not be useful to the reader. Prerequisites The dd binary is, to my knowledge, included on macOS and all major Linux distributions. Writing the file dd if= of= status=progress The if option tells dd to read from the provided path instead of stdin. The of option tells dd to write to the provided path instead of stdout. The status option tells dd to show periodic transfer statistics. The status option is primarily included because the program can otherwise seem unresponsive upon writing large .iso files, as the transfer to disk can take several minutes to complete. ...

September 14, 2025 · 1 min · Kristoffer Opsahl
My Alacritty, Zellij, and Helix Development Setup

My Alacritty, Zellij, and Helix Development Setup

This article is a public note-to-self where I’ll go through the basic configuration I use to get new computers ready for programming in just a couple of minutes. It is centered around the following pieces of software: Alacritty, a terminal. Zellij, a terminal multiplexer. Helix, a text-editor with support for LSP, and tree-sitter. In my selection process, I heavily emphasized performance, as I strongly dislike when my IDE can’t keep up with my thoughts. I also favored software with sane defaults, such that almost zero configuration is required for great usability. The programs are free, cross-platform, open-source, and they all happen to be written in Rust. ...

July 7, 2025 · 4 min · Kristoffer Opsahl
Breaking AES-ECB with an Encryption Oracle Attack

Breaking AES-ECB with an Encryption Oracle Attack

This is a write-up of one of the challenges from this year’s TG:Hack. I wrote about my participation in another post: 3rd Prize at TG:Hack. Background TG:Hack is a Capture-the-Flag competition where the objective is to identify and leverage security flaws in various entities. As evidence of a successful hack, you must extract small secrets, i.e., flags, and provide them back to the organizer. The flags are strings that look like this: TG25{some_secret_value}. ...

April 29, 2025 · 11 min · Kristoffer Opsahl
3rd Prize at TG:HACK

3rd Prize at TG:HACK

I recently participated in TG:Hack, which is Norway’s largest Capture The Flag (CTF) competition. It is hosted at and is a part of Norway’s largest LAN party: The Gathering. The competition runs over four days, and the goal is to leverage your knowledge of computers, networking, programming, operating systems, compilers, authentication, cryptography, steganography, safe-cracking(!), and more to coerce secrets from combinations of data, programs, and hardware. After a nail-biting last leg with strong finishes by several teams, featuring both jury interventions and pwned competition infrastructure, I was positively excited to be awarded the 3rd prize of NOK 2000. ...

April 22, 2025 · 1 min · Kristoffer Opsahl

Java's Optional has a Problem

Java’s Optional is over a decade old, and has been subject to intense debate since long before its release. With this in mind, I will argue a particular aspect of its design was a rather unfortunate mistake, and show how it can lead to bugs. I will moreover discuss potential mitigations, and what a better design could have looked like. While tangentially related, this post is not about Optional not being a monad. For more on that, I refer you to this somewhat famous comment on the OpenJDK mailing list. Key excerpt: “(…) but the goal [with Optional] is NOT to create an option monad or solve the problems that the option monad is intended to solve.” ...

March 25, 2025 · 11 min · Kristoffer Opsahl

From Zero to Hello World with Apache Kafka® in 2025

This is a guide on how to run Apache Kafka® locally, and how to start using it. I found the resources I used myself to be needlessly and frustratingly complicated, as well as outdated. Thus my goal is to give a simple set of instructions that works almost everywhere, regardless of operating system, etc. Structure The guide has three parts. Install podman and use it to start an Apache Kafka®-cluster Configure IntelliJ IDEA to connect to the Apache Kafka®-cluster. Write two separate programs in Java that publishes and consumes a “Hello, world!"-record respectively. 💡 If the nomenclature specific to Apache Kafka® is confusing, I have written a short explanation of the core concepts. ...

March 7, 2025 · 7 min · Kristoffer Opsahl

Core Concepts in Apache Kafka®

This post is intented to give a high-level description of the basic components of Apache Kafka® (Kafka) for someone that is entirely new to it, and that is sufficient to get building. For significantly more detail and nuance, refer to the official documentation. Records Records are the fundamental units of data in Kafka. They describe the idea that something happened, i.e. events, and are immutable data structures containing some combination of data and metadata. ...

March 6, 2025 · 3 min · Kristoffer Opsahl