My life mission is to reduce the global cost of software maintenance by 100x.I've worked in programming tools for 15 years across 5 companies, graduated with 2 degrees at age 20 from CMU, won the "20 Under 20" Thiel Fellowship, and have a Ph. D. in programming languages from MIT. My work has been featured in the New York Times.
As a cofounder of UpToSpeed, we are solving the problem that AI is making us 10x faster at writing code, and yet our ability to understand code remains as slow as ever
As the founder of Mirdin, I turn good software engineers into great ones by turning advanced research topics into actionable software engineering advice.
There's a few obvious suggestions -- discuss design tradeoffs with the AI extensively, make sure you understand all your code, and understand the refactorings.
I think using Command Center can lead to much better skills growth than any other agentic coding environment. Which is a lot like saying that a shrubbery is much taller than grass, when you need your skills to grow into a tree.
This is a problem that no-one has solved. I think we might have it solved by the end of the year (we've been doing deals with a lot of universities and are being pulled in that direction),
The things humans can offer over AIs: product sense, greater context, taste. Of these, taste (really: software architecture and design) is the one that's most fundamentally about software engineering skill. I wrote recently about this at https://self-service.mirdin.com/software-design-in-the-age-o...
The big problem: it's very hard to develop enough taste to be a general without actually being in the trenches. This goes for pretty much any field, including literal war.
I've trained about 500 software engineers. But all of them were working professionals, who would take the training back on the job each week and see all the lessons playing out in their own and their coworker's code. If they were just chatting with AI and never having to get halfway through a big feature only to realize that the design was just fundamentally flawed, rate of growth would probably be much slower.
In short: lots you can do to grow faster than someone who just stares at the Claude CLI all day and never opens an editor. But how to become actually good while still doing AI coding? Unsolved problem.
> Heh, personally I fixed this by just adopting the sleep cycle my body wants of going to bed at 04:00/05:00 and going up at 11:00/12:00, life is much better now when I just accept it. One approach if your life can allow it :)
That was my life in my mid-late 20's.
But as I've gotten older, my sleep schedule has only gotten more messed up. Now I consider it a victory if I manage to go to sleep before the dawn.
> Very much so, obviously prefer something async if possible, just a .patch file could suffice I suppose, but could do a call to have a look if that's the only way :) Reach out to my email from my profile and we can coordinate :)
Most days I don't ship 20 PRs. But I think my record is 30.
Three things made that possible.
The first, obviously, is having Command Center.
The second is that a lot of those were fixes or UX improvements under 100 lines.
The third is, no joke, not sleeping. I've had quite a few 20+ hour days in the last 6 months. Some of that is work pressure, but also I've considered getting evaluated for a broken circadian rhythm.
> I'd be curious to see some of those PRs if you're saying you've essentially solved the holy paradox of "ship fast = shit code" or "ship slow = good code".
If you're serious, I'll be happy to get on a call and show you.
On the one hand, it is true that the website code was pushed 0 minutes before this announcement went up.
On the other hand, I tested just now on two different phones and didn't see any issues. Can you say in more detail what you expected vs. what actually happened?
There was an occlusion issue on some smaller screens, but it's been fixed now.
The basic answer is that it runs locally. If you turn telemetry off and don't use our free Gemini credits, it's trivial to verify that no traffic goes to our servers other than a tiny subscription check. For our enterprise customers, we offer a version that doesn't even do that. Everything stays between you and your model providers (and we support custom and local models).
SOC2 is still a work in progress. I'm a former security researcher with work featured in the New York Times, and I know that doing it right (and not going through Delve) takes time. I can tell you that we have passed a compliance check for a company in a highly-regulated space.
I didn't find your contact info, but I'm available at [email protected], and happy to discuss your needs.
The final moments before this launch announcement consisted of me twiddling my thumbs while waiting for our designer to upload any version he could get ready in time that is better than the previous version of our website. So we knew we'd be launching with a lot of imperfections in the visuals. Did test in mobile, but not on iPad.
In fairness, I did most of these interviews last summer, and I know some people have changed. And while I did go a fair bit outside my network to interview people, there are all sorts of hard-to-understand selection effects that come from me being me. A 21 year-old frat boy who tried doing the same kind of interviewing with the people he could find to interview would probably get different results.
But yes, that is indeed what happened. Multiple times, I'd talk to someone that I'd expect to not be reading the code at all (solo founder, mostly nontechnical), then I'd interview him in detail about his workflow and think "Huh, there was absolutely no point in there where he was reading stuff," and then I'd ask "So how much of your time is reading code?" "60, maybe 70%"
In honesty, that's not a bad idea, and we hadn't thought of that.
It's pretty expensive to measure even for small programs. It's also more of a relative than an absolute measure, i.e.: it scores two variants of the same codebase, but the raw scores aren't very meaningful on their own. So our goal had been to use this in the benchmark set we're working on when we release a standalone refactoring product.
But the more I think about this suggestion, the more I think: "Hmmm, why not?"
And indeed, I think we're the only agentic coding environment with jj support.
The most difficult code in the 1.0 release is some gymnastics to avoid the appearance of a concurrency conflict with a user running their own jj commands, made at the request of the person who introduced me to jj.
Ooh. The answer is probably more interesting and philosophical than you expected
I can tell you that we do extensive testing, we figured out how to objectively measure the code quality on certain benchmark problems, empirically it's extremely helpful nearly all the time.
But in the general case: it is not actually possible to guarantee this.
That's because whether a change improves the code often depends on information which is literally not present in the codebase.
Some of these are more trite. E.g.: whether a comment is helpful or redundant slop depends on the audience.
A simpler example: There's a function that's never called. Should it be deleted?
There's a number of factors outside the codebase that determine the answer. Including the obvious one "Not if your next prompt is going to start using it."
I started playing didgeridoo 10 years ago for precisely this reason. Sleep apnea already cured by weight loss, but I knew by air pathways were prone to it, and I never wanted it to come back.
It worked
It took me 1-2 years to learn circular breathing, but even just learning to play for 15 seconds on one breath can give the "oxygen high" from breathing so much.
I don't see how. Cases are decided by facts and law, not feelings -- except to the extent those feelings are probative of state of mind, which is relevant for some legal issues but not others. My understanding is that the crux of the case is on the extent to which a number of informal messages should be considered a binding contract.
Trying to go from a single admission like this to an overall legal conclusion is a lot like seeing a single line in a program and then concluding there's a bug -- without having ever seen the rest of the program. You might think "this line always crashes, " but actually it's never called (does not go to any matter at issue), or none of the terms mean what you think they mean, etc.
Have found in that roadmap things that would help me personally like making async functions dyn-compatible. Have not found the deeper stuff I thought you were hinting at.
Last year, I wanted to use the 5- line Result.flatten function, abs then found it had been stuck in experimental....for 5 years. That left me with no confidence of the language's dev velocity.
This is getting pretty funny. In this branch of the thread alone, I've seen the defenses of: (1) "Rust is fine, you're just expecting the affordances of a GC language." (2) "Rust is fine, you're just expecting the affordances of Haskell," and now (3) "Rust is fine, you're just not used to systems programming"
It's okay if your language has problems (I have plenty of criticisms of my favorite languages), but I find it odd and concerning how frequently I've seen Rust programmers try to deflect instead of engaging in criticism.
I actually have a huge systems programming background and identify as a systems programmer. C and C++ by and large do not have the problems I've written about. These things are Rust problems, not systems problems.
Oy. It is also a common experience that, when I struggle in Rust to use a pattern that's common in nearly every other language or find another way to achieve the same goal, people who know of my Haskell background call it a "Haskell pattern," and thereby avoid facing the suggestion that their favorite language is missing some pretty basic affordances.
No, boxing everything does not magically make things more dyn-compatible. It will not magically solve the issue that tokio does a whole-program transformation that does its most restrictive checking only after all local checks have been resolved. It will not magically allow more reuse between datatypes. It will solve none of the problems I encountered... because if beginner-Rust could solve any of these problems, then they would have ceased to be problems for me by the time I became intermediate.
> Rust programmers tend to obsess over minimizing those tradeoffs to get abstractions that are zero-cost. So doing it “the rust way” is often very complicated and tricky to get right while satisfying the borrow checker and type system, but once found is lean, fast, clean, and safe.
You and I must be using very different definitions of "lean." For me, "complicated" and "lean" do not go together
Please respect the fact that I do not understand how one can like Rust without giving up caring about modularity.
I have pretty good reason for thinking this is a possibility. Directly, because the Rust experts I asked for help did in fact advocate giving up modularity. Indirectly, in that I've seen something similar but much stronger in a different language. That culminated in a conversation with several of the creators of that language, in which they argued their language was great for generic programming...while revealing some pretty basic holes in their understanding of generic programming (while calling me a "Haskell weenie," among other abuse). I am very confident in my conclusion about this other language community and not interested in getting into the details of this event. I am just sharing where I'm coming from, in not immediately dismissing this idea as too absurd to consider even when I have no other hypothesis.
I acknowledge that you feel personally insulted by me having a hypothesis that requires a large group of people behave in ways I consider strange. I have evidence for that hypothesis, and have been unable to find a better one. I hope you can see how the comment I am responding to crosses an extra line and is directly personally insulting.
I would very much like to come away from this discussion no longer believing that Rust programminh is at odds with modularity. I have shared some fairly basic and detailed criticisms, the ones I still remember after a year out of the language. Perhaps your can play a role in offering solutions to them -- or admit that these are indeed problems your hadn't noticed before or had gotten used to
Just investigated -- looks like this works now! Yay!
For this family of examples, had been completely stymied by AsyncFnOnce not being released yet. IIRC it had been in the works for several years, was still an experimental feature when I was trying to use it, and I gave up after much frustration at trying to get a version of Rust with experimental features working under devenv (nix).
A subtraction then to my frustrations with Rust -- though I'd still be very wary of doing this, having seen how fragile higher-order functions have been in the past.
*`dyn Writer`. `impl Writer` can only be used in function parameters.
This was one of the example approaches I gave. This works...at first. The problem is that, if you want to add a new function to the Writer trait which makes Writer no longer dyn-compatible, such as, say, any async function, then you can no longer write `Box<dyn Writer>` and need to rewrite all code that uses it.
(although you can dig under the hood and specify a pinned-down Future type, covering one kind of awfulness with another)
> Look up "callback hell". Basically they encourage spaghetti.
Ah. I think you're confusing the general idea of a callback with one particular style of use. "callback hell" refers to the deep indentation that occurs when trying to program in monadic style in languages without syntactic support for monads. It was mostly solved by adding async/await syntax, aka syntactic support for the continuation monad. "Callback hell" is not spaghetti in any deep sense, merely syntactically cumbersome.
But a "callback" is a more general term, sometimes a synonym for "function parameter," sometimes for more narrow kinds of function parameter (e.g.: void function, invokable once). Many people will refer to the function argument of the `map` function as a callback, but no-one would refer to that as "callback hell."
And when I did, I largely got it by figuring stuff out myself, while being told by multiple Rust experts that I either shouldn't care about the verbosity and lack of modularity, or that if I have a problem like "using the interface instead of the implementation" it must be because I'm a Haskeller.
Well, my ultimate solution was to start working on a new product, and to not use any Rust, except for some performance-heavy libraries. With the first product, the market had changed too much by the time we were ready for prime-time, and I'd put somewhere between 25% and 70% of the reason for that delay on our choice to start building new parts of the backend in Rust.
> Macros are a perfectly reasonable thing to use in Rust, even if they are best avoided where possible. Exactly like unsafePerformIO.
Good comparison!
> Despite that it's still probably the best language we have for a surprisingly large range of domains.
I agree with this. I just don't agree that that list of domains has a very large intersection with the set of applications.
As a cofounder of UpToSpeed, we are solving the problem that AI is making us 10x faster at writing code, and yet our ability to understand code remains as slow as ever
As the founder of Mirdin, I turn good software engineers into great ones by turning advanced research topics into actionable software engineering advice.
Personal: www.jameskoppel.com Startup: www.up-to-speed.ai / www.auditlabs.ai Training Business: www.mirdin.com Blog: www.pathsensitive.com