Getting Started

About the language

What is Vary?

Vary is a statically-typed language that compiles to JVM bytecode. It is also an experiment in two things: using LLMs to help build a programming language, and using mutation testing to keep LLM-generated code honest.

LLMs write code confidently whether it is correct or not. They also write tests confidently, and those tests often pass without actually checking anything useful. Vary's built-in mutation testing (vary mutate) is designed to catch exactly that. It modifies your code in small ways and checks whether your tests notice. If they do not, your tests have a gap, regardless of who wrote them.

The language itself has readable syntax with static types, null safety, and a single CLI that handles running, testing, formatting, and mutation testing. But the reason it exists is to explore what happens when you build a language and its toolchain alongside AI from the start.

Why create a new language?

In part, because we can. We live in a "just do things" kind of world, and the cost of doing it has dropped.

AI-assisted coding means a small team can generate, test, and iterate on a compiler far faster than before. Writing a lexer, a parser, a type checker, and a bytecode generator is still real work, but the volume of code that needs to be written and the speed at which it can be tested has changed. The same applies to the test suite: writing hundreds of test cases for edge cases, error messages, and mutation operators is the kind of repetitive, precise work that AI tools handle well.

That changes what a new language can be for. Instead of spending months or even years just getting a compiler to work, you can spend that time exploring ideas that existing languages have not prioritized. For Vary, that means mutation testing as a first-class feature, not a third-party plugin. It means a single CLI that covers the full development lifecycle. It means asking what a language looks like when the toolchain is designed to catch AI-generated code that looks right but behaves wrong.

We also ship an LLM skill that gives AI coding assistants the full language reference, so they can write valid Vary without falling back to Python habits. LLMs will still make mistakes with a new language, but the skill combined with mutation testing means those mistakes get caught.

None of this required a new language in theory. In practice, bolting mutation testing onto an existing language means working around its compiler, its test runner, and its build system. Starting fresh means these features are part of the design instead of afterthoughts wired together with plugins.

Is Vary ready for production?

No. Vary is alpha-stage. The compiler, type system, and standard library are all under active development. Syntax and APIs may change between releases without notice.

Vary is suitable for experimentation and exploring language design ideas. We do not recommend it for production workloads at this time.

I tried Vary and it doesn't work. What gives?

Sorry about that. Vary is alpha software, so there may be issues. If something is not working, please submit a bug report with what you tried and what went wrong. We read every report and often ship fixes within a few days. varyup makes it easy to grab the latest release, which may already include a fix.

Most of our testing happens on Linux, so Windows and macOS get less coverage. If you are on either of those platforms, bug reports are particularly useful.

Isn't creating a new language impossibly hard?

Historically, yes. But it is more possible now than it used to be.

AI-assisted coding has changed the economics of compiler development. Large parts of the work that used to require deep specialized knowledge can now be iterated on faster with the right tooling and feedback loops. Building on the JVM helps too. You get 30 years of garbage collection, JIT compilation, threading, and runtime infrastructure for free. The JVM handles the how, which lets you focus on the what: language design, developer experience, and tooling.

Getting from "working compiler" to "production-ready language" is a different scale of effort entirely, though. It takes years of testing, edge case handling, performance work, and real-world usage. Vary is not there and does not pretend to be.

What is Vary good for?

Targeting the JVM means Vary is better at some things than others.

Use caseFitWhy
Long-running servicesGoodThe JVM warms up over time. Services benefit from JIT compilation, mature GC, and real threading.
HTTP APIsGoodBuilt-in HTTP support, and mutation testing catches the logic bugs that unit tests miss.
CLI toolsDecentJVM startup adds around 100ms, which is slower than native binaries but fast enough for most CLI workflows. The built-in mutation testing and static types make it a reasonable trade-off for CLI tools where correctness matters.
Systems programmingNot idealNo direct memory access, no value types, no inline assembly. That is not what the JVM is for.

The main advantage is the integrated environment. The compiler, test runner, formatter, and mutation testing all ship as one CLI. You do not need to assemble a toolchain from separate projects. For longer-running services where correctness matters, static types combined with mutation testing tell you whether your tests actually check behaviour, not just run without failing.

What is mutation testing and why does Vary treat it as a core feature?

Code coverage tells you a line ran during a test. Mutation testing tells you whether the test would notice if that line did something different. The compiler makes small changes to your code (flipping a > to >=, replacing a return value with a default) then runs your tests. If the tests still pass, they have a blind spot. This matters more now that LLMs write tests that look thorough but check nothing.

In most languages, mutation testing means installing a third-party tool and wiring it into your build system. Most teams never bother. In Vary it is a built-in command: vary mutate. Targeting the JVM is what makes this practical: the compiler mutates bytecode directly and runs each variant in an isolated classloader, so mutations are fast and never touch your source files. Results are cached across runs. See the mutation testing docs for details.

Why did you make "X" decision?

There are a handful of big decisions and thousands of little ones. Some have good reasons behind them. Others were made on instinct, or because something had to be picked and we picked it. The language design choices page covers the ones worth explaining.

What we are trying to get right are the underlying basics: the type system, the compilation model, the testing philosophy, and how the toolchain fits together. The surface-level choices (syntax details, API naming, CLI flag conventions) are less permanent. If something does not work, we will change it.

Is Vary actually "very good"?

The name is tongue-in-cheek. Vary is alpha software, so no, it cannot honestly claim to be "very good" at everything yet. Parts of it work well, especially mutation testing and the integrated toolchain. Other parts are still rough. That is what alpha means.

The name actually comes from "variations", as in the code variations that mutation testing creates. The fact that it sounds like "very" is a happy accident we are not above leaning into.

AI and LLMs

New languages are hard for LLMs. How do you handle that?

LLMs perform poorly with languages they have not seen in training data. Code assistants will hallucinate syntax, invent nonexistent APIs, and struggle with anything outside their training distribution.

We know this and are leaning into it. Vary is partly an experiment in what it looks like to build a new language alongside AI tooling. That means exploring questions like:

AreaWhat we're exploring
AI-assisted codingHow well can models adapt to unfamiliar syntax with the right context?
Testing and lie detectionCan mutation testing catch cases where generated code looks right but behaves wrong?
Toolchain integrationWhat does a compiler look like when it's designed to give AI-readable feedback?

We also ship a Vary skill for AI coding assistants that gives them the full language reference, syntax rules, and common patterns. It does not make LLMs perfect at Vary, but it closes the gap between "hallucinated Python" and valid code. Combined with mutation testing, the skill means LLMs can write Vary and the toolchain can verify it.

LLMs will write worse Vary than they write Python or TypeScript. We are building the tooling to catch the mistakes they make.

Does the project use AI-assisted coding?

Yes, extensively. The compiler, test suite, and documentation are all built with AI coding tools.

We did this on purpose. Most code will eventually be written by LLMs, and we want to know what happens when you point mutation testing at that code. Can vary mutate reliably catch the cases where an LLM writes something that compiles and passes tests but does the wrong thing? That is what we are trying to find out.

If you're building a language for LLMs, shouldn't it look radically different?

If the goal were a language designed for LLMs to write, it probably would. But that is not the goal. Vary is a language for humans that LLMs can also use.

The syntax is meant to be readable and familiar. If you know Python, you can read Vary. We are not trying to invent a notation that optimizes for token prediction or model internals. The language should make sense to a person looking at it for the first time.

Where LLMs come in is on the verification side. LLMs generate code confidently regardless of whether it is correct. Vary's mutation testing is designed to catch that. When an LLM writes a function and a test for it, vary mutate tells you whether the test actually checks the behaviour or just happens to pass. That is the AI story here: not a language shaped around LLMs, but a toolchain that catches them lying.

Technical decisions

Why the JVM?

Two reasons.

First, targeting the JVM makes it possible to build a complete language in less than 100k lines of code instead of millions. The Rust compiler, for example, is over 2 million lines. You do not need to write a garbage collector, a JIT compiler, a threading model, or an operating system abstraction layer. The JVM provides all of that. Kotlin, Scala, Clojure, and Groovy made the same choice.

Second, JVM bytecode is ideal for mutation testing. The compiler can emit bytecode variants, swap individual instructions, and run the mutated code in an isolated classloader without touching the source. Bytecode-level mutation is fast and precise in a way that source-level text rewriting is not.

What language is the compiler written in?

Kotlin. Since Vary targets the JVM, writing the compiler in a JVM language means the compiler and the code it produces share the same runtime. The bytecode generator uses the ASM library directly, and runtime support functions are plain @JvmStatic methods that compiled Vary code calls without a foreign function boundary. Kotlin also gives us sealed classes for modelling the AST, coroutines for the language server, and access to the full Java ecosystem for things like classloader isolation in the mutation engine.

Why not write your own runtime from scratch?

A native runtime needs platform-specific code generators, OS abstraction layers, and years of tuning to get any of it production-ready. The Go runtime alone is hundreds of thousands of lines.

We would rather spend that effort on the mutation engine, the test DSL, and the integrated toolchain. The JVM handles everything below that, which keeps the compiler small enough for a small team to maintain.

Isn't garbage collection bad?

GC is a trade-off: it removes an entire class of memory safety bugs at the cost of some runtime overhead. For most systems, that trade is worth it. Billions of lines of Java running in production over three decades means we have a good understanding of how GC behaves, when it pauses, and how to tune it. We are comfortable with that trade-off.

Project and licensing

Is Vary open source?

The compiler source is currently not available. The compiler itself is free to download and use. Grab varyup and you can have a working toolchain in under a minute. See the install docs for platform-specific setup.

We do ship other pieces as open source, though. The AI coding skill, the VSCode extension, example projects, and documentation are all publicly available. The compiler itself is the part we have not opened up yet. We are considering what to do with the compiler source as the project moves forward, and open sourcing it is a definite possibility.

Do you accept source code contributions?

Not at this time, though it is a possibility in the future. LLMs have made open source projects interesting in a new way: the volume of submissions has gone up, and we do not have the capacity to review them. Reviewing code properly takes time, and doing it badly is worse than not doing it at all.

At this stage, ideas and testing are worth more than code. We appreciate any suggestions about the language or toolchain, and especially results from testing. If you tried something and it broke, or behaved unexpectedly, that is exactly the kind of feedback that helps. Use the contact form to get in touch.

What kind of support do you provide?

We want people to try Vary and tell us what they think, but we are not in a position to provide direct support. There is no help desk, no SLA, and no guaranteed response time.

If you hit a bug or have a suggestion, use the contact form. We read everything. Because the project is small and the toolchain is AI-assisted, good feedback can be incorporated quickly, sometimes within a few days. We cannot promise a fix or a timeline for every report, and there is no corporate support.

Do you publish a roadmap?

Not yet. We maintain an internal roadmap and plan to publish it once we are out of initial alpha. If you have thoughts on what Vary should prioritize, we would like to hear them via the contact form.

Is it Vary, vary, or varylang?

All are acceptable. "Vary" is the language name. "vary" is what you type in the terminal. "varylang" is the project name used for the website. Use whichever fits the context.

Who created Vary?

Curtis Collicutt. Curtis has worked in university libraries, startups, and enterprises, mostly on making systems safer and easier to use. He also runs TAICO.

← Quick reference
Glossary →