šŸ‘‹šŸ»  Hello!

Thanks for visiting! You'll find a bunch of musings I've been writing around these parts since the early 2000's. Lately, I've been reviewing a lot of books. But I also write about code and my experiments using generative AI. But really, you're just here to see pictures of Benson.

Blog Posts

SCHUMAKER 55

I’ve written a bit about my Dodgers fandom on this blog. Last night, I watched from afar (thank you, streaming services) as Clayton Kershaw notched his 3,000th strikeout, becoming the 20th pitcher to ever do it (and only the 3rd pitcher to rack up 3K strikeout for one team).

He’s definitely my favorite active player on the Dodgers (we even got to see him deal when we went to game 1 of the 2017 World Series). But it got me thinking: who is my absolute favorite player of all time?

There’s only one answer, and it goes back as far as I can ever remember: Orel Hershiser.

So much so, that when I was a wee little lad, I would write him actual letters and send them to Dodgers Stadium via the post office. I have no idea what I said. Probably something in an 8-year-old’s hand writing that said, ā€œDear Mr. Hershiser, you are my favorite baseball player and I’m going to be just like you when I grow up and blah blah blah.ā€

I remember writing him numerous times. One thing I do know: I never asked for anything*. Never for tickets to a game. Never for an autograph. Then, one day, we received a letter in a big envelope from Dodger Stadium. Do you know what it contained?

Are you kidding me?! Looking at that photo you can see it’s definitely been through some stuff over the years. Pre-teen and teen version of me probably just stuffed it in some folder that got lost in my room, stepped on, and whatever else. Anyway, I ultimately framed it and still have it today!

All of this brings me to the title of this post: ā€œSCHUMAKER 55ā€. For reference, Hershiser wore number 55 throughout his career.

So, as a kid, I would play baseball in our backyard, pretending to pitch and throw tennis balls at the garage, where I had drawn a small ā€œstrike zoneā€ in chalk.

(Side note: hey, I won a school wide pitching competition in 5th grade — maybe this pretend play helped!)

All the while, I would wear this homemade uniform in honor of him, where I had written ā€œDodgersā€ in blue marker on the front and ā€œSCHUMAKER 55ā€ on the back. I wish I had pictures. It was probably cheesy.

So, imagine my shock, surprise, and delight when the Dodgers acquired Skip Schumaker in 2012. And do you know what number he wore? Do you! Guess!

LOS ANGELES, CA – JULY 27: Skip Schumaker #55 of the Los Angeles Dodgers reacts to his two run homerun with A.J. Ellis #17 for a 3-2 lead over the Cincinnati Reds during the fifth inning at Dodger Stadium on July 27, 2013 in Los Angeles, California. (Photo by Harry How/Getty Images)

You know, I don’t have many regrets in life. But I definitely regret never getting an actual jersey!

—

* Regarding the never asking for anything comment:

So, I do remember asking for one thing. My mom was going to take me to a baseball game in August of 1992 (more on that in a bit). I think I wrote months ahead of time how I was going to my first baseball game with my mom and I hoped he would pitch.

So, we went and BY SOME COINCIDENCE, HE DID! HE PITCHED THE GAME!

Over time, the memories of that game faded away and I wished I could remember what game we actually went to.

Talking to my mom, we remembered three ultra specific things: An afternoon game. Orel Hershiser started. Darryl Strawberry hit a home run.

Thanks to the wonders of Baseball Reference, that is literally all you need to find something. The game my mom and I went to? Wednesday, August 21st, 1992.

When Darryl Strawberry went up to bat with the bases loaded in the fifth inning of the Dodgers’ 9-5 victory over the San Diego Padres on Wednesday, coach Bill Russell nudged someone in the Dodgers’ dugout.

ā€œIf I’m the pitcher, I’d intentionally walk him,ā€ Russell said. ā€œGive up one run instead of four.ā€

If only the San Diego Padres’ Ricky Bones had been listening. Three pitches later, Strawberry hit one over the left-center-field fence for a grand slam.

[…]

But before 32,864 on a warm afternoon, Strawberry did more than pad his statistics. He did more than help Orel Hershiser run his record to 5-2 in 5 2/3 innings of pain-free work.

What Strawberry did was restore flickering Dodger spirits. For the first time in weeks, the Dodgers actually looked as if they were having fun.

Ultimately, Darryl Strawberry hit two home runs (one of which was a grand slam)! Talk about an exciting and fun game.

Git Branch Manager: a manager for git branches

A logo that was completely generated with AI, like everything else in the project. (Source: ChatGPT)

I don’t mind the term ā€œvibe codingā€œ, when used correctly. A lot of people (at least on Reddit) seem to think it means ā€œany time you code with AI.ā€ I prefer Andrej Karpathy’s original definition: ā€

There’s a new kind of coding I call ā€œvibe codingā€, where you fully give in to the vibes, embrace exponentials, and forget that the code even exists. It’s possible because the LLMs (e.g. Cursor Composer w Sonnet) are getting too good. […] I ask for the dumbest things like ā€œdecrease the padding on the sidebar by halfā€ because I’m too lazy to find it. I ā€œAccept Allā€ always, I don’t read the diffs anymore. When I get error messages I just copy paste them in with no comment, usually that fixes it. The code grows beyond my usual comprehension, I’d have to really read through it for a while. Sometimes the LLMs can’t fix a bug so I just work around it or ask for random changes until it goes away. It’s not too bad for throwaway weekend projects.

Emphasis mine.

That last bit is key. For throwaway weekend projects, vibe coding is this magical state where you have an idea but absolutely no desire to setup boilerplate, read API documentation, or even want to deal with the plumbing. You just want the thing to exist.

A few evenings ago, I decided to put in a serious vibe coding session using one of my favorite tools, Claude Code via SSH through Blink on my iPhone (!), to create a CLI utility to help manage the endless number of branches I have on my machine, all because of our huge monorepo.

For reasons I’m not entirely sure about, I decided to use Python. A language I know approximately nothing about beyond ā€œwhite-space mattersā€, ā€œthere’s probably a library for that,ā€ and ā€œprint("Hello, world!").ā€

(Hey, I’d have to turn in my software engineering badge if I didn’t attempt to reinvent the wheel every so often)

So, picture this scenario: I’m staring at my terminal after I had just typed git branch. I’m looking at a screen with about 37 branches in various states of decay. And of course there are numerous unhelpful branches with names like, daves/no-jira/hotfix, daves/no-jira/hotfix-2, daves/no-jira/hackweek-project-cool. My terminal is just a wall of branch names, most of them mocking my organizational skills.

(By the way, what was hackweek-project-cool? I don’t know… I never committed any code to it!)

I needed a better way to manage this chaos. So naturally, instead of cleaning up my branches like a responsible developer, I decided to build a tool. In a language I don’t know. Using only Claude Code. What could possibly go wrong?

Claude Code is great. It never gets tired. It never gets angry. Even if I kept asking questions and piling more features on top.

  • ā€œLet’s make a shell script using Python to display Git branches.ā€
  • ā€œOhhh, can we make it show which branches have uncommitted changes?ā€
  • ā€œOh, oh! Add some colors, but tasteful colorsā€¦ā€
  • ā€œHey, there are a lot of branches here. What if pressing shift + d deleted branches (but we should probably have a confirmation…)?ā€
  • ā€œYou know what it really needs now? A loading spinner!ā€

After a few hours of asynchronous back and forth, we had a result! Git Branch Manager: a terminal UI that actually shows useful information at a glance. Navigate your branches with arrow keys, see visual indicators for everything important, and perform common operations without memorizing Git commands.

For me, those little indicators are game changers:

  • * Current branch
  • [modified] Has uncommitted changes
  • [unpushed] Exists locally but not on remote
  • [merged] Already merged (why is this still here?)
  • ↓ Remote branch you haven’t checked out yet

One feature that I love: Smart stash management. When you try to switch branches with uncommitted changes, gbm asks if you want to stash them. But here’s the cool part: it remembers which stashes it created and gives you a notification when you switch back. Press ā€˜S’ and boom! Your changes are restored!

This process still blows my mind. I describe what I wanted in plain English, and Claude Code would translate these chaotic ideas into actual, working Python. ā€œMake old branches look oldā€ turned into color-coding based on commit age. ā€œIt should be smart about stashingā€ became an entire stash management system.

Installation is pretty simple, too. No pip, no dependencies, just curl and go:

# Quick install
sudo curl -L https://raw.githubusercontent.com/daveschumaker/gbm/main/git-branch-manager.py -o /usr/local/bin/git-bm
sudo chmod +x /usr/local/bin/git-bm

# Additionally, add as a git alias
git config --global alias.bm '!git-bm'

Now you can just type git bm anywhere. Pretty neat!

There’s also browser integration (press b on any branch), worktree support, and a bunch of other features I’m proud of, err, creating, despite not having touched the code.

Here’s the thing about vibe coding with AI: it completely changes what’s possible for a weekend project. I built a legitimate, useful tool in a language I don’t know and using standard libraries I’d never heard of.

If you asked me 6 months ago if someone with no knowledge could build useful tools or websites using AI prompts only, I might have said no. ā€œYou still need people who understand software engineering principles, who understand what the code is doing,ā€ I’d (not so) confidently say.

But now… it’s getting crazy. Is this the future of programming? To be a glorified conductor who oversees an orchestra of AI agents? Maybe!

Bottom line: my Git branches have never looked better, and I didn’t have to spend six months learning Python to make it happen! So, if you’re buried in branches like I was, give gbm a shot: github.com/daveschumaker/gbm

Now if you’ll excuse me, I need to go stare at my beautifully organized branch list again.

P.S. Yes, I realize I could have just cleaned up my branches manually in less time than it took to build this. But where’s the fun in that?

Steer clear of those crows

A crow perched on our roof, looking at me wearily.

A frequent sound around our house lately has been an intense banging on the roof. It honestly sounds like someone has climbed up there and decided to hammer away for fun.

Curiosity finally got the better of me, and I grabbed a ladder to investigate. When I reached the top, I discovered the source of the obnoxious noises: an aggressive crow trying to crack open a walnut. We have a flat roof, so apparently it’s a perfect landing spot / walnut abuse space for them. I made a few attempts to shoo it away, waving my hands wildly and making all sorts of strange noises. The crow looked unimpressed and returned to its task.

I figured a more creative approach was needed, so I turned to the garden hose. Thankfully, no neighbors were around to question why I was suddenly watering the roof. The water seemed to have worked, as the crow took flight, leaving behind its walnut. Victory!

Or maybe not. I recently read about how long crows hold a grudge.

From a NY Times article, ā€œIf You Think You Can Hold a Grudge, Consider the Crowā€œ, published in October 2024:

Renowned for their intelligence, crows can mimic human speech, use tools and gather for what seem to be funeral rites when a member of their murder, as groups of crows are known, dies or is killed. They can identify and remember faces, even among large crowds.

They also tenaciously hold grudges. When a murder of crows singles out a person as dangerous, its wrath can be alarming, and can be passed along beyond an individual crow’s life span of up to a dozen or so years, creating multigenerational grudges.

Oh, cool! This must explain all the aggressive cawing I hear from the trees as I walk to kids to school each morning.

Update (2024-05-24): I have video of these punks! Watch out.

Ā 

Gemini: replace “this” with “this”

For the most part, I’ve had pretty positive experiences using AI tools to help enhance my coding activities (though there was the one time…).

A recent experience with Google’s new Gemini model left me frustrated. After prompting it to help me find and update some relevant code, it confidently informed me that it had identified the exact snippet that needed replacing. Great news, I thought, until I realized it was instructing me to replace the code with… exactly the same code.

I pointed out the issue. Gemini politely apologized for the confusion and assured me it would correct its mistake. To my disbelief, it promptly suggested the very same replacement again! And again!

Oh, I have receipts. Join me on this little adventure!

Maybe we don’t have to worry about AI taking our jobs just yet!

Book Review: Co-Intelligence by Ethan Mollick

If you’re casually interested in AI, then I think Ethan Mollick’s ā€œCo-Intelligence: Living and Working with AIā€ is a book that you might find interesting. It’s not a technical book, and I believe it would be easy for someone not deeply involved in this world to read. It provides a very general introduction into how to utilize Large Language Models (LLMs) and serves as an introduction of what it means to live and work alongside these new tools.

ā€œCo-Intelligenceā€ unpacks the arrival and impact of LLMs, including tools like ChatGPT, Claude and Google’s Gemini models. Mollick, a professor of management at Wharton, approaches AI not as a computer scientist, but rather focuses on the practical applications and societal implications. In his own classroom, he has made AI mandatory, designing assignments that require students to engage with AI for tasks ranging from critiquing AI-generated essays to empowering them to tackle ambitious projects that might otherwise seem impossible (like encouraging non-coders to develop working app prototypes or create websites with original AI-generated content). He guides the reader through understanding AI as a new form of ā€œco-intelligence,ā€ which can be harnessed to help improve our own productivity and knowledge.

One concept I found interesting is what Mollick calls the ā€œjagged frontierā€ of AI. This refers to the sometimes unpredictable nature of AI’s abilities. It might perform complex tasks with ease, like drafting a sophisticated marketing plan, and then struggle with something that seems simple to us. He gives an example of an AI easily writing code for a webpage but then providing a clearly wrong answer to a simple tic-tac-toe problem. This highlights why we can’t blindly trust AI and understanding its specific strengths and weaknesses through experimentation is key.

Mollick also delves into AI’s creative ability. He discusses how AI can excel in creative tasks, sometimes outperforming humans on subjective tests. This leads to interesting discussions about the future of creative work and education. The ā€œHomework Apocalypseā€ he describes, where AI can effortlessly complete traditional school assignments, is a challenge educators and parents are currently facing. Mollick suggests this doesn’t mean the end of learning, but rather a shift in how and what we learn, emphasizing the need for human expertise to guide and evaluate AI.

The sheer volume of AI generated content being posted on the internet has is also becoming a problem and something we need to figure out how to navigate.

Even if AI doesn’t advance further, some of its implications are already inevitable. The first set of certain changes from AI is going to be about how we understand, and misunderstand, the world. It is already impossible to tell AI-generated images from real ones, and that is simply using the tools available to anyone today.

[…]

Our already fragile consensus about what facts are real is likely to fall apart, quickly.

Well, that’s just downright cheery! If anything, it highlights the importance of developing our ability to think critically and analytically in an AI-influenced information age.

Mollick lays out ways that we can better work with AI and leverage its strengths to help us, calling it the ā€œfour rules of co-intelligence.ā€ These include always giving AI tools a seat at the table to participate in tasks, maintaining a human-in-the-loop throughout the the process to validate and verify AI work, treating AI as a specific kind of collaborator by telling it what persona to adopt, and remembering that current AI is likely the ā€œworstā€ version we’ll ever use due to rapid improvements.

The bit on assigning personas was interesting. In my own experience, I’ve seen the benefits of giving AI a persona through system prompts. There’s also this fun example.

To make the most of this relationship, you must establish a clear and specific AI persona, defining who the AI is and what problems it should tackle. Remember that LLMs work by predicting the next word, or part of a word, that would come after your prompt.

[…]

Telling it to act as a teacher of MBA students will result in a different output than if you ask it to act as a circus clown. This isn’t magical—you can’t say Act as Bill Gates and get better business advice—but it can help make the tone and direction appropriate for your purpose.

The idea of these rules is that it can (theoretically) make working with AI feel less like a technical challenge and more like a collaborative effort.

Mollick also examines some philosophical questions that the use of AI brings, such as a ā€œcrisis of meaningā€ in creative work of all kinds. One specific example:

Take, for example, the letter of recommendation. Professors are asked to write letters for students all the time, and a good letter takes a long time to write. You have to understand the student and the reason for the letter, decide how to phrase the letter to align with the job requirements and the student’s strengths, and more. The fact that it is time-consuming is somewhat the point. That a professor takes the time to write a good letter is a sign that they support the student’s application. We are setting our time on fire to signal to others that this letter is worth reading.

Or we can push The Button.

The Button, of course, is AI.

Then The Button starts to tempt everyone. Work that was boring to do but meaningful when completed by humans (like performance reviews) becomes easy to outsource—and the apparent quality actually increases. We start to create documents mostly with AI that get sent to AI-powered inboxes, where the recipients respond primarily with AI. Even worse, we still create the reports by hand but realize that no human is actually reading them.

Side note: this exact scenario is something I’ve recently joked about with a manager at work. We have our yearly performance reviews and have to write a self assessment. Everyone now feeds a list of bullet points into their favorite LLM. The manager takes this overly verbose text and feeds it into an LLM to simplify the text.

On top of all this, Mollick also points out the need to always be skeptical of AI generated output, citing a famous case in 2023 where an attorney used ChatGPT to prepare a legal brief and was caught when defense lawyers could not find any records of 6 cases that were cited in the filing.

There is an interesting website I recently heard about, that is tracking fake citations used in court filings. 121 instances have currently been identified!

All in all, it’s a clear reminder of AI’s capacity for hallucination and the critical need for human oversight. The book frames AI not as a replacement, but as a powerful, though sometimes flawed, partner that can augment our abilities.

Overall, ā€œCo-Intelligenceā€ offers a decent overview for those curious about using current AI tools and thinking about their future integration into our lives. While it may present a more surface-level exploration for those already deeply familiar with LLMs, it provides some useful insights into the shifts AI is bringing to work and creativity. For someone looking for a general, non-technical introduction to the topic, it’s a solid read.

Lenticular clouds on Mount Rainier

I’ve been in Seattle for the past week for one of our semi-quarterly work retreats. The weather has been absolutely perfect. Insane visibility that showed off the region’s geologic wonders.

As our plane received takeoff clearance and turned onto the runway, I was treated to this incredible view of Mount Rainier behind Sea-Tac’s control tower, draped by a lenticular cloud. Chef’s kiss.

Hardware experiment: Connecting ESP32s via Bluetooth

Awhile back, I was fortunate enough to be invited to a semi-weekly ā€œbuild night.ā€ It’s a casual gathering where a bunch of random folks hack on all sorts of things: software, hardware, AI tooling, art. It is awesome! There are some seriously inspiring people there.

One longtime attendee showed off a project involving 3D-printed tiki sculptures lit from within by LEDs. Each sculpture had an ESP32 inside, controlling the LEDs and communicating via Bluetooth LE. A scroll wheel controller mounted on top could change the brightness and pattern, and the effects would sync across all the sculptures. It was ridiculously cool!

I happened to randomly have an ESP32 dev kit sitting inside a box of random electronics in my garage. I ordered a few more (these things are ridiculously cheap) and decided to experiment. Despite not having touched ESP32s before, it felt like a fun challenge.

Ultimately, I ended up cutting off a few LEDs from a WS2812 LED strip, soldering some wires up to the necessary connectors and then plugged them into a breadboard.

After snipping a few LEDs off a WS2812 strip and wiring them up to a breadboard, I used VS Code and the PlatformIO extension to vibe-code a basic Bluetooth host and client (shout-out to Claude for the help!).

The result?

  1. The host ESP32 registers itself as a Bluetooth service using a UUID, loops through a series of colors, and broadcasts the current color value.
  2. The client ESP32 scans for that UUID. If it finds it, it listens for the color data and updates its own LED. If not, it pulses red with a slow ā€œheartbeatā€ to signal it’s waiting.

You can see it in action, below. Pretty wild! It starts off with the host disconnected. The only communication between the two is via Bluetooth.

OpenAI’s new image generation models are… insane

You can probably repeat this blog post headline for any given service every week at this point…

Anyway! I’ve been on board the generative AI train for a few years now and it’s amazing to see how far it’s come. In October 2023, I got access to DALL-E 3 and was pretty impressed with its ability to render text.

Yesterday, OpenAI announced 4o Image Generation and boy does it kick things up a notch or two!

It’s ability to generate images and render text according to your exact prompt is incredible. We can now have full on automated AI memebots.

A four panel cartoon strip

  • first panel: a software engineer sitting in front of a computer screen on a Zoom meeting
  • second panel: the software engineer tells the participants (with a speech bubble): ā€œI’m telling you, AI is coming for our jobs!ā€
  • third panel: we just see a slight closeup of the software engineer (the computer monitor isn’t visible)
  • fourth panel: same as the first panel except all the participants are now robots

Same angle and setup in every panel, reduced art style, broad outlines

Or, how about:

Cartoon drawing of a bored computer programmer sitting in front of a computer just pressed ā€œenterā€ over and over. He is sarcastically excited and says, ā€œVibe coding. Wooooo.ā€

You can also feed it source images and it will run with it as well. So, obviously we need to use the Canine Calibration System.

I even gave it an image of me and told it to make a movie poster:

Create a dramatic cyberpunk 1980s horror movie poster image featuring a Computer Monster (We see an LCD screen with evil eyes and fangs and it has robotic legs) in a dark alley. In front of the monster, we see the man in this source image passed out on the ground, broken glasses lay next to him. At the top of the poster is the title of the movie in digital writing: ā€œBUFFER OVERFLOWā€ at the bottom in the billing area, we see text that says, ā€œSome bugs were never meant to be fixed.ā€

Or rewrite history…

Or really, really rewrite history…

It’s just wild. It’s coming for us as engineers, as musicians, as artists, as writers. This 2024 post on Twitter sums it up:

You know what the biggest problem with pushing all-things-AI is? Wrong direction. I want AI to do my laundry and dishes so that I can do art and writing, not for AI to do my art and writing so that I can do my laundry and dishes.

– Joanna Maciejewska on Twitter

Hmm, this sounds like a 4-panel comic to me!

I should have written a blog post…

Last summer at work, I embarked on a solo project to convert over 800 of our unit tests for various React components from using Enzyme1 to React Testing Library2 as part of a larger migration to React v18, TypeScript, and moving our code into a larger monorepo at Zillow.

This process was made much easier thanks to using the power of LLMs!

Just this week, I have seen two blog posts from various dev teams detailing how they did the same thing!

ā€œHow we navigated the shift from Enzyme to React Testing Library at The New York Times.ā€œ

As part of our efforts to maintain and improve the functionality and performance of The New York Times core website, we recently upgraded our React library from React 16 into React 18. One of the biggest challenges we faced in the process was transforming our codebase from the Enzyme test utility into the React Testing Library.

And today, I saw this from the AirBnb Tech Blog: ā€œAccelerating Large-Scale Test Migration with LLMsā€œ

Airbnb recently completed our first large-scale, LLM-driven code migration, updating nearly 3.5K React component test files from Enzyme to use React Testing Library (RTL) instead. We’d originally estimated this would take 1.5 years of engineering time to do by hand, but — using a combination of frontier models and robust automation — we finished the entire migration in just 6 weeks.

1 Enzyme is a JavaScript testing utility, originally developed by AirBnb, for React that allows developers to ā€œtraverse, manipulate, and simulate interactions with component treesā€, but it relies on various implementation details and has become less relevant with modern React practices.

2 React Testing Library is a lightweight testing framework for React that focuses on testing components as users interact with them, emphasizing accessibility and avoiding reliance on implementation details.

Lazy AI

This is a first for me. Cursor attempted to ā€œfixā€ an issue I was having with TypeScript by adding a // @ts-nocheck statement to the top of the file, essentially preventing TypeScript from running validation checks against the code.