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

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

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

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

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

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

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

Wagner Tubas on the Workbench

10/4/2026

5 Comments

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

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

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

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

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

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

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

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

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

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

It's All Greek to Me

2/3/2026

6 Comments

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

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

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

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

So a sequence of work comes first.

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

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

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

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

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

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

The Piece Window

21/2/2026

9 Comments

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

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

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

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

A Window That Does Several Jobs at Once

The piece window exists to keep everything else clean.

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

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

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

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

Calm

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

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

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

Not Igor 2.0

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

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

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

The Frontend Architecture Guide

18/2/2026

0 Comments

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

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

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

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

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

Surface Tension

17/2/2026

10 Comments

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

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

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

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

The Ordinary Work

11/2/2026

3 Comments

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

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

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

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

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

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

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


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

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

First Window

27/1/2026

12 Comments

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

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

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

Frontend Events: One Evening's Work

27/1/2026

3 Comments

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

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

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

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

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

    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