I wanted to share a little experiment I recently did. There are two parts to this. I had never fully “vibe coded” any software before (that is instructing an LLM to do all the implementation, and not coding yourself), but I was curious to at least try it to understand what is happening. I also wanted to do something with the new image processing capabilities in Picard 3. I had this stupid idea that there should be a plugin that lets your nice digital cover images age like an old paper vinyl sleeve based on the age of the release.
As I was unlikely to implement the plugin myself anytime soon (I have doubts anyone will actually use it, including myself
), I decided to combine this with the vibe coding experiment. My expectations where low, I thought the LLM might not fully understand the plugin structure. I expected the resulting plugin not be runnable without some additional tweak, having basic functionality at best, the image manipulation being flawed and overall there being bugs.
The setup
I used Claude Code for generating this project. The prompt used with Claude Code was intentionally vague, explaining primarily the general idea and leaving the details to the LLM. Only a few guiding words where included to set some expectations on the resulting code.
The full prompt used was:
Goal is to implement a plugin for MusicBrainz Picard 3. The API is documented on picard/docs/PLUGINSV3/API.md at master · metabrainz/picard · GitHub . The plugin will apply some artificial wear to cover art images, based on the age of the music release (as given by the release date of the e.g. music album). The wear must mimic damage that would happen over time to paper vinyl sleeves. For this the plugin implements a cover art filter. Image manipulation must use the capabilities provided by Qt6 / PyQt6. Not other external dependencies must be used.
A few notes on the setup:
- The prompt was entered into Claude Code from inside the already created, but completely empty plugin repository.
- The model used was Claude Opus 5 (1M context).
- Apart from the prompt, no other prompting was used afterwards to modify the generated code. The result seen here is the direct output of this one prompt. Any request by Claude to run commands or access and modify files was granted. The only prompting after code generation was instructing Claude to commit the changes.
- While running the prompt, Claude detected that the plugin directory had a parent directory called
musicbrainz. It also found apicarddirectory within that as well aspicard-plugins-registryand two pluginspicard-plugin-haikuattrsandpicard-plugin-replaygain2. From inspecting those directories, Claude correctly concluded thatpicard/docsalready contained the full Picard plugins documentation. It also used the existing plugins as reference. One can see this clearly from accompanying files like the ruff and pre-commit config or license files, that were taken from the existing plugins. Hence the wheatheredcover plugin follows my personal best practices without this having been explicitly requested. - Claude took overall 40 minutes for that (I tried to quickly check and allow anything it asked permission for).
The result
The resuling Picard 3 plugin can be found at Philipp Wolfer / picard-plugin-weatheredcover · GitLab
Here is a screenshot of the options UI:
There are quite a few things that surprised me:
- The plugin worked fully without any additional changes.
- Without having prompted it, there is an extensive list of actually useful options. And a fully functional options page, with live preview of the changes.
- A test script to test the results for various years of aging with an arbitrary image was included and used to generate examples.
- There are several different aging effects, that can be enabled separately and are overall quite solid. There are a few details not working that well (I don’t really like how the “bumped and worn corners” look), but overall this works much better than expected.
- A full README was generated with details on all the effects.
There are surprisingly little bugs. Two things I noticed (but haven’t corrected yet):
- All options are marked to be usable in Picard’s option profiles. But the plugin’s UI does not highlight the options used in profiles correctly. The LLM tried to add the necessary setup, but failed to get it right. Actually this hints to a problem with our documentation, a human developer would have likely struggled in a similar way.
- The install instructions in the README are plain wrong. You shouldn’t copy any files. Instead use “Install Plugin…” in the plugin options and install it from the git repository URL.
Conclusions
I don’t really know what to make of this, to be honest. I’m overall rather impressed by the result, and it is fun to play with the effects and load some releases to see how the worn covers look like. But the result is also not my plugin, it is my rough idea implemented by someone else. Just that it is not someone, but a thing that itself has no opinion on the generated result nor does it have any nostalgic feelings about the covers the plugin generates.
From a practical perspective I think it shows that we have done quite a few things right with Picard’s new plugin system. The plugin system offers a better API, more information for developers during implementation (we have now a proper API, and Python type hints in place for most of the plugin facing code) and is overall well documented. But it also shows we need to document a few things better, see the bugs above. Also the cover art filters can be used for some fun stuff (Picard itself only uses it for boring things like image resizing and format conversion).
I’m not yet sure whether I will do some fixes to the plugin or just leave it there as it is as an exhibit.
