Taming jagged intelligence with beads and jj
There’s no need for a prelude on how agential harnesses such as Claude Code, Codex, and Opencode are changing the landscape and political economy of software engineering. The entry barrier on writing code that compiles has never been lower. LLM-enabled agential harnesses won’t replace software engineers wholesale. But their existence and reasonable accessibility (while frontier labs maintain monthly subscription pricing) dramatically refactor parts of the economic calculus of building, customizing, and maintaining software. Paraphrasing Steve Klabnik as he put it in a presentation at a conference I organized earlier this year, the hysteria around the imminent demise of software engineering and (sometimes, even) computer science, is an ironic phenomenon with a touch of poetic justice. Software engineers have been threatening, and every so often actually succeeding in automating humans in other industries out of their jobs for decades. In 2026, our LLM overlords have deigned to descend from on high to give the most talented doctors of 10-times (computerized) capitalism a taste of their own medicine.
I’m lucky to be a graduate student in a humanities program in the midst of this 2026 overture to the great age of gentle singularity. Courtesy of the generalized inexistence of career trajectories in the not-explicitly-scientific academy, I was graciously disabused many years ago of the idea that any kind of full-time job (let alone one that pays reasonably) would be waiting for me once I graduate. The economy isn’t structured to prioritize the kinds of work we should care about—but I digress. We are here to walk through what context engineering can look like, and how I use the terminal as my daily driver for research and development with LLMs.
For context, I am currently writing and maintaining a CLI tool written in Rust, a distributed system in O(x)Caml, an interpretability research harness that is mostly Python, and several full stack platforms (Node, React, Bonsai, etc.). I run NixOS on both my desktop and laptop, and have primarily viewed, edited, and written code in a customized version of Neovim since approximately 2019. Despite this relatively unique personal computing configuration—and intractable codependency on vi shortcuts and text-based user interfaces—I believe that the workflows detailed below are nonetheless fairly general: one could set up similar environments on Mac or Windows, with VSCode or other code editors using analogous plugins.
Planning with beads
Beads is “a coding agent memory system” that Steve Yegge built and released in October 2025. It has since become the foundation for two relatedly wild software projects, gastown and gascity, both of which urgently require critical attention from close readers, if only for the conceptual aesthetics of their documentation. I don’t believe in the full-blown ‘no code’ approach these two latter frameworks incline towards, in part because I don’t trust that AI agents will (always) write better code than I can in a shorter amount of time. The main reason for my scepticism, however, is that refusing to look directly at the code as a matter of (quasi-religious) principle seems to me as though it is a practice based on a misconception of the value of code in the enterprise of software engineering and development, whether it is small-scale or industrial.
When I have an idea for a software system, I refine my conception of it through observing the ways in which existing programming languages allow me to realize it. Code is one of the most essential mediums of this conversation between me, the machine, and the material social history of software in public or otherwise accessible packages and libraries. Code is the way in which I ‘see’ the functionality and performance tradeoffs that have been made in every piece of software, including the software that I am actively developing or maintaining. Delegating the art of looking at code to an LLM is like building a house purely in 3D simulation, refusing ever to step foot in the physical space. It might be possible to build a house this way; but why would you not visit the construction site if the option were available to you?
What Yegge has got right, I think, is that LLMs can do much more when we package the work we give them more thoughtfully. LLMs exhibit a jagged intelligence (putting to one side the obvious pitfalls of surrealizing a machine’s capabilities as ‘intelligence’). If it is right to think about the ability to set an agent to work through an agential harness as analogous to having infinite interns, then it’s clear that we shouldn’t just let them loose on every half-baked thought that crosses the mind as we build out software. The beads CLI is one of the best tools that I know for cueing up prompts that are ultimately dished out to an agent to complete.
I currently use a fork of Yegge’s original codebase called beads_rust (br) and a TUI to visualize beads in a repo called abacus.18 Here’s how abacus looks when open in a repo with beads:
I use each bead to represent one ‘unit’ of work that an LLM agent can complete. These are created through a planning process in which I work collaboratively with an agent in order to file features and bug fixes as beads or bead epics (associated sets of beads). The planning process is aided by a global CLAUDE.md which details codebase-agnostic workflows combining beads and jj. The directive I currently give to ensure the creation of beads I can easily reference is:
**Bead names:** Keep them as short and simple as possible. Prefer concise 3-4 character identifiers over descriptive hyphenated names. For example, `rwq` is much better than `airborne-splash-rwq`. The bead ID carries the identity; the name is just a local shorthand.
Beads are a useful way of cueing up work and saving state in their own right, rather than relying on an agential harness’s in-built memory. Using beads means that if you run out of tokens mid-feature, another agent can always pick up the work without redoing too much work, provided you’ve kept the scope of your beads in check. They also shoulder some of the state-keeping burden that agential harnesses do mostly (as far as I can tell) through writing Markdown files to disk. It’s not likely that we’ll get away from Markdown in agential harnesses any time soon, as I suspect that it’s effectively packaged in as part of the reinforcement learning stage of model training. But I’ve found that working first to architect beads epics representing a project’s roadmap seems to free up space for the agential harness to run through tasks more effectively, as it’s common knowledge by now that these models perform more reliably when the scope of the prompt is smaller.
Beads really come into their own, however, when coupled with a version control system like jujutsu or git.
Version control with jj
Because LLMs cannot be depended upon to write high quality code, version control (VCS) is an essential part of context engineering (as opposed to its irresponsible younger sibling, vibe coding). Jujutsu is a lighter touch, more powerful, and back-compatible VCS in comparison to git, which is why I use it almost exclusively as my version control system.19 The processes explained below, however, are likely mostly reproducible using git as a substitute for jj if you prefer.
Here is the elementary step I define in my CLAUDE.md to harness beads and jj together:
**Per-task sequence:**
1. `br update <id> --status in_progress`
2. `jj log` — if empty unnamed commit below working commit, name it: `jj describe -m "..."`
3. `jj new` — fresh working commit
4. Do the work, run tests
5. `br close <id> --reason "Done"` — close BEFORE squash; this writes `.beads/issues.jsonl` into `@`, which gets included in the next squash
6. `jj squash --use-destination-message` then `jj describe -r @- -m "Present tense description"` — using `--use-destination-message` avoids the interactive editor that pops up when both commits already have descriptions
7. `jj log` — verify history shows correct author on each commit; `@` must be empty and unnamed
As an agential harness is working on a beads issue, it is marked in_progress, so that I can easily locate it in my abacus view. Once it thinks it has completed the work, it squashes it into a distinct revset so that it is packaged and ready to review. I use a combination of neovim and tuicr to review the changes, which gives me a rough equivalent of the GitHub PR feature set, i.e. adding comments to independent lines, blocks of code, or on the changes in general, and seeing everything with syntax highlighting—but all locally on my machine. I’ve also configured my editor with a slightly enhanced form of jj.nvim so that I can easily switch between jj commands, real neovim, and tuicr:
This set of customizations to Neovim makes it my one-stop shop for code review. I ferry reviews from tuicr sessions to my agential harness through the beautiful simplicity of copy-paste: I have a shortcut to :clip the full set of comments (a tuicr feature) to clipboard, and then I navigate into my other tmux pane where Claude Code or similar is running. A screencast of the side-by-side setup of tmux, abacus, neovim with jj.nvim and tuicr, and Claude Code is at the top of this post. I refer the detail-oriented reader to my NixOS config, which contains the mechanisms for neovim customization, versions of software, etc. (If you are part of the lilliputian part of the population who doesn’t use NixOS, point an agent at my post and the repo and ask: “how do I get the same Neovim/tuicr/jj.nvim setup in my terminal given I am not on NixOS?”. Your mileage may vary.)
I generally instruct my agents to package revisions in response to review as new jj revsets. The exception to this is when the work they’ve done is wrongheaded in some fundamental way, in which case I just squash their fresh approach into the revset with their first attempt. In projects where I am making related changes across multiple repos, I generally start an agent at the root and then selectively file and work on beads issues in individual repos.
Reflections on context engineering
The power of automatic interns comes with a kind of responsibility, though one more gentle than the ethical responsibility we should have if the interns were real people. While I don’t have deep blue, I do think that the art of software engineering is changing dramatically. I don’t think that the category of software engineers will be automated out of existence, as this thought suffers from a category error regarding why software engineers exist. Engineering is about working with meaningful concepts at the boundary of scientific understanding and machines. Computer engineering is about working with concepts that map abstract (scientific) understandings of how computers and code work to what concrete computers and code actually do. As long as we want computers to do things for us, some form of computer engineering will exist.
My undergrad advisor Arvind Narayanan recently gave an excellent keynote at ICML puncturing some of the inflated notions about the death of computer science. He grounds a set of his claims in an historical analogy between electrification and LLM-ification. In the same way electricity illuminated (pun intended) an entirely new scope of what was possible in physical space, LLMs and their effective deployment in agential harnesses change the way we (should) think about software production and maintenance.
Maybe now more than ever, we need careful, calculated, and critical thinking about how software works and how it is deployed and maintained. We need to be able to adjudicate when software can help us do something more effectively, and this shouldn’t just mean ‘faster’ or ‘at lower cost’. It is ridiculous to think that LLMs will be ‘better’ at tasks ‘in virtually all domains of interest’ (Nick Bostrom’s definition of superintelligence), as this would require us restricting the domain ‘of interest’ to exclude activities like ‘having sex’, ‘enjoying a meal’, or ‘watching sport’. But LLMs do change the state of the art of software development in a meaningful way, and one ignores shifting goalposts in artistic and scientific arenas such as computing only at one’s own risk. As local models become viable, and as frontier labs stick their heads in the sands of the arid inevitability of climate collapse for the sake of competitive advantage and profit, we ought to take political and social action accordingly. Getting a practical sense of how these jagged creatures do and don’t work is par for the course.