OOLOI.ORG
Menu

OOLOI

An Organism Evolved.

OVERVIEW

DOCUMENTATION

NEWSLETTER

Wagner Tubas on the Workbench

10/4/2026

5 Comments

 
Back in Sweden at the workbench with the instrument library. I'm finding it a little difficult to concentrate on architectural work this week. So I'm doing practical things instead.

The Instrument Library mechanism is done: the editors, the persistence, the validation, the conflict-free multi-user layer. Multiple users can edit the same library concurrently without colliding.

The single-user case (engravers working on their own computer, the normal case) is now a special case of a collaboration group whose size happens to be exactly 1. No branch in the code. No fallback. No 'offline mode'. No special case. Same logic, same invariants, same code paths, same tests, for a group size of 1 as for a group size of 30. This is the first subsystem in which that collapse is visible end-to-end, and therefore the first concrete evidence that the collaboration machinery underneath Ooloi works the way it was designed to.

So the road map looks like this. The next major thing is the Piece Window: the view in which scores are managed, and the central surface of the whole application. It's no longer a large task. Almost everything it needs already exists: drag and drop, field editors, validation machinery, persistence, undo. All of it was built for the Instrument Library, and all of it generalises directly. The Piece Window is, in effect, a new arrangement of parts that are already on the shelf.
PictureColour choices
Which is precisely why I'm tidying the workshop before I start on it. Meaning: field validation for every editor, properly factored, so I never have to think about 'did I validate this one yet?' again. Splash window timing. Colour schemes. UI principles. None of it is glamorous, but all of it is important because the UI is how Ooloi will be perceived. My aim throughout has been that the program should disappear as much as possible, so the user is in charge and can work undisturbed by technical things. There has to be a certain kind of quiet to what the end user sees.

And, in parallel whilst adding those bits of wiring, I'm filling the Instrument Library with real instruments.

The quiet chaos that is Wagner tubas, for example. Every composer who has written for them labelled them by key, from Wagner himself onwards. The tenor is always in B♭; the bass is always in F. So the library needs 'Tenor Wagner Tuba in B♭' and 'Bass Wagner Tuba in F', in four languages.

Historical notation, again, turns out to deserve a mention. Modern scores write Wagner tubas in treble clef, transposing a perfect fifth below written, the same as Horn in F, which lets horn players switch between horn and Wagner tuba parts without any mental recalibration. But Bruckner's symphonies put the tenor in B♭ basso sounding a major ninth below written and the bass in F sounding a perfect twelfth below, in bass clef; Strauss keeps the same major-ninth/perfect-twelfth transpositions but writes them in treble clef. Neither convention is wrong. Both are alive in the literature, so Ooloi provides both. This isn't a new principle. Ooloi already does the same for old horn notation, which still turns up in any nineteenth-century orchestral part you open; and for the bass and contrabass clarinet variants, which notate differently in the French and German traditions.

Mostly, though, this is a procession of small, specific questions. How do the Italians abbreviate Tuba wagneriana bassa? How do the French abbreviate le Grand Highland Bagpipe, given that no French orchestra has ever scored for one?

It's a quieter kind of work than architecture. Suits me well this week.

Picture
"Hojotohorns" (though they aren't horns by any means)
5 Comments

Three Platforms and an Old Laptop

6/4/2026

0 Comments

 
Picture
​Ooloi runs on macOS, Windows, and Linux. Each platform gets its own self-contained bundle, built separately on a machine running the target architecture natively. You download the one for your platform. It works.

On Windows and Linux there's nothing remarkable to report. On the Mac, however, Ooloi ships an Apple Silicon bundle. No Intel Mac support. This isn't controversial by any means; every Mac user knows this transition happened – no new Intel Mac has been manufactured since 2020, Apple classified the 2017 models as 'vintage' in 2024, and Rosetta 2 is being removed in macOS 28. There's a deeper reason specific to JVMs that makes Intel bundles on Apple Silicon particularly problematic, but the practical reality is simpler: Apple Silicon is where the Mac is, and it's where Ooloi's audience overwhelmingly already is.

As it happens, I develop Ooloi on a 2017 Intel MacBook Pro. There's a point to using old hardware: if there are bottlenecks in the architecture, they show up sooner. A machine that's nine years old and was never fast by today's standards will punish you for inefficiency in ways a current machine won't.

So far, I haven't seen any. This says more about Clojure's architecture than it does about the laptop. The 2017 MacBook Pro has been a surprisingly honest development partner. But you never know, moving forward.

When the deeper Skia rendering work starts – GPU-accelerated layout, real-time scrolling through large scores – I'll likely have to move to my 2024 M3 MacBook Pro, but not just for speed: Skia's GPU path on macOS is moving from deprecated OpenGL to Metal, and Metal is where Apple Silicon lives natively. As an added benefit, early benchmarks (which I've posted here before) already show a two-to-three-times speedup on CPU-bound work, and later processors like the M4 and M5 push that even further. If Metal delivers what it should, large orchestral scores won't need an overdimensioned workstation to scroll and edit smoothly.

The full technical analysis, including the JVM-under-Rosetta performance data and a four-case architecture matrix, is in ADR-0050: Platform Support Policy.
0 Comments

Non Expecto Resurrectionem Mortuorum

4/4/2026

5 Comments

 
Picture
​I'm writing this from a mountainside near Palermo on Easter Eve, the day the liturgical calendar leaves empty. Yesterday was the Crucifixion. Tomorrow is the Resurrection. Today is the silence between them; the day when, if you take the story seriously, God is dead and nobody yet knows what comes next.

Yesterday, one of my closest friends hanged himself. He is now unconscious on a ventilator. Nobody knows why he did it. Nobody knows what comes next for him either.

I'm not a believer. I've never been a believer. But I am an organist, and I've participated more times than I can count in that piece of symbolic theatre we call the liturgy. I have watched the Easter arc – from Maundy Thursday through the desolation of Good Friday to the silence of Saturday and the blazing major key of Sunday morning (Richard Strauss would of course have set it as a C major 6/4 chord) – move people in ways that have nothing to do with whether the story is true. The psychological architecture of it is real, even if its subject is not. I understand Easter Saturday better today than I did yesterday, and not because I've found faith, but because I'm living in the structure.

So I sit on a terrace in Sicily with a stupendous view and seven people I'm fond of, and the light is extraordinary, and a friend is suspended between life and death 2500 kilometres away, and there's nothing I can do. Which makes it a reasonable day to take stock.

​We went to the Teatro Massimo two days ago. It's the third largest opera house in Europe, and the building itself is magnificent: the kind of architecture that earns the word. What happened on stage, however, was something else.

Don Quichotte. Classical ballet. Minkus.

Classical ballet of this type is a closed system of circular reasoning so thorough that its practitioners no longer notice it. It no longer has anything to say, yet they defend Minkus's oom-pah-oom-pah as though it were art. They define 'musicality' as the ability to dance in time with the beat. A musician would find this primitive in the extreme, and in fact not a description of musicality at all, but a description of mere competence. It's the conflation of floor with ceiling.

And yet the system sustains itself, because it has constructed an aesthetic vocabulary that exists only to justify its own continuation. Any external reference point is treated as irrelevant. What remains is religion, not art.

I recognise the pattern. I've encountered it in functional programming circles too: articles of faith masking real emptiness, defended not by argument but by social enforcement. The dynamic is identical. The domain is irrelevant.

In the Christian calendar, today is the day of unresolved tension, the day when the official story hasn't yet provided its answer. What I find clarifying about this particular Saturday is the absence of dogma. The story hasn't yet told you what to believe. For twenty-four hours, you're left with the facts.

I prefer the facts.

When people ask why this blog looks the way it does – why there's so much documentation, so many architecture decision records, so much apparent excess – the honest answer again has to do with death.

I created Igor Engraver in the mid-1990s because I hated Finale. I had written an entire opera in it and the experience was sufficiently wretched to convince me that the problem was one of fundamental architecture. Igor was a music notation system that was, by most accounts, genuinely ahead of its time. It was acquired by idiots and left to die.

What I've come to understand, twenty-five years later, is that almost every fundamental architectural decision in Ooloi is a response to what happened to Igor, whether I originally intended it that way or not.

Open source, so that no individual's mismanagement can bury the work. Open-source components throughout, so that no proprietary dependency can become a chokepoint. ADRs. Guides. A RAG system that can answer deep, architectural questions about the codebase. A public blog that documents development as it happens, including the false starts and course corrections.

This is not a vanity exercise in transparency. It's an insurance policy. If I'm hit by a bus tomorrow, the work survives. Someone can pick it up, read why every decision was made, and continue. The documentation isn't supplementary to the project. It's structural. It's the specification.

Igor died and nothing survived it. I'm sixty-four. Therefore the work must be legible without its author.​

I never discuss other notation programs on this blog, and people occasionally find this odd. The reason isn't diplomatic restraint; it's that I genuinely don't think about Ooloi in competitive terms. Ooloi exists because I'm convinced there's a better way to represent music computationally, and I believe I've found a significant part of it, and I want to build it properly and make it available, so that a field that's been stagnant for forty years has a reason to move​. That is the entirety of the motivation.
​
​
What I am doing inside Ooloi is architecturally different. And that's why I've named it after a third-gender space alien. It's a categorically different thing, and it needs to be. The technical argument for why is elsewhere on this blog, at length, and I won't repeat it here. What matters today is that the work exists, that it's open, and that it's legible. Because today is a day for thinking about what survives.

What connects the friend on the ventilator, the ballet at the Teatro Massimo, the small dogmas of programming communities, and the theological void of Easter Saturday – apart from fragility, ossification, and death – is perhaps nothing more than this: that I have no patience for systems of thought that protect themselves from examination. Religious faith (which is wishful thinking fanned by fear of death) does this by design; classical ballet and programming communities accomplish the same thing through ossified aesthetic insularity and social enforcement respectively, but the mechanism is identical. All of them ask you to treat the absence of external validation as evidence of self-sufficiency rather than what it actually is: a warning.

Tomorrow is Easter. The faithful will celebrate a resurrection I don't believe in. My friend may wake up, or he may not. The view from this mountain is unchanged. Sicily doesn't care about any of it.

​That, too, is a kind of honesty.
5 Comments

Stave Size Matters

29/3/2026

9 Comments

 
Picture
Working on the Instrument Library – which has occupied the last few posts – I came to the point of editing staves inside instruments. That led, as it does, to clef representation; and clef representation led to the question of stave heights; and stave heights, once you look at them honestly, open onto a set of questions about what the numbers actually mean and who they serve. This is how development works: you pull on one thread and another appears. You pull that one and something else comes loose. The art is not pulling on all threads at the same time, or you end up with all yarn in one tangled clump. And when the threads start to proliferate, that is the signal to stop pulling and start architecting.

So: stave sizes. One thread at a time.

The stave space – the distance between two adjacent stave lines – is how Ooloi measures everything. Glyph dimensions, stem lengths, beam thicknesses, spacing: all of it derives from that single value, stored in millimetres. Not stave height; the space. The height is a consequence.

I spent some time recently with the rastral table. A rastrum was a pen with five nibs, drawn across the copperplate page to produce a music stave in one stroke. The finite set of available pen widths produced nine standard stave heights, numbered 0 (largest) to 8 (smallest), each associated with a particular use. The pens are gone; the vocabulary remains. When an engraver says 'Rastral 3', the meaning is immediate: 7.0 mm, standard parts, piano. No conversion required, no mental arithmetic. It encodes decades of professional judgement about what is legible at what distance for which purpose.
Picture
These values follow Gould (Behind Bars). Ross gives very slightly different numbers at some sizes – tenths of a millimetre – but Gould is the more recent authority and the more widely referenced in current practice.
Ooloi's sizing model is compositional. The base stave space propagates through a scaling chain – system, instrument, stave – where each level is a ratio against its parent. Change the base and everything follows. An ossia stave sits at two-thirds; a cue stave at three-quarters. The user works in ratios. The system reports the consequences in millimetres, with the approximate rastral equivalent alongside.

That last part is where the investigation led somewhere I hadn't originally planned. Once I had the scaling chain and the rastral table in front of me, the obvious next question was: should Ooloi simply display the effective size, or should it also say whether that size is appropriate for what the layout appears to be?

The answer, I think, is that it should. Wherever Ooloi reports an effective stave size – layout inspector, part configuration, print preview – the display will include a contextual assessment. Not just '7.4 mm (Rastral 2)' but whether that size makes sense for a flute part, or is slightly small for a piano reduction. The assessment will draw on published professional standards: MOLA puts 7.5 mm as the most readable size for orchestral parts, with anything below 7.0 mm unacceptable. The NZSO requires parts between 7.0 and 7.5 mm and rejects submissions outside that range.

The software will tell you what it knows. It will not prevent you from doing anything.
​
Rastral presets will appear on the base stave size control as named starting points, and again as targets when generating parts. Three places in total; nowhere else. The vocabulary will thread through the workflow without touching the architecture. A professional courtesy, not a load-bearing wall.
9 Comments

Bundled SMuFL Music Fonts

26/3/2026

0 Comments

 
Ooloi bundles the following SMuFL notation fonts, together with their associated text fonts, as internal application resources:
  • Bravura
  • Leland
  • Petaluma
  • Leipzig
  • Sebastian
  • Finale Ash
  • Finale Broadway
  • Finale Engraver
  • Finale Jazz
  • Finale Legacy
  • Finale Maestro

They are therefore available to every Ooloi user immediately, without installation, font management, or machine-specific setup.

This is not merely a convenience feature. It means educators, publishers, and other institutions can rely on identical font availability across workstations from the first launch. This is particularly important for collaboration.

​The full architecture is in ADR-0047: Font Management. And how Ooloi uses SMuFL to let the user specify glyphs with full control is here: ​ADR-0048: SMuFL Glyph Selection Architecture.
Picture
Picture
0 Comments

Write Pizz, Hear Pizz

26/3/2026

3 Comments

 
Picture
​A recent exchange with Magnus Johansson in the comments on the Instrument Library post made me realise something worth saying at the top level, rather than buried in a reply thread. Magnus had compared Ooloi's bundled instrument library with Igor Engraver's and noticed that Igor's was substantially larger. The question was reasonable; the answer turns out to illuminate something fundamental about what Ooloi is actually for.

But first, a correction.

I keep encountering the claim – usually from AI systems summarising the project – that Ooloi is 'for advanced notation users'. This is wrong in a way that matters. The architecture is advanced; the user experience aims to be the opposite. The entire point of doing the hard work underneath is so that people don't have to do hard work on top. A tool that requires expertise to operate has failed at its job, regardless of how much expertise went into building it.

Zero-effort playback is one example of what this means in practice.

What Igor Did

​Igor Engraver shipped with Synth Matrices – text files that described every common hardware synthesiser on the market: available patches, controller mappings, pitch bend ranges, channel limitations, stereo position. When a user set up a score with, say, two flutes, a cor anglais, and strings, the Synth Matrix for their synthesiser took care of everything: patch selection, channel allocation, balance, panning. The user spent zero time on MIDI configuration. Zero. They dragged instruments from the library, wrote music, and heard the right sounds during input.

This was 1996. Hardware synths, MIDI cables, 7-bit controllers. And yet a composer or arranger never touched a patch change, never drew a controller curve, never thought about channels. The system did it.

We also collaborated with Johan Sundberg's Musical Acoustics department at the KTH Royal Institute of Technology, whose research had quantified things that musicians do instinctively: soloists anticipate the beat by about four milliseconds; phrase dynamics follow predictable contours; onset timing varies with articulation. Those findings went directly into Igor's playback engine. The result was that pressing Play on an orchestral score produced something that sounded like musicians playing, not a sequencer clicking through events.

Now, I don't have Igor's code, I don't have any manuals, and I haven't run it in 25 years. The comparisons with Igor are inevitable when I write about playback, but Ooloi is not a resurrection. The ideas are the same kind of ideas I've always had, expressed through modern means. What follows is about where those ideas go next.

​The MIDI Prison

​That was nearly thirty years ago. What has changed since?

Remarkably little, if you look at how most notation software handles playback. The underlying protocol is still MIDI – a 7-bit serial standard from 1983, designed for connecting keyboards to synthesisers over DIN cables. It has no concept of musical structure. It cannot distinguish between a quarter note and a dotted eighth tied to a sixteenth. It knows NOTE_ON, NOTE_OFF, velocity, and a handful of continuous controllers. That's the vocabulary through which an entire industry still attempts to communicate musical intent to sound-producing devices.

The consequences are visible in every professional composer's workflow. You write a crescendo hairpin in your notation software. It looks correct on the page. You press Play. Nothing happens – because a hairpin is a musical concept, and MIDI has no musical concepts. To hear that crescendo, someone has to draw a CC11 expression curve in a DAW, by hand, matching the shape and timing of the hairpin. For every hairpin. In every part.

This is what Hans Zimmer's assistants do. They sit in studios translating musical intent into controller data, note by note, gesture by gesture. If you are scoring a film with 40 staves, that translation is a full-time job for several people. If you're a composer working alone – which is to say, if you're almost any composer – it means choosing between hearing your music properly and finishing it on time.

NotePerformer addressed this by sitting between notation software and playback, interpreting the score with a one-second lookahead buffer. It was a genuine breakthrough: finally, a tool that read musical markings and translated them into expressive performance. But NotePerformer is, by design, a workaround for deficiencies in a MIDI-based architecture. It exists because the notation software itself cannot do the translation. It patches over a gap that should not be there.

Not Bypassing – Just Doing It Right

​When I first started describing Ooloi's approach to playback, I found myself reaching for the word 'bypassing'. Ooloi bypasses MIDI. Ooloi bypasses the DAW. And then I caught myself, because that word tells you something about how deeply the old paradigm has colonised our thinking. You only 'bypass' something that is assumed to be in the path. MIDI is assumed to be in the path because it has been in the path for forty years, and an entire industry has built its workflows around that assumption.

Ooloi doesn't bypass MIDI. Ooloi simply doesn't use it. The distinction matters. Bypassing implies a workaround, a detour around an obstacle that remains in place. What Ooloi does is address the problem directly, using the technology available in 2026 rather than routing everything through a protocol designed when Margaret Thatcher was in her first term.

Ooloi drives virtual instruments directly. No MIDI channel allocation. No patch changes. No 7-bit controller resolution. The notation engine communicates with sample libraries through their native host interfaces – VST3 parameters, note expression, articulation selectors – with full precision, in the plugin's own language. This is not a technical curiosity; it's the removal of an entire layer of translation that has stood between composers and their sounds for decades.

OVID's Metamorphoses

The mechanism that makes this work is called OVID – the Ooloi Virtual Instrument Definition. OVID is the modern successor to Igor's Synth Matrices, but operating at a fundamentally higher level.

A Synth Matrix described a hardware synthesiser: which patches lived where, how to select them, what the pitch bend range was. OVID describes a virtual instrument library: what playing techniques it offers, how to select them, how loud each articulation is relative to the others, how to compensate for onset timing differences between legato and staccato samples.

The practical consequence is that Ooloi understands what it means to play an instrument, not merely what MIDI messages to send. Write 'pizz' above a string passage and Ooloi selects the pizzicato articulation from your sample library. Write a tremolo and it selects tremolo. Write a crescendo hairpin and the dynamics follow the wedge shape automatically, using whatever expression mechanism the library supports – continuous controllers, note expression, parameter automation – without the user knowing or caring which one.

And because OVID maps canonical technique names to vendor-specific implementations, the same score plays back correctly through different sample libraries. Switch from Spitfire to Vienna Synchron and the pizzicato is still a pizzicato; the selection mechanism changes, but the musical intent is preserved. Share a piece with someone and they can listen to it as you intended it to sound, without any setup.

A glissando on a harp is not a glissando on a trombone. A trill on a flute is not a trill on a kettledrum. These are musically obvious statements, but no MIDI-based system can act on them without external help. OVID knows the difference natively, because it operates at the level of musical semantics rather than note events.

The Instrument Library Connection

This brings us back to where we started: the instrument library.

The bundled library is deliberately finite – roughly 270 instruments in up to four language editions. Magnus's comparison with Igor's list is instructive, because Igor's larger catalogue was itself driven by Synth Matrices. Every instrument in that list existed because some hardware synthesiser had a patch for it, and the Synth Matrix mapped the instrument name to that patch. The noble Crwth was there not because orchestral composers regularly write for the crwth, but because a sample existed and the mapping was trivial. Remove the Synth Matrix context, and that instrument list was a reflection of available synthesiser patches, not a statement about what a notation program ought to bundle.

The Ooloi instrument library serves a different function. Each instrument carries not only its notation properties – name, clef, transposition, range – but also its OVID mapping. When you drag a cor anglais from the library into your score, Ooloi knows which virtual instrument to load, which articulations are available, how to calibrate loudness against the oboe in the next staff, and how to handle the specific timbral characteristics of that instrument across your installed sample libraries. If your preferred library lacks a particular technique – col legno battuto, say – the OVID fallback chain searches your other installed libraries and finds it there.

This is why the bundled library is sized the way it is. Every bundled instrument maps to an OVID profile that produces correct, calibrated, expressive playback out of the box. The library ships with OVID definitions for BBC Symphony Orchestra Discover, which is free, and Virtual Playing Orchestra as a fallback. Install both – fifteen minutes, zero cost – and every instrument in the bundled library plays back with intelligent articulation handling, loudness calibration, onset alignment, and humanisation. No DAW. No MIDI. No configuration.

Humanisation deserves a word of its own. This is not random velocity variation to break up a machine-gun effect. Ooloi's humanisation applies the same principles we implemented in Igor, informed by Sundberg's research: soloists anticipate the beat; ensemble players lock to it; phrase dynamics follow natural contours; articulation affects onset timing. The intelligence is in the notation engine, not in a third-party plugin with a narrow one-second lookahead buffer.

The Creative Source

I built this because I need it. I am a composer; I've written opera, orchestral music, chamber music. When I write a crescendo hairpin, I need to hear a crescendo. When I write a string tremolo, I need to hear a tremolo. I do not want to open a DAW, create tracks, assign patches, route MIDI, and draw controller curves before I can hear whether my orchestration works. That workflow is not composing; it is bookkeeping.

A DAW still has its place, of course – for final production, mixing, mastering. But the compositional workflow, the sketch, the orchestration, the moment when you need to hear whether that horn entry works against the divided violas: that must be immediate. Write the music. Press Play. Hear it as a musician would play it.

Music notation is, ultimately, about music. The technology that serves it should be invisible. If you find yourself thinking about patch changes, you are no longer thinking about your piece. For who, in the end, cares about patch changes? Really?
3 Comments

Drag Show

22/3/2026

8 Comments

 
Picture
The above GIF demonstrates some of the functionality of the Instrument Library and Piece Window at this point: selection of score language, filtering on names, drag-copying, deleting, etc. What you see above is not the full 1000+ instrument selection, but a smaller library I use for development and testing. The notifications to the lower right are likewise for development.
8 Comments

Glenfiddich Highland Pipes in G sharp

17/3/2026

28 Comments

 
Picture
The complete bundled instrument library is now documented.

The new guide, Instrument Library Catalogue, lists the default instrument set that ships with Ooloi: modern orchestral instruments, historical families, keyboards, plucked strings, voices, choirs, percussion, special-effect instruments, and various things that have no fixed abode but nevertheless turn up in scores. A total of roughly 270 instruments, yielding just over 1,000 language-specific library entries.

The architectural decisions behind it remain where they belong, in ADR 0045: Instrument Library. 

This catalogue is not a theological statement about which instruments deserve to exist. It is the default library: broad, practical, and sufficient to start work. If you find yourself asking, 'You have ocarinas but not Glenfiddich Highland Pipes in G sharp?!', the answer is simple: not by default. Add them in the Instrument Library window, save them, and they are yours permanently.

​In other words, the bundled set is a starting point, not a border guard. 
28 Comments

Horns in Bass Clef

13/3/2026

9 Comments

 
Picture
Magnus's question yesterday about soprano recorder clefs sent me down a path I'd been meaning to write about.

His question was straightforward: can the Instrument Library default to a treble ottava alta clef for the soprano recorder? Yes, trivially – the template carries the staff spec, you change the clef, done. But the exchange reminded me of a more consequential case where the relationship between clef and transposition isn't merely cosmetic but changes the sounding pitch of the notation itself.

From roughly 1750 until well into the twentieth century, horn parts in bass clef were transposed downward from concert pitch rather than upward. For a horn in F, treble clef notation sounds a perfect fifth below the written pitch – the modern convention. But in bass clef, the same instrument's notation sounds a perfect fourth above the written pitch. The difference is an octave, and the practical consequence is that the transposition interval depends on which clef is active at any given moment in the part.
Picture
​This is not an obscure historical footnote. It's Beethoven, Brahms, Wagner, Strauss, Mahler, Shostakovich – the central orchestral repertoire spanning two centuries.
Picture
​The convention had a practical origin. Before valves, horn parts were limited to the notes of the harmonic series, and bass clef passages used only the lowest few harmonics. Writing them an octave lower than sounding pitch kept the notes within the staff when two parts shared a single staff. The convention outlived its original purpose by about a century.
Picture
Ooloi's instrument definitions support clef-dependent transposition intervals. When a horn in F switches from treble to bass clef, the transposition changes accordingly – no phantom instrument changes, no hidden octave lines, no typographic compromises. The notation looks correct, the playback sounds correct, and the relationship between the two is maintained automatically.

Which is, after all, the point.
9 Comments

The Instrument Library

12/3/2026

7 Comments

 
Picture
"Brünnhilde, a Franciscan friar, and a Moog synthesiser walk into a library."
Undo and redo landed a couple of days ago. The next item on the plan was the Piece Settings window – the place where a score's global configuration lives. But Piece Settings requires instrument assignments, and instrument assignments require a working Instrument Library. So the sequence revealed itself, as it does: not Piece Settings next, but the thing Piece Settings depends on.

This is not an unwelcome discovery. The Instrument Library turns out to be the cleanest possible entity to build at this stage, precisely because it depends on nothing. No piece identity, no piece lifecycle, no window hierarchy. It is global and singleton: one library per backend, shared across all connected clients, persisting across restarts. It holds templates, not instances – when a musician is assigned an instrument, the piece receives a copy of the template and the two are independent from that point. Renaming a template later has no effect on instruments already in scores.

That independence from the rest of the system makes it the right place to establish something that will govern every piece of shared state Ooloi ever manages: the invalidate/fetch/replace pattern.

The Pattern

The pattern is this. When the library changes on the backend, the server broadcasts a notification that any copies 'out there' are now stale. Clients that receive it mark their local cache stale. If the Instrument Library window happens to be open, they fetch immediately and re-render. If the window is closed, nothing happens until it opens – at which point the fetch occurs and the window renders from fresh data. A client that never opens the window pays no cost at all, even if the library is modified repeatedly during the session by other clients. 
​
The sending client follows the same path as everyone else. It does not update its local state from the success response; it waits for the event it will receive as a subscriber, then fetches like any other client. There is one code path for state updates regardless of where the change originated.

In practice

Working through the implementation surfaced several problems, each with a clean answer. Two users editing the library simultaneously must not silently overwrite each other's work, so a change is rejected if someone else updated the library first – the conflict is surfaced explicitly, and the second user reapplies their change on top of the current state. Instruments deleted by the user must stay deleted across application updates that ship new default entries, which requires tracking deletions rather than simply omitting items. Display order within a family must survive both user rearrangement and future additions from updates, which requires ordering to be stored explicitly rather than inferred from position.

What the exercise confirmed is the value of the division of concerns itself. The backend stores state, enforces consistency, and broadcasts invalidation events. The frontend gets the data when required, transforms it locally through whatever editing operations the user performs, and submits the result. The backend does not participate in editing decisions; the frontend does not manage persistence concerns.

That division – established here on clean, self-contained ground – is the same division that will govern every piece of rendered state going forward. The Instrument Library is the first authoritative backend entity that is not a piece; its clean behaviour under load, concurrency, and updates confirms that the model generalises. Everything built on top of it will follow the same pattern.

Read all about it in ADR 0045: Instrument Library.
7 Comments

The Lens We Can No Longer Take Off

8/3/2026

2 Comments

 
In which we examine why a habit of mind is mistaken for the nature of things
Picture
​There's a habit of mind so pervasive in software development today that it's ceased to be visible as a habit. It presents itself, rather, as common sense: ship early, iterate fast, learn from users, move fast and break things. The vocabulary is Silicon Valley but the reach is global, and it has colonised not just how software is built but how software is judged. A project that doesn't fit the pattern isn't evaluated on its own terms; it's measured against the pattern and found wanting.

This is how cultural hegemony works: a local methodology, exported with the efficiency that US capitalism has always brought to the business of making its assumptions universal, ends up masquerading as common sense. The psychological mechanisms by which technical workers are recruited into this system – the mythology of meritocracy and the linguistic inflation that expands responsibility while eliminating agency –  are explored at length in 'Help! Help! I'm Being Repressed! (But You're Grateful Instead). What concerns us here is a different consequence of the same hegemony: not what it does to the people inside the frame, but what it makes invisible outside it.

The promise attached to the methodology (and this is what makes it effective as ideology rather than merely as practice) is that if you play by the rules, you participate in the dream. Adopt the two-week sprint, the MVP, the continuous deployment pipeline, the growth metrics, and somewhere at the end of the process stands the exit and the private jet. The methods and the mythology travel together; you don't merely acquire a development process but a tribal identity and a ready-made trajectory. The cargo cult: the rituals, performed faithfully, in the expectation that the planes will land.

They mostly do not land, of course. What most people acquire is the methodology without the outcome. But this doesn't dislodge the faith, because the faith isn't really about the outcome. It's about the framework through which all technical work is now perceived.

What the Lens Cannot See

​Take TeX, or the Linux kernel, or the protocols on which the internet runs. None of it was built by this method and none of it could have been. Donald Knuth spent a decade on TeX, not because he was slow, but because the problem required it. The domain had correctness conditions that couldn't be satisfied incrementally. Calling partial correctness an MVP doesn't make it one; it makes it a wrong answer with better branding.

There's a further irony here that the dominant methodology prefers not to examine. Much of modern software culture sits on infrastructure built by people who worked in exactly the way it now derides: with correctness as the primary criterion and visibility as an afterthought. 'Move fast and break things' is, in this sense, parasitic: it depends for its very existence on layers of prior work whose authors would have found the phrase somewhere between baffling and contemptible.

Music notation is another such domain. It's a semantic, mathematical, historical, and representational system that's been accumulating edge cases for five hundred years. Accidentals, time signatures, polytonal harmony, the memory rules that govern when a sharp must be reprinted and when it may be assumed: these are formal systems with correctness conditions, not UX choices to be iterated toward, and a notation engine that handles eighty percent of cases is simply broken.

The architecture must be right before anything is visible, because the visible parts depend entirely on the invisible ones. You cannot ship a thin slice of correct rational arithmetic. You cannot gather user feedback on whether your hierarchical key signature partitioning handles organ notation correctly. The feedback loop here isn't user adoption; it's whether the semantic representation is sound enough that hard problems become tractable. These loops aren't merely operating on different timescales; they're incommensurable. User-visible behaviour and internal semantic correctness cannot be measured on the same scale, and conflating them is a category error, not merely a methodological one.

The particular cruelty of the dominant methodology is that it treats foundational work as delay. Eighteen months of semantic infrastructure before a window opens is by the startup template a red flag, evidence that the team can't ship. By any other standard, it's exactly what the domain requires.

The Moral Dimension

The methodological misreading would be merely irritating if it were innocent. It's not quite innocent, which is what gives it its edge.

To look at a project operating outside the disruption frame and conclude that it's slow or self-indulgent requires a particular kind of incuriosity: an unwillingness to ask whether the frame itself might be the wrong instrument for the measurement. That incuriosity isn't random; it's cultivated by an intellectual monoculture that has made one historically contingent approach to software development appear to be the only conceivable one.

There are people who cannot imagine a domain where the architecture must be correct before anything else is possible, because they've only ever worked in domains where it doesn't need to be. That's forgivable. But there are also people who, when presented with evidence that the domain is different, prefer the template to the evidence; a failure of intellectual range, and at some level a moral one, because it renders invisible entire categories of value, including most of the software the world actually relies on.

What the Domain Actually Demands

The disruption methodology assumes a forgiving domain: one where the cost of being wrong is low and the complexity lives in the interface rather than the semantics. Most web software fulfils these conditions reasonably well. A social media feed or a SaaS dashboard: if you get the data model slightly wrong, you refactor. If the UI is poor, you redesign. The feedback loop is fast and the penalties are recoverable.

Music notation violates every one of these assumptions. The real distinction is between domains where a representational error can be repaired after the fact and domains where it metastasises, where every layer built on top of a flawed foundation inherits and amplifies the flaw, until the accumulated damage is structural and irreversible. Notation is the latter kind of domain. The semantic layer isn't a detail to be addressed after launch. The heuristics that commercial notation software relies on aren't temporary expedients awaiting a proper solution; they're the permanent consequence of foundations that made exact solutions intractable. Once that choice is made, it cannot be unmade. The technical debt is original sin, not a balance sheet entry awaiting repayment.

The correct solutions exist, and not because of clever algorithms: a correct representation makes correct solutions possible. The problems didn't require heuristics. They required a foundation that sprint-cycle development philosophies, tuned for domains where being wrong is cheap and reversible, reliably select against.

Music notation has been accumulating edge cases for five hundred years. It doesn't care about your sprint velocity.

​(This article is also available on Medium)
2 Comments

A Reading Path

6/3/2026

0 Comments

 
Picture
The documentation has accumulated to the point where it doesn't naturally sort itself for a first reader. Architecture Decision Records are numbered chronologically — in the order decisions were made, not in the order you need to encounter them. Reading straight through means confronting distributed-systems reasoning before you know what a `Piece` contains. The answer keeps arriving before you've understood the question.

There's now a guided path that reorganises the material by conceptual dependency: nine phases, starting with motivation and working through data model, language choices, addressing, pitch representation, the plugin system, rendering, and the frontend. Each phase builds the vocabulary the next one requires.

Think of it as an adjunct to the Librarian — where the Oracle answers specific questions, this path builds the context that makes those answers land correctly. It's now the canonical entry point to the technical documentation. It's here.
0 Comments

It's All Greek to Me

2/3/2026

6 Comments

 
Picture
Open Settings, switch the locale. Every open window follows: menus, the About dialog, Settings itself. English to German to French to Danish, pausing on Greek. Then it repeats.

This is chrome – wiring things up, giving Ooloi a face.

The obvious next step seemed to be collaboration. The architecture has supported shared backends since day one; the collaboration ticket and ADR systematise how they are handled, add authentication, authorisation, piece invitations.

But you can't test the collaboration paradigm just on application settings. Theme preferences, locale, autosave interval – these are local. They don't live on a shared backend. To verify that the pattern works, you need an actual piece: something that lives on a server that one or more clients connect to.

So a sequence of work comes first.

Undo and redo for settings changes. Every setting change already records the old value alongside the new; the undo stack accumulates and replays inverse events. No piece dependency. This establishes the mechanism before anything more complex exists.

Then creating and opening pieces — not in a naïve single-user way, but written from the start for an environment where the backend may be shared. Even locally, the model has to reflect that reality.

Then undo and redo for piece content: a single authoritative stack on the server, shared across everyone editing simultaneously. The undo gesture in the frontend inspects which tier holds the more recent operation and routes accordingly.

Then the Piece Settings editor, with the Instrument Library window.

Here is where the collaboration pattern is actually demonstrated. Consider adjusting beam thickness or the default appearance of piano pedal extension lines: ordinary engraving decisions. Now add a collaborator with the same editor open on the same piece. Your changes appear in their view instantly. Theirs in yours. Both of you can undo, on the same data, with the same shared history.

This is not a special case requiring special handling. If the preceding layers are in place, this is what falls out of the existing architecture. But it should be done as early as possible, before additional layers complicate things, so now is the right time.
6 Comments

Ask the Librarian

25/2/2026

2 Comments

 
Picture
The Ooloi documentation has grown considerably. ADRs, guides, READMEs, newsletters, blog posts – there's a lot of it, and not all of it is easy to navigate. So I've built something to help.

The Ooloi Librarian is a small RAG system – Retrieval-Augmented Generation, for the uninitiated – that answers questions about Ooloi's architecture and design directly from that documentation. It retrieves the relevant chunks, passes them to Claude Haiku as context, and returns a grounded answer with source citations. If nothing relevant is found, it says so rather than making something up. This is enforced in code, not by prompting.

It's live now in the Ask the Librarian section of the Documentation page. Try it. Ask about the accidental rendering algorithm, or why Ooloi uses STM, or what the timewalker is. The answers come from the docs, not from the model's general knowledge.

The backend runs on AWS – API Gateway, Lambda, Bedrock – rate-limited and CORS-restricted to this domain. Roughly four cents per thousand queries, and nothing at all when idle.
Picture
2 Comments

New Guide: MIDI in Ooloi

21/2/2026

0 Comments

 
Picture
And we also have a new Guide: MIDI in Ooloi. It explains why Ooloi takes MIDI input but produces no MIDI output, and why that is a considered choice rather than an oversight. In 2026, there are cleaner ways to control virtual instruments than routing through MIDI, and the guide explains what Ooloi does instead.

Deeper technical details here: 0044-MIDI-Input-Library-and-Boundary-Architecture.
0 Comments

The Piece Window

21/2/2026

9 Comments

 
Picture
​Magnus Johansson asked in the comments of 'Surface Tension' whether Ooloi would have a separate piece window, as Igor Engraver did. I told him that the first version of it already existed on screen, and that I'd write a post explaining why it's there. This is that post.

Magnus isn't a casual observer. He's almost certainly the person alive today who knows Igor Engraver most deeply – including me, at this point. He translated the software into Swedish. He still uses it as his preferred notation tool, describing it as 'like playing an instrument': muscle memory, not nostalgia. He was interviewed by Realtid about what happened to NoteHeads. When I come to reimplement Flow Mode, Magnus is the person I will be consulting, because he carries it in his hands in a way that no documentation can replace.

When Magnus asks about the piece window, it's not a feature request. It's the question of someone who understands, at the deepest level, why it was there the first time.

The window is empty for now, and there's no reason to pretend otherwise. On a commercial software blog you'd never show this: you wait until the feature is complete, populated with convincing content, ready to impress – and then you present it. This blog has never operated that way. It's a development record, transparent about what exists, what doesn't, and why decisions were made. You're welcome to follow the journey.

A Window That Does Several Jobs at Once

The piece window exists to keep everything else clean.

Ooloi's menu bar is short. There are no floating palettes at startup, no icon strips demanding attention, no panels pre-opened on the assumption that you'll need them. The application doesn't perform its capabilities on arrival. What the piece window makes possible is precisely this restraint: a large category of operations – who's playing, how they are grouped, which layouts exist, how musicians are assigned to them – lives in one place, expressed through drag and drop rather than through menus or dialogs. Every operation that lives there is one the menu bar doesn't need to carry, one palette that doesn't need to exist, one dialog the user doesn't need to find.

But the piece window isn't merely a space-saving device. It's a direct reflection of the semantic model.

A piece of music isn't a score. The score is one possible view of the music: a particular arrangement of staves, systems, and pages assembled for a specific purpose. The music itself exists at a different level – the musicians, their instruments, the content they carry. Layouts are derived from the piece. A flute part may or may not appear in a conductor's score; it'll certainly appear in a parts layout, transposed and extracted, but always as a view of the same underlying musical object. The piece window is where that underlying object lives. The Layouts panel is where you decide how it will be seen.

You open the Instrument Library and drag a Flute into the Musicians panel. A musician appears. You drag a Violin section, a Cello. You've described what the piece is, independently of how it will be presented. Then you drag those musicians into the Layouts panel: a full score receives all of them, a string parts layout receives only the strings. The interface overload so typical in notation software – the proliferation of modal dialogs, configuration screens, the menus that keep growing – is the visible consequence of not having this separation. The piece window exists because the model does, and it saves screen space, menu space, and cognitive space as a direct result.

Calm

When Ooloi opens, nothing appears beyond the menu bar and whatever windows you last had open. No floating palettes, no icon strips, no panels staking out territory in advance of being needed.

When you double-click a measure in the score, a slowly pulsating hairline cursor appears. You're in Flow Mode. The application has understood what you intend and responded to it; you summoned nothing, declared nothing. Palettes exist and can be opened, but they're not assumed to be wanted. When Ooloi needs to tell you something, a notification fades in over three quarters of a second, remains for ten, then fades out over three. It doesn't flash. It doesn't ask to be acknowledged. It informs and withdraws organically and gently.

The word for all of this is calm. Not minimalism as a style choice, but the recognition that the person using this software is a musician trying to think about music, and that every uninvited visual element is a small interruption of that thinking.

Not Igor 2.0

​The piece window isn't here because Igor Engraver had one. Ooloi isn't Igor 2.0, and I want to be precise about this: the two systems share no code, no architecture, no technical lineage. What they do share is a set of convictions about how human beings and creative software should interact, because the person who designed both is the same person, with the same ideas – and those ideas haven't changed. They've deepened.

Igor had the piece window because the semantic model required it. Ooloi has it for exactly the same reason. Igor had Flow Mode because a musician entering notes shouldn't have to think about the software. Ooloi will have it for exactly the same reason, and Magnus will be part of getting it right. What Ooloi takes further is everything underneath: the concurrency model, the rendering architecture, the collaboration layer, the foundations that Igor never had the chance to build correctly.

The window is empty now. Not for much longer.
9 Comments

The Frontend Architecture Guide

18/2/2026

0 Comments

 
Picture
I've published a guide to Ooloi's frontend architecture – long, precise, and detailed, written for architects and developers who want to understand the system from the inside.

It covers window lifecycle, event architecture, the rendering pipeline, fetch coordination, localisation, collaboration, and the testing model. Together with the Timewalking Guide and the Polymorphic API Guide, it forms the main conceptual gateway into Ooloi's internals.

Worth flagging for experienced frontend developers: this architecture inverts several instincts. The frontend holds no semantic authority. It is computationally strong and structurally subordinate; that subordination is precisely what makes distributed collaboration, transport independence, and first-class plugin composition possible without architectural compromise. The guide explains why. I think the argument is sound, though I'm aware it might feel distinctly odd, or even regressive, to a developer whose instincts were formed in React or a similar ecosystem.

If you work in notation – as a musician, engraver, or editor – and find this kind of writing opaque, current large language models are genuinely useful here. Feed the guide to one and ask what it means for your daily work. It's a reasonable use of the technology, and the answers tend to be surprisingly good – when they're not inventing things I'd never claim ;)

Worth stating plainly: the subject here is art, and the technical rigour exists in service of that, not despite it. This blog documents the reasoning behind Ooloi as it develops – for future contributors, researchers, maintainers, and critics. Systems like this have a lineage and a psychological architecture as much as a technical one. I want that visible. This blog has a voice because it was written by someone who considers authorial invisibility a failure mode rather than a virtue.
0 Comments

Surface Tension

17/2/2026

10 Comments

 
Picture
Ooloi is now a running desktop application on macOS, Windows, and Linux. It opens, it responds, it remembers where you left it. A concrete thing, like any other program.

But that's not enough. The next step is teaching it to talk. Ooloi's frontend and backend have always been separate components communicating through a defined protocol; in standalone mode, they simply appear as one and the user needn't think about it. But this disciplined split personality was designed that way for a reason, and it's now time to act on it.

ADR-0036 lets the two halves run apart — so one Ooloi can connect to another, or to a centralised server. You invite a collaborator; a secure connection opens. They disconnect; the application returns to working alone. No restart, no mode switching.

The separation was always there. Now it becomes visible.
Picture
10 Comments

Where the Freedom Comes From

15/2/2026

2 Comments

 
Picture
That room. The tape drives in their cabinets along the far wall, the operator's console in the centre, the line printer to the right. It looks like something from Kubrick: the same antiseptic geometry, the same monolithic seriousness, the same implication that whatever happens here is important enough to require its own architecture.

This is a Philips P1100. In 1973, I was twelve years old, and this is where I started programming.

I got the opportunity through school. The P1100 was a Dutch mainframe, not widely known outside Northern Europe, and the fact that a twelve-year-old was permitted to approach it probably says more about 1970s Scandinavian attitudes to children than about any pedagogical intention. But approach it I did. COBOL and FORTRAN, mostly. Punch cards. Line printers. Typewriter console input. Thirty-six-bit words and 32K words of core memory – actual magnetic cores, the kind you could theoretically see with a magnifying glass. Spinning tape stations and disk units. The whole physical apparatus of computation as it existed before anyone thought to make it personal.
Picture
P1100 product reveal
What the photographs convey, and what no description quite captures, is the physicality of early computing. These were rooms, not screens. You walked into the machine. The tape drives were furniture. The noise was constant. Programming in that environment carried a particular weight; there was nothing casual about it, nothing disposable, nothing you could do from bed with a laptop. The seriousness was built into the space.

I don't mention this for nostalgia. I mention it because something from that period has stayed with me through fifty years of subsequent work, and I think it matters for understanding why I build the way I build.

A Language That Trusts You

Six years after the P1100, in 1979, I encountered Lisp. I was eighteen, and the encounter came through the legendary August 1979 issue of BYTE magazine, devoted entirely to Lisp. I've written about this before, so I won't repeat the full story here; but the experience deserves its place in this genealogy because it changed the direction of everything that followed.

I should say what computing felt like in the late 1970s, for anyone who wasn't there. The dominant paradigm was procedural: FORTRAN, COBOL, Pascal, various assembly languages depending on your hardware. Programming meant telling the machine what to do, step by step, in a language designed for the machine's convenience as much as the programmer's. The programmer was an operator. The metaphor was industrial. I had spent six years in that world. It was what programming was.

Lisp was different in kind, not just in degree. What I encountered was a language that didn't tell me what to do. It waited. It provided a set of primitives so minimal they seemed almost absurd; seven or eight special forms, a way to define functions, a way to combine them, and the extraordinary implication that this was sufficient for anything I could imagine. The language was smaller than what I'd been using, and it could do more. That paradox has never stopped being interesting to me.

What Lisp offered, and what I wouldn't have the vocabulary to articulate until years later, was freedom. Not freedom as a marketing term or a political slogan, but freedom as an engineering condition: the ability to reshape the language to the problem rather than reshaping the problem to fit the language. In Lisp, the programmer was not an operator. The programmer was a maker of tools, a builder of languages, a creative agent trusted with the full power of the system.

The culture around Lisp carried this same ethos. The people who shaped it (Steele, Gabriel, Kiczales, Norvig, among others) were not priests. They were builders, hackers, improvisers. They valued expressiveness, wit, elegance in the mathematical sense, and above all, the conviction that the person at the keyboard was intelligent enough to be trusted with dangerous tools. The community was irreverent, argumentative, often brilliant, and entirely uninterested in policing anyone's tone or orthodoxy. You were judged by what you built, not by which catechism you recited.

I mention these names because they are not abstractions to me. I was eighteen. I was reading their papers. I was trying to implement what they described. Immediately after that BYTE issue, I implemented a Lisp in 6502 assembler, using an assembler I had written in BASIC. I tell you this not to impress but to convey the intensity of the response. When something is that good, you build it yourself to understand it.

CLOS and the Workshop Tradition

The progression from basic Lisp to the Common Lisp Object System (CLOS) in the mid-1980s was not, for me, a move from one paradigm to another. It was an expansion within the same tradition.

CLOS is difficult to explain to anyone whose experience of object-oriented programming was formed by Java, C++, or Python. In fact, some of us maintained even then that CLOS was not object-oriented at all; the name was a concession to the terminology of the period, not a description of what it actually was. Those languages treat objects as containers: data and methods bundled together, accessed through interfaces, extended through inheritance. The programmer works within the object. CLOS transcends this entirely. Methods don't belong to objects; they belong to generic functions. Dispatch can happen on any combination of argument types. Method combinations (:before, :after, :around) let you layer behaviour without modifying existing code. The Metaobject Protocol (MOP) lets you redefine how the object system itself works.

The result is a system of extraordinary power and openness. You could override anything. You could extend anything. You could reshape the behaviour of the system at any level, including the level at which behaviour is dispatched. CLOS treated the programmer not as a user of the object system but as its co-author. The system was a workshop, not a cathedral, and the door was always unlocked.

This mattered to me practically, not just aesthetically. When I built HotLisp for the Royal College of Music in Stockholm (a Common Lisp implementation written in C that treated MIDI events as first-class citizens), I was already integrating music directly into the computational core. When I later built Igor Engraver, CLOS became the substrate on which the entire semantic model rested. The ability to extend, compose, and reshape; to add new types of musical objects that participated seamlessly in existing operations; to layer specialised behaviour onto generic frameworks without breaking them: these weren't theoretical luxuries. They were the reason the software worked.

I taught algorithmic composition using Lisp at the Royal College. My students, who were composers, not computer scientists, understood the freedom immediately. You could express musical ideas directly, without the mediation of a language designed for someone else's problems. The gap between thinking and making was as small as I have ever seen it in any medium.

Having Been There

​I am, as of this writing, sixty-four years old. I have been programming for over fifty years. I say this not as credential but as context, because having been there changes what you see.

I was there for the AI winter. I watched a field that had promised the moon retreat into a decade of funding cuts and reputational collapse, dragging Lisp's standing down with it. The language didn't deserve the association; it was punished for the sins of researchers who had over-promised. I kept using it anyway, because the language hadn't changed, only its fashionability. This was the first time I learned that technical merit and cultural standing are largely unrelated.

I was there for the object-oriented conquest of the 1990s. I watched as C++ and then Java established OOP as orthodoxy, complete with design pattern catechisms and UML diagrams that looked more like religious iconography than engineering documentation. CLOS, which had solved the problems these languages were struggling with years earlier, was invisible because it ran on the wrong platform and belonged to the wrong tribe. The industry chose what was marketable over what was good. This was the second time I learned that lesson.

I was there for the web's arrival, which changed everything about deployment and nothing about the fundamental problems of building complex software. I was there for the enterprise Java years, when 'architecture' meant XML configuration files and dependency injection frameworks and a peculiar conviction that more abstraction was always better, regardless of what it cost in comprehensibility. I was there for the functional programming renaissance, which rediscovered principles that Lisp had embodied since the 1950s, often without acknowledgement and frequently with a missionary zeal that replicated the very dogmatism it claimed to reject.

I am here for the current AI explosion, which rhymes with the original AI boom in ways that make my skin prickle. I have seen this arc before: extraordinary technical promise, sweeping claims about imminent transformation, and a market that moves faster than the underlying science. Time will separate what is durable from what is fashionable.
​
None of this is complaint. It is observation. When you have been programming for fifty years, you develop a particular relationship with trends: you have seen enough of them arrive, dominate, and recede to know that the arrival tells you very little about the value and the dominance tells you nothing about the longevity. What remains after the trend passes is what was true about it. Immutability was true about functional programming. The JVM was true about Java. Interactive development was true about Lisp all along.

The thing that has remained true for me, through every cycle, is the freedom principle. The conviction that the programmer should be trusted, that the tools should serve the maker rather than constrain them, that the ability to reshape your instruments is not a luxury but a precondition for doing serious work. I did not learn this from a manifesto. I learned it from a mainframe in 1973 and a Lisp prompt in 1979, and everything since has confirmed it.

What Was Lost

Igor Engraver was the fullest expression of this principle I had achieved. Twelve people, $7.5 million in investment (2024 equivalent), a music notation system built entirely in Common Lisp that introduced semantic modelling to the field. Conductors were interested. Composers were interested. The architecture was sound.

The project ended in 2002 after a combination of venture capital pressure, management-imposed feature creep, and the collapse of M&A activity following September 11, 2001. The technical architecture was sound; the business environment was not.

I won't rehearse the full history here; it's documented elsewhere. What matters for this essay is what was lost and what survived. What was lost was the software, the team, and the years of accumulated work. What survived was the knowledge: of what works in music notation architecture, of what CLOS makes possible, of what fails when business logic overrides engineering discipline. And what survived, underneath all of it, was the conviction that the freedom principle was correct and that the work deserved to be done properly.

Most people, having had a project of that scale taken from them, do not try again. I understand why. The rational calculus says the risk exceeds the reward. But the rational calculus doesn't account for the fact that you still know how to do it, that you've learned what you didn't know the first time, and that nobody else is going to build this.

The Return

When I came to Clojure, I came home.

I don't mean this sentimentally. I mean it technically. Clojure is a Lisp; it thinks in the same shapes, provides the same minimal-but-sufficient primitive set, and trusts the programmer with the same radical freedom. But it adds things that Common Lisp never had and that my work desperately needed: immutable data structures by default, Software Transactional Memory for concurrent coordination, and the entire JVM ecosystem for deployment, GUI development, and cross-platform reliability. I've written extensively about these on the blog, so I won't rehearse the technical details here. What matters for this essay is the genealogical thread.

I've called this 'Clojure for closure', and the wordplay is deliberate. It is a return to a native language after decades away, carrying everything those decades taught me.

The CLOS patterns came with me. Ooloi uses Clojure's multimethods with the Methodical library to achieve CLOS-like method combinations: :before, :after, :around modifiers that layer behaviour exactly as they did in Common Lisp. The hierarchical type system uses Clojure's `derive` mechanism to create inheritance-like relationships without classes, mirroring CLOS's approach to multiple inheritance through composition rather than rigid hierarchy. Generic functions dispatch on argument types just as they did in CLOS, with operations defined outside the data they manipulate.

Rich Hickey, Clojure's creator, made choices that resonate specifically with the tradition I come from. 'Mutability in bounded contexts is fine'. 'Solve problems first'. The emphasis on what you can build, not on what catechism you recite. Clojure didn't inherit the Lisp purity culture that never really existed in the first place; it inherited the Lisp builder culture, the one that judged you by what you shipped rather than which monads you could name.

But Clojure also gave me something new. Immutability as a default changes how you think about time, state, and coordination. In Common Lisp, you could write immutable code, but the language didn't push you toward it. In Clojure, immutability is the grain of the wood. This inversion turned out to be profound for music notation specifically, because a musical score is a temporal structure where the meaning of any element depends on everything that precedes it. The semantic engine that results from this is something Igor Engraver, for all its strengths, could never have achieved.

Where the Genealogy Arrives

Ooloi's plugin system is, in a specific sense, the culmination of everything this essay describes.

The core engine is written in Clojure and architecturally closed. I've written about this elsewhere as the 'monastic core' principle. The freedom is at the perimeter: any JVM language can write plugins, and the plugin API speaks each language's idioms natively. A Java developer writes Java. A Kotlin developer writes Kotlin. Nobody is forced to learn Clojure or to understand the internals. The benefits of the architecture propagate without requiring conversion.

This is the CLOS principle, expressed architecturally. The system trusts the developer. The developer works in their own language, with their own patterns, and the underlying architecture handles the coordination. The monastery uses Latin internally because Latin is precise; but when teaching farmers improved agriculture, you speak their language. This is not compromise. It is proper boundary design, and it is the lesson of fifty years in the workshop tradition.

When I sit at this keyboard today, fixing a macOS menu bug or stripping debug symbols from a jlink runtime, I am using skills accumulated across the full span of what I've described. The mainframe taught me that serious work requires serious infrastructure. Lisp taught me that freedom is an engineering condition, not a slogan. CLOS taught me that the system should trust the programmer. The loss of Igor Engraver taught me that good architecture survives the business that funded it, if someone is stubborn enough to rebuild. Clojure taught me that immutability changes what's possible. The whole genealogy is present in every design decision, whether or not it's visible.

I don't know if Ooloi will succeed, whatever that is. I know the architecture is right. I know the foundations carry what needs to be built on top of them.

​And I know where the freedom comes from, which is what I wanted to write down.
2 Comments

The Ordinary Work

11/2/2026

3 Comments

 
Picture
After nineteen months of building systems that nobody can see – temporal traversal, accidental algorithms, transducer pipelines, STM coordination – I have spent the past fortnight making menus behave.

Menus. On three operating systems. macOS wants an application menu in the system bar. Windows wants Exit in the File menu and About in the Help menu. Linux wants Quit in the File menu and Settings in the Edit menu. None of them is wrong, exactly, but none of them agrees with the others, and they all have opinions.

This is normal engineering. It is, after the intensity of the semantic work, refreshingly boring.

Dark mode and light mode. A splash screen that shows each component as it initialises. Window state persistence so the application remembers where you left it. An About dialog with a background of engraved music, rendered through the same windowing path as everything else. Translation keys for every user-visible string, verified at build time against PO files. Fixing the JVM's 64KB static initialiser limit because 185 multimethod symbols turned out to be too many for a single class. Stripping debug symbols from the jlink runtime to bring the application bundle down from 213 MB to 173 MB.

None of this is interesting in the way that a deterministic accidental rendering algorithm is interesting. And that's the point.

Ooloi now has a face and a body. It boots, shows what it's doing, presents platform-appropriate chrome, responds to commands, and shuts down cleanly. The experience of seeing it is strange – like hearing a recording of a piece you've been composing in silence. You know every voice, every structural decision, but the thing sitting there on the screen, with its dark window and its OK button, is suddenly external. It exists in the world rather than in your head.
Picture
The current GitHub tickets
The project board tells the story plainly enough: 61 tickets closed, the combined application framework just completed, and one ticket in progress. That ticket is multi-mode clients – the work that will let an Ooloi talk to other Oolois and to dedicated servers. A student working alone invites a teacher; the teacher connects, helps, disconnects, resumes their own work. An institution runs a 24/7 server. A string quartet in four cities annotates bowings in the same score.

​This is why I'm doing it now, before rendering, before input, before any of the visible musical functionality. Collaboration in Ooloi isn't a feature bolted on at the end; it's a consequence of the architecture. Immutable data, STM transactions, gRPC transport, VPD-based addressing – these were built for correctness, not for collaboration, but they make collaboration nearly trivial. The hybrid transport architecture lets the application start standalone and accept collaborators dynamically, without restart, without mode switching. Once this works – and it will work, because the foundations were built for it whether I knew it at the time or not – I need not spend any more time on it for the foreseeable future.


Then the real work begins: making Ooloi do what it was built to do. Drawing music.

But for now, I'm fixing a macOS bug where "Show All" doesn't unhide windows, and adding a theme toggle. Ordinary work. I find I don't mind it.
3 Comments

The Bazaar and the Cathedral

30/1/2026

0 Comments

 
Picture
​In a blog post from some time ago, Penitenziagite!, I wrote about linguistic impedance in software: the way systems shout incomprehensible demands at contributing developers, forcing them to think in the wrong language. That post was about architecture as translation – the scriptorium at the centre speaking Latin for precision, and the gate speaking the vernacular so people can actually participate.

This post is about governance.

Specifically: why Ooloi is open source, but not open in the way some people expect. And why it cannot be.

The Myth of the Open-Source Bazaar

​There is a persistent belief among developers that open source implies a particular governance model. In this vision, design is open, debate is open, architecture is open, decision-making is open, and even the rewriting of foundations is treated as normal community activity. The project becomes a bazaar: a bustling marketplace of patches and opinions, competing visions and negotiated direction.

This model works for some kinds of software. It fails for others. Music notation software belongs firmly in the latter category.

The problems Ooloi addresses – temporal coordination, concurrent structural mutation, global layout decisions, semantic correctness across voices – are not decomposable into independent opinions. They cannot be negotiated piecemeal. They require conceptual unity, which is another way of saying they require architectural closure.

A bazaar cannot produce that. However, a cathedral can.

What 'Closed' Means Here

Ooloi's core is closed – but not in the sense of secrecy. The code is MPL-2.0: inspectable, forkable, modifiable. What I mean by closed is something more precise: closed in the sense of authority over semantics.

The musical model is fixed. The invariants are fixed. The staged pipeline is fixed. The authority boundaries are fixed. This does not mean that development has stopped, or that new functionality will not appear. It means that the conceptual foundations are no longer under negotiation.

Closure is not Stagnation

​A closed semantic core is often misread as a claim of finality: finished, complete, unchangeable. That is not what I mean.

What is closed is the space of permissible reinterpretation. New features will arrive, new capabilities will arrive, refinements and extensions will arrive – but they must fit within the established model rather than redefine it.

This distinction matters because most architectural failure in open projects does not come from lack of innovation. It comes from uncontrolled semantic drift: the gradual erosion of guarantees as each contributor reinterprets the foundations to suit local convenience. Ooloi explicitly forbids that drift.

Why the Core must be Closed

​Ooloi's correctness depends on architectural decisions that only work as a coherent whole.

Immutability is treated as a semantic guarantee rather than a performance trick. STM is not merely one possible concurrency implementation among several; it is the concurrency model, because the alternatives import failure modes that Ooloi is explicitly designed to eliminate. Structural sharing is not optional; it is a prerequisite for the kind of scale where a full orchestral score can be edited in real time without the system grinding to a halt. Computation is staged because global layout decisions are otherwise intractable. Piece state is single-authority because reconciliation architectures – the kind where multiple sources of truth must be merged – create exactly the class of bugs that have plagued notation software for forty years.

These are not interchangeable components. They are constraints, and constraints that reinforce each other. You cannot selectively replace one of them. You cannot introduce mutability 'for performance'. You cannot swap out the concurrency model. You cannot dissolve authority boundaries. Each such change collapses guarantees that are only meaningful because the other constraints hold.

The cathedral stands because the architecture must stand.

Why This Enables Real Openness

​Here is the paradox: by closing the core, Ooloi makes everything around it genuinely open.

Because the centre does not move, APIs stop being provisional. Semantics do not drift. Performance characteristics remain predictable. Plugin contracts remain valid across versions, which means plugin authors can build with confidence rather than anxiety about the next breaking change.

Plugins become first-class citizens rather than tolerated afterthoughts. Any JVM language can participate without translation into a single house dialect. Boundaries stay explicit. Failure modes stay contained.

This is the same pattern that made TeX durable, SQLite coherent, and the JVM stable enough to host entire ecosystems. A fixed centre enables freedom at the edges.

The Cuckoo-Chick Problem

Visibility attracts contributors. Most are helpful; some are enthusiastic but misaligned; a few arrive with expectations the project cannot and will not meet.

I have learned to recognise two failure modes.

1: Misaligned help

These contributors mean well. They propose changes that would, in effect, produce a different system entirely.

They might want the core rewritten in another language. They might want STM replaced with actors, or argue for mutability 'for performance'. They might want the semantic model redesigned, or the staged pipeline replaced with heuristics. They are not malicious – they simply assume the architecture is provisional, a starting point for negotiation rather than a finished foundation.

As you have seen, it is not.

2: The arena-seeker

Here the motivation is not technical at all. The project becomes a venue for resolving old arguments, validating preferred tools, or reenacting disputes imported from elsewhere. When the architecture does not bend, pressure escalates. When boundaries hold, frustration surfaces.

At that point refusal is often reinterpreted as hostility, silence as arrogance, and constraint as personal exclusion.

This is a category error. Refusal is governance. In Ooloi, it is exercised deliberately.

Why Refusal is Non-Negotiable

If the core were open to redesign, plugin contracts would break. Semantics would drift. Stages in the rendering pipeline would start interfering with each other. Concurrency guarantees would dissolve. Correctness would become probabilistic – which is to say, the system would regress to precisely the type of architecture Ooloi was built to escape.

By enforcing architectural closure, contributors learn where pressure will not be applied. Plugin authors learn what will not change. Users get stable behaviour. The system remains intelligible.

Boundaries are not unkind. They are protective.

Open Source Without Negotiation

​Ooloi is open source in a precise, literal sense: inspectable, forkable, extensible, durable.

It is not open in the sense of open-ended architectural debate. It is not open in the sense of consensus-driven semantics. It is not open in the sense of renegotiating authority with each new voice that arrives.

The core is not a public workshop. It is a composition. Collaborative compositions exist – devised theatre, collectively improvised music – but they are specialised forms suited to particular purposes, not universal methods. Ooloi's architecture is not that kind of work. Its structure must be fixed before others can build upon it.

The bazaar is not inside the cathedral; it is outside, at the gate, where plugins flourish without threatening the foundations.

The Gate & the Bazaar

The Penitenziagite! post argued that architecture should not shout incomprehensible demands at its users. This post argues the complement: governance should not shout incomprehensible demands at its contributors.

Ooloi's structure is explicit. There is the cathedral/scriptorium: the core, architecturally closed and semantically fixed, where the hard problems are solved. There is the library: canonical plugins and reference implementations, where patterns are demonstrated rather than debated. And there is the gate and the bazaar beyond it: the plugin ecosystem, open and multilingual and creative, but separated from the core by a boundary that preserves the integrity of the whole.

This is not a contradiction. It is a design pattern.

A stable centre enables a flourishing perimeter. A closed semantic core enables an open ecosystem. A cathedral enables a bazaar – but only if the gate between them holds.

0 Comments

First Window

27/1/2026

12 Comments

 
Picture
This is the very first window Ooloi has opened. Ever.

Not a console command or REPL experiment - a window created through the infrastructure completed yesterday (ADR-0031), using the new UI Specification Format (ADR-0042) that amongst other things makes all UI elements accessible to plugins as first-class citizens.

Another quiet decision: localisation from the start. ADR-0039 establishes that every UI string is translatable from day one, using GNU gettext's standard .po format. The tooling ecosystem is mature: Poedit, Crowdin, Transifex, Weblate, Lokalise, POEditor, OmegaT. Translators know these tools. Workflows exist. Nothing proprietary, nothing invented here.
​
Not retrofitted later. Built in.
12 Comments

Frontend Events: One Evening's Work

27/1/2026

3 Comments

 
Picture
Well, that was quick! The multi-tiered frontend event infrastructure is complete and implemented. One evening's work added the Event Router, the Rendering Data Manager, and the Fetch Coordinator. This implements ADR-0031 and shows that having the implementation architected in detail before writing the code saves a lot of time. I'd expected to be busy with frontend events for some time.

Now that that's out of the way comes what it enables: windows, dialogs, menus, notifications. I'll be working with JavaFX, cljfx, AtlantaFX: what's called 'UI chrome'.

It's concrete work without semantic subtleties for a change: does the window open? Does the NordDark theme apply correctly? Does the dialog render? Aesthetic decisions instead of semantic ones.

I expect these blog posts will turn quite practical in tone for a while, as this is standard engineering, plumbing, connecting things, turning detailed ADRs into working code. Quite relaxing, as a matter of fact.

And I can now, after 18 months, finally give in to that desire to actually open a window. Fresh air!
3 Comments

The Final Bit of Engine in Place

25/1/2026

0 Comments

 
Picture
Today, hierarchical key signature overrides were completed. Global key signatures can now be overridden at the instrument level as well as the staff level, as many times within a measure as required, with fully deterministic accidental handling. The updated ADR-0035 documents the algorithm.

This sounds narrow. It isn't. The ability to handle this correctly, without manual intervention or heuristic guesswork, required everything underneath it to be correct first. The last piece going in means the semantic aspect of the engine is complete.

Eighteen months of invisible work, ended.

The focus now shifts to the frontend event system, then to opening windows, etc. The infrastructure phase succeeded by disappearing; the next phase will succeed by appearing. Different disciplines, different anxieties.

I find it difficult to articulate what this moment feels like. The closest analogy I have is from composition: finishing a score and waiting for the first rehearsal.
​
A carefully prepared potentiality, awaiting concretion. 
0 Comments

Why Ooloi Doesn't Need a DAW

21/1/2026

9 Comments

 
Picture
For decades, orchestral playback has been organised around an absence of trust.

The score was not considered precise enough to stand on its own, so it had to be translated. MIDI became the intermediary. DAWs became the place where music was made to behave. Templates grew until they resembled orchestras-in-storage. Machines were added not because the music required it, but because the protocol did.

Ooloi takes a different position.

The score is treated as the authoritative description of the music. Pitch, timing, articulation, phrasing, microtonality and humanisation are not annotations awaiting interpretation elsewhere. They are part of the structure. Playback does not correct the score. It follows it.

For that reason, Ooloi has no MIDI output in the core. Audio is produced entirely by frontend plugins: VST/AU instruments, SoundFonts, synthesis engines. The backend never allocates channels, never bends pitches, never streams audio. It manages musical structure. Plugins turn that structure into sound. The instruments run inside Ooloi, not in an external DAW waiting for MIDI.

Pitch is represented symbolically and exactly. A note is not a frequency approximation or a MIDI pitch with heavy makeup but something like "C###4+50". A sustained chord can contain a continuously glissing inner voice without splitting staves, duplicating instruments, or consuming additional channels. There is no pitch-bend choreography, no controller bookkeeping, no library-specific workaround logic. The DNA soup is gone.

For readers coming from notation, this restores the score's authority. Slurs, dynamics, accents, register and phrasing are no longer hints for later repair. They are the performance.

For readers coming from virtual instruments, this architecture removes entire categories of work that have become normalised:

- No permanent DAW templates holding a full orchestra 'just in case'
- No slave machines preloading instruments that never play
- No CC drawing to approximate phrasing already present in the notation (the work that currently keeps Hans Zimmer's assistants employed)
- No channel allocation strategies for divisi or microtonality
- No waiting for templates to load before hearing a single note

Because the semantic model captures what is actually written, playback plugins can analyse the score and load only what is required. If a piece contains no contrabassoon, no contrabassoon need exist in memory. If a technique is missing in one library, another can be invoked for that passage alone. Routing, balance and reverberation can follow from structure, not from global assumptions.

This is why large template-based setups become unnecessary. Not because of optimisation tricks, but because they were compensating for a semantic gap between notation and sound. The architecture closes that gap.

Do DAWs still matter? Yes, but later. Mixing, sound design, video synchronisation and final delivery remain DAW territory. What changes is that the DAW is no longer required to make the music behave like music.

Ooloi does not replace the DAW.

It removes the need for the DAW to do a job it was never meant to do.
9 Comments
<<Previous

    Author

    Peter Bengtson –
    Cloud architect, Clojure advocate, concert organist, opera composer. Craft over commodity. Still windsurfing through parentheses.

    Search

    Archives

    April 2026
    March 2026
    February 2026
    January 2026
    December 2025
    November 2025
    October 2025
    September 2025
    August 2025
    July 2025
    June 2025
    April 2025
    March 2025
    September 2024
    August 2024
    July 2024

    Categories

    All
    Accidentals
    Alfred Korzybski
    Architecture
    Benchmarks
    Clefs
    Clojure
    CLOS
    Common Lisp
    DDD
    Death Of Igor Engraver
    Documentation
    Donald E Knuth
    Dorico
    Dynamic Programming
    Finale
    Fonts
    FrankenScore
    Franz Kafka
    Frontend
    Functional Programming
    Generative AI
    GRPC
    Igor Engraver
    Instruments
    Jacques Derrida
    JVM
    License
    LilyPond
    Lisp
    Localisation
    MIDI
    MPL 2.0
    MuseScore
    MusicXML
    Ooloi
    Ortography
    Pitches
    Playback
    Plugins
    Python
    QuickDraw GX
    Rendering
    Rhythm
    Rich Hickey
    Road Map
    Scheme
    Semiotics
    Sibelius
    Silicon Valley
    Site
    Skia
    Sponsorship
    Transposition
    UI
    Umberto Eco
    Vertigo
    VST/AU
    Wednesday Addams

    RSS Feed

Home
​Overview
Documentation
About
Contact
Newsletter
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.


  • Home
  • Overview
    • Background and History
    • Project Goals
    • Introduction for Musicians
    • Introduction for Programmers
    • Technical Comparison
  • Documentation
  • About
  • Contact
  • Home
  • Overview
    • Background and History
    • Project Goals
    • Introduction for Musicians
    • Introduction for Programmers
    • Technical Comparison
  • Documentation
  • About
  • Contact