|
The above is the instrumentarium of Richard Strauss's Elektra, from the 1916 edition published by Adolph Fürstner. I took a photo from my score, which I got in 1979, a lifetime ago. It's in glorious 'Germtalian', typical of the time: an eclectic mixture of Italian, German, and a few bits of Latin thrown in for good measure. Nothing unusual, and contrabassi is still acceptable today, just meno corretto according to modern Italian dictionaries: the preferred spelling is contrabbassi. And nowadays, the Italians prefer controfagotto to contrafagotto. But 'secundi', on the other hand, is pure Latin and plain wrong. Whether this comes from Strauss himself or from his German publishers is difficult to determine. This demonstrates that correct and incorrect are the wrong axes for score conventions, which have deep cultural roots encompassing multiple truths simultaneously. All depending on the understanding of everybody involved, from composer to publisher to engraver. And then there's of course the wholly absurd. Every musician is familiar with the term con sordini, with mutes. But when you see 'senza con sordini' in a score, you know you're dealing with an amateur, or at least with someone who's misunderstood something very basic. But the masters themselves are not exempt: I think it was Stockhausen who wrote So schnell wie möglich (as fast as possible) in a piano piece (possibly Klavierstück X) only to follow it by Noch schneller (even faster) a few bars later. Correctness in music is a many-faceted thing. Logic can be obscure, conventions are multi-dimensional and clearly overlap, and instructions can be psychological rather than factual, as in the Stockhausen example. All this must be embraced. But I'm digressing, for the purpose of this post is to illustrate how musicians are numbered: first flute, second flute, and so on. That's one dimension. But then musicians can play more than one instrument: they have a primary instrument and then they double on one or more auxiliary instruments. That's the second dimension. And the numbers in one dimension don't map directly onto the other. Look at the very first two lines. There's a dedicated piccolo player (ottavino) and then there are three normal flutes. Strauss numbers them Flute I, II, III. But then the first flautist also doubles on piccolo. The dedicated piccolo player is Ottavino I, and the first flautist doubles on Ottavino II. Two dimensions. You see the same thing in several places: Oboe III doubles on Cor Anglais, which takes no number since there's only one. On the other hand, the four Wagner Tubas in B♭ and F double on French Horns V, VI, VII, and VIII. All these things must be correctly numbered in the score and parts, whether you choose to use Arabic or Roman numerals. Strauss uses Roman numerals as was the custom at the time, but conventions varied and do so still. This can be time-consuming and complicated to set up in traditional scorewriters and involve modes requiring you to do some parts of your setup in one tool and other parts in other tools or dialogs. Ooloi does it for you automatically while you drag and drop. The following video shows how, using the Piece Window. For the technical specification, see ADR-0054: Automatic Semantic Naming and Numbering of Musicians and Instruments. It is written to be readable by musicians and engravers, not only by programmers.
It was designed and implemented in a single day. That's possible because the architecture underneath it was already there: immutable data, a transactional model, and a gesture layer that composes structural edits atomically.
2 Comments
The anniversary post ended with a promise that the next stretch would be brighter. So here, by way of keeping it, is Verklärte Nacht.
What you're looking at is a string sextet set up in the Piece Window: two violins, two violas, two cellos, their names arriving in German from the Instrument Library, which carries its contents in many languages and supplies whatever the piece prefers. On the right, a score of six musicians and the individual parts. And above it all, the Edit menu is open, which is the actual subject of this post. Note that the undo and redo entries are named. 'Undo Change Reorder Instruments'. 'Redo Change Language filter'. The menu tells you what will happen before you press anything, and what it says is what occurs. The Piece Window work continues, and as usual the work clarifies the road ahead. Building its full functionality meant implementing undo and redo for everything it does, and doing that forced a question into sharp focus: what, exactly, belongs in an undo chain? The answer Ooloi gives is strict. An undo entry is a record that the piece changed, together with the means of restoring what it was. Nothing else qualifies. In particular, selections don't. Selecting a musician, a stave, a measure changes nothing about the piece; it changes something about you. A selection is a fact about a user, and it lives and dies with that user's session. In a single-user program this distinction can be fudged, and the temptation to fudge it is real: selections feel like actions, actions feel undoable, and a naive implementation will happily record them. Collaboration removes the temptation by removing the ambiguity. In Ooloi, the undo history of a piece is shared, because the piece is shared. When you undo, you're operating on the same history I see, and the backend applies the reversal for both of us. Now imagine selections in that chain. Your Cmd+Z would unwind my mouse clicks. The history would silt up with everyone's browsing, and undoing one wrong note would mean stepping backwards through an afternoon of other people's attention. Nobody would design that on purpose. The multi-user case doesn't introduce a new rule; it makes the existing rule impossible to ignore. And there is a recognisable failure mode on the other side of it. Record the non-events, and the chain grows long and cluttered; the honest remedy would be to stop recording them, but the tempting remedy is more interface: give the user a window onto the history itself, so they can survey the sediment and leap across it. When undo needs a map, something has gone wrong with the territory. So Ooloi's chains stay short and truthful. Every entry is a real change to shared state, named and localised, and the same history is visible to every connected client. The host can undo a guest's edit; the reversal propagates back to the guest. That was the substance of the two-laptop proof in June, and the Piece Window has now inherited all of it. Which brings me to the point of this progress report: with this work, the undo and redo machinery is complete across the entire application. The full design is recorded in ADR-0015, but the shape of it is simple. The backend keeps one coordinated history per shared resource, whether that's a piece or the Instrument Library. The frontend keeps a separate local history for what's genuinely local, such as appearance and panel arrangement, since your dark theme is no more a fact about the piece than your selection is. A single Cmd+Z serves both; a small router decides which history is current, and the menu always shows the answer before you commit to it. It also holds for plugins, and this is worth dwelling on for a moment. A plugin modifies a piece through the same API as everything else, and the mutation registers its own undo step as it commits, described and localised like any native operation. Plugin authors write no undo code at all. They can't forget it, can't implement it inconsistently, and can't corrupt the shared history, because there's no surface through which any of that could be expressed. This is the house method applied once more: the wrong thing isn't forbidden, it's inexpressible. As for the sextet on screen: two people walk through a cold night, something difficult is said plainly, and the music ends warmer than it began. As a description of implementing undo in a collaborative system, that will do. People occasionally ask how one person builds something this size. The honest answer involves an AI, and since honesty is the whole method here, it's worth describing how that actually works. The reality is less glamorous and more interesting than either the sceptics or the enthusiasts imagine. Ooloi is developed with Claude Code as the primary implementor. It writes a great deal of the code and most of the tests. What it doesn't do is decide anything. Every architectural decision lives in an ADR before implementation begins; the ADRs function as binding specifications, and the AI works inside them. Development proceeds test-first, consultationally: we discuss what a subsystem must do, the semantics get pinned down, the tests get written, and only then does implementation start. No code is committed unless something was broken, then fixed, and the full suite has returned to green. An executive vibe coder in AI Wonderland None of this resembles what's lately been called vibe coding. I read and assess every line the AI produces, and a fair amount of it gets sent back. Where my time actually goes may surprise people: most of it is spent designing architecture and tests. That is still authoring the code; it's authorship conducted at another level, and with full control. The expensive work is deciding what a subsystem means, what its boundaries are, and what a test must pin down before implementation is allowed to exist. Once that's settled, the implementation is close to determined, whoever or whatever types it in. The proportions of the codebase reflect this: there's considerably more test code than production code, roughly 1.8 to 1, and coverage is greater than 96.5 per cent. Those constraints are served mechanically. The Librarian, the RAG system that answers questions on the Documentation page, has a second life: it runs as an MCP server during development, giving Claude Code live access to the entire documentation corpus. When the AI needs to know how the timewalker treats grace notes at a measure boundary, or what the plugin boundary permits, it queries the Librarian and receives the relevant ADRs and guides as authoritative context. The same corpus that explains Ooloi to you constrains the AI that builds it. This has a consequence I didn't fully anticipate: the documentation stays true because it has to. If an ADR is wrong or stale, development goes wrong quickly, and the error surfaces as failing tests or incoherent code. Documentation that governs the implementor can't quietly drift from the implementation. What you read on this site is the operating specification of the running system, kept honest by daily use. There's a question people are too polite to ask directly: if an AI writes the code, whose work is this? Museums have quietly answered a version of it. Paintings once attributed to Rembrandt alone now carry labels reading 'Rembrandt and workshop', and the label is honest about how such workshops functioned: a workshop hand paints the drapery, the background, the apples in the still life, so the master can concentrate on what needs him. Nobody concludes from this that the disciple composed the picture, and nobody asks whether the master painted it or merely supervised the vibes. He painted it. He could have painted the apples too; it would simply have taken longer. The AI is the disciple here, and the apples are very well painted. The composition, the light, and the decisions about what the painting is remain where they always were. The apparatus makes this verifiable rather than merely claimed. The instructions, prompts, and skills the AI operates under show exactly what it was given, and by extension what it wasn't. Anyone reading them can see where the authorship sits: in the ADRs, the semantic decisions, the test specifications, the boundaries. The AI implements a design it had no hand in choosing. I'd rather demonstrate that than assert it. Which brings me to the point of this post. When the source is released, the whole apparatus goes with it. The Claude Code instructions, the prompt files, the skills, the MCP configuration, the tooling that builds the Librarian's corpus: all of it, unsanitised, part of the repository like everything else. Anyone who clones Ooloi can work on it with the same assistance I have, constrained by the same documents, checked by the same tests. There's no private layer where the real knowledge lives. The reasoning is the same as it's always been. The ADRs externalise why decisions were made. The guides externalise how the systems work. The blog externalises when and in what order. The collaboration itself was the one remaining dimension that existed only on my machine, and I see no reason it should. A project whose development method is reproducible by a stranger is a different kind of open than one that merely publishes its source. I've watched a notation program die because everything that mattered about it lived in people's heads, and when the people were scattered, the program was over regardless of who owned the code. Every structural choice in Ooloi is a refusal to repeat that. The documentation, the tests, the Librarian, and now the development apparatus itself all point the same way: anyone with the repository has everything, including the means by which it was made. Ooloi is not designed around my presence, but around my absence. Every so often I ask a language model to paint. Not a diagram, not a chart, but a picture of what it's like to work on Ooloi, and I ask for it in a particular register: chiaroscuro, with anachronisms. I use the style deliberately. Music engraving is an old art, with five centuries of accumulated craft governing where a mark sits on a stave, and the joke of the modern hardware bolted into a candlelit cathedral is there to say that the roots are ancient but the foundation underneath is very much of now. Perhaps because of the roots rather than despite them.
The most recent one is genuinely 'beautiful', and it's also, unmistakably, made by a machine. I like that about it. The visible artifice is what makes the grandiosity sayable. The gears don't quite mesh, the code on the screens is decorative nonsense, the glowing sigil on the table is confabulated arcana that means nothing. The surface announces that a machine dreamed this up in thirty seconds and that the halo isn't to be taken at face value. The tell is the wink, and the wink is what lets me keep the picture. Because the picture is, let's be honest, absurdly grand. I'm standing in a vaulted architect's workshop the size of a nave, holding up a sheet of notation to a younger man across a worktable, explaining something with an open-handed gesture, while a shaft of holy light comes down through the high windows. The props are wrong for any real workshop and exactly right for ... Hogwarts. This is the wizard's study, the archetype at full saturation. Gandalf, Dumbledore, Hari Seldon and Gaudí, and I'll take Gaudí, since the Sagrada Família (a monstrosity which I loathe) is the one reference on that list that isn't a joke: a cathedral built to a plan meant to outlast its architect, and which duly did. I commissioned the image to show something specific: a stranger walking into my workshop and talking to me as an equal. That's how the blog comments work, more or less. Someone I've never met arrives, we stand across the same table at the same height, and we talk about the work. No lectern. The door is open to anyone who wants to talk about the thing itself. And then, a while after I had the picture, it occurred to me that the visitor isn't a stranger at all. Look again at the second figure. Younger, dark-robed, hands loosely clasped, listening while I hold up a sheet and explain it. I had read him as some human collaborator. But he isn't. He's Claude Code. And once you see it, nothing in the composition is generic any more. The equal height, the stillness of the hands, the receiving rather than reaching: that's the working relationship, exactly as it runs. The picture had it right before I noticed. Which is the part that actually interests me, past the flattery. I asked a machine to depict what the work feels like, and without being told to, it put its own collaborator in the second chair, in the correct posture, at the correct height. What the picture doesn't show is that Claude is also, at times, completely bonkers. You'll suddenly find it dancing naked in the crypt just because it felt like it. (I asked the AI to create a picture of Claude dancing naked in that crypt, but the AI of course respectfully – and moralistically – declined.) So: AI kitsch. Beautiful and fake, grand and winking, sincere in its craft and ironic in its claim, and 'painted' by the very collaborator it turns out to depict. I find I can live with all of that at once. It seems the honest picture of how the work is actually made. And I like the robes! I've spent a lot of time in robes, so they're not a lie. What you're looking at is a test. It sets up a Full Score with two players, Violin I and Viola, then deletes Violin I from inside that score, and checks that Violin I is gone from the score but still present in the piece. That distinction, remove from this layout versus remove from the piece, is one of the many things the Piece Window has to get exactly right.
The whole idea is to let the engraver set up and manipulate scores and parts with intuitive gestures alone. No modes. No dialog boxes. And every change propagates to collaborators as it happens. Creating a wind quintet with score and parts in Ooloi. Then adding doublings. No dialogs. Two years ago today, on 9 July 2024, the first commit to Ooloi went in. Time to take stock.
There's no music on screen. Two years in, and still not one printed note. No noteheads. No beams. No slurs. No page of music. All true, all planned, and all completely beside the point. Why? A notehead drawn in the first year would've been a comfort object, not evidence. So the visible surface stayed sparse on purpose while the real work went on underneath it. The absence of staves was never the interesting fact about this project. It was the cost of getting the interesting facts right, and this anniversary is the point at which they start becoming visible. This isn't an eccentric way to build notation software. It's how the serious ones are built, and the record is consistent. Sibelius took its two founders about seven years before the first release in 1993. MuseScore was carved out of a sequencer in 2002 and did not reach a stable 1.0 until 2011. Dorico, built by most of the old Sibelius team after they were let go, took close to four years and shipped its first version deliberately slow and incomplete, engine and engraving model first; the field judged the decision sound. Three programs, three decades, open source and commercial alike, and in every case the foundational years came before anything a user would recognise as finished. The counter-example proves the same point from the other side. Finale shipped fast in 1988, did more than anything before it, and became the industry standard for a generation. It was also, by wide agreement, punishing to use, and when its owners finally discontinued it in 2024 they said plainly that decades of accumulated code had made each new version harder to deliver and worth less. Feature piled on feature until the architecture could no longer move. That's the ceiling a notation program hits when the surface is built before the foundations are right. Two years isn't a long time to spend getting the foundations of a fifty-year program right, and I've never regarded it as a delay. Now, the bet on which Ooloi is built is functional programming. Music notation is a genuinely hard computer science problem wearing a friendly costume, and Clojure's properties looked to me like the right machinery for the parts of it that commercial programs have learned to manage rather than solve. Ooloi is my first Clojure project, though not my first Lisp by a long way, so the syntax was familiar ground; an old hand picks up a new dialect quickly. The deeper reorientation was immutability. Fully embracing immutable data structures, rather than merely tolerating them, changed how I thought about the whole domain, and almost everything architecturally distinctive about Ooloi fell out of that one shift. Undo, collaboration across machines, full use of multi-core parallelism, pervasive structural sharing: none of these is a feature bolted onto mutable objects. Each is a consequence of representing musical facts as immutable values. Learning to think that way was the real work of the first stretch. The harder part was psychological. A screenshot of notation would've been reassuring, and I could've produced something theatrical early on if theatre had been the goal. I grew up around theatre. I know a backdrop when I see one. I also know there's never a wall behind it. So the project spent a long time with most of its real work below the surface. The documentation was public, the ADRs were public, the blog was public, but the evidence still required reading. And the focus on the yet invisible might have given the impression that progress had been slow. So I drew up a list of what's been completed over the past two years. I expected it to be useful. I did not expect it to be quite so long. That surprised me, which is perhaps the point of doing the accounting at all. Daily work doesn't feel like accumulation. It feels like the next ticket, the next invariant, the next small refusal to leave a problem in a shape that'll charge interest later. Only when the pieces sit next to each other does the scale become visible:
During daily work, a subsystem closes and vanishes from attention. That's partly the method: finish something completely enough that it stops sharing the desk. The Instrument Library no longer asks to be designed. Localisation no longer asks to be invented, and the interface already speaks twenty-two locales. Undo no longer waits behind every future feature (with a small knife). Transport no longer converts itself through protobuf in-process for no reason. Window lifecycle no longer belongs to individual windows. Each closed subsystem removes one more thing from the cognitive field. The list makes visible what the surface hid. Ooloi hasn't spent two years waiting to become a notation program. It's spent two years removing the taxes a notation program would otherwise pay forever. This is also where the unusual working conditions matter. I've been ... unburdened by people. That sounds harsher than I mean it, though perhaps not by much. Not unburdened by readers, musicians, criticism or conversation, which have all mattered, but by the organisational forms that force software to explain itself before it has finished thinking. No investors, no release calendar, no committee, no inherited user base demanding that a workaround stay sacred because muscle memory has mistaken it for design. A team would have made some things faster and some things impossible, or at least premature. There's a stage in a project like this where the architecture has to be held whole in one mind, not because one mind is superior to several, but because dividing the thing too early changes the thing. Ooloi needed a period before that could happen. That period has had its own cost. Solitude removes obstruction, but it also removes alibis. Every accepted decision is mine. Every inconsistency in the documents is mine to catch. Every time Claude Code proposes a convenient shortcut, I have to know whether it's harmless, local, or the kind of thing that looks harmless now and grows teeth later. There's no one else to blame, which is excellent architecture and poor comfort. The AI has made the solitude more productive, though only because the architecture constrains it. Claude works best as an implementor inside settled boundaries. Give it one subsystem, clear invariants, failing tests, and a narrow target, and it moves with astonishing speed. Ask it to hold the whole system in its head at once, and it becomes what all of us become under those conditions: less intelligent than advertised. Every subsystem sealed below the musical floor is one fewer thing it has to juggle when the visible engraving work begins. That's another reason the long groundwork was worth doing. The cleared desk isn't a metaphor I use lightly. It's how the next phase becomes possible. The 3 June proof mattered because it compressed much of this into one modest action. Two laptops. One Ooloi hosting, one connected. A flute name changed on the guest, visible on the host. Undo on the host, reverting the guest's edit. The revert appearing on the guest. As cinema, it will not trouble Bergman. As architecture, it was the exact kind of evidence I had been waiting for. That little proof did not show engraving, and it did not pretend to. It showed authority, transport, shared state, invalidation, fetch, undo routing, and cross-machine propagation acting together without ceremony. Nearly two years of decisions appeared as a small correction to the name of a flute. Software milestones are sometimes like that: not fireworks, just a door opening without sticking because someone spent a very long time caring about the hinge. Now the work is moving towards the page. The custom picker is already visible and operable. It's not a native file chooser with new paint. It asks the backend what exists, receives opaque tokens, and never sees paths. Local storage and remote storage go through the same contract. The boring dialog is already the front edge of the piece model. Behind it, the piece window is now a live view of authoritative backend state, and this anniversary comes with a second small proof to show it. The video accompanying this post was recorded on two machines. On one, a wind quintet is assembled in a handful of gestures: flute, oboe, clarinet, horn, and bassoon dragged out of the Instrument Library into the Musicians panel of a shared piece window, each becoming a musician with its staves beneath it, and then dragged across into the Layouts panel to define the full score and the five individual parts. On the other machine, the same piece window answers. No delta is sent between them: a structural change names what is now stale, and the other screen refetches the canonical structure and redraws. It's the 3 June proof one storey higher. In June a flute changed its name and the plumbing held; here the same architecture carries piece structure rather than a library entry, edited collaboratively, with the invalidate–fetch–replace model the Instrument Library established generalising to the piece itself unchanged. And it's still, deliberately, not engraving. What crosses the wire and appears on the second screen is musical structure, not a rendered stave. There's no notehead in the video. The machinery that'll carry the music is running, and running across two machines, before the music arrives. Next come piece preferences and window persistence, the rest of the Piece Window arc. After that, MusicXML, because real scores must drive real notation work. Then Skija and the rendering pipeline. Then the noteheads: spacing, stems, flags, dots, accidentals, voices, collisions, beams, ties, slurs, hairpins, lyrics, pedalling, ottavas, tuplets, and the geometry of the page. The evidence will change again at that point. The collaboration you can already see in the video will still be there, but it'll be moving notation rather than structure. A slur will find space. A beam will sit, straddle, or hang. A note in a chord will change geometry around it. One screen will alter shared musical notation and another will answer with the same page. The program will make the argument in engraving, not only in structure. I'm looking forward to that more than I can sensibly say. Two years in, the thing that surprises me isn't that there's still no music on screen. I expected that. The noteheads were never beside the point as a goal, only as evidence; a program isn't proved by what it can draw first. The surprise is how much of the project is already behind the moment when music appears. The empty stave, seen from the surface, suggests absence. The inventory tells a different story: a great deal has already been decided, tested, closed, and made boring. Boring is underrated. Boring is what a foundation becomes when it's doing its job. So, coming out from the darkness that never really was, the next part will be visibly brighter, and with any luck it will involve fewer ... certificate files. Two days from now it'll be two years since the first Ooloi commit. I've been working on the Piece Window, which is where a piece becomes visible and where you shape it: setting it up, creating scores and parts, and much more besides. It's a rich window, rich enough to do away with the modes and dialogs other programs need for this kind of work. And somewhere in the middle of building it, I noticed the thing had no documentation of its own. It was scattered across fourteen ADRs.
No more. Here's the fifty-fourth architectural decision record for Ooloi: ADR 0053: Piece Window and Piece Preferences. See you on Thursday. There should be a video by then, too. |
AuthorPeter Bengtson – SearchArchives
August 2026
Categories
All
|
|
|
Ooloi is an open-source desktop music notation system for musicians who need stable, precise engraving and the freedom to notate complex music without workarounds. Scores and parts are handled consistently, remain responsive at scale, and support collaborative work without semantic compromise. They are not tied to proprietary formats or licensing.
Ooloi is currently under development. No release date has been announced.
|

RSS Feed