Cursor CEO Michael Truell suggested that a new kind of language be introduced for writing and maintaining software:
“You have a representation of the logic of your software that does look more like English…You can imagine kind of an evolution of programming language towards pseudocode. You have written down the logic of the software, and you can edit that at a high level.”
It’s worth pulling this thread, but that requires grasping what makes programming languages different than language.
A program can be as simple as “if X then do Y.” In a programming language, we’d have something like:
function main(input) {
if (input === "do it") { console.log('Did it!') };
}
// In English: If the input of main is "do it," then log "Did it!" to the console.Before LLMs, a file of pseudocode instructions would, arguably, be harder to read and reason about than a programming language’s syntactic structure.
However, after LLMs, models can normalize pseudocode instructions into a programming language, preserving the readability/maintainability of syntactic structure but with the ease of English.
Let’s look at another example.
function main() {
let str = "";
for (let i = 0; i < 9; i++) {
str += i;
}
console.log(str);
}
// In English: Start with an empty string, count from 0 to 9,
// append the current number to the original string,
// and then output the final string after counting.In this example, the value of the syntactic structure becomes prominent. Proximity to “plain English” is not the measure for readability/maintainability.
However, pseudocode may be more precise than my example. It could contain the niceties of color-coordination and symbols that make instructions more clear.
main()
BEGIN WITH an empty String:str
COUNT to 10
APPEND COUNT>Index to str
FINALLY, LOG strHere, we can see some tradeoffs.
The most “plain English” versions could drift from giving programmatic instructions to output commands without any visual indication that this shift has taken place. However, when you are working in a defined programming language, you are always bound to programmatic instructions to arrive at the end goal. Comments are a non-essential feature where non-programmatic communication can provide further clarification.
The programming language makes reasoning explicit, and so, it is easier to reason about. Unlike output commands, you have an interpretable trace of “how the problem was solved,” not just “that the problem was solved.”
Perhaps you could craft a cleaner pseudocode grammar, but it likewise could drift from explicit reasoning to output commands without any visual indication.
Putting this together, the consistency of programming languages to adhere to bind you to “here’s how we get there technically” instructions provides real value.
But this is oversimplified. Programming languages already let you collapse explicit reasoning into a reusable command, which is what a function is, so collapsing reasoning into output isn't unique to pseudocode. It is the habit of software engineers to create layers of abstraction that effectively create output commands so instructions can be reused without the verbosity of the explicit reasoning each time. This gives you the speed and brevity of processing output commands while preserving the option to see the explicit instructions. The speed and brevity of processing, however, can be watered down when you have to traverse multiple layers of abstractions to fully understand the explicit reasoning that is taking place. This is the complexity of developing software.
Perhaps the matter is not quite as black and white as we perceive. Imagine if we could provide a syntactic structure that makes the shifting from output commands to explicit reasoning prominent:
function sum(left, right) {
return left + right;
}
function main() {
return sum(2, 2) * sum(3, 3);
}
// becomes
🧠 sum(left, right) { return left + right }
📣 Multiply 🧠sum(2, 2)by 🧠sum(3, 3)
// Another Example
function main() {
let str = "";
for (let i = 0; i < 9; i++) {
str += i;
}
console.log(str);
}
// Could be rewritten as a mix of output commands and explicit reasoning
📣 Log "0123456789" by 🧠counting to 9 and 🧠appending the count index to a stringOne can think of better examples. The point is to highlight the potential for symbolically differentiating command and reasoning. This directly answers the silent drift problem from earlier. Now, the shift between explicit reasoning and output command is marked, not assumed.
Although, my example isn’t concerned with how my symbols can be processed into lower-level code and the computational tradeoffs involved. However, LLMs lessen this concern since they have the intelligence to normalize such a pseudocode at scale, though whether that normalization can be trusted is a separate question.
There could be a legitimate workflow, as Truell suggests, where pseudocode is what is immediately written and maintained by the LLM, and some standardized, LLM-driven tooling can process into lower-level code to run in various environments.
Wherever this goes, it is something more complex than “explicit versus readable” carries.

