Sharing Skipboi

I'm kind of on a roll.

The Problem

At least 40 hours of my week every week is spent in various terminal windows and listening to music on Apple Music. It's the nature of the beast.

I have two external keyboards (a mechanical and an ergonomic), two laptops with slightly different keyboard form factors, and for funsies a case on my iPad that has an third layout. This isn't to brag, but I think it's important to know.

No matter how good my playlists are (they're great), sometimes there's a song or two that you want to skip. Sometimes you need to hop on a virtual meeting and you need to pause. All of the aforementioned keyboards have a key for this, but the layouts are different enough that I can't perform those tasks without stopping and looking at the keyboard to remember where "that" button is on "this" keyboard.

The Spark

On a particularly bad playlist run, I found myself skipping every other or every third song. This is more annoying than skipping every other song because it forces a bounce back. Every time I performed this action, I had to leave the "flow" or sometimes the VS Code window I was in to perform the operation.

The Solution

Skipboi

This is a CLI tool written in swift that allows you to manipulate functionality around Apple Music without ever leaving your terminal window.

Play, pause, skip forward, skip backward, enable/disable shuffle, enable/disable repeat (all and one), mute, unmute, volume up, and volume down are all accounted for.

The Process

Starting

Similar to institutionalized, I started this with the "jump start your project with Copilot" option when creating the new repo. As I've done this a couple of times, I've gotten a little better about fitting the prompt into the 500 character limit and covering the requirements I have for my "MVP."

In this case, I realized that I didn't even have swift installed on my machine. I guess I could have let it ride just to see what happened, but I installed Xcode, pulled the branch, and verified the functionality.

Building

I won't rehash the same processes I used before, but I will use this opportunity to explain an edge case I hit that shows where the wall is for agentic coding and why the "driver in the loop" is so important.

This was my first time implementing Homebrew in a project. The goal was to make this sit in line with the other tools I used in a way that institutionalized (at the time) didn't. I understood some of the core functionality, but I decided to leverage the agent to see how far it would get.

What It Did Well

It was able to successfully scaffold the Homebrew configuration and document out what I needed to do in order to complete the process. It gave me usage instructions and the whole lot. The instructions were easy to follow and, much to my surprise, worked right out of that gate as it said on the tin.

In that same documentation, it had a section called "possible future enhancements" with some suggestions as to what could be added to make the user experience better.

Where It Fell Apart

One of those suggestions (and an observation I made in the process) was that it required the user to have Xcode installed in order for Homebrew to compile the app. While this isn't a huge deal, it did throw up a potential barrier to a non "power" user that may be trying to use it. The recommendation was to use "bottles" which are pre-compiled binaries that can be installed anywhere as long as there is a binary for it.

The first pass went okay. It took some coaxing to help the Copilot agent connect what it had already done to what it thought it should do, but we were able to eventually get there. That first pass only covered two versions of macOS, but didn't include the Tahoe which is installed on both of my machines. This meant that I couldn't really test the bottles process and it would default to the previous, somewhat clunky process.

So the next logical iteration was to add bottles for all currently supported versions of macOS. Through this process there was a lot more coaxing to connect the dots. Once all of the dots were connected, the changes were merged, and the CI issues were fixed it was time to test.

In testing, I found an issue where the v in the version number was being dropped one time and not the rest. This meant that v1.2.1 was getting a broken url because the path looked like .../v1.2.1/skipboi-1.2.1.* which there was no release for. Because this was my first adventure in Homebrew, I asked the Copilot agent to investigate.

I got to see the most legendary AI crashout I've ever seen.

Note: maybe I didn't use "crashout" correctly there. I coach a high school team and I'm afraid to ask the rules...I just go on context clues.

Sometimes the agents will do this thing where you ask it to solve a problem, it thinks it has a solution, it tries to process that solution, realizes it's not a solution, and then goes into this loop. It feels like it's talking to itself. A weird computer version of "rubberducking" where it just spirals on potential solutions and talks itself out of the solution.

Eventually, after some time watching it spin out, it comes back and says "I don't know how to fix this, you're going to have to troubleshoot this." A fun admission from our future robot overlord that we're all somewhat fallible at times.

To fix this, I dropped the v from the version number all together. This worked, but I still wanted to see if I could prompt my way through it. To go at it another angle, I created an issue in GitHub and assigned it to the Copilot agent there. I gave it a ton of information and let it go. That agent's solution was to actually gut the entire process in a way that didn't make sense.

I merged it, it broke everything, and so I reverted it and we're back working. It was worth the "git-fu" to see where the edges are of the LLM's and their ability to actually troubleshoot code.

The Closing

Again, I want to acknowledge that AI is a complicated matter. I've talked about this elsewhere, but I know that at some point someone who hasn't read anything else I've written is going to come at me about how I'm ruining the planet or putting people out of jobs.

That said, the current implementation of this application handles everything I think you could want to do while listening to music. All music functionality as well as the ability to toggle audio settings. I'm working on a way to handle AirPod controls, but it's messy and I don't like it.

If you're a sicko like me and live in a macOS terminal and listen to Apple Music, give it a go.

Besos!