Tech
27 posts
Agentic Coding in 2025
What I've Been Up To: Claude Code
It's pretty fun
Tech Debt Is a Limited Metaphor
It breaks down when you look too close
The Tool Lifecycle Trap
Investing in speedups that don't become speed bumps
The Interpreter Has Been Crafted
Just two short years later
Implementing Semantic Search
Easier than it sounds
Tasks and Dates
There's much more than just due dates
Building a Locally-hosted Todo App
A practical tool using a practical tech stack
Hosting a Full Stack App for Free
With staging and production environments, secrets management, and automated deployment
Errors as Values in Rust and Go
Chips 101 and Nvidia
Tech for Teaching
I taught a tutorial at PyCon a few days ago. It went well, but what I want to discuss are some technical things I did that went well and (I think) made the presentation easier for students to follow.
Python Exceptions: Bonus Content
This post is a followup to my article The Basics of Exceptions in Python, but should make sense on its own as long as you are familiar with raise and try/except.
Let’s cover a few more advanced aspects of the Python exception system. We’ll move a bit faster and talk at a higher level than we did in the last post.
Topics we’ll hit:
The Basics of Exceptions in Python
This post was originally meant to be a small part of my discussion of the Go programming language (coming soon) as a way of drawing contrast between Python and Go, but turned out to be extensive enough to justify its own post.
Python’s model of exceptions is quite similar to that of other popular object-oriented languages like Ruby, JavaScript, and Java1. Errors flow differently than regular data; if not “handled”, they rise up through the entire function stack and crash the program. Developers are encouraged to write code to anticipate those exceptions, handle them before everything explodes, and change the logic flow of the program accordingly.
What exactly needs to be done in that “handling” step typically depends on what went wrong, and so there are many types of errors. Programmers can check the type of an error to determine what went wrong and react accordingly. Errors can be thought of as objects and their types as classes that can be subclassed like any other class. But unlike other data, they follow an error-specific path through the code, short-circuitiing functions all the way up the stack until handled.
Careers in Programming
Crafting Interpreters
Timezones
24+ Places (and Times) to Lose Your Mind
Is PyScript a Big Deal?
Apartment Hunting with Python
I recently crossed the 9-month mark as a Chicago resident. The time has come for a big decision: renew my lease, or make the move to a new apartment?
I really like my current home. Two bedrooms, a back porch, a garage, and more grounded outlets than even a tech nerd like me could want. It’s in Little Italy, which is not a popular choice for Chicago young professionals, but is comfortable and has a decent set of restaurants. I suspect that a similar unit in a more “hip” neighborhood might be out of my price range. And my real office (as opposed to my extra bedroom, which has been serving in that capacity since I moved here) is a 10-minute bike ride away. The north side, home of many of those hip neighborhoods, would bring with it a commute at least twice as long.
On the other hand, my primary motivation in moving to a big city was exploration and experience. I wanted to get to know Chicago, particularly its neighborhoods. Moving would offer me a change of location, unlocking many new walkable or bikable destinations. Additionally, none of my friends live near my current apartment; most are in various parts of the northern neighborhoods, while I live somewhat south and west of the Loop (the downtown area of Chicago). Seeing most friends requires a 15+ minute drive or 30+ minute train ride.
Apple Music Had Its Chance
State of the Tools 2020: Hardware
Scaling Data Science Across Python and R
Linux for Data Scientists, Part 1
Automation at 84.51˚
Setting Up Raspberry Pis (the Full Version)

I’ve set up three Raspberry Pis over the last two days. By set up, I mean I burned the disk image to the SD card, got the Pi connected to the network and open to SSH, installed the tools I’m going to want every time, etc. Basically, make it just another identical worker node. I own six Pis total (for now), so I’ve done this before, and I’ll do it again. In fact, two of the installs I did were on Pis I’d owned for a while; I just wanted to wipe them and start fresh.
So after the first two this weekend took me a lot longer than they should have, I realized it was about time I documented my process and made it repeatable.