Customizing
Written in Go
Shelley is primarily written in Go.
Why Go
The current hype cycle around code entirely written by agents is focused on TypeScript and Rust. There is nothing wrong with this. TypeScript, along with JavaScript, is one of only two correct choices for in-browser software, and has a well-established server-side presence. Rust is a good systems programming language. You can write a lot of great software in both of these languages.
But as hype cycles are wont to do, they tend to take something clearly true, like “TypeScript and Rust work,” and extrapolate it. One of those extrapolations is that Go does not work, or at least no longer makes sense in a world where code is agent written.
This is not an obvious conclusion to us. While arguments over programming languages have always been painfully qualitative and aesthetic, Go’s popularity among programmers suggests at a high level that there is value in it as a language for writing software. It’s good for developers.
A working principle at exe.dev is that “what is good for developers is good for agents.” That is why we spent so much time on optimizing our API for human use, even as we enter an age where APIs are exclusively used by our machines on our behalf. Our LLMs are trained on the history of developers, and until they are training themselves, there is value in our past norms that we have not managed to fully articulate.
Go is a compiled language, and its compiler is fast. Dependencies are relatively easy to install and manage. The language is relatively efficient, but most importantly, it is easy to profile and improve the efficiency of programs, and agents are good at doing it.
There are weaknesses. Over time the build cache grows on CI machines, and needs some fiddly management. Some popular third-party dependencies are both somehow very heavy, and lacking in features. If your program is successful and develops hot paths, you have some work to do to minimize heap allocations on those hot paths (beyond what the compiler does for you with automatic stack allocation conversion). These are manageable by developers, and manageable by agents.
Overall, Go is an imperfect programming language, and sits in the pantheon among all the other imperfect languages, each with tradeoffs. It makes tradeoffs that are for the most part practical. In short: all the traditional arguments you have read for and against languages continue to apply.
So we decided to bet on Go. It is good for us, we think it is good for agents. And so far Shelley has been a delight to develop with Shelley. If you take it and make it your own, we hope you find the same.
The web UI is Vue
The web UI is the exception: it’s a Vue 3 app in TypeScript, built on
PrimeVue components, under
ui/. It starts at
ui/src/vue/main.ts, with the components in ui/src/vue/components/.
esbuild bundles it into ui/dist/, which the Go binary embeds, so Shelley
still ships as a single file; in the browser, the UI talks to the server over
a JSON API and one long-lived server-sent events stream.
Will Shelley always be written in Go?
Probably not!
Traditionally, software projects rarely change the language they are written in. Even “easy” moves like GCC going from C to C++ were huge undertakings. Projects like the Go compiler toolchain conversion from C to Go is some of the gnarliest engineering I have ever seen.
But now moving languages is practical for large projects, using agents.
There is no obvious choice of language we would move Shelley to today. However I find it extremely unlikely that we have seen the end of programming language development. Once this initial frontier model race subsides and diaspora of programming models appears, people will start building programming languages in conjunction with training models. This will introduce a new era programming languages (that have the potential to look alien to us human programmers), and we should reconsider as technology changes.