Show HN: Huzzah – a novel approach to coding with AI (danielvaughn.dev)

1 points by danielvaughn ↗ HN
Hello everyone. I've been working on this experimental editor called Huzzah.

I've been working almost exclusively with coding agents since January of this year, and over the past few months I began to feel utterly exhausted by them. They're great, but I'm finding it more and more tedious to write full sentences for every change I want. Not only that, but it seems there's a complexity limit for codebases - beyond a certain point the agent begins confusing itself.

I'd like to go back to writing code, but I don't want to go all the way back to fully manual coding. So I've come up with this interaction paradigm where you:

  1. write pseudocode in whatever way makes the most sense to you
  2. on save, the editor synchronizes your work to real source code
  3. the pseudocode is persisted alongside the generated code, making your prompt effectively a stored record of intent.
It may not work for every use case, but in my limited playthroughs I've found it very enjoyable.

Right now it's just a proof of concept - installation instructions are here in the readme: https://github.com/danielvaughn/hz

You can also watch a video of it in action here: https://x.com/danielvaughn/status/2090456808431165715

Cheers!

203 comments

[ 0.31 ms ] story [ 8.7 ms ] thread
Are we supposed to be able to read the examples with our eyes? It looks like black text on a very dark grey background on my iPhone.

EDIT: same on Firefox on my Mac (macOS Ventura).

I’ve been thinking about something along these lines for some time. I really like the direction of this.

The challenge I see more broadly is we (as engineers now empowered by LLMs) are trying to find the right level of abstraction to operate in. Writing long form sentences and (sometime) reviewing the output feels too far away. But having an LLM work directly with you in an IDE feels too close to “the old way”.

Personally for me the approach here still feels a little too close to the lower level old way, but it’s better than the two approaches above.

Excited to see where you take it!

Right level of abstraction is a good way of putting it. It's basically like creating a custom DSL, but flexibility of LLMs allow the DSL to be ad-hoc.

At what point will you need formal rigid syntax? Or is not having rigid syntax the point? If the latter, how much "informational noise" or ambiguity can you inject before the "DSL compiler" gets confused?

Scaling is another bit. Convertible Psuedocode a great pattern for writing functions, but is it useful for writing modules? If you're writing a paragraph to change behavior of a function, you're underutilizing LLMs. Paragraphs are best for spec'ing modules, and the LLMs already fill in the blanks. Not sure if it would be faster to psuedocode the entire module (although maybe just the interface would be a sweet spot...)

Yeah exactly. The module/directory level is currently untested. I'm working on a desktop version so I can talk to a file system, and then I'll be able to explore those problems.

My guess is that if you simply write `use some_fn from $repo/some/path`, the LLM _should_ be smart enough to infer in most cases. But we'll have to see how reliable that is.

Definitely an approach worth exploring! I actually started to look into semi formal spec language like Quint because I wanted something more structured then prose, so I feel like this goes into the right direction.
Writing fizzbuzz requires that you understand algo + you credit card, while agent requires only your credit card. I believe most of people will pick the 2nd one.
Yes for many non-technical people who are building stuff for the very first time, this is absolutely true. Natural language will always be easier for them. But experienced engineers are wanting to use AI for very complex codebases, and AI struggles significantly beyond a certain point.
Would need to try out in a complex project to have opinion. However I already see few problems. Slower development due this loop of generating code from you mini spec. I would snap and start writing code at one moment. Different agent different code, off by one errors that agent deducts itself, and you miss because spec doesn't force you to write correct code. Those might be caught by unit tests, but then why not generate code based on tests, as uncle Bob does...

With scale problems arise.

You seem to be conflating two things: how to prompt, and how to share sessions. You can already use pseudo-code today if you want to. As for sharing, you can commit (a link to) it, use `git notes` (as I do), or a service like entire.io.

I think you should work on your differentiation. The session management stuff is the greater concern, in my opinion; pseudo code is not a novelty.

Help me understand - what do you mean be "share sessions"? And yes you can definitely use pseudo code today - that in and of itself is not a novelty at all. The specific novelty is the fact that the editor assumes two equivalent sources - your pseudocode which acts as a prompt, and the source code generated from that prompt. The editor also provides a source map for the two, so that as a codebase grows in size and complexity, it's trivial to link a specific section of code back to a human's written intent.
(comment deleted)
Dumb question:

Why not just put an instruction into your favorite harness’ system prompt: “If I give you pseudo code, spell out my intent, and then write and test it in real code.”

I think that just adds another unnecessary level of abstraction that you then have to understand before you can approve. It feels like taking a half-step backwards before moving forwards again.
Hmm. Interesting idea.

What about multi-file / larger changes? How would you express files being connected, imports, and exports? Or are you thinking the hz files are disposable per change?

The intention is for the files to persist, and I didn't mention it, but a core part of the system is that the editor persists source maps. So at any point in time, you can map any generated line back to the line of pseudocode that generated it.

I'll be looking into multi-file stuff soon - it's an interesting can of worms to think through.

I think the idea of having a human-written persistent document describing the operation of the code is a great idea. This document acts as the prompting interface instead of the chat window and changes can still be tracked. Surely something as simple as a skill.md can be made for such a setup, right? I think the pseudocode style is a seperate axis to this setup.
This is basically a compiler, but we’re moving up a layer of abstraction.
curious if you’ve tried Kiro or spec-driven development? that seems like it would solve at least some of the issues you raised with agent based development, albeit in a different way without the emphasis on pseudo code
yeah in the blog post I should have outlined the things I first tried to solve the problem. I tried a variant of gherkin rules, using them for the behavioral spec for a project. It works reasonably well, but without a direct source map from the rules to the code, you still end up with a very difficult-to-understand codebase.
I'm confused, it looks like you've just written a new terse language that now costs money to compile?
Afaik there's no language - the pseudocode can be written however you want. And the costing money to compile? If you're prompting an llm you're already doing that, just with prose instead of pseudocode. I'm not sure this approach is a good idea, but it might be - and imo it's worth trying :)
> I'm not sure this approach is a good idea, but it might be

After the last year, I feel like this sentence could replace half my outbound emails.

Technically speaking everything costs money to compile in the form of electricity. This is just...inefficient compilation.
I have to admit, I am unsure if this article was some sort of parody.
Same, I am still thinking that it's a parody: going full loop back to programming
Basically yes that’s what I’m proposing. Not sure if I’d describe it as a loop though - more like returning to some midway point after having traveled too far in one direction.

Fully manual coding is the most reliable but extremely slow and costly.

Fully LLM driven coding is extremely fast, but for serious work is too unreliable.

Spec-driven development might be viable, but too often the specs end up being LLM maintained, which defeats the purpose.

You need some hard boundary in the codebase where only human hands touch the files. And you want to enable the velocity that AI allows. So yes, semi-formal programming does seem like a promising solution.

Yes exactly. Except now, the language has zero constraints. It can be a perfect distillation of your intentions.

You might think, well code is perfect. But code is syntactically perfect, because it has to be. Because compilers can handle very little ambiguity. But that doesn't mean it's a perfect representation of your thoughts. A huge part of language design is for the compiler, not for the author.

And I'm not 100% sure of this, but I'm fairly confident that this approach would be far more token efficient than the way we currently use AI for programming.

I could this before too. The way I work is that I just write some functions, fully annotated, in whatever language the project is in, with a comment on what I expect the code to do, and an empty return. Then get an LLM to fill in the functions.

Helps me think about the problem, like your post mentioned, but I don't have to pay a tax on converting a prototyping language to a different language.

This is how I liked to write software pre-LLM. Top down. Write the interface and tests first, implementation second. I think I got it from SICP. "Wish-driven programming" I think I heard once.
That’s exactly what this editor is for, except that your original written version is retained and source-mapped to the code that it generated. So as a project grows in size and complexity, you have a smaller foot print of human-written intent that acts as a reference. There’s no “prototyping language”, it’s just whatever you want to write.
not sure if the hz file artifact is needed, you can enter pseudocode directly into chat or even on an existing code file and with minor comment agents will be able to work with it. i write this type of pseudocode to existing code files often to great results.
Isn't this just spec-driven development in a different language?
I'd call this one Micropilot.

As in micromanagement.

> There’s no reliable record of human intent.

Every engineer I have ever mentored got a lesson on how to write a good commit message that included this. This is exactly that.

Further Huzzah from skimming it over seems to be re-inventing documenting your code.

Together I can only surmise that the author is new out of school or has simply not yet worked on a team with good coding practices.

Two clicks from the article:

> Welcome to my Github! I'm a web engineer who's been building front-ends since 2009. Most of my work is either closed source or behind paywalls, but here is where I tinker on side projects in my spare time.

No need to dismiss the person - you can just say you don't like the approach

A good commit message is not a record of human intent, it's a record of changes in human intent. You can read a change log to see the evolution of a codebase, sure.

But before AI arrived on the scene, source code was a single artifact that directly expressed the intended behavior of a piece of software as it currently exists. After AI, the artifact is still there, but it's no longer the true record of human intent.

A good commit message will survive longer than this proposal is the point.

What the author is proposing has a long history of similar ideas: Literate Programming, UML modeling, DSL crazes, and now to LLM-generated abstractions. AI isn't special. They always fail in the same ways as basic "commenting your code". One can even argue that unit tests are a close cousin to this same problem. Taken one step further how is Huzzah better than just using property tests?

What I find interesting about this + a random bucket of associations because I’ve fallen under the spell of Satan’s Lettuce:

Just a few days ago someone was talking about a machine - human patois.

This (your project) sits somewhere between Lean and BDD cucumber syntax.

At the same time Claude spits out phrases like “a container paying the price of -42px”.

Recently I was listening to a lecture about metaphor in poetry, the misconception that poems are riddles whereas we use metaphors all the time in our language because they convey the meaning more precisely.

Appreciate the new word in my lexicon - had to google "patois", and I love thinking about this as a way towards code "dialects." Even the example I gave sits somewhere between python and, idk, something else. In other examples I wrote, I found myself intermixing Rust and Lisp.

Also love the BDD reference - this is in fact an evolution of an earlier approach where I was trying to combine DDD event storming with Gherkin Rules. Very keen observation.

I think "the pseudocode is persisted alongside the generated code" just reinvented jira/linear tickets and PR descriptions. We have ways of using git and tracing the code write to the thought process behind it.
The difference is that linear tickets, PR descriptions, git commits etc all track changes to the code, but not the code itself. You could read a changelog to understand the evolution of an application, but it wouldn't give you a stable, clear sense of what the intended product is right now.
Plus, it'll go stale as quickly as comments do. Some might be correct, but I think a lot of code gets fixed or changed pretty quickly, meaning the pseudocode is basically useless afterwards, unless it's updated... And that's a whole new effort.
I think the reverse direction is more important: taking a massive complex problem/codebase and decomposing it to short pseudocode. Then you could edit the pseudocode and compile it back into the system.

That's the way software engineers working on large projects work anyway: you first gather context on the state of the system and read it at a level you can understand. Then you propose a change on the simplified representation, and then holistically update the machine-runnable format ("implementation").

I'd be interested in tools that formalize/automate this process more.

Clever! :)

Difficult! :(

I don't think it's particularly difficult, or clever. You can prompt your way into this with frontier models, especially if your codebase is designed for it from the ground up (architecture well factored, documented, tested, harnessable, so that it even has a pseudocode representation in the first place).

The biggest issue is you end up leaning heavily on the quality of the model. Lower fidelity models tend to make a mess and add tech debt that you must frequently repay with intentional cleanup passes from a higher quality model, or else the rate of useful progress will fall off a cliff. At least that's my experience.

Massive, complex codebase…short pseudocode.

The fact that you don’t think this is particularly difficult makes me questions everything after that statement.

I'm working on a bidirectional version of this! The big challenge is keeping the various versions of the thing in sync through edits.
This is the entire domain of programming language design, except with the goal of doing it reliably and deterministically enough that you didn't need to look past the short version of the code at the compiled output.

We all know how badly that failed once we started coming up with AI, and could outsource dealing with all that bullshit.

Yeah I'm not opposed to bi-directionality, though right now there are a ton of projects attempting to do some variation on that theme. Extracting specs from code, producing short summaries, etc. I've tried a few ideas at the company I work for, and they never seem to pan out. At the end of the day, you need something that was simply written by human hands.
I had a LLM based prototype called "cleanroom" which would convert a program into a spec and then back into a program.

The results were disgusting: the spec would encode all sorts of irrelevant implementation details, and then the new version would reimplement them faithfully, and be 3x more bloated than the original. The exact opposite of what I was going for!

I didn't put much effort into it, maybe it was solvable with prompting (or more likely, more human effort on the spec phase), but it looks like the LLM has the same problem as the human, it can't know what the intention was, and it can't know what's relevant, what's essential and incidental.

But basically, what I needed wasn't a spec but user stories. (And probably multiple prototype outputs to choose from...)

I should definitely give it another crack though...

---

P.S., Spoiler for next ten years: software as biology (esp. crossbreeding, mutation, selection pressure...)

This largely matches my experience, and was one of the motivators behind this project. For some reason, LLMs are still very bad at distillation. We had a really large and complex codebase at my job that I had to quickly ramp up on. I asked an LLM to generate product docs from it, and it barely helped me.

I came to the conclusion that something in the codebase needs a hard boundary, where the team agrees that only human hands touch it. Otherwise the entire repo becomes untrustworthy as far as discovering intent goes.

I just use a lot of folders, like folder for ever class and manager class with it and anything else. So its kind of organized by folders like plugins. Much easier to reason about. The biggest problem is the central class that glues everything is now 30 thousand lines, but its mostly repetitive delegation, init update, draw, delete. Still should be some nicer solution than having a huge class in center.
Terse pseudo code > verbose prose

Coding Encoding Think about the terms

If the pseudocode is precise, what you want is a compiler. Otherwise the LLM is still making decisions for you.
I think that this would be easy to criticize without interfacing with their underlying idea here.

It's cool that with a tool like this you don't NEED to get all aspects of your code finalized and ready. It's possible to be vague when you want to and specific when you need to.

I'm not sure if that itself would work well in practice, but the project is still quite cool nonetheless.

Invented New coding language that transpile to other coding languages and saying it novel approach.
I like the direction of capturing the human intent as a durable artifact, but I dislike how you've gotten there.

Let's look at your fizzbuzz example. Unfortunately, if you wanted to have the agent implement fizzbuzz for you, it looks like, in your example, you would have to already know how to effectively write fizzbuzz. Specifically, you call out the use of the modulo.

In your prompt, for the traditional agentic development path, you already declared the intent. There is some imperative language in there, sure, "Create a function that ...", but also there is the declarative state, that doesn't require knowledge of specific programming syntax or semantics.

What I've relied on is a more formal location/syntax for acceptance criteria are in code. These are then used to generate tests, and implementations. It isn't perfect, and more investment is needed, but it starts getting at the root of the problem.