cd ..
kronos programming-languages systems building-in-public

Kronos: I Built a Programming Language (No Idea What I’m Doing)

Kronos started as a Python proof-of-concept and turned into a C project I’m too invested to quit. Here’s what it is, why I built it, and where it’s headed.

February 1, 2026 5 min read

There’s a saying in the programming world… don’t create web frameworks and don’t create programming languages because most of the time, you probably don’t know what you’re doing. Let me tell you firsthand: I don’t know what the f**k I’m doing, and yet, I built a programming language.

What is Kronos?

What is Kronos, you may ask? Kronos is a programming language. It was initially built using Python as a proof-of-concept and borrowed a lot of syntax from Python, but was later ported to C, and has continued development in C. It also borrows heavily from the philosophy of Perl of being a human-first language.

If you want to skip this post and jump straight into using it, here are the docs:

Why build a programming language?

You might be wondering… why? Or what is wrong with me? Believe me, I hear you. I myself am wondering why, and what is wrong with me for undertaking such a herculean task. Unfortunately, I’m invested in it too much to back down now.

The reason I built Kronos was to see what I can do if I put my mind to it, because up to this point, I had quite a few unfinished projects. Kronos was the one project that I would actively contribute to, maintain, and support—as well as my entry into building in public.

The reason “why” has also evolved from just “seeing what I can do” to being a programming language that I hope can be used one day to teach students interested in programming. Kronos has, and will always have, an easy-to-read syntax that allows beginners to understand it and pick it up quite easily.

Kronos has been the source of a lot of sleepless nights and way too many hair-pulling bugs. I’ve run into issues along the way that took wayyy too much time to debug and implement a fix for. I’ll be sharing more about these in a later blog post.

Why the name “Kronos”?

You might also be wondering: why the name “Kronos”? Well, when I was looking for a name, I was in a bit of a Greek mythology naming system, and… it sounds cool af.

All 2 of my remote servers are also renamed to match Greek mythology—my main server is called Hermes, my storage cluster is called Hades, and the private network bridging the two is called “The Bifrost”. That last one is not quite Greek, but fitting nonetheless.

What I want Kronos to be

I wanted Kronos to be an easy-to-run language, similar to Python and JavaScript/TypeScript, but with the performance capabilities of Rust—without the lengthy build step—the concurrency of Go, and the resilience of COBOL. Quite the goal I’ve set out to accomplish.

I’ve also borrowed a few features from TypeScript. Some already exist in Kronos, and others will be added in the future. One thing that does exist is the finally block in try/catch to aid in cleaning up resources. Another is variables: for mutable variables, Kronos requires the let keyword, and for immutable variables, we use set. Lastly, we also borrow type annotations from TypeScript.

# Variables: let (mutable) vs set (immutable)
let counter to 0 as number       # mutable, can be reassigned
set MAX_ATTEMPTS to 3 as number  # immutable, cannot be reassigned

# Type annotations: "as <type>"
let username to "guest" as string
let is_valid to false as boolean

function validate_input with value:
    if value is less than 0:
        raise ValueError "Input must be non-negative"
    if value is greater than 100:
        raise RangeError "Input exceeds maximum"
    return value times 2

# Try/catch/finally
try:
    let counter to counter plus 1
    set result to call validate_input with -5
    print f"Result: {result}"
catch ValueError as err:
    print f"Validation failed: {err}"
catch err:
    print f"Unexpected error: {err}"
finally:
    print f"Attempt {counter} of {MAX_ATTEMPTS} complete"

Under the hood (at a high level)

  • A bytecode VM
  • An LSP for editor tooling
  • A built-in REPL for quick experiments
$ ./kronos
Kronos REPL - Type 'exit' or 'quit' to quit (or Ctrl+C)
>>> set name to "Alice" as string
... let count to 0 as number
...

>>> let count to count plus 1
... print f"{name}: {count}"

Alice: 1
>>> try:
...     raise "oops"
... catch err:
...     print f"Caught: {err}"
... finally:
...     print "done"
...

Caught: oops
done
>>> exit

Releases and where things are at

I recently released version 0.4.5-beta, which included a docs website and some general bug fixes. Version 0.5.0-beta is in active development.

What can Kronos do?

Kronos has almost everything a general-purpose language should be capable of doing. On a high level, we have variables, data types, operators, control flow, functions, collections, modules, and a standard library that contains collection functions, file I/O, math, regex, and type conversion.

Roadmap (beta → 1.0)

Even though the roadmap indicates that v0.5.0 will be the last beta version before a production release at v1.0.0, there’s still a lot more that needs to be implemented before we can get to a production release. I’ll be moving some of the v1.0.0 features into their own beta releases so I can get them thoroughly tested before a production release.

There is nothing concrete on which features I will be implementing as part of v0.6.0 and beyond on our journey to v1.0.0, but please keep an eye out on our roadmap for changes.

Contributing

Kronos is free and open-source software, released under the MIT License. If you want to get involved, contributions are welcome—bugs, docs, features, even just feedback.

See the contributing guide on GitHub: CONTRIBUTING.md

—Ned

P.S. If you break Kronos, please open an issue. If Kronos breaks you, also open an issue.