Why a reading-first language? The ideas behind Ori


I started Ori thinking about a fairly small problem: I wanted a language where reading code felt as natural as reading a specification. But as I sketched the first pieces, it became clear the decision touched something much bigger — syntax, the type system, tooling, even how AI agents read code.

A question has been bothering me for a while, and it is simple: why do most languages optimize for the writer, when we spend far more time reading? Each syntactic shortcut seems harmless on its own. But when a project accumulates hundreds of them, reading turns into decoding — especially for newcomers, whether a person or a code agent.

What I was trying to solve

I want a systems language simpler than Rust on the surface, without giving up explicit types or native (AOT) compilation. “Simple” here does not mean limited: it means the basics should be obvious, and complexity shows up progressively, only where it makes sense.

Where the obvious solution starts to fail

The obvious path would be to take an existing syntax and adjust it. Rust has the ecosystem, Go has the simplicity, Python has the readability. But each carries a philosophy that is not the one I want: Rust demands a lot from beginners, Go hides too much power in the name of simplicity, Python pushes errors to runtime. None of them was designed thinking about “how does an agent understand this module without loading the whole repository?”.

The alternatives that make sense

In the current design, three forces pull in different directions:

  • Reading ergonomics: explicit syntax, little magic, names that say what they do. It costs verbosity.
  • Native performance: AOT with a serious backend. It costs implementation time — every feature has to survive codegen.
  • Tooling from day one: LSP, good diagnostics, runnable examples. It costs speed, because documentation and friendly errors take as much work as the compiler itself.

The option that interests me most today

Right now, keeping the compiler in Rust with AOT feels like the most coherent combination: low-level control, a growing tooling ecosystem, and a core independent of the interface. The syntax stays readable by default, and any syntactic sugar has to justify its existence by showing it does not hurt reading.

That does not mean the decision is final. It only means that, today, it pays for its own cost.

What still worries me

Two things. First: how far can you simplify before the language becomes a toy? Second: diagnostics. A reading-first language that returns cryptic errors betrays its own proposal — and good errors are expensive to build.

Next steps

The real test is getting non-trivial examples to compile, measuring, and watching where the syntax starts to hurt. If the pain always shows up in the same place, that is where the next decision lives. The current state is in the repository — open spec, examples and changelog.