Reflections on vibecoding ticket.el
A recap on writing an Emacs module without knowing Elisp nor looking at the code
It has now been a month since I started playing with Claude Code “for real” and by now I’ve mostly switched to Codex CLI: it is much snappier—who would imagine that a “Rewrite in Rust” would make things tangibly faster—and the answers feel more to-the-point than Claude’s to me.
As part of this experiment, I decided to go all-in with the crazy idea of vibecoding a project without even looking at the code. The project I embarked on is an Emacs module to wrap a CLI ticket tracking tool designed to be used in conjunction with coding agents. Quite fitting for the journey, I’d say.
In this article, I’d like to present a bunch of reflections on this relatively-simple vibecoding journey. But first, let’s look at what the Emacs module does.
Background
CLI-based ticket tracking seems to be a necessity to support driving multiple agents at once, for long periods of time, and to execute complex tasks. A bunch of tools have shown up to track tickets via Markdown files in a way that the agents can interact with.
The prime example is Beads by Steve Yegge. I would have used it if I hadn’t read otherwise, but then the article “A ‘Pure Go’ Linux environment, ported by Claude, inspired by Fabrice Bellard” showed up and it contained this gem, paraphrased by yours truly:
Beads is a 300k SLOC vibecoded monster backed by a 128MB Git repository, sporting a background daemon, and it is sluggish enough to increase development latency… all to manage a bunch of Markdown files.
Like, WTH. The article went on to suggest Ticket (tk) instead: a pure shell implementation of a task tracking tool backed by Markdown files stored in a .tickets/ directory in your repo. This sort of simple tool is my jam and I knew I could start using it right away to replace the ad-hoc TODO text files I typically write. Once I installed the tool and created a nixpkgs package for it—which still requires approval, wink wink—I got to creating a few tickets.
Welcome to ticket.el
As I started using Ticket more and more to keep a local backlog for my EndBASIC compiler and VM rewrite, I started longing for some sort of integration in Doom Emacs. I could edit the Markdown files produced by tk create just fine, of course, but I wanted the ability to find them with ease and to create new tickets right from the editor.
Normally, I would have discarded this idea because I don’t know Elisp. However, it quickly hit me: “I can surely ask Claude to write this Emacs module for me”. As it turns out, I could, and within a few minutes I had a barebones module that gave me rudimentary ticket creation and navigation features within Emacs. I didn’t even look at the code, so I continued down the path of refining the module via prompts to fix every bug I found and implement every new idea I had.
By now, ticket.el works reasonably well and fulfills a real need I had, so I’m pretty happy with the result. If you care to look, the nicest thing you’ll find is a tree-based interactive browser that shows dependencies and offers shortcuts to quickly manipulate tickets. tk doesn’t offer these features, so these are all implemented in Elisp by parsing the tickets’ front matter and implementing graph building and navigation algorithms. After all, Elisp is a much more powerful language than the shell, so this was easier than modifying tk itself.
Should you want to try this out, visit jmmv/ticket.el on GitHub for instructions on how to install this plugin and to learn how to use it. I can’t promise it will function on anything but Doom Emacs even if the vibewritten README claims that it does, but if it doesn’t, feel free to send a PR.
Reflections
Alright, so it’s time for those reflections I promised.
Does the project work?
Well, yes! It took more-or-less prodding to convince the AI that certain features it implemented didn’t work, but with little effort in additional prompts, I was able to fix them in minutes.
A big part of why the AI failed to come up with fully working solutions upfront was that I did not set up an end-to-end feedback cycle for the agent. If you take the time to do this and tell the AI what exactly it must satisfy before claiming that a task is “done”, it can generally one-shot changes. But I didn’t do that here.
At some point I asked the agent to write unit tests, and it did that, but those seem to be insufficient to catch “real world” Emacs behavior because even if the tests pass, I still find that features are broken when trying to use them. And for the most part, the failures I’ve observed have always been about wiring shortcuts, not about bugs in program logic. I think I’ve only come across one case in which parentheses were unbalanced.
Would I have built this without AI?
Certainly not. While learning Lisp and Elisp has been in my backlog for years and I’d love to learn more about these languages, I just don’t have the time nor sufficient interest to do so. Furthermore, without those foundations already in place, I would just not have been able to create this at all.
AI agents allowed me to prototype this idea trivially, for literal pennies, and now I have something that I can use day to day. It’s quite rewarding in that sense: I’ve scratched my own itch with little effort and without making a big deal out of it.
Do I feel proud about the project?
Nope. Even though I just said that getting the project to work was rewarding, I can’t feel proud about it. I don’t have any connection to what I have made and published, so if it works, great, and if it doesn’t… well, too bad.
This is… not a good feeling. I actually enjoy the process of coding probably more than getting to a finished product. I like paying attention to the details because coding feels like art to me, and there is beauty in navigating the thinking process to find a clean and elegant solution. Unfortunately, AI agents pretty much strip this journey out completely. At the end of the day, I have something that I can use, though I don’t feel it is mine.
Did this free up my time?
Not really, and supports why people keep bringing up the Jevons paradox. Yes, I did prompt the agent to write this code for me but I did not just wait idly while it was working: I spent the time doing something else, so in a sense my productivity increased because I delivered an extra new thing that I would have not done otherwise.
One interesting insight is that I did not require extended blocks of free focus time—which are hard to come by with kids around—to make progress. I could easily prompt the AI in a few minutes of spare time, test out the results, and iterate. In the past, if I ever wanted to get this done, I’d have needed to make the expensive choice of using my little free time on this at the expense of other ideas… but here, the agent did everything for me in the background.
Did I learn anything in doing this?
Other than how to better prompt the AI and the sort of failures to routinely expect? No.
I’m as clueless as ever about Elisp. If you were to ask me to write a new Emacs module today, I would have to rely on AI to do so again: I wouldn’t be able to tell you how long it might take me to get it done nor whether I would succeed at it. And if the agent got stuck and was unable to implement the idea, I would be lost.
This is a very different feeling from other tasks I’ve “mastered”. If you ask me to write a CLI tool or to debug a certain kind of bug, I know I’ll succeed and have a pretty good intuition on how long the task is going to take me. But by working with AI on a new domain… I just don’t, and I don’t see how I could build that intuition. This is uncomfortable and dangerous. You can try asking the agent to give you an estimate, and it will, but funnily enough the estimate will be in “human time” so it won’t have any meaning. And when you try working on the problem, the agent’s stochastic behavior could lead you to a super-quick win or to a dead end that never converges on a solution.
Is the code slop?
Of course it is. Regardless, I just don’t care in this specific case. This is a project I started to play with AI and to solve a specific problem I had. The solution works and it works sufficiently well that I just don’t care how it’s done: after all, I’m not going to turn this Emacs module into “my next big thing”.
The fact that I put the code as open source on GitHub is because it helps me install this plugin across all machines in which I run Doom Emacs, not because I expect to build a community around it or anything like that. If you care about using the code after reading this text and you are happy with it, that’s great, but that’s just a plus.
What about bloat?
I opened the article ranting about Beads’ 300K SLOC codebase, and “bloat” is maybe the biggest concern I have with pure vibecoding. From my limited experience, coding agents tend to take the path of least resistance to adding new features, and most of the time this results in duplicating code left and right.
Coding agents rarely think about introducing new abstractions to avoid duplication, or even to move common code into auxiliary functions. They’ll do great if you tell them to make these changes—and profoundly confirm that the refactor is a great idea—but you must look at their changes and think through them to know what to ask. You may not be typing code, but you are still coding in a higher-level sense.
But left unattended, you’ll end up with vast amounts of duplication: aka bloat. I fear we are about to see an explosion of slow software like we have never imagined before. And there is also the cynical take: the more bloat there is in the code, the more context and tokens agents need to understand it, so the more you have to pay their providers to keep up with the project.
What’s the meaning for open software?
And speaking of open source… we must ponder what this sort of coding process means in this context. I’m worried that vibecoding can lead to a new type of abuse of open source that is hard to imagine: yes, yes, training the AI models has already been done by abusing open source, but that’s nothing compared to what might come in terms of taking over existing projects or drowning them with poor contributions.
I’m starting to question my preference for BSD-style licenses all along… and this is such an interesting and important topic that I have more to say, but I’m going to save those thoughts for the next article.
Conclusion
Vibecoding ticket.el has been an interesting experiment. I got exactly what I wanted with almost no effort but it all feels hollow. I’ve traded the joy of building for the speed of prompting, and while the result is useful, it’s still just “slop” to me. I’m glad it works, but I’m worried about what this means for the future of software.
Visit ticket and ticket.el to play with these tools if you are curious or need some sort of lightweight ticket management system for your AI interactions.

