OOLOI.ORG
Menu

OOLOI

An Organism Evolved.

OVERVIEW

DOCUMENTATION

NEWSLETTER

Ask the Librarian

25/2/2026

2 Comments

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

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

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

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

New Guide: MIDI in Ooloi

21/2/2026

0 Comments

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

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

The Piece Window

21/2/2026

7 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.
7 Comments

The Frontend Architecture Guide

18/2/2026

0 Comments

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

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

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

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

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

Surface Tension

17/2/2026

10 Comments

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

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

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

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

Where the Freedom Comes From

15/2/2026

2 Comments

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

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

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

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

A Language That Trusts You

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

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

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

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

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

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

CLOS and the Workshop Tradition

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

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

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

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

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

Having Been There

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

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

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

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

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

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

What Was Lost

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

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

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

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

The Return

When I came to Clojure, I came home.

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

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

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

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

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

Where the Genealogy Arrives

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

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

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

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

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

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

The Ordinary Work

11/2/2026

2 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.
2 Comments

    Author

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

    Search

    Archives

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

    Categories

    All
    Accidentals
    Alfred Korzybski
    Architecture
    Benchmarks
    Clojure
    CLOS
    Common Lisp
    DDD
    Death Of Igor Engraver
    Documentation
    Donald E Knuth
    Dorico
    Dynamic Programming
    Finale
    FrankenScore
    Franz Kafka
    Frontend
    Functional Programming
    Generative AI
    GRPC
    Igor Engraver
    Jacques Derrida
    JVM
    License
    LilyPond
    Lisp
    Localisation
    MIDI
    MPL 2.0
    MuseScore
    MusicXML
    Ooloi
    Ortography
    Pitches
    Playback
    Plugins
    Python
    QuickDraw GX
    Rendering
    Rhythm
    Rich Hickey
    Road Map
    Scheme
    Semiotics
    Sibelius
    Site
    Skia
    Sponsorship
    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