HackerReposA FIELD GUIDE TO OPEN SOURCE
ProSponsor the shelf♧ 0
← Back to top all-time
akkartik
mu
Assembly2015–2026
akkartik / mu

mu

Soul of a tiny new machine. More thorough tests → More comprehensible and rewrite-friendly software → More resilient society.

14Distinct people
102Mentions
3Explicit recommenders
1.4KGitHub stars
REPOSITORY AT A GLANCE

What to know before exploring

What it is

Soul of a tiny new machine. More thorough tests → More comprehensible and rewrite-friendly software → More resilient society.

GitHub

Where it is used

No documented product use was verified in the last source check.

What people are saying

> My favorite project along those lines is Kartik Agaram's Mu[3], which wraps emulation, tracing, and time-travel debugging around a subset of x86 assembly language. From…

mncharity used a recommendation phrase. 4 indexed comments match. This is a phrase match, not a verdict.

No classified warning is attached to this page. Read the discussions before treating silence as approval.

Also in these discussions

No other repository is repeatedly linked in the same discussions.

This week on Hacker News

Nov 8–Nov 15 UTC · Direct repository links and separately labeled related project stories. Indexed through 11/15/2026, 9:01:12 PM UTC.

No direct repository links were found in the indexed HN discussions over the past seven days. Older discussions are available below.

Mentions over time

HN mentions by year102 dated mentions

Observed mentions: 2015-03-09 08:11:23 UTC to 2026-10-01 12:57:18 UTC.

051015202015-01-01 00:00:00 UTC to 2016-01-01 00:00:00 UTC (exclusive): 4 mentions; 0 submissions, 4 comments20152016-01-01 00:00:00 UTC to 2017-01-01 00:00:00 UTC (exclusive): 22 mentions; 1 submissions, 21 comments2017-01-01 00:00:00 UTC to 2018-01-01 00:00:00 UTC (exclusive): 6 mentions; 0 submissions, 6 comments2018-01-01 00:00:00 UTC to 2019-01-01 00:00:00 UTC (exclusive): 4 mentions; 1 submissions, 3 comments2019-01-01 00:00:00 UTC to 2020-01-01 00:00:00 UTC (exclusive): 16 mentions; 1 submissions, 15 comments2020-01-01 00:00:00 UTC to 2021-01-01 00:00:00 UTC (exclusive): 6 mentions; 0 submissions, 6 comments20202021-01-01 00:00:00 UTC to 2022-01-01 00:00:00 UTC (exclusive): 20 mentions; 2 submissions, 18 comments2022-01-01 00:00:00 UTC to 2023-01-01 00:00:00 UTC (exclusive): 11 mentions; 0 submissions, 11 comments2023-01-01 00:00:00 UTC to 2024-01-01 00:00:00 UTC (exclusive): 3 mentions; 0 submissions, 3 comments2024-01-01 00:00:00 UTC to 2025-01-01 00:00:00 UTC (exclusive): 5 mentions; 0 submissions, 5 comments2025-01-01 00:00:00 UTC to 2026-01-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments2026-01-01 00:00:00 UTC to 2027-01-01 00:00:00 UTC (exclusive): 4 mentions; 1 submissions, 3 comments. Incomplete calendar period.2026*

* An incomplete calendar period is marked with an outlined bar. Its count is not directly comparable with a full period.

Counts come from the repository’s dated source evidence. Index cutoff: 2026-11-02 08:16:59 UTC.

View mention counts and date ranges
UTC ranges include their start and exclude their end. Select a period to filter the source evidence.
PeriodStart (UTC)End (exclusive, UTC)MentionsSubmissionsComments
20152015-01-01 00:00:00 UTC2016-01-01 00:00:00 UTC404
20162016-01-01 00:00:00 UTC2017-01-01 00:00:00 UTC22121
20172017-01-01 00:00:00 UTC2018-01-01 00:00:00 UTC606
20182018-01-01 00:00:00 UTC2019-01-01 00:00:00 UTC413
20192019-01-01 00:00:00 UTC2020-01-01 00:00:00 UTC16115
20202020-01-01 00:00:00 UTC2021-01-01 00:00:00 UTC606
20212021-01-01 00:00:00 UTC2022-01-01 00:00:00 UTC20218
20222022-01-01 00:00:00 UTC2023-01-01 00:00:00 UTC11011
20232023-01-01 00:00:00 UTC2024-01-01 00:00:00 UTC303
20242024-01-01 00:00:00 UTC2025-01-01 00:00:00 UTC505
20252025-01-01 00:00:00 UTC2026-01-01 00:00:00 UTC101
2026 (partial)2026-01-01 00:00:00 UTC2027-01-01 00:00:00 UTC413

What Hacker News says

22 sources
Interestingly, that is precisely the way I've been framing the problem for several years now. For example, here's a comment from a couple of years ago: https://news.ycombinator.com/item?id=8308881. And one from a couple of months ago: https://news.ycombinator.com/item?id=12668086. "I think we're in a preliterate state with programming: it's hard for anyone to quickly look at a program listing and answer the basic sorts of comprehension questions we might test school kids on for prose. "What we find easy is to read programs we wrote. Recently." Here's my manifesto based on the same starting insight as you: http://akkartik.name/about. And my project (with one other collaborator): https://github.com/akkartik/mu Nice to meet ya! I'd love to chat more at some point once the HN rush dies down, perhaps over email (address in profile). We seem to
Read the rest
be attacking the same problem but from very different directions. I'm focusing on new methodologies rather than tools, and heading down to fix the foundations before creating empowering interfaces on top. Cross-pollination of ideas would be useful.
In What's wrong with Software nowadays and how we can fix it
Thanks! I'm very happy that you noticed that little feature about immutability so quickly. I'd love to hear from you off-thread if you have any more questions or comments about Mu (email address in my profile). I tried in my original comment not to bring Linus into it. I didn't want to be just another person on the internet poking holes at a famous person. If the examples had both included a guard for the end of the list I'd have been like, "eh, no accounting for taste, but ok," and moved on in silence. But we shouldn't be teaching/encouraging people to focus on minor considerations like the number of `if`s when there's a larger problem with undefined behavior. Since you already took a look at Mu, here's a place where I try to elaborate on this belief system: https://github.com/akkartik/mu/blob/07b54625f7/001help.cc#L7...
In Applying the Linus Torvalds “Good Taste” Coding Requirement
".. if you think the good version is overly clever, you probably have a very fundamental problem with your abstract reasoning.." Just to show that you're talking out your ass, here's a code snippet where I did the address of address thing in precisely the same "remove from linked list" situation. In a VM and programming language and operating system that I wrote from scratch[1]. https://github.com/akkartik/mu/blob/a90faae990/edit/003-shor... [2] Moreover, I lived with it for months before I decided it wasn't worth the cleverness[3]. In this case. So I have some plausible claim to having found the "simplicity on the other side of complexity" in this case[4]. As a general rule I'd recommend not reaching conclusions about people from things they write in a comment on the internet. You're looking at them through a tiny peephole into their bel
Read the rest
ief system. When in doubt, ask questions. "Excuse me sir, do you have much experience with C?", "Are you saying pointers to pointers are always bad?", and so on. (Clever analogy there about 0. Totally agree with it. Utterly non-applicable in this instance.) [1] https://github.com/akkartik/mu [2] Hard to read, I admit. There's a colorized version at http://akkartik.github.io/mu/html/edit/003-shortcuts.mu.html, but I only host the most recent version there. [3] https://github.com/akkartik/mu/commit/ea5e7fd4cb from Apr 2016. The previous version was from Sep 2015. [4] https://en.wikipedia.org/wiki/Shuhari
In Applying the Linus Torvalds “Good Taste” Coding Requirement
This is probably simplistic, but in my safe, toy assembly language for teaching programming I simply avoid ever sharing (always refcounted) pointers between threads. Instead it pervasively uses channels for communication, and while channels are generic anything you put in them gets deep-copied on write. The deep copy is smart enough to preserve cycles, so say if you send in a linked list that contains a cycle the reader will see a linked list with an identical topology. It will just be utterly disjoint with the original linked list. These design decisions allow me to provide safe pointer access and avoid all race conditions while teaching programming and concurrency, but they probably incur significant performance loss on certain programs. My hope is that the design constraints they impose on the programmer aren't insurmountable. We'll se
Read the rest
In Reference Counting: Harder Than It Sounds
Since I have you here: I teach programming with this portable, safe assembly language (as opposed to the portable, expressive assembly language that was C). It has bounds-checked arrays. It always initializes variables. The type system is strong, so you can't ever create an address out of a number. It compiles with -ftrapv so any signed overflow immediately triggers an unrecoverable error. It has pointers and requires manual memory management, but it has refcounts so you can't ever have a use-after-free error. As a consequence any copy of an address incurs some overhead to update refcounts, and any copy of a struct incurs even more overhead to update refcounts of all addresses contained within. Between initialization, bounds checking, overflow checking and refcounting, I think I've pretty much eliminated all sources of undefined behavior.
Read the rest
In Understanding Integer Overflow in C/C++ (2012) [pdf]
Avoiding this hairy problem was why I went[1] with a more verbose and more alien-looking -- but much more regular -- s-expression syntax for what is still exactly a C type system: number (address number) (address address number) (address array character) (map (address array character) (list number)) (function number -> number) etc. For simple types you can replace brackets with colons: address:array:character But you have full expressiveness if you need it. [1] https://github.com/akkartik/mu
In Building a C Compiler Type System – Part 1: The Formidable Declarator
I use a layer-based approach described at http://akkartik.name/post/wart-layers in https://github.com/akkartik/mu. It's 20kLoC of literate code, and I was super concerned about optimizing it for non-linear reading, because that's how I need to browse the code for myself. It's not a system to generate multiple views like you want; instead, it's a single view that I find easy to skim and easy to reorganize at will: a) Each layer puts more important stuff up top. So you can start skimming from the first layer, but you don't have to read all the way down each layer, just get a sense of what it provides and why. b) There's not much emphasis on lengthy comments (which would get linear). Instead just the order in which code is presented does a lot of heavy lifting. c) The tangled code is intended to be readable (unlike Knuth's original tools), s
Read the rest
o I often jump down into it when I feel the need. Error messages and debugger support do show lines in the original literate sources, however.
In Literate programming: presenting code in human order
I'm exploring something similar in my project: https://github.com/akkartik/mu. Where C was designed as a more portable+expressive assembly language, Mu is designed as a more portable+safe assembly language. You have to manually manage memory, but you can't ever end up corrupting your heap or using pointers after free. I provide these guarantees by allocating a refcount with every single allocation. The only way to reclaim memory is to clear a pointer. If you happen to still have other pointers to the allocation you won't actually reclaim it. Given this setup I can prototype programs without thinking about memory at all. When my program runs out of memory I start measuring allocations and insert the odd pointer clear at strategic places until I don't, then I continue on my merry way. 99.9% of programs we write don't require thinking of "no
Read the rest
memory leaks" as a black-and-white cast-iron guarantee. This setup also provides a really nice teaching experience where students can learn about pointers and write all sorts of programs without ever running into weird bugs due to use-after-free or overflowing bounds. However it adds some overhead akin to a realtime GC: everytime you copy a struct you have to increment refcounts of any pointers nested arbitrarily deep within it (Mu maintains a flattened bitmap for each type to make this not utterly suck). Sum types get even crazier, because you might have a pointer at offset x depending on the state of the tag at offset y, and so on. I'll try to measure the overhead at some point..
In Bone Lisp – Lisp Without Garbage Collection
"..trace logs, a relatively old technique that glorifies printf as First-Class Citizen Of The Testing Guild.." I don't understand the stigma attached to logs and debug-by-print. When is a tool that uses x to provide y 'glorifying' x? I've built and regularly use two tools that rely on logs: a) I write white-box tests that allow me to check not just what a function returns but specific events in the course of the function running: http://akkartik/name/post/tracing-tests. This allows me to check, for example, that searching in a sorted array doesn't require double the lookups when the size of the array doubles. It also allows me to test subcomponents without calling them directly, leaving their interfaces underspecified and flexible to change later without needing to modify a bunch of tests. b) I often debug my programs by dumping a trace a
Read the rest
nd running it through a 'trace browser' which starts out showing just the coarsest level and allows me to drill down in specific places as I want. This 'zoomable' google-maps-like UI gives me all the benefits of time-travel debugging at a fraction of the system engineering it usually takes. (I still can't get the feature to work in gdb..) Try it out: $ git clone https://github.com/akkartik/mu $ cd mu $ ./mu browse-trace .traces/factorial-test It'll take ~30s to compile the first time you run it (C compiler required on Linux/OS X). Once it compiles, you'll see an ncurses program. Use 'q' to quit, hit enter to zoom into lines (you can see how many lines are collapsed in parens), backspace to zoom out on a line. These are both things nobody can do on a conventional toolchain, and super easy to build. Maybe print seems trivial because nobody's building tools around it?
In Distributed Systems Testing: The Lost World
There's been a lot of discussion about undefined behavior on HN recently, and I'm gradually starting to question if the conventional approach to compilers might be a giant dead-end. In this case, our conventional languages provide no way for a programmer to say "I care about overflow". Because face it, the vast majority of programs a compiler sees are written extremely sloppily. Most of the time there's this huge disconnect between the amount of effort the programmer and the ghost of the compiler writer are putting into considering such situations. Now, most of the time this disconnect is a good thing. Division of labor ensures that the work of the compiler writer is amortized across many many programmers. But the discussion around undefined behavior is a sign that the load on the compiler writer has gotten too onerous, to the point that
Read the rest
everybody is paying a cost (in reduced performance, in increased compiler complexity leading to reduced compiler stability, in compilers antagonistically interpreting standards like lawyers) for a level of correctness along one narrow dimension that only a tiny fraction of users actually care about. What if we instead said, "compilers will never ever consider overflow" and let those who care about overflow fend for themselves in the source language? Among other things that would allow integers to always be the word size of the computer they're running on. (My interest in these questions stems from trying to program in an idealized assembly language for the past year: http://github.com/akkartik/mu. After writing 10kLoC of assembly to build a simple text editor (http://akkartik.name/post/mu) I'm surprised to find it quite ergonomic. High level languages today seem to provide three kinds of benefits over traditional/ugly assembly: expressiveness (e.g. nested expressions, classes), safety (e.g. type checking) and automation (e.g. garbage collection). An idealized assembly language gives up some expressiveness, but doesn't seem to affect the other benefits. As such, it's at an extreme end of the trade-off I describe. I'm hoping my experience will largely translate even when Mu eventually implements a high-level language.) Edit 21 minutes later: For reference, here's how I've been thinking about undefined behavior while building Mu: https://github.com/akkartik/mu/blob/5dd82a8a70/001help.cc#L4.... Comments most welcome.
In A bit of background on compilers exploiting signed overflow
I don't think the paper contradicts the second quote. It just points out that things got a lot more complex since. "this again shows that getting software right is not easy." Not easy, yes, but in my experience getting software right isn't too difficult. What seems impossibly hard is keeping software right, maintaining correctness in the presence of new requirements, compatibility constraints and just sheer caring about different things than we used to[1]. At some point I suspect you'd get a better design by rewriting things from scratch. But the way we do development makes rewriting stressful and error-prone, leading to the repeated arguments about whether rewriting is good or bad[2]. The question isn't whether rewriting is good or bad. Software is the most malleable medium known to man, and we should do all we can to embrace that essent
Read the rest
ial malleability that is its primary characteristic and boon. The question is how not to mess up rewriting, how to keep our clay from gradually getting more and more brittle under the weight of added constraints. (I work on this problem: https://github.com/akkartik/mu/blob/7f5a95cdbe/Readme.md. It's been 31 days since I last got on my soapbox in this forum: https://news.ycombinator.com/item?id=11285529.) [1] "The future is a disagreement with the past about what is important." http://carlos.bueno.org/2010/10/predicting-the-future.html [2] Against rewrites: http://www.joelonsoftware.com/articles/fog0000000069.html; https://steveblank.com/2011/01/25/startup-suicide-%E2%80%93-...; https://basildoncoder.com/blog/pg-wodehouse-method-of-refact.... Pro-rewrite seems the minority position: http://brettweigl.tumblr.com/post/48385335083/what-can-produ...; http://building.wanelo.com/2012/09/14/the-big-switch-how-we-...; http://alicebob.cryptoland.net/why-i-rewrote-quivi-from-scra... (with many apologies). And yet we've seen several major rewrites: Netscape (for all Joel Spolsky's criticism above, would Firefox had been possible without the rewrite? Echoing Jeff Bezos's dictum, open source projects can afford to be misunderstood for a long time), Python 3 [edit: no, Python 3 was not a rewrite as I was corrected below], Perl 6, Angular 2. A more balanced viewpoint: https://blog.learningbyshipping.com/2013/04/02/surviving-leg....
In The Linux Scheduler: A Decade of Wasted Cores [pdf]

Showing the 15 most recent of 22 sources. Enable JavaScript to search and browse every indexed mention.

MAKE YOURSELF AT HOME

A few shortcuts

/
Search the collection
?
Open this guide
Esc
Close dialogs and navigation

Your saved repositories and interests stay in this browser.