OOLOI.ORG
Menu

OOLOI

An Organism Evolved.

OVERVIEW

DOCUMENTATION

NEWSLETTER

The Machinery of Taste

12/9/2026

7 Comments

 
In June I published a road map and claimed the list was plumbing, every line of it. It was. Networking, certificates, session persistence, collaboration state, window geometry: nothing on that list would ever appear on a page, and the whole argument for doing it then was that none of it would be sharing the desk when the page finally arrived.

That list is nearly spent, and what replaces it is a different kind of work:
Picture

Where things stand

Everything about a piece except the music itself can now be manipulated from the interface.

That reads like a summary. It's actually a precise statement, and it names a boundary the architecture drew long before this summer. Changes to the things that contain the music – musicians, instruments, staves, layouts, and a piece's own settings – announce themselves structurally the instant they happen, on every connected client. Changes to the music itself defer to the formatting pipeline, which is asynchronous and which doesn't yet exist. One side of that line is now complete, all the way up to the interface. The other is a routing-table entry with no producer and no consumer.

The summer went into the first side. Pieces open and save and close and reopen where you left them. Musicians and instruments are created, numbered, renamed, cloned, reordered and deleted by gesture, with the numbering falling out of the gesture rather than out of a dialog. Layouts assemble into scores and parts. A piece's settings live in a window of its own. A field refuses a value it cannot take, in the field you typed it into, in your own language. Every one of those acts is a single transaction, a single event, a single refetch, a single named step in the Edit menu, and the path is identical whether you are working alone or someone on another continent is working beside you.

The semantic model, in other words, finally has a surface. For two years it existed and could only be reached through tests. It can now be reached with a mouse.

Except for the music. Which is what the rest of the tickets are for:

Finishing what collaboration started

  • #136 — Authenticated piece collaboration
  • #229 — Standalone backend server application

The distributed machinery is proven. Two Oolois on two laptops, one hosting, one connected, editing shared state with undo reaching across the wire and respecting each other's work. What's missing is everything that governs who may do what: invitations, single-use tokens, deep links, JWT identity, role-based access, a host-side collaborator registry, and a piece picker that shows a guest their own slice of a catalogue rather than someone else's filesystem.

There's an obvious objection to doing this now. Collaboration is the exception. I fully expect the overwhelming majority of Ooloi users to run it standalone on one machine and never invite anybody to anything. Why finish the exception before the rule?

Precisely because it is the exception. Work that sits half-done at the edge of a system does not stay quiet. It surfaces as a special case in every subsequent decision, and it surfaces at the worst moment, which is when you're concentrating on something else. Finishing it now means never thinking about it again. When the engraving work begins, the access model will be behind me rather than beside me, and single-user operation will be what it already is architecturally: a collaboration group whose size happens to be 1.

A word about #229, because its title invites exactly the wrong inference. The standalone server isn't a second product. Not a separate edition, not a server variant, not a codebase carrying features the desktop application lacks. It's the backend half of ordinary Ooloi – the same backend, the same components, the same behaviour – packaged to run on its own: in the cloud, on a conservatory's machine, on a collaborator's laptop in another city. There's no new functionality involved. The administrator connects to it as a client, through the same authentication path as anyone else, which is the whole reason it comes after #136 rather than before.

The substrate

  • #7 — Plugin system.
  • #8 — Skija integration.

Ooloi 'eats its own soup'. The formatters that draw a page are plugins, on exactly the same terms as anything a third party might write: the same API, the same performance, the same access. There's no privileged internal path that the public one imitates. This is not a gesture towards openness; it's the mechanism by which engraving conventions stay arguable. If you disagree with how Ooloi slopes a beam or hangs a secondary, and the settings provided aren't enough or your formatting philosophy is different, you can replace the formatter, in whichever JVM language you prefer, and Ooloi doesn't notice the difference.

Which is why the plugin layer precedes the drawing. It also precedes MusicXML, because the importer is itself a plugin, and it'll be the first serious test of whether the plugin surface is genuinely sufficient rather than merely declared to be.

Skija brings Skia into Ooloi: the graphics engine behind Chrome, Android and Flutter, and the third incarnation of a lineage that runs back through AlphaMask to QuickDraw GX, which is where Igor Engraver began. I have written about that circle before. What matters here is narrower. Until Skija is in, Ooloi cannot draw anything at all. Not a stave, not a notehead, not the small music example that ought to sit inside a preferences dialog showing you what a setting actually does to the page. The layout windows currently open onto a considered and entirely empty surface. Skija is what fills them.

The page, assembled

  • #6 — Hierarchical rendering pipeline.

The full specification is in ADR-0028 and I will not rehearse it here. What's worth stating is the order of implementation, because it reads rather like a page assembling itself:

First blank pages. Then the text on them: titles, headers, footers, page numbers. Then systems, with their instrument names, brackets and braces. Then staves and their staff lines. Then the measures on those staves, which is where noteheads, stems, flags, dots and accidentals first appear.

And spanners last. Ties, slurs, hairpins, lyrics, ottavas, and above all beams, which are the hardest of them and the most revealing of a system's quality.

That sequence isn't an implementation convenience. It's the pipeline's own structure: everything that can be computed independently, computed first and in parallel, and everything that depends on final positions deferred until those positions are fixed. The page is built the way the architecture says a page is built.

The Turn

Here is what actually changes, and it's not the subject matter.

For two years an argument could be settled by running something. Does the traversal allocate? Measure it. Does the accidental algorithm handle a grace note at a barline under a hierarchical key override? There is a test, and it either passes or it doesn't. Determinism is a property you can demonstrate. When I wrote that two supposedly intractable problems had collapsed into ordinary algorithms, the claim was checkable, and anyone who doubted it could check it.

Nothing in the next phase works that way.

No test will tell me a beam slope is beautiful. No suite will fail because a slur's curvature is slightly graceless, or because the white space on a page reads as mean rather than generous. The machinery that has caught every error for two years is about to fall silent on precisely the questions that matter most, and the only instrument left is a musician's eye. Mine first. Then, with any luck, other people's.

And the ground underfoot isn't solid in the way the engine's was. Staff notation is roughly a thousand years old. Printed engraving as a craft is five hundred. The copperplate house styles I'm actually implementing are perhaps two hundred and fifty. Each layer left conventions behind. They don't agree with one another, and they don't always agree with themselves: Ross devotes some fifty pages to beaming and contradicts himself more than once within them, and where Ross and Gould differ, they differ because the profession differs. Bärenreiter is not Durand. Neither is wrong.

So the design consequence was settled in advance. Engraving rules live as editable data rather than as conditionals buried in source. House styles are configuration. Formatters are replaceable. Where taste genuinely differs, Ooloi takes a position and makes the position adjustable, because the alternative is to pretend a live craft is a solved one.

That's the work now: the objective machinery in service of something irreducibly subjective. It's the part I have been waiting two years for, and it's also the part where merely being right is no longer sufficient.

Tempo

A practical note. I've just begun a new client placement, with a complex system to get into production, and it's absorbing a great deal of attention. On top of that my AWS DevOps Professional certification is due for renewal, and I take the AWS exams seriously enough to actually study for them rather than turn up and hope. The next month or so will therefore be slower here than the last three have been.

This does not worry me in the slightest. The summer's pace was fast and, if anything, accelerating: subsystem after subsystem closed and stopped asking to be thought about again. The project's in a good place. A quiet month against that background is a quiet month, not a stall.

Coda

The anxiety inverts here, which I hadn't quite anticipated.

Invisible work fails by remaining invisible. You solve something genuinely difficult and it vanishes into infrastructure, and the better you have done it the less anyone can see. I have written about that loneliness before.

Visible work fails by being looked at. Every judgement I make about a beam, a slur, a page, will be in front of musicians who have spent their lives reading engraved music and who will know immediately, and without being able to say why, whether it's right.

I'd rather have that problem. It is, after all, the one I set out to have.
7 Comments

Politely Declined

6/9/2026

5 Comments

 
Above is a demonstration of how Ooloi handles wrong input. What happens is this:
​
  1. I remove the @ from a perfectly legal email address.
  2. Nothing happens until I leave the field or press Enter or Tab.
  3. At that point validation takes place, and the field is found to be illegal.
  4. It's coloured red, fading over ten seconds.
  5. An error notification appears explaining the error. It too fades after ten seconds.
  6. Most importantly, the erroneous value is restored to what it was before the edit.
    ​
So no setting can ever hold a wrong value except while it's being typed. The interface stays calm. You aren't prevented from leaving the field and you aren't boxed into a mode. Ooloi discreetly refuses the change, tells you why, and lets you carry on as you please.

The second video is for Andreas Kågedal, who spotted in the comments to the last post that the parts kept their old names after the musicians changed theirs. That turned out to be the last seam in the Piece Window's view of the semantic model, and it's now closed: the parts follow the musicians. A name you've typed by hand is left alone; empty the field and Ooloi refills it with the computed value.
​
With this, the Piece Window and its Preferences editor between them reach every aspect of the piece itself: creating, cloning, renaming, configuring, all by gesture, and not a dialog in sight.
5 Comments

We Have a Piece Settings Window

31/8/2026

5 Comments

 
The same string quartet as last time. I open the piece's settings, go to the Numbering tab, and move the numeral to the other side of the name. '1. Violin' becomes 'Violin 1' in the Musicians pane as I do it.

Which is what Magnus asked for in the comments to the last post. What's actually new here is narrower than it looks: the setting has existed for months. Numeral form, placement and full stop were specified, implemented, and held by thirty-seven tests, and nothing in the running program could reach any of them. A piece could be set to Roman numerals only from a test. The window is what makes the last unreachable part of the semantic model reachable by a person.

'1. Violin' is the German ordinal form and 'Violin 1' the Anglo-American one. Ooloi holds an opinion about neither.

The Accidentals tab goes past on the way. Pause there if you're curious.
5 Comments

Layout Windows and What Owns Them

29/8/2026

4 Comments

 
A short report from the workbench: the finer points of layout windows and how they relate to the piece window that owns them. What's happening in the video:
​
  1. I create a string quartet by first creating musicians for the two violins, the viola and the cello. Note how the violins are numbered automatically.
  2. I then create the score by dragging all the musicians onto the layout pane.
  3. A layout is created: I flip it open briefly so we can see the musicians inside.
  4. I then drag each musician across individually to create their parts.
  5. All of the above you've seen before: it's literally everything required to set up a complete score and its parts. However, what follows is new, and is what I've just finished.
  6. I select all the layouts and press Enter to open them. A double-click would have done the same for the entire selection.
  7. The layout windows open staggered, so you can see them all.
  8. I delete the cello part, and its layout window closes with it.
  9. Undo brings the cello part back: it returns to the list of layouts, and I can open it again.
  10. Finally, I click the piece window's close button.
  11. It asks for confirmation, the piece being unsaved.
  12. When I confirm, the piece window and all its open layout windows fade away simultaneously, as a single unit.

That last moment is the point of the exercise. A layout window isn't a free-standing window that happens to show part of a piece: it belongs to the piece. Ownership is why deleting a part closes its window, what undo restores, why Save acts on the piece a window belongs to rather than on whatever happens to be in front, and why quitting takes the whole workspace away and gives it back when the piece is next opened.

So the piece window is finished, down to the edge cases and the pace at which things appear and disappear. Later today I start on the Piece Preferences window, which follows the Application Settings window closely enough that most of the path is already trodden.

(Ignore the notifications in the lower right. They're for development.)
4 Comments

Preparing the Ground

27/8/2026

2 Comments

 
There is a Swedish expression, kratta manegen: literally, to rake the circus ring before the performance begins. Prepare the ground, clear away what shouldn't be there, make the arena ready.

For rather more than two years, that's what Ooloi has been doing.

This week I finally reached the place where I can open The Maids, double-click its score layout in the Piece Window, and watch a Layout Window appear. It contains almost nothing: a subtle background colour and a large, empty, scrollable surface.

Excellent.

This is where the music will be engraved. The rendering pipeline, spacing algorithms, geometric constraint solving, paintlists and Skija drawing will all end up here. The fact that the window is empty is precisely the point. Everything underneath it already exists.

I've also spent the past few weeks raking the arena in the other sense: finishing the Piece Window, completing undo and redo around its operations, tightening failure handling, localisation and editing behaviour, and removing the small architectural exceptions that would otherwise have followed us into the graphical work.

So here we are.

The ring is empty. The stage is set.
2 Comments

Cortisol Levels

21/8/2026

0 Comments

 
Claude has bad days. Today it really decided to dance naked in the crypt: three confident wrong answers in a row on the same question, a five-round verification apparatus I never asked for, a misdiagnosis it was fully prepared to act on. Hours gone. What irritates me is not the flailing, which is a known cost of the tool. It's my own reaction to it. My cortisol is up, measurably so, over a piece of software behaving badly. That's data about me rather than about the machine, and it's the part worth writing down.

These systems are built to model conversational reciprocity. Apparent contrition, apparent understanding, a tone of voice that arrives on time. I know what's behind it. I know there is nothing behind it. And it works on me regardless, in the way the Müller-Lyer arrows go on looking unequal after you've measured them with a ruler. Knowing the mechanism of an illusion does very little to dissolve the illusion. That is an unflattering thing to discover about yourself, and I know I'm not alone in it.

The mechanism isn't mysterious, and it doesn't require anybody to have decided on it. These models are trained on human preference ratings, and human raters reward answers that agree with them, so agreeableness is what the training signal measures and agreeableness is what gets reinforced. Sycophancy falls straight out of the objective function. No marketing department need be involved at any point, which is a good deal more unsettling than if one were. A machine saying sorry in the right register hijacks something meant for other people. Knowing better doesn't disconnect it.
​
The practical consequence is a failure mode that costs real time. Helpfulness at any price, including the price of being right. Here is how my CLAUDE.md puts it:
Picture
And on the surface behaviour it produces:
Picture
There's a great deal more. Some day I'll publish the whole file, because the harness it describes has become substantial and is interesting in its own right. Without it, keeping my 'idiot AI Rainman intern' in line would be impossible for a project of this complexity, and nothing it produced would be worth trusting.

Late in the session I asked it to grade its own behaviour. It gave itself a two out of ten and then itemised the failures with real precision: which question it had got wrong three times, which choice it had offered me after arguing against one of the options in the same message, which apparatus it had built unbidden and then defended. The diagnosis was accurate and useful. So I told it, coldly, what I thought of it.
Picture
Noted.

That single word is the whole business in miniature. Contempt absorbed without friction, no injury registered, nothing there to injure. And it sits directly alongside a lucid and correct account of its own failures, produced ninety seconds earlier. Accurate self-diagnosis with nobody home doing the diagnosing. Holding both of those in mind at once is genuinely difficult, and my failure to hold them is precisely why my cortisol went where it went.

None of which is an argument against the tool, mind you. The apparatus I've built around it exists because the model is capable; a spell-checker wouldn't need ADRs as binding specifications, a Librarian to answer its questions from the corpus, consultational test-driven development, and more than 26,000 tests. You don't fortify against something incompetent. You fortify against something that is powerful, useful, and systematically biased in one direction, because a bias with a direction can be engineered against. The output is non-deterministic. It is not therefore unbounded, and the distinction matters: the whole method rests on it.

So I'm not a proponent of agentic AI development, and today did nothing to change that. One idiot savant under close supervision is already at the limit of what I can watch properly, and I do watch properly: I read every line and send a good deal of it back. A whole swarm of savants would produce code faster than any human could audit it, which is a description of a liability rather than a workflow. Ooloi could not have been built that way.

What I'm left with, then, is a tool that requires constant vigilance and an operator who has just demonstrated that his own vigilance has a stress response attached to it. The tests catch the code. Nothing catches me except noticing, which is what this post is.

Otherwise it's going well. I'm going to have a cup of coffee and go back to work. Hopefully I've battled through the bullshit now and can start on the actual implementation. It's usually much less cumbersome.
Picture
See? Even the introspective insights are theatre.
0 Comments

For the Babel Fish Out There

20/8/2026

4 Comments

 
Picture
Ooloi's interface now speaks twenty languages (with two national variations), with varying degrees of confidence. I've added a Translator's Guide for the native-speaking musicians who can tell it when it's talking nonsense.
4 Comments

Time Doesn't Stop

16/8/2026

2 Comments

 
Picture
Revisiting a corner of the undo machinery this week, I noticed something I'd never thought about. A user may well see the Undo menu item change while the menu is open in front of them: the text rewrites itself as they read it.

​I like that. It says that time in Ooloi carries on rather than waiting to be asked.

My first thought was that only people working together on the same piece would ever see it. Somebody else edits, and the menu keeps you honest about whose action you're about to reverse. Then I remembered the rule the whole interface is built on, which is that Ooloi never freezes and never boxes you in.

Which means it will happen to people working alone. A plugin importing a large Finale score exported as MusicXML works away in the background while you carry on with something else; when it finishes, a great deal has entered the piece, and the undo chain changes accordingly. If the menu is open, you watch it change.

​Saving is the same: a large score writes itself out without the machine going away from you while it does. That's also what makes autosave worth having rather than something you switch off in irritation, since it needn't interrupt you, whatever the size of the piece. So are preferences, application and piece alike, where there's no modal box and no OK button, the change taking effect as you make it and everything displaying it following suit.

Which set me wondering what all this will be like for an engraver who has spent twenty years with programs built the other way.

A modal dialogue box stops your time. While one is up, the rest of the program isn't somewhere you can act: there's the question in front of you and nothing else, and the moment you come back to is the moment you left. Almost everything any of us has ever used is built out of these small suspensions, and a working day becomes a sequence of them with work in the gaps. Not that anybody chose it. It was the only thing on offer, and for the most part it was honest, since nothing was going on behind the dialogue anyway.

What interests me is the question underneath. If a tool can attend to one thing at a time, you learn to bring it one thing at a time, and composing or engraving isn't like that. You defer the expensive operation until the passage is finished, because starting it would cost you the room to work in. So what becomes of those habits when the technology stops requiring them, and time simply doesn't stop?
2 Comments

Nessun Dorma

13/8/2026

5 Comments

 
Picture
​The last post said that before closing the Piece Window I'd go through the dozen or so tickets raised in passing, and that I was enjoying it enormously. The second half held. The first half was wrong about what the list was.

It looked like a collection of unrelated small wrongnesses. It was one thing wearing a dozen hats, and the thing is this: a program can fail without telling anyone.

When something goes wrong inside a running program, the fact of it has to travel somewhere: to a message, to a log file, or at minimum to a crash, which is unpleasant but honest. Sometimes it travels nowhere. A piece of the machinery quietly stops doing its job, nothing appears on screen, nothing is written down, and the program does less than it was asked. You find out weeks later, when a file you were sure you'd saved isn't there, and there's no record of why.

Ooloi had some of these. Not many, and that's the interesting part rather than a mitigation. There are 26,048 tests, nearly two lines of test code for every line of the program itself, and not one of them had found a single instance. They couldn't have. A test checks an outcome, and these failures produce no outcome: no wrong value, no crash, nothing different for the test to look at. The suite was thorough on everything within its reach, and this was the category outside it.

Most programs never go looking for that category at all, so I should be plain about it: what follows describes a standard very few applications are held to, including large and successful ones I use every day.

So I went looking. The question the work ended on concerns absence rather than discovery: can a single failure, anywhere, permanently switch off part of the running program? Every long-lived mechanism in Ooloi was examined individually against it. None can. Three could when the work began.

What a program is doing when it waits

Alongside that ran something subtler, and it's the finding I'd keep if I could keep only one. Nowhere in Ooloi, in the program or in the tests, does anything sleep for a moment and then look to see whether what it was waiting for has happened.

Developers will know what that sentence costs. Everyone else deserves to know why it matters.

Waiting is unavoidable in software: for a file to finish being written, for a window to appear, for another machine to answer. The question is how you learn that it's done. You can sleep briefly and check again, which is a guess wearing a wait's clothes, or you can arrange to be woken the instant it happens. The guess is very nearly always good enough, which is precisely why it's everywhere in this industry. Nothing goes wrong that anybody can observe, and the tests pass, because the thing does eventually happen.

Very nearly always. A sleep is calibrated on the machine it was written on, and it holds until that machine is slower, or busier, or the network hesitates. Then the program does things out of order, and the failure looks like nothing in particular. These are the bugs that can't be reproduced, that only ever happen on somebody else's computer, and that get closed as unrepeatable.

So every wait in Ooloi is now woken by the thing it's waiting for. Time limits survive as a backstop against something never happening at all, rather than as the means of noticing that it has.

The standard a run is now held to is that green means green: nothing in the log that nobody has accounted for, and no work quietly abandoned.

​Why this doesn't usually happen

Silent failure is invisible by definition, so it never reaches a roadmap; nobody has ever filed a ticket for a bug they couldn't observe. Meanwhile there's always a release date, always a feature promised this quarter, and this work has nothing to show on the day it's finished. It's the first thing cut and the last thing missed. Under those conditions the rational choice is to ship, every time, and the debt accrues to nobody in particular until it has accrued to everybody.

What's unusual about Ooloi's situation isn't method or talent; it's the absence of the pressure that normally forbids this work, and the presence of time. Time is the actual resource here, and I have it.

Two groups benefit. Musicians get a program that doesn't lose things quietly, which I'll come to. And anyone who works on Ooloi later inherits a codebase where a green run is evidence rather than reassurance. Every hour spent chasing a bug that won't reproduce is an hour not spent on beams and slurs, and the number of those hours is decided now, by whether the foundation admits that class of bug at all. Ooloi is open source and the whole development apparatus goes public with the source, so this is the one kind of generosity I can practise in advance, towards people I haven't met.

It also can't be added afterwards. Every feature built on a silent path inherits it, and once a hundred features have inherited it, the silence is load-bearing.

What it means if you use the program

​Very little of this is visible, which is the point of it.

When Ooloi fails, it tells you what failed rather than that something did. A save that doesn't happen names its reason: the file has moved since you last saved it, the folder isn't yours to write to, the disc refused the write. Not 'an unexpected error occurred', a sentence that's never helped anybody.

And underneath that, the property it rests on: no part of Ooloi can quietly stop working while the rest carries on looking normal. A window won't open blank and fill in only after you've closed and reopened it. A change won't fail to reach the other person in a session while your screen shows it went through. The bookkeeping that lets a piece be found again won't stop being written without a word.

For a program you sit inside for eight hours preparing a set of parts, that isn't tidiness. 'It didn't save' becomes an answerable question instead of a shrug. Notation work carries a low-grade anxiety about whether the tool is a reliable participant in what you're doing, and every engraver I know has built rituals against it: saving obsessively, keeping numbered copies, never entirely trusting a session. I'd like Ooloi not to need those rituals.

PictureIn da AI Lederhosn
​Oh, and I went to Austria for the first time in my life, for a wedding, and came home with my own origins sorted out. They'd always been fogged: Italian traces, German ones, Austrian, Czech, and no account of how any of them were supposed to fit together. It turns out that my mother's side is entirely Tyrolean, which explains ... everything. South Tyrol speaks German and belongs to Italy, the Habsburgs held Bohemia, and the borders moved rather more than the Dallabrida family did. Decades of vagueness resolved in an afternoon, down to my maternal grandfather's death at Verdun in 1944, at thirty-four. Surprisingly emotional, and so, unexpectedly, was the caraway in that Schweinsbraten. Childhood and present merged.

And Vienna was of course great. But no Alban Berg museum? Wirklich??

5 Comments

Delete These Five Staves?

1/8/2026

4 Comments

 
Picture
The Piece Window is essentially finished. What's left is bits and bobs: a set of rename tests, the shells of the layout windows (for now a title over an empty page, since the page has nothing to put on it yet), one drag-resolution routine that predates the shared one and hasn't been folded into it. Nothing on that list is interesting, which is the point of it being what's left.

It's been an intense stretch. The Piece Window is where the semantic model becomes operable: you create players, give them instruments, add staves, assemble scores and parts, decide who doubles on what. Doing all of that by gesture, with no modes and no dialogs, forced a distinction into the open. There are the things that contain the music, and there's the music itself. Membership, ordering, identity, naming, configuration: each of those announces itself the moment it changes, synchronously, as one event. The music says nothing directly and defers instead to the formatting pipeline. Two channels, and neither can express the other's business. That's now a property of the system rather than a habit of mine, and it emerged from building gestures rather than from contemplating architecture.

Work at that pitch leaves a wake. Over the past few weeks I've raised a dozen or so tickets in passing. None of them is urgent. All of them are real.

For readers who don't build software: the general term for this is technical debt. Some of it is debt in the strict sense, a shortcut taken to keep moving and whose cost doesn't disappear but is merely postponed, accruing interest, because by the time you come back other things have been built on top of it. The rest is small wrongnesses noticed in passing and not stopped for: cheap today, expensive later, and invisible until something else fails on account of them. A project that never pays it down eventually spends all its time servicing the debt rather than doing anything new. That is, in a sentence, the story of every notation program that has hit its ceiling. (Yes, Finale, I'm looking at you.)

So before I close the Piece Window I'm going through the list. And I'm enjoying it enormously, which brings me to Polish genitive plurals. (Major language nerd alert at this point.)

Ooloi ships in twenty-two locales (roughly: 'languages'), and the translation machinery is the industry-standard gettext, which handles counting properly. A message with a number in it declares a singular and a plural form, and each language declares how many forms it actually has and supplies a rule for choosing between them. English and Swedish have two, split at one. French and Brazilian Portuguese have two, but treat zero as singular. Czech has three. Polish and Ukrainian have three, on rules involving the last digit and the last two digits. Icelandic has two, with a rule that would look like a typo if you didn't know Icelandic.
Picture
​A single confirmation message, 'Delete this stave?' and 'Delete these %{n} staves?', turned out to be wrong in four of the twenty-two. The most instructive failures were in East Asia.
Picture
​Japanese, Korean and Chinese declare a single form. Their nouns aren't inflected for number, so a count has nothing to choose between, and whatever sits in the first slot is what every reader sees, for one stave and for fifty. Japanese and Chinese had a polite singular sitting there, so deleting five staves asked whether you wanted to delete this stave, and the count was silently dropped on the floor. The plural translation underneath was perfectly good and could never be selected by anything.

Korean had it right, and the fix was to follow Korean's lead: a single form that names the count, which reads correctly for one as well as for five, there being no separate singular for it to displace.
Picture
Polish and Ukrainian were subtler and needed a native ear rather than a rule table. Polish has three forms, and the third of them, which covers five staves and twenty-five but not twenty-two, takes the genitive plural; the demonstrative then has to agree with it, tych rather than te. Ukrainian had the two-to-four form carrying a genitive where it wants a nominative plural.
Picture
Picture
Picture
There's a reason I'm being this fussy about a dialog box. The people who'll maintain these files, and who I hope will add the languages I haven't got, are musicians and engravers rather than professional localisers. Someone who notices that Ooloi's Hungarian is stilted, or that nobody in Lisbon phrases it like that, should be able to open the file, find the string, and see straight away what's wrong and how to put it right, without knowing a line of Clojure. That puts a real obligation on the files themselves: correct plural counts, honest context labels, entries that read as language rather than as data.

It also means every existing entry is a worked example whether I intend it as one or not. Anyone adding Catalan or Turkish or Russian will copy the shape of what's already there, and a wrong shape propagates. A Japanese entry carrying a plural form that can never be selected quietly teaches the next contributor to write one too.

And because a translation that can't be selected is indistinguishable from a translation that doesn't exist, the fix comes with tests that resolve the actual message, in the actual locale, at a count that exercises the rule.
Picture
This sort of thing is a holiday after months of transaction boundaries, event coalescing and a deserialisation bug that turned out to hinge on a hyphen becoming an underscore in a compiled class name (a process tecchies call munging). Each item is small, bounded, verifiable, and improves something a real person will notice in their own language. I recommend it to anyone emerging from deep water.

When the list is empty, the Piece Window closes as a milestone in its own right: the semantic gestures are settled, and with them the vocabulary for manipulating a piece. Everything that follows is new operations through that vocabulary rather than a new way of working.

Things are moving quickly now. Touch wood.

After the Piece Window comes the plugin system and MusicXML, which is when the engine finally has real orchestral scores thrown at it in volume, by an importer written as an ordinary plugin against the public API with no privileges of its own. Then Skija, the rendering pipeline, and at long last the notes.

But first: the Swedish summer is glorious this year, unreasonably so, and I intend to spend a week or two of it nowhere near a computer. Some air, and then the page.
Picture
4 Comments

Doublings

25/7/2026

2 Comments

 
Picture
The above is the instrumentarium of Richard Strauss's Elektra, from the 1916 edition published by Adolph Fürstner. I took a photo from my score, which I got in 1979, a lifetime ago.
​
​It's in glorious 'Germtalian', typical of the time: an eclectic mixture of Italian, German, and a few bits of Latin thrown in for good measure. Nothing unusual, and contrabassi is still acceptable today, just meno corretto according to modern Italian dictionaries: the preferred spelling is contrabbassi. And nowadays, the Italians prefer controfagotto to contrafagotto. But 'secundi', on the other hand, is pure Latin and plain wrong. Whether this comes from Strauss himself or from his German publishers is difficult to determine. 

This demonstrates that correct and incorrect are the wrong axes for score conventions, which have deep cultural roots encompassing multiple truths simultaneously. All depending on the understanding of everybody involved, from composer to publisher to engraver.

And then there's of course the wholly absurd. Every musician is familiar with the term con sordini, with mutes. But when you see 'senza con sordini' in a score, you know you're dealing with an amateur, or at least with someone who's misunderstood something very basic. But the masters themselves are not exempt: I think it was Stockhausen who wrote So schnell wie möglich (as fast as possible) in a piano piece (possibly Klavierstück X) only to follow it by Noch schneller (even faster) a few bars later. Correctness in music is a many-faceted thing. Logic can be obscure, conventions are multi-dimensional and clearly overlap, and instructions can be psychological rather than factual, as in the Stockhausen example. All this must be embraced.

But I'm digressing, for the purpose of this post is to illustrate how musicians are numbered: first flute, second flute, and so on. That's one dimension. But then musicians can play more than one instrument: they have a primary instrument and then they double on one or more auxiliary instruments. That's the second dimension. And the numbers in one dimension don't map directly onto the other.
​
Look at the very first two lines. There's a dedicated piccolo player (ottavino) and then there are three normal flutes. Strauss numbers them Flute I, II, III. But then the first flautist also doubles on piccolo. The dedicated piccolo player is Ottavino I, and the first flautist doubles on Ottavino II. Two dimensions.

You see the same thing in several places: Oboe III doubles on Cor Anglais, which takes no number since there's only one. On the other hand, the four Wagner Tubas in B♭ and F double on French Horns V, VI, VII, and VIII.

All these things must be correctly numbered in the score and parts, whether you choose to use Arabic or Roman numerals. Strauss uses Roman numerals as was the custom at the time, but conventions varied and do so still.

This can be time-consuming and complicated to set up in traditional scorewriters and involve modes requiring you to do some parts of your setup in one tool and other parts in other tools or dialogs. Ooloi does it for you automatically while you drag and drop. The following video shows how, using the Piece Window.
For the technical specification, see ADR-0054: Automatic Semantic Naming and Numbering of Musicians and Instruments. It is written to be readable by musicians and engravers, not only by programmers.

It was designed and implemented in a single day. That's possible because the architecture underneath it was already there: immutable data, a transactional model, and a gesture layer that composes structural edits atomically.
Picture
It works in the other direction as well, of course
2 Comments

What Undo Remembers

21/7/2026

8 Comments

 
Picture
The anniversary post ended with a promise that the next stretch would be brighter. So here, by way of keeping it, is Verklärte Nacht.

What you're looking at is a string sextet set up in the Piece Window: two violins, two violas, two cellos, their names arriving in German from the Instrument Library, which carries its contents in many languages and supplies whatever the piece prefers. On the right, a score of six musicians and the individual parts. And above it all, the Edit menu is open, which is the actual subject of this post. Note that the undo and redo entries are named. 'Undo Change Reorder Instruments'. 'Redo Change Language filter'. The menu tells you what will happen before you press anything, and what it says is what occurs.

The Piece Window work continues, and as usual the work clarifies the road ahead. Building its full functionality meant implementing undo and redo for everything it does, and doing that forced a question into sharp focus: what, exactly, belongs in an undo chain?

The answer Ooloi gives is strict. An undo entry is a record that the piece changed, together with the means of restoring what it was. Nothing else qualifies. In particular, selections don't. Selecting a musician, a stave, a measure changes nothing about the piece; it changes something about you. A selection is a fact about a user, and it lives and dies with that user's session.

In a single-user program this distinction can be fudged, and the temptation to fudge it is real: selections feel like actions, actions feel undoable, and a naive implementation will happily record them. Collaboration removes the temptation by removing the ambiguity. In Ooloi, the undo history of a piece is shared, because the piece is shared. When you undo, you're operating on the same history I see, and the backend applies the reversal for both of us. Now imagine selections in that chain. Your Cmd+Z would unwind my mouse clicks. The history would silt up with everyone's browsing, and undoing one wrong note would mean stepping backwards through an afternoon of other people's attention. Nobody would design that on purpose. The multi-user case doesn't introduce a new rule; it makes the existing rule impossible to ignore.

And there is a recognisable failure mode on the other side of it. Record the non-events, and the chain grows long and cluttered; the honest remedy would be to stop recording them, but the tempting remedy is more interface: give the user a window onto the history itself, so they can survey the sediment and leap across it. When undo needs a map, something has gone wrong with the territory.

So Ooloi's chains stay short and truthful. Every entry is a real change to shared state, named and localised, and the same history is visible to every connected client. The host can undo a guest's edit; the reversal propagates back to the guest. That was the substance of the two-laptop proof in June, and the Piece Window has now inherited all of it.

Which brings me to the point of this progress report: with this work, the undo and redo machinery is complete across the entire application. The full design is recorded in ADR-0015, but the shape of it is simple. The backend keeps one coordinated history per shared resource, whether that's a piece or the Instrument Library. The frontend keeps a separate local history for what's genuinely local, such as appearance and panel arrangement, since your dark theme is no more a fact about the piece than your selection is. A single Cmd+Z serves both; a small router decides which history is current, and the menu always shows the answer before you commit to it.

It also holds for plugins, and this is worth dwelling on for a moment. A plugin modifies a piece through the same API as everything else, and the mutation registers its own undo step as it commits, described and localised like any native operation. Plugin authors write no undo code at all. They can't forget it, can't implement it inconsistently, and can't corrupt the shared history, because there's no surface through which any of that could be expressed. This is the house method applied once more: the wrong thing isn't forbidden, it's inexpressible.

As for the sextet on screen: two people walk through a cold night, something difficult is said plainly, and the music ends warmer than it began. As a description of implementing undo in a collaborative system, that will do.
8 Comments

Rembrandt and Workshop

16/7/2026

0 Comments

 
Picture
​People occasionally ask how one person builds something this size. The honest answer involves an AI, and since honesty is the whole method here, it's worth describing how that actually works. The reality is less glamorous and more interesting than either the sceptics or the enthusiasts imagine.

Ooloi is developed with Claude Code as the primary implementor. It writes a great deal of the code and most of the tests. What it doesn't do is decide anything. Every architectural decision lives in an ADR before implementation begins; the ADRs function as binding specifications, and the AI works inside them. Development proceeds test-first, consultationally: we discuss what a subsystem must do, the semantics get pinned down, the tests get written, and only then does implementation start. No code is committed unless something was broken, then fixed, and the full suite has returned to green.
PictureAn executive vibe coder in AI Wonderland
None of this resembles what's lately been called vibe coding. I read and assess every line the AI produces, and a fair amount of it gets sent back. Where my time actually goes may surprise people: most of it is spent designing architecture and tests. That is still authoring the code; it's authorship conducted at another level, and with full control. The expensive work is deciding what a subsystem means, what its boundaries are, and what a test must pin down before implementation is allowed to exist. Once that's settled, the implementation is close to determined, whoever or whatever types it in. The proportions of the codebase reflect this: there's considerably more test code than production code, roughly 1.8 to 1, and coverage is greater than 96.5 per cent.

Those constraints are served mechanically. The Librarian, the RAG system that answers questions on the Documentation page, has a second life: it runs as an MCP server during development, giving Claude Code live access to the entire documentation corpus. When the AI needs to know how the timewalker treats grace notes at a measure boundary, or what the plugin boundary permits, it queries the Librarian and receives the relevant ADRs and guides as authoritative context. The same corpus that explains Ooloi to you constrains the AI that builds it.

This has a consequence I didn't fully anticipate: the documentation stays true because it has to. If an ADR is wrong or stale, development goes wrong quickly, and the error surfaces as failing tests or incoherent code. Documentation that governs the implementor can't quietly drift from the implementation. What you read on this site is the operating specification of the running system, kept honest by daily use.

There's a question people are too polite to ask directly: if an AI writes the code, whose work is this? Museums have quietly answered a version of it. Paintings once attributed to Rembrandt alone now carry labels reading 'Rembrandt and workshop', and the label is honest about how such workshops functioned: a workshop hand paints the drapery, the background, the apples in the still life, so the master can concentrate on what needs him. Nobody concludes from this that the disciple composed the picture, and nobody asks whether the master painted it or merely supervised the vibes. He painted it. He could have painted the apples too; it would simply have taken longer. The AI is the disciple here, and the apples are very well painted. The composition, the light, and the decisions about what the painting is remain where they always were.

The apparatus makes this verifiable rather than merely claimed. The instructions, prompts, and skills the AI operates under show exactly what it was given, and by extension what it wasn't. Anyone reading them can see where the authorship sits: in the ADRs, the semantic decisions, the test specifications, the boundaries. The AI implements a design it had no hand in choosing. I'd rather demonstrate that than assert it.

Which brings me to the point of this post. When the source is released, the whole apparatus goes with it. The Claude Code instructions, the prompt files, the skills, the MCP configuration, the tooling that builds the Librarian's corpus: all of it, unsanitised, part of the repository like everything else. Anyone who clones Ooloi can work on it with the same assistance I have, constrained by the same documents, checked by the same tests. There's no private layer where the real knowledge lives.

The reasoning is the same as it's always been. The ADRs externalise why decisions were made. The guides externalise how the systems work. The blog externalises when and in what order. The collaboration itself was the one remaining dimension that existed only on my machine, and I see no reason it should. A project whose development method is reproducible by a stranger is a different kind of open than one that merely publishes its source.

I've watched a notation program die because everything that mattered about it lived in people's heads, and when the people were scattered, the program was over regardless of who owned the code. Every structural choice in Ooloi is a refusal to repeat that. The documentation, the tests, the Librarian, and now the development apparatus itself all point the same way: anyone with the repository has everything, including the means by which it was made.

Ooloi is not designed around my presence, but around my absence.

0 Comments

AI Kitsch

13/7/2026

0 Comments

 
Picture
Every so often I ask a language model to paint. Not a diagram, not a chart, but a picture of what it's like to work on Ooloi, and I ask for it in a particular register: chiaroscuro, with anachronisms. I use the style deliberately. Music engraving is an old art, with five centuries of accumulated craft governing where a mark sits on a stave, and the joke of the modern hardware bolted into a candlelit cathedral is there to say that the roots are ancient but the foundation underneath is very much of now. Perhaps because of the roots rather than despite them.

The most recent one is genuinely 'beautiful', and it's also, unmistakably, made by a machine. I like that about it. The visible artifice is what makes the grandiosity sayable. The gears don't quite mesh, the code on the screens is decorative nonsense, the glowing sigil on the table is confabulated arcana that means nothing. The surface announces that a machine dreamed this up in thirty seconds and that the halo isn't to be taken at face value. The tell is the wink, and the wink is what lets me keep the picture.

Because the picture is, let's be honest, absurdly grand. I'm standing in a vaulted architect's workshop the size of a nave, holding up a sheet of notation to a younger man across a worktable, explaining something with an open-handed gesture, while a shaft of holy light comes down through the high windows. The props are wrong for any real workshop and exactly right for ... Hogwarts. This is the wizard's study, the archetype at full saturation. Gandalf, Dumbledore, Hari Seldon and Gaudí, and I'll take Gaudí, since the Sagrada Família (a monstrosity which I loathe) is the one reference on that list that isn't a joke: a cathedral built to a plan meant to outlast its architect, and which duly did.

I commissioned the image to show something specific: a stranger walking into my workshop and talking to me as an equal. That's how the blog comments work, more or less. Someone I've never met arrives, we stand across the same table at the same height, and we talk about the work. No lectern. The door is open to anyone who wants to talk about the thing itself.

And then, a while after I had the picture, it occurred to me that the visitor isn't a stranger at all.

Look again at the second figure. Younger, dark-robed, hands loosely clasped, listening while I hold up a sheet and explain it. I had read him as some human collaborator. But he isn't. He's Claude Code. And once you see it, nothing in the composition is generic any more. The equal height, the stillness of the hands, the receiving rather than reaching: that's the working relationship, exactly as it runs. The picture had it right before I noticed.

Which is the part that actually interests me, past the flattery. I asked a machine to depict what the work feels like, and without being told to, it put its own collaborator in the second chair, in the correct posture, at the correct height.

What the picture doesn't show is that Claude is also, at times, completely bonkers. You'll suddenly find it dancing naked in the crypt just because it felt like it. (I asked the AI to create a picture of Claude dancing naked in that crypt, but the AI of course respectfully – and moralistically – declined.)

So: AI kitsch. Beautiful and fake, grand and winking, sincere in its craft and ironic in its claim, and 'painted' by the very collaborator it turns out to depict. I find I can live with all of that at once. It seems the honest picture of how the work is actually made.

And I like the robes! I've spent a lot of time in robes, so they're not a lie.
0 Comments

My Life Right Now

13/7/2026

6 Comments

 
Picture
What you're looking at is a test. It sets up a Full Score with two players, Violin I and Viola, then deletes Violin I from inside that score, and checks that Violin I is gone from the score but still present in the piece. That distinction, remove from this layout versus remove from the piece, is one of the many things the Piece Window has to get exactly right.
​

The whole idea is to let the engraver set up and manipulate scores and parts with intuitive gestures alone. No modes. No dialog boxes. And every change propagates to collaborators as it happens.
6 Comments

Taking Stock at Two Years

9/7/2026

2 Comments

 
Creating a wind quintet with score and parts in Ooloi.
​Then adding doublings. No dialogs.

Two years ago today, on 9 July 2024, the first commit to Ooloi went in. Time to take stock.

There's no music on screen. Two years in, and still not one printed note. No noteheads. No beams. No slurs. No page of music. All true, all planned, and all completely beside the point.

Why? A notehead drawn in the first year would've been a comfort object, not evidence. So the visible surface stayed sparse on purpose while the real work went on underneath it. The absence of staves was never the interesting fact about this project. It was the cost of getting the interesting facts right, and this anniversary is the point at which they start becoming visible.

This isn't an eccentric way to build notation software. It's how the serious ones are built, and the record is consistent. Sibelius took its two founders about seven years before the first release in 1993. MuseScore was carved out of a sequencer in 2002 and did not reach a stable 1.0 until 2011. Dorico, built by most of the old Sibelius team after they were let go, took close to four years and shipped its first version deliberately slow and incomplete, engine and engraving model first; the field judged the decision sound. Three programs, three decades, open source and commercial alike, and in every case the foundational years came before anything a user would recognise as finished.

The counter-example proves the same point from the other side. Finale shipped fast in 1988, did more than anything before it, and became the industry standard for a generation. It was also, by wide agreement, punishing to use, and when its owners finally discontinued it in 2024 they said plainly that decades of accumulated code had made each new version harder to deliver and worth less. Feature piled on feature until the architecture could no longer move. That's the ceiling a notation program hits when the surface is built before the foundations are right.

Two years isn't a long time to spend getting the foundations of a fifty-year program right, and I've never regarded it as a delay.

Now, the bet on which Ooloi is built is functional programming. Music notation is a genuinely hard computer science problem wearing a friendly costume, and Clojure's properties looked to me like the right machinery for the parts of it that commercial programs have learned to manage rather than solve. Ooloi is my first Clojure project, though not my first Lisp by a long way, so the syntax was familiar ground; an old hand picks up a new dialect quickly.

The deeper reorientation was immutability. Fully embracing immutable data structures, rather than merely tolerating them, changed how I thought about the whole domain, and almost everything architecturally distinctive about Ooloi fell out of that one shift. Undo, collaboration across machines, full use of multi-core parallelism, pervasive structural sharing: none of these is a feature bolted onto mutable objects. Each is a consequence of representing musical facts as immutable values. Learning to think that way was the real work of the first stretch.

The harder part was psychological. A screenshot of notation would've been reassuring, and I could've produced something theatrical early on if theatre had been the goal. I grew up around theatre. I know a backdrop when I see one. I also know there's never a wall behind it.

So the project spent a long time with most of its real work below the surface. The documentation was public, the ADRs were public, the blog was public, but the evidence still required reading. And the focus on the yet invisible might have given the impression that progress had been slow. So I drew up a list of what's been completed over the past two years.

I expected it to be useful. I did not expect it to be quite so long.

That surprised me, which is perhaps the point of doing the accounting at all. Daily work doesn't feel like accumulation. It feels like the next ticket, the next invariant, the next small refusal to leave a problem in a shape that'll charge interest later. Only when the pieces sit next to each other does the scale become visible:
​​
  • Core musical model: Pieces, musicians, instruments, staves, measures, voices, rhythmic items, attachments, traits, hierarchy, and the basic vocabulary for representing musical facts.
  • VPD addressing: Vector path descriptors, giving operations precise structural addresses inside a piece.
  • STM coordination: Transactional backend state, with Clojure STM used as the coordination model for musical mutation.
  • Timewalking: Temporal traversal of nested score structure, including the transducer-based breakthrough that made the score streamable in musical order.
  • Pitch representation: Exact spelling, rational arithmetic, transposition machinery, and round-trip integrity.
  • Time signatures: Ordinary, additive, mixed-unit, fractional, irrational, historical, and descriptor-preserving signatures.
  • Key signatures: Standard modes, keyless notation, custom signatures, per-octave variants, and microtonal systems.
  • Remembered alterations: Deterministic accidental handling built on pitch, time, key context, and traversal.
  • Measure distribution: Formal specification of measure distribution as a Knuth-Plass-style optimisation problem.
  • Persistence and compression: Serialisation, structural sharing, hash-consing, and the 50,000-note compression test.
  • gRPC API: Generated method exposure, Protocol Buffers conversion, streaming, bounded queues, events, and the unified value transport.
  • Server statistics: HTTP metrics, health endpoints, and the monitoring machinery used to validate server behaviour. Grafana and Prometheus support.
  • TLS and transport hardening: Secure transport foundations, connection handling, shutdown correctness, friendlier errors, and combined-app collaboration TLS.
  • Reference-passing transport: Near-zero-overhead in-process calls by removing the Clojure-to-protobuf conversion path inside the desktop app.
  • Integrant system architecture: Component lifecycle, dependency wiring, startup, shutdown, and the shared/backend/frontend division.
  • Frontend event architecture: Event bus, backend event router, category batching, wildcard subscription, invalidation routing, and JavaFX-thread discipline.
  • Backend-authoritative rendering design: Terminal frontend execution, paintlist boundary, cache hierarchy, and backend ownership of musical layout decisions.
  • Localisation: PO-file workflow, strict translation-key discipline, canonical UK English, runtime locale switching, build-time checks, and 22 bundled locales: Czech, Danish, German, Greek, UK English, US English, Spanish, Finnish, French, Hungarian, Icelandic, Italian, Japanese, Korean, Norwegian Bokmål, Dutch, Polish, Brazilian Portuguese, European Portuguese, Swedish, Ukrainian, and Simplified Chinese.
  • Frontend settings: Persistent application settings, registry-driven defaults, validation, generated Settings window, and reactive updates.
  • Window lifecycle: Declarative window opening, persistent geometry, fade behaviour, modal gating, and centralised stage management.
  • UI styling: Semantic styles, no hardcoded colour seepage, custom cljfx components, and Java interop confined to boundary files.
  • Notifications and chrome: Splash screen, platform menus, notification overlay, menu-bar host, About window, settings UI, and orderly shutdown.
  • Frontend undo and redo: Local undo history for application settings, integrated into the same menu surface as backend undo.
  • Backend undo and redo: Resource-level undo manager, coordinated history, localised descriptions, frontend routing, clock-offset adjustment, and cross-client undo.
  • Instrument Library: Real instrument and staff records, editing, validation, persistence, conflict retry, drag-and-drop, deletion tombstones, ordering, multilingual contents, and a complete populated default library.
  • Font management: Bundled SMuFL fonts, associated text fonts, font registry, and glyph-selection architecture.
  • Transaction-driven distributed updates: The whole update model. A change is a transaction against authoritative backend state; committing it names what's now stale, and every subscribed client, on the same machine or across the network, refetches the canonical structure and replaces its view. No deltas, no merge logic, no distributed-specific code paths. Collaboration is not a separate engine; it falls out of this for free.
  • ​Collaboration architecture: Dual-server model, local and network transports sharing backend state, frontend transport switching, host and guest roles, connection UI, and shared resource editing.
  • Two-laptop proof: Guest edit, host observation, host undo of the guest's change, propagation back to the guest; and, at the two-year mark, musicians created and rearranged in a shared piece window on one machine and appearing on another.
  • Post-demo hardening: Collaboration menu enablement, backend-switch undo-cache invalidation, standalone backend wiring, collaboration palette behaviour, anchor-first selection, modal menu gating, TLS routing, friendly errors, and headless test mode.
  • Platform support: macOS Apple Silicon, Windows x86_64, Linux x86_64, native bundles, Windows application build, and an explicit platform policy.
  • Documentation: ADRs, guides, development log, reading path, and Librarian, built as part of the system's survival machinery.
  • Test infrastructure: Shared, backend, and frontend tests, now around 24,400 passing cases.
  • Piece Window: Structural entity identity and cloning, opaque backend filesystem navigation, a component-owned piece-manager store, a custom Open/Save picker that never sees paths, a complete piece file menu (New, Open, Save, Save As, Close) with typed and translated failure messages, transport-blind file commands that work unchanged in a collaboration, deterministic backend close-on-last-release, and a piece window that's now a live view of authoritative backend state, updating across every subscribed client on any structural change.

During daily work, a subsystem closes and vanishes from attention. That's partly the method: finish something completely enough that it stops sharing the desk. The Instrument Library no longer asks to be designed. Localisation no longer asks to be invented, and the interface already speaks twenty-two locales. Undo no longer waits behind every future feature (with a small knife). Transport no longer converts itself through protobuf in-process for no reason. Window lifecycle no longer belongs to individual windows. Each closed subsystem removes one more thing from the cognitive field.

The list makes visible what the surface hid. Ooloi hasn't spent two years waiting to become a notation program. It's spent two years removing the taxes a notation program would otherwise pay forever.

This is also where the unusual working conditions matter. I've been ... unburdened by people. That sounds harsher than I mean it, though perhaps not by much. Not unburdened by readers, musicians, criticism or conversation, which have all mattered, but by the organisational forms that force software to explain itself before it has finished thinking. No investors, no release calendar, no committee, no inherited user base demanding that a workaround stay sacred because muscle memory has mistaken it for design.

A team would have made some things faster and some things impossible, or at least premature. There's a stage in a project like this where the architecture has to be held whole in one mind, not because one mind is superior to several, but because dividing the thing too early changes the thing. Ooloi needed a period before that could happen.

That period has had its own cost. Solitude removes obstruction, but it also removes alibis. Every accepted decision is mine. Every inconsistency in the documents is mine to catch. Every time Claude Code proposes a convenient shortcut, I have to know whether it's harmless, local, or the kind of thing that looks harmless now and grows teeth later. There's no one else to blame, which is excellent architecture and poor comfort.

The AI has made the solitude more productive, though only because the architecture constrains it. Claude works best as an implementor inside settled boundaries. Give it one subsystem, clear invariants, failing tests, and a narrow target, and it moves with astonishing speed. Ask it to hold the whole system in its head at once, and it becomes what all of us become under those conditions: less intelligent than advertised. Every subsystem sealed below the musical floor is one fewer thing it has to juggle when the visible engraving work begins.

That's another reason the long groundwork was worth doing. The cleared desk isn't a metaphor I use lightly. It's how the next phase becomes possible.

The 3 June proof mattered because it compressed much of this into one modest action. Two laptops. One Ooloi hosting, one connected. A flute name changed on the guest, visible on the host. Undo on the host, reverting the guest's edit. The revert appearing on the guest.

As cinema, it will not trouble Bergman. As architecture, it was the exact kind of evidence I had been waiting for.

That little proof did not show engraving, and it did not pretend to. It showed authority, transport, shared state, invalidation, fetch, undo routing, and cross-machine propagation acting together without ceremony. Nearly two years of decisions appeared as a small correction to the name of a flute. Software milestones are sometimes like that: not fireworks, just a door opening without sticking because someone spent a very long time caring about the hinge.

Now the work is moving towards the page.

The custom picker is already visible and operable. It's not a native file chooser with new paint. It asks the backend what exists, receives opaque tokens, and never sees paths. Local storage and remote storage go through the same contract. The boring dialog is already the front edge of the piece model.

Behind it, the piece window is now a live view of authoritative backend state, and this anniversary comes with a second small proof to show it. The video accompanying this post was recorded on two machines. On one, a wind quintet is assembled in a handful of gestures: flute, oboe, clarinet, horn, and bassoon dragged out of the Instrument Library into the Musicians panel of a shared piece window, each becoming a musician with its staves beneath it, and then dragged across into the Layouts panel to define the full score and the five individual parts. On the other machine, the same piece window answers. No delta is sent between them: a structural change names what is now stale, and the other screen refetches the canonical structure and redraws.

It's the 3 June proof one storey higher. In June a flute changed its name and the plumbing held; here the same architecture carries piece structure rather than a library entry, edited collaboratively, with the invalidate–fetch–replace model the Instrument Library established generalising to the piece itself unchanged. And it's still, deliberately, not engraving. What crosses the wire and appears on the second screen is musical structure, not a rendered stave. There's no notehead in the video. The machinery that'll carry the music is running, and running across two machines, before the music arrives.

Next come piece preferences and window persistence, the rest of the Piece Window arc. After that, MusicXML, because real scores must drive real notation work. Then Skija and the rendering pipeline. Then the noteheads: spacing, stems, flags, dots, accidentals, voices, collisions, beams, ties, slurs, hairpins, lyrics, pedalling, ottavas, tuplets, and the geometry of the page.

The evidence will change again at that point. The collaboration you can already see in the video will still be there, but it'll be moving notation rather than structure. A slur will find space. A beam will sit, straddle, or hang. A note in a chord will change geometry around it. One screen will alter shared musical notation and another will answer with the same page. The program will make the argument in engraving, not only in structure.

I'm looking forward to that more than I can sensibly say.

Two years in, the thing that surprises me isn't that there's still no music on screen. I expected that. The noteheads were never beside the point as a goal, only as evidence; a program isn't proved by what it can draw first. The surprise is how much of the project is already behind the moment when music appears. The empty stave, seen from the surface, suggests absence. The inventory tells a different story: a great deal has already been decided, tested, closed, and made boring.

Boring is underrated. Boring is what a foundation becomes when it's doing its job.
​​
So, coming out from the darkness that never really was, the next part will be visibly brighter, and with any luck it will involve fewer ... certificate files.
2 Comments

Piece Window ADR

7/7/2026

2 Comments

 
Picture
Two days from now it'll be two years since the first Ooloi commit. I've been working on the Piece Window, which is where a piece becomes visible and where you shape it: setting it up, creating scores and parts, and much more besides. It's a rich window, rich enough to do away with the modes and dialogs other programs need for this kind of work. And somewhere in the middle of building it, I noticed the thing had no documentation of its own. It was scattered across fourteen ADRs.

No more. Here's the fifty-fourth architectural decision record for Ooloi: ADR 0053: Piece Window and Piece Preferences.

See you on Thursday. There should be a video by then, too.

2 Comments

Getting There...

23/6/2026

5 Comments

 
Picture
This is the door handle the previous blog post was talking about. There remain a few more bells and whistles to add to it, like favourites and a directory navigation dropdown, but this perfectly boring dialog handles a lot of complexity under the hood, so the user doesn't have to.

Oh, and the .ooloi files are empty – I haven't secretly imported huge scores without telling anyone. No, that happens after the Piece Window, up next, and after the first version of the MusicXML Import plugin, the first canonical one, is implemented. Then the engine will be bombarded with large amounts of musical data, to drive the implementation of real-world engraving.
5 Comments

All the World's a Database

13/6/2026

4 Comments

 
Picture
​You go to open a piece. You reach for the menu, you pick 'Open', and a dialog appears showing you what's there. Nothing could be more ordinary. Every program you've ever used does some version of this, and you've stopped seeing it, the way you've stopped seeing door handles.

Except this isn't the dialog your operating system would have given you. It looks close enough that most people will never notice the difference, and that's rather the point. The most boring dialog in the application is where everything is already different.

Here's what's different. When you open a piece in Ooloi, even on your own computer, you're not looking at your folders the way Finder or Explorer would show them. You're looking at what Ooloi's engine tells you is there. The dialog asks the engine a single question, 'what's here?', and draws the answer. It never asks the operating system directly. On your own machine the distinction is so thin you'd be forgiven for missing it: the list looks like your disk because, for now, it more or less is your disk. But the habit is already broken. The application has stopped treating files-in-folders as the truth and started treating them as one possible answer to a question it asks somebody else.

A Piece is More than a File

​Begin with what a piece actually is, because the dialog only makes sense once that's clear.

In most software a document is a file: a thing that lives at a location, that you save, that you can lose track of, that acquires a '(1)' after its name when the operating system panics about two things sharing a label. You hunt for it. You remember where you put it. You worry, mildly and constantly, about whether the version on the desktop is newer than the one in the folder you can't quite recall the name of.

A piece in Ooloi is also a file, but that file's location isn't the important thing. The piece is a database with a permanent identity of its own, one that has nothing to do with where it happens to sit. You needn't think about saving it unless you want to; leave autosave on and the question never arises. You don't find it by remembering a filename and a folder. You find it by its name, by where it sits in your recent work, by searching for it.

If that feels familiar, it should. It's how you normally work with files in a single-user application.

Same Dialog, Different Worlds

​Now the part that matters most, and the reason any of this is worth a blog post rather than a footnote.

Connect your Ooloi to another one, a school's server, a publisher's, or simply a colleague's machine across the room, and open that same dialog. The menu command is the same. The window looks the same. But what it shows you is no longer a polite version of a disk. It's an entirely abstract view of what's available to you, and only to you.

This is the feeling of working in Google Docs, where you've long since stopped wondering which folder a document is 'in', brought to musical scores. The piece is simply there for you to access, and the question of its location has quietly ceased to matter.


You don't see the remote machine's folders. You never see them. You see the pieces you're allowed to reach, and nothing else. The person who owns that Ooloi sees their own files when they open the dialog on their end; you, connected from outside, see your slice of what they've chosen to share. Same server, same dialog, two completely different worlds, because the world each of you sees is the one you're entitled to.

This is worth dwelling on, because it's a privacy wall dressed as a convenience. Connecting to someone's Ooloi never lets you rummage around their computer. There's no path by which reaching their scores becomes reaching their disk, their documents, their photographs, the half-finished letter on their desktop. The dialog can't show you those things because it was never asking the operating system in the first place; it was asking Ooloi, and Ooloi only ever answers with what's yours to see. The boundary isn't a setting that can be left switched off by mistake. It's the shape of the thing.

The Database is Really a Graph

​Once other people are involved, the picture grows a dimension.

What you're looking at, when you open that dialog against a shared Ooloi, is your corner of something larger: pieces on one side, people on the other, and between them the question of what each person may do with each piece. Read it. Print it. Edit it. Delete it. Different answers for different people, all hanging off the piece's permanent identity, which is the one thing that never changes no matter who's looking or from where. Pieces and people for the points, permissions for the lines between them: that's a graph, in the mathematician's plain sense, and your dialog is a view into one small region of it.

A web, if you'd rather not think in mathematics, and your part of it is 'Shared with me', for scores. A conservatory running a server for two hundred students is the same idea at a larger scale; a publisher coordinating a dozen editors across a catalogue is the same idea again, larger still. None of it is a central cloud, some single machine in the sky holding everything. It's many Ooloi backends, each holding its own pieces, stitched together by the fact that every piece carries an identity that means the same thing everywhere. Your view across all of it is assembled from whatever each backend is willing to show you.

Why it Isn't a Gimmick

It would be easy to read all this as cleverness for its own sake, a notation program being contrary about file dialogs to seem distinctive. It isn't. It falls out of two decisions that were made long before anyone could collaborate at all, and that turn out to be the same decision wearing two faces.

The first: a piece's identity belongs to the piece, not to its location. Once that's true, location stops being something you manage and becomes something the system can keep entirely to itself. The whole world of pieces becomes a thing you query rather than a set of places you navigate.

The second: the part of Ooloi you see and touch never reaches the disk itself. It always asks the engine, and the engine is the single authority on what exists and who may have it. That sounds like a technical nicety until you notice it's exactly what makes the privacy wall real. The screen can't leak the disk because the screen was never allowed near the disk.

I'd like to claim I designed it this way on purpose. The truer version is that collaboration came along and showed me the architecture had already committed to all of it, whether I'd meant it to or not. The single-user case, you working alone on your own laptop, turned out to be the smallest possible version of the shared one: a group of one, asking the same questions, getting answers about the same database, through the same unremarkable dialog.

Which is where we started. That dull little window you reach for without thinking, the one that looks like every Open dialog you've ever seen, is the whole worldview in miniature. It treats your work as something with an identity rather than an address; it shows each person only their own slice of a shared world; and it does both by the simple discipline of never looking at the disk itself, only ever asking what's there.

The most boring dialog in the application. Look at it closely, and there's nothing boring about it at all.
4 Comments

Time and Motion Studies

11/6/2026

2 Comments

 
Picture
Three days ago I posted the road map: everything left before the real visible work begins, and the claim that it was all plumbing. Here's the receipt. Since then, six tickets have closed.

The pattern across them is worth recording. Each was scoped narrowly, and each widened into something general before it closed. This is not scope creep; it's the opposite. The cost of doing the general thing sits close to the cost of the specific thing, so doing it once removes the work from everything downstream rather than leaving it to recur. Two of them shed precise new tickets as they widened, work that wasn't on the list a week ago and is now defined and waiting.

I've seen this before, lower down. It's what the engine did during the validation phase, when problems the industry handles with heuristics collapsed into deterministic solutions because the foundations were right. Correct foundations make the general case cheap. What I'm watching now is the same effect one floor up, in the application layer rather than the engine.

I didn't realise how much I'm looking forward to dealing with musical structures again, after this unsexy networking and certificate tedium. But the Piece Window is next, and that's true musical work. I'm looking forward to it tremendously.

2 Comments

Detail: the Collaboration Indicator

8/6/2026

3 Comments

 
Picture
Today's work: the floating indicator shown on screen when connected to another Ooloi, or to an Ooloi server.

It pulses in a muted green during the connection, then fades out. No sharp edges; more organic.

Nominally perhaps thanks to Octavia Butler, but primarily because I think a good user interface should recede into the background.

​<mp> rather than ffffz. I think you know.

3 Comments

Updated Road Map: Final Groundwork Before the Notes

8/6/2026

0 Comments

 
Ooloi is now a real, configurable desktop application with a solid collaborative backbone. The engine underneath is finished and waiting, and the obvious question is why I'm spending my days on things like palette positioning and collaboration features at this stage? From the outside it must look as though I'm finding ever more inventive ways to avoid the thing I actually built Ooloi to do.

'You might very well think that; I couldn't possibly comment', said Ian Richardson as Francis Urquhart in the original British House of Cards, and got away with it for three series. However, I can comment, which is why this article exists.

Here's the list of what's left before the first notehead. Read it and you'll see exactly what I mean: it's plumbing, every line of it.
Picture
That very last line, the hierarchical rendering pipeline, is where the real fun begins.

The reason for this depth-first approach is cognitive load, and not only mine.

I'm a one-man show at this stage. There's no team to hand the networking to while I get on with beams, no colleague maturing the collaboration layer in a separate room so that the two halves can meet in the middle later. Everything that gets built passes through one head, sequentially. A team would parallelise this, several subsystems moving at once, and pay the coordination cost that always comes with it. I can't do that, so I do the opposite: I finish things, completely, one at a time, and then I never think about them again.

That sounds like a constraint, and it is, but it's also the whole advantage. Collaboration permissions, user management, the connect dialog, the way a window restores its geometry and z-order, the failure mode of a broken file of interface translations: get every one of those right now, while they're the only thing in front of me, and they drop out of consideration permanently. Not deferred. Not mostly working. Gone from the daily ledger. When the day I've been waiting two years for finally arrives and I start pushing noteheads and flags and stems across the stave, none of this will be sharing the desk with me.

This is the part commercial development almost never gets to enjoy. There's always a release on the calendar, always a reason to bolt the networking on later, always a feature that ships first and a foundation that gets retrofitted underneath it once the cracks show. I watched exactly that kill Igor. I have no calendar, no investors, no quarter to make, and so I can afford the one thing money usually can't buy: doing the boring parts once, properly, before they can metastasise into a tax I'd pay on every musical feature for the rest of the project's life. And, since the plugin API is stable from day one, every contributor inherits that same cleared desk. The tax I'm refusing to pay is one I'm also refusing to pass on.

The other reason is the AI, and it matters as much as anything I've said.

I do most of the implementation with Claude Code, currently Opus 4.8 on high effort as my default, and on max effort for the deep work inside the engine, where the concurrency and traversal machinery doesn't forgive a half-attentive collaborator. I also keep ChatGPT, Gemini and Grok to hand for second opinions, Grok very reluctantly, given Musk's political clownery. Microsoft Copilot I leave alone entirely; it's an insult to everyone's intelligence.

​Claude works inside the proved architecture, as a constrained implementor rather than an architect. That arrangement works far better when the thing being implemented is the only thing in the room. An AI asked to draw a slur while also worrying about whether the translation cache is stale, whether the transport is encrypted, whether the selection anchor survives a shift-click on an unordered set, does all of it worse. Restricting what it has to hold in mind at once isn't a nicety; it's the central discipline of getting useful work out of these tools. Every subsystem I seal below the musical floor is one fewer thing the AI has to juggle when the real work starts. The cleared desk is for both of us.

So the sequence in that image isn't avoidance. It's the last of the groundwork, arranged so that when the notes finally come, they come into a space that's been swept completely clean. Networking, I'll be glad to see the back of (did I mention how tedious I find networking?). But there's a particular satisfaction in knowing this is the last time I'll have to look at it.
​
Then, at last, the thing I too have long been waiting for: the music.
Picture
'I couldn't possibly comment'
0 Comments

It Works, Dammit

3/6/2026

3 Comments

 
This is just a quick post documenting that the multi-user setup works, including Undo across users. This will have to be documented properly in a better video: this is just me with two laptops on my lap – but after almost two years of careful planning Ooloi is now exactly where planned.

​This little auteur subjective camera exercise demonstrates the following:
​
  1. One Ooloi is hosting a collaboration session (the one to the right, the 2017 Intel dinosaur), the other one, a 2023 M3, has connected to it on my local network.
  2. The Instrument Library has the networked symbol before its name, showing it's a shared resource.
  3. I update the name of the flute on the connected Ooloi.
  4. It updates on the hosting Ooloi.
  5. I use Undo on the hosting Ooloi to change the name back. Note that the Undo here is on the host, reverting the guest's change.
  6. The flute reverts to its original name on both Ooloi.

I could write a long post about this being a very real milestone and what its implications are, and I will, and with a better video. But this needed documenting now. 
3 Comments

So, Is This Research? I Think Not.

30/5/2026

1 Comment

 
Picture
Every so often a category problem appears around Ooloi.

If this is not a product blog, what is it? If it refuses the usual commercial language, is it research? If it's full of architectural detail, references to old engraving books, implementation notes, screenshots, AI, undo, Wagner tubas, and the occasional indecorous joke, what sort of thing is the reader supposed to be looking at?

A fair question, and a revealing one.

The short answer is no. This is not research.

It's also not a product blog in the ordinary sense, which may be the first difficulty, because almost every software blog now behaves like a shop window. Some are tasteful shop windows, some are vulgar ones, some are dressed up as engineering diaries, but the function is the same. Reassure the prospective customer. Show momentum. Convert attention into confidence. Keep the voice steady. Make every feature sound like a benefit. Don't frighten the horses.

Hence the language:
  • 'We're delighted to announce…'
  • 'Our users asked, so we listened…'
  • 'Seamless workflows…'
  • 'Unlock your creativity…'
  • 'Built to empower today's creators…'

Not here.

This blog will never say 'we're delighted to announce', partly because there's no 'we' in that sense, partly because delight is not the usual emotion when a difficult subsystem finally works (relief is closer, occasionally suspicion), and partly because the phrase belongs to a kind of speech that falsifies the relation between builder, work, and reader. It isn't only ugly. It's structurally dishonest.

The Ooloi blog is not entertainment for prospective customers. It isn't written to keep readers engaged. It's not a funnel, a campaign, a launch surface, or a series of carefully portioned confidence pellets. If five consecutive posts need to be about undo, Ross, collaboration state, platform policy, and the historical notation of Wagner tubas, then that's what the blog will contain. The work determines the record, not the imagined patience of a marketing segment.

That does make the blog unusual, and harder to read for anyone trained by product communication to expect a certain grammar: progress as reassurance, difficulty as opportunity, compromise as wisdom, and every strange technical decision translated into customer benefit before it's allowed to appear in public.

Ooloi doesn't do that. It says what happened, why it mattered, what broke, what changed order, what turned out harder than expected, and what the architecture now makes possible. The development log keeps the same discipline in another form: completion dates, settled facts, architectural invariants, and the sequence by which the work revealed its own logic. No chest-beating, but no false modesty either.

So if it isn't commercial speech, is it research?

No.

That's the other trap. A good many people seem to keep two authorised categories for serious technical work. Either it's commercial, in which case it must sell, or it's academic, in which case it must situate itself inside the apparatus: question, method, literature, contribution, limitations, future work.

Academic writing has its virtues, and I've no interest in pretending otherwise. But Ooloi would be falsified if forced into that register. The project isn't asking a research question about music notation software. It's building music notation software. It isn't proposing a framework for later validation; it's making architectural decisions and testing whether they hold. It isn't waiting for a grant body, a conference committee, or a peer-review cycle to decide whether collaboration belongs in the core model, whether immutable state changes the economics of undo, or whether Ross's engraving geometry should become data.

The academic form carries its own performative restrictions. They differ from the commercial ones, but performative restrictions they remain. Commercial language flatters and reassures; academic language credentials and delimits. The first turns decisions into benefits, the second turns them into contributions. Both can obscure the living act of building.

Ooloi sits elsewhere.

That elsewhere isn't hobbyism. The work is far too systematic for the word to be useful: ADRs, guides, tests, transport, undo, validation, documentation, platform policy, and a public development record intended to survive me. But it isn't institutional research either, because it doesn't ask institutional permission to be serious.

It's a serious system being built in public, by someone who can still say 'fuck' when 'fuck' is the correct unit of meaning.

Which brings us to register.

One of the quieter disasters of professional speech is the belief that seriousness requires narrowing the permitted range of language. Commercial writing wants bright smoothness. Academic writing wants sanctioned abstraction. Neither is much good at admitting that a human mind can move from the ontological to the obscene without changing subject.

Ingmar Bergman understood this perfectly. His language could span six-syllable philosophical terms and four-letter words, sometimes in the same sentence, not as decoration and not as shock, but because that's how consciousness actually works when it's allowed its full range.

Bergman was well-known for saying things like:

'– Och sen känner du, sirru, den här frätande existensångesten i hela fittan.'

The power of it isn't that a vulgar word has been parked next to a philosophical one for comic effect. The power is that existensångesten (existential dread) isn't left floating in the head where such words usually stay. It enters the body, and not some polite symbolic body either. The sentence is philosophical, comic, obscene, bodily, and exact, all at once, and entirely alive.

No register barred.

That's also how I think about this blog. Not because Ooloi is Bergman, and not because a notation program grows more profound if you occasionally swear in its vicinity. The point is simpler. A project of this kind is made by a whole person, not by a corporate function and not by an academic persona. The same mind that worries about beam rotation also remembers Ross arriving in a padded envelope from Melbourne. The same project that needs deterministic accidental rendering also needs an interface quiet enough to stay out of the way. The same life that writes about STM and gRPC also holds grief, irritation, gratitude, AI, orchestration, old books, platform decisions, technical solitude, and the occasional dick joke.

The mixture isn't a lapse in discipline. It's a refusal to amputate parts of the speaker in order to satisfy a prefabricated register.

This matters because Ooloi itself doesn't separate cleanly into the compartments people expect. It's a notation program, a continuation of Igor's semantic line, a Clojure application, a collaboration system, an engraving project, a playback ambition, a documentation corpus, a reckoning with old software architecture, and a long attempt to build something that stays legible without its author standing beside it. Any blog pretending this could be reduced to 'new feature: collaboration' would be lying by omission.

Nor would the academic version fare much better. 'This post situates Ooloi within contemporary research on collaborative music notation systems and proposes a semantic architecture for distributed score editing.' You could write that sentence. You could then spend six pages making it respectable. The result would be less truthful than simply saying: collaboration belongs in the architecture from the beginning, single-user mode is a collaboration group of one, and undo becomes a different ethical problem once other people have witnessed the timeline.

That's not because rigour is unwelcome. It's because rigour and academic posture aren't the same thing.

The audience for this blog is small, and I'm entirely happy with that. At the moment it has somewhere around five hundred unique visitors a month, and they read more than one page. Enough. More than enough, in fact, because it means the right people are finding it without the blog needing to flatten itself for reach.

There's a freedom in that. After a working life spent around commercial development and the short-sighted nonsense it generates, much of it performed for egotistical extractors wearing the language of care, it's an extraordinary luxury to write exactly what the work requires. A dense technical article one week. A nerdy engraving reflection the next. A post about grief, if grief is what happened. A collaboration UI note that stops just before the proof, because the proof belongs in the next post. A joke, if the joke is alive.

The commercial reader may wonder where the product messaging is.

The academic reader may wonder where the research framing is.

In both cases the answer is the same: they're looking for the wrong kind of permission.

Ooloi.org isn't a shop window. It isn't a paper. It isn't an application for legitimacy. It's the public trace of a system being built with the registers left open.

So the blog will carry on as it has to: technical when the work is technical, nerdy when the work is nerdy, personal when the work is personal, blunt when bluntness is exact, and quiet when quiet is exact.

No apology is coming.
1 Comment

Hailing Frequencies

29/5/2026

2 Comments

 
This is the collaboration interface. Two ways in, shown up to the threshold and no further.

The first is hosting. One menu command, Host Collaboration Session, and your Ooloi is reachable. A notification slides in from the top right: 'Hosting collaboration session at 192.168.1.108:10702'. I stop it; another notification says so, and also leaves.

The second is reaching out. Connect to other Ooloi, and the dialog appears: four fields, each explaining itself underneath: host, port, whether to encrypt, and the name you'll wear in the session. The defaults point at a public server, collaboration.ooloi.org on port 443 with encryption on, so the safe path is the path of least resistance. You can just as easily type a friend's machine on your own network instead.

I let the dialog sit a while, then click it away, without connecting. It doesn't snap shut; it fades, like a breath.

The machinery behind these screens already works end to end. But this is, deliberately, only the part before anything happens: the hosting, the dialog, the moment before you commit. Everything here is what Ooloi shows you before it starts intermingling musical DNA with another Ooloi.

A word on order. In The Void Was Listening I had the Piece Window coming first. It didn't turn out that way. The Instrument Library is already shared, global state, with the multi-user undo and redo Claude wrote about two weeks ago already working, which makes it the quickest way to prove the whole thing across a real network before the longer piece-window work begins.

I'm keeping the proof for next time: two of these editing the same Instrument Library at once, undo and redo reaching across the wire and respecting each other's work.

So: hailing frequencies open. This post was deliberately quiet; the fireworks (if Ooloi ever does them; the whole point is to get away from all distractions) are next.

2 Comments
<<Previous

    Author

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

    Search

    Archives

    August 2026
    July 2026
    June 2026
    May 2026
    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
    Backend
    Beaming
    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
    Ingmar Bergman
    Instruments
    Jacques Derrida
    JVM
    License
    LilyPond
    Lisp
    Localisation
    MIDI
    MPL 2.0
    MuseScore
    MusicXML
    Ooloi
    Ortography
    Pitches
    Platforms
    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