jb… a weblog by Jonathan Buys

LLMs have made simple software trivial

January 9, 2026

I was out for a run today and I had an idea for an app. I busted out my own app, Quick Notes, and dictated what I wanted this app to do in detail. When I got home, I created a new project in Xcode, I committed it to GitHub, and then I gave Claude Code on the web those dictated notes and asked it to build that app.

About two minutes later, it was done…and it had a build error. 😅

But it was a simple fix, I fixed it, and the app was running on my phone. And you know what? It worked. The UI wasn’t perfect, but it was damn close. And I already had a product that achieved the goal I set out to achieve. All in all, I’d say it was about 10 minutes from idea to functioning MVP (and half of that was finishing my run).

If we could figure out how to do this without consuming the power equivalent of New England in the winter, I’d be all for it.

Jump to Post


How the hell are you supposed to have a career in tech in 2026? - Anil Dash

January 5, 2026

What you can control, though, are small iterative things that make you feel better on a human scale, in little ways, when you can. You can help yourself maintain perspective, and you can do the same for those around you who share your values, and who care about the same personal or professional goals that you do.

A lot of us still care about things like the potential for technology to help people, or still believe in the idealistic and positive goals that got us into our careers in the first place. We weren’t wrong, or naive, or foolish to aspire to those goals simply because some bad actors sought to undermine them. And it’s okay to feel frustrated or scared in a time when it seems to many like those goals could be further away than they’ve been in a long time.

I do hope, though, that people can see that, by sticking together, and focusing on the things that are within our reach, things can begin to change. All it takes is remembering that the power in tech truly rests with all the people who actually make things, not with the loudmouths at the top who try to tear things down.

Lovely essay by Anil Dash, and besides his abstractions he does include some very actionable advice. Like building expertise and investing in relationships.

Jump to Post


Solving for Meaningfulness - MacSparky

January 3, 2026

Some things deserve to be slow. That’s where the meaning lives.

Good reminder for the new year from the Apple communities uncle, MacSparky.

Jump to Post


Accepting friction - listening without a streaming subscription (Part 1) – Tracy Durnell's Mind Garden

January 3, 2026

Kyle Raymond Fitzpatrick remembers the “homework” we used to do as music fans – reading reviews, seeking out the opinions of music critics – “all in the service of purchasing music.” Now there’s a pre-made playlist for every moment; we no longer need to spend hours curating playlists for ourselves if we want a different mix for working out, for writing, for cooking dinner. Streaming saves us a lot of work… but, ironically, people like things better when we have to work to find them. Being served music instead of seeking it out for ourselves makes us into consumers moreso than listeners. Fitzpatrick continues: “This passivity makes us as audiences, as people, less engaged with what we’re doing.”

Being more mindful, present, and engaged with whatever I’m doing is in line with this year’s theme of Getting Real1. I’ve been thinking more about my personal music collection, and how important music used to be to me. I remember doing a presentation for one of my clases on how impactful music can be back in 8th grade. I’ve even started building up a vinyl collection, and have really enjoyed the ritual and intentionality of spending time “listening to music”.

I’m not ready to cancel my Apple Music streaming account, my entire family uses it. But, I think it might be fun to sign out on my MacBook and rebuild my personal, curated, and beautifully organized mp3 collection again.

Jump to Post

  1. Not to be confused with the Basecamp book of the same name. 


The Year That Kicked My Ass - furbo.org

January 2, 2026

Consider my ass well and truly kicked.

Absolutely heartbreaking year for Craig Hockenberry. I just purchased Tot. I’d suggest you do as well.

Jump to Post


Lifting the Fog

December 18, 2025

To say that 2025 has been a hectic year would be an understatement. Even in my personal corner of the world, my work life has been chaotic, far more than I would have liked. I’ve lost one team member, brought on a new one, weathered changes and challenges at the company level, and overall become far more reactive than proactive than I’d like. Feels like I’ve been trying to steer a ship through the fog, with only the dimmest lighthouse to guide the way.

Part of that is my own confusion about where I wanted my professional life to go. Since being promoted from Staff Engineer to Engineering Manager (and seeing my old team dismantled and handed over to foreign contractors), I’ve been unsure about how much time I wanted to dedicate to maintaining my technical skills. Not only that, but the additional uncertainty present with the proliferation of AI tools and massive layoffs in tech has also caused me to question my place in the industry for the next part of my career.

Am I still an engineer? Was I ever? Am I now just a manager?

I think the answer for the foreseeable future is going to be both… and more.

I’ve been what I would describe as a competent programmer. My history with Objective-C, and experience with Python and other languages along the way, has given me a good foundation for understanding the concepts and syntax needed to build applications. However, most of my professional experience has been focused on scripting and DevOps-centric tasks. Building pipelines, setting up system automations, etc. From time to time, I’ve dabbled in other languages, but I haven’t gone all in on any of them. I’d like to change that. One of the things I’m going to focus on in the new year is learning Rust. I’m not one for making resolutions; instead, I create yearly themes, with a few ideal outcomes for the year. I’m not “resolving” to learn Rust this year, but I am focusing on it as part of my overall theme.

As a sysadmin, and later a DevOps engineer, I’ve always focused on deep technical expertise. That meant understanding filesystems at the kernel level, tracing TCP packets through the system, and occasionally spelunking through the Linux kernel source code. Over the past few years of cloud automation, though, a lot of that has fallen to the wayside to make way for learning the AWS APIs. I’ve missed the low-level operating system work. I haven’t had to manage a RAID array in nearly 10 years, nor have I had to track down why a deleted file still has an open handle. However, I do now have an opportunity to dig back into some hard low-level problems, and I’m looking forward to seeing what new skills I can learn.

Taking on a management role has been one of the most challenging things I’ve done in my career. Not because of my plans for where I’d like the systems we’re responsible for to go, but because of all the other interpersonal tasks that are now my responsibility. Last year I hired the first person on my team, and this year I had to let a person on my team go. Both decisions were difficult, and the second took far longer than it should have. That was a lesson learned, one that cost me months of productivity. There are other management tasks that are difficult, like deciding on metrics to gather, how to build reports that are worthwhile, and how best to accurately reflect the value of our team. Management has a lot of abstractions, time-consuming tasks that attempt to convey an idea, either to my team, to my boss, or to the rest of the company. Difficult, but interesting.

Thinking through these aspects of my career informs my position on AI. I’ve gotten to where I am by prioritizing expertise, technical knowledge, quick learning, and being able to get things done. What I’ve noticed using AI occasionally over the past couple of years is that it makes me intellectually lazy. When faced with a difficult problem, my first impulse isn’t to dig into the problem and discern a solution, it’s to hand the problem over to AI and see what it has to say. This unhealthy habit undermines the very thing my career has been built on, thinking clearly. When I offload a task to AI I’m offloading my own thinking, and that’s something I just can’t do. On top of that, AI has very real environmental problems and a questionable financial future, at least in its current form. I understand the usefulness of AI for many tasks, but for me, personally, I can’t risk my career on outsourcing my brain.

So, that’s 800 words or so on why I’m thinking my next yearly theme should be “The Year of Thinking Clearly”. My focus will be on building my expertise, communicating effectively, and, as an essential part of having a clear head, building and maintaining a consistent and challenging exercise program. Healthy body, healthy mind. I’m looking forward to 2026. I think it could be one of my best years ever.


xkcd - Fifteen Years

November 25, 2025

Absolutely beautiful.

Jump to Post


Searching for Non-Printable Characters in Text

August 14, 2025

One of the systems at work accepts data in csv format, which is essentially plain text with columns separated by commas. Occasionally a client will upload a file with mistakes in it, and while our applications are fairly robust and can handle most issues, sometimes one slips by that we weren’t expecting. When this happens, as it has twice in the past as many days, I’m called in to find out why.

The first issue was with a Python application that was pulling a file from S3, parsing it, and turning it into a tab-separated values file before uploading it back to S3 to be further processed by another system. The error given by Python’s csv package was:

_csv.Error: need to escape, but no escapechar set

Which was odd because we process many, many files during a day and this same code hasn’t needed to set anything else. After a bit of faffing around replicating the error locally, and isolating where in the code the error was occuring, I finally got it in my head to just grep the file for special characters. Sure enough, I found that the file contained tabs inside of the values, which given the logic of our program was causing it to have a bad time of it.

The command grep '\t' in.csv gave me the lines containing the offending tabs, and grep -n '\t' in.csv | cut -d : -f 1 gave me just the line numbers, which is what I was asked for. The cut command lets me select specific parts of a line, in this case I asked for -d : which set the colon as the delimiter, and -f 1 which asked for just the first column.

This morning I was asked to look at another task that had failed, this time using a custom Go binary that, again, parsed a csv file from S3. Thinking I might get lucky I ran the same search for tabs in the file but came up empty. After some looking around I found a Stack Overflow question that pointed me in the right direction, but I first had to install the GNU version of grep.

When Mac OS was merged with NeXTSTEP to create Mac OS X, the NeXT OS brought with it pure Unix underpinnings thanks to BSD1. Thanks to that lineage, the Mac contains all the Unix tools we’d expect, but it does not include the Linux tools you’d expect. There are sometimes subtle differences between the tools, and I’ve found that the (ugg…) GNU/Linux version of grep to be more flexible. Luckily, Homebrew makes it trivially easy to install standard GNU tools, and running brew install grep provided me with the ggrep binary.

Equipped with the right tools for the job, I ran this command:

LC_ALL=C  ggrep --color='auto' -P -n "[\x80-\xFF]" in.csv

I’ve written about setting LC_ALL=C before, so I’ll skip that here. The rest of the command I’ll cover below.

--color='auto', this makes it much easier to spot the matching characters in a long string.

-P, tells grep to use Perl-compatible regular expressions

-n, print the line numbers

"[\x80-\xFF]", This searches the text for the extended ASCII characters ranging from hexadecimal code 80, or €, to code FF, the ÿ, or “Latin small letter y with diaeresis”, according to the ASCII table hosted at ascii-code.com.

Finally, in.csv is just the file name.

After editing the file, re-uploading, and kicking off the job again, it completed successfully. How in the world is it 2025 and we still have text encoding issues?

  1. I thought for years that NeXTSTEP was based on FreeBSD, but Wikipedia tells me that it was actually built initially on the older 4.3BSD-Tahoe. Sometimes I forget how long ago that really was, and how fast Steve Jobs was pushed out of Apple after the announcement of the Mac in 1984. 


Bright Gold in Dark Times

August 10, 2025

On August 6th, in the White House, Tim Cook announced that Apple is committing an additional $100 billion dollars in American manufacturing. If only he’d left it at that. If only Cook had simply announced the additional investment, bringing Apple’s commitment up to $600 billion over the next four years, and then politely thanked the president and walked out of the room, he may have held on to his integrity. But that’s not what happened. Instead, Cook kissed Trump’s ass and gave him a gold participation trophy.

The trophy is a glass plaque, “made in America”, and “designed by a former Marine” (probably while a bald eagle flew overhead singing “God Bless the U.S.A.”, wearing the American flag as a cape, with a gun in one claw and the Constitution in the other) that sits in a 24 karat gold base. The trophy itself is, honestly, kind of ugly. It doesn’t give off the “Designed by Apple in California” vibes I would expect from something that they actually put a lot of effort into. It looks like a high-school shop class project. However mediocre the actual object, Cook’s gift represented his, and Apple’s, subjugation. Bending the knee and kissing the ring. I nearly threw my iMac out the window.

But I didn’t, because my mind grinds slow and fine. I thought on it for days before reading Gruber’s take on Daring Fireball, where he says that Cook:

…is keenly aware that trust and reputation are only accrued slowly, but are always at risk of being squandered quickly, and that this applies both to how he is perceived personally and how Apple is perceived as an institution — a pillar of American ingenuity and industry. His life’s work. And that despite all of that, Cook concluded that debasing himself, selling some shares of his own dignity, was the best course of action — for Apple, for Apple’s customers (and, yes, shareholders), and perhaps even for the country. That ruthless practicality is necessary merely to stay afloat in a sea of abject graft, extortion, and cronyism. That’s dark. That requires considering that the problem isn’t the greed of a few billionaires and executives who ought to resist burgeoning corruption, but that Trump and his sycophants in the Republican Party have already succeeded in corrupting the system. That the corruption isn’t happening, but happened. The United States isn’t heading for existential trouble. We’re in it — and a pathway out is not yet clear. That’s not to say all is forever lost, but that we are, in our current political moment, beyond the point where the game can be played successfully on the level. You can choose to play a crooked game straight, but you can’t win. Business is competition. A loser who played above reproach is still a loser. You need to choose your battles. US manufacturing is Cook’s choice.

Once again, Gruber is faster to put into words what I’ve been mulling over.

To be clear, I fully support Apple bringing manufacturing back to the United States. In rural Iowa, small towns have been decimated over the past few decades by big manufacturers leaving the country and building overseas or in Mexico. Newton’s loss of Maytag is the poster child for describing how lives can be upended and entire ways of life lost due to the greed of corporations chasing the cheapest labor. The loss of identity and self-respect associated with losing a career is one of the reasons we’re in this mess with Trump and his ilk to begin with. But, one can both agree with bringing manufacturing back to the US and despise the bootlicking at the same time. With many things with the Trump administration, it’s not just what is being done, but how they are going about doing it.

Yes, bringing manufacturing back to the US is a good and nobel goal. I hope we can actually do it, but I also hope that we can do it in an environmentally clean way, leveraging renewable energy and sustainable materials harvesting whenever possible. The Republicans want to tout new investments in the US and new jobs, but they don’t believe in climate change, and their oil-drilling overlords won’t let them invest in clean energy alternatives. Since the MAGA cult is in charge of everythign for at least the next year and a half, if not till 2029, the United States is in a downward spiral that I don’t see a way out of.

The government is now blatantly, openly corrupt. Gifts like Cooks are now just the way things are done to win favor. The US is doing everything it can to roll back environmental protections, dissuade people from buying electric or investing at all in renewable energy. The health department is making it harder to get vaccinated. The Department of Education is being dismantled, which will make it easier to send public funds to private religious schools. There are literally masked gangs of thugs kidnapping people off the street in broad daylight and putting them in camps. And just to really own the libs, they give the camps fun names like “Alligator Alcatraz”.

Cook’s display of fealty has given me pause when considering future Apple purchases, but changing my computing platform of choice would be like cutting off my nose to spite my face. The answer isn’t in punishing individual companies (which would also be punishing myself and my family) that are playing by the current rules, the answer is to change the rules. To try to rebuild a fair, just, and civil society, free from the corruption of the MAGA movement. The only way we are going to do that is by making sure we vote out every Republican currently in office, so that not a single one of those sycophantic cowards ever get close to holding power again. Is that likely? Probably not. Not anytime soon anyway. The bad guys won. We’re living in their world now.

I hope Trump scratches the base of his little trophy someday to discover that it is only “gold plated”, and as fake as his orange tan.


ChatGPT Designed Programming Language

July 2, 2025

On a whim, I asked ChatGPT today:

If you were to design a new programming language intended to be written by AI large language models like yourself, and understood by humans who need to check your work, what would the language look like?

I found it’s answer fascinating. Enough that I’d like to preserve it here. It even came up with a nice name for the language, “Clarion”.

Clarion

Below is a high‑level design sketch for “Clarion”, a hypothetical general‑purpose language optimized for two simultaneous audiences:

  • Primary author: an AI large‑language model (LLM) that can generate vast amounts of code quickly.
  • Primary reviewer/maintainer: a human engineer who must be able to audit, reason about and safely evolve that code.

1. Design Goals

Goal Rationale
Machine‑writeable Syntax must be regular, unambiguous and easily producible by generative models (no “smart” whitespace, few context‑sensitive rules).
Human‑verifiable Semantics must be obvious, explicit and compact; defaults that hide complexity are disfavoured.
Formally checkable Every construct should have a precise, machine‑readable specification enabling static verification, model checking and proof generation.
Audit‑friendly Traceability from requirement → spec → test → implementation is first‑class, not external paperwork.
Gradual adoption Can interoperate with C/Python/Rust so that teams can introduce AI‑generated modules incrementally.

2. Core Language Shape

2.1 Surface Syntax

  • Indentation‑agnostic but terminator‑rich: every block ends with an end keyword carrying the block’s opening token, e.g. end func. This sacrifices a little brevity for total clarity.
  • YAML‑like metadata headers precede each file and major declaration, containing:

    ### spec:
    # requirement: REQ‑TR‑017
    # safety‑critical: true
    # proof‑obligation: VerifiedBy="SPARK"
    ###
    
  • UTF‑8 by default but the grammar restricts identifiers to ASCII letters, digits and _ to minimise visual confusion.

2.2 Types and Contracts

Feature Notes
Algebraic data types & pattern matching Like in ML/Rust; deterministic exhaustiveness‑checked.
Refinement types type Positive = Int where value > 0 for lightweight correctness specs.
Dependent‑like “ghost” expressions Allowed only in contracts; erased before runtime.
Units‑of‑measure Prevent dimension errors (Speed = m/s).

Contracts use Dijkstra‑style syntax:

func divide(n: Int, d: NonZeroInt)
    -> (q: Int, r: Int)
pre  d != 0
post n == q*d + r  &&  0 <= r < abs(d)
end func

2.3 Concurrency & Effects

  • Capability‑based effects: Every function’s signature declares which side effects it may perform (io, net, fs, db). The compiler refuses calls across mismatched capabilities.
  • Structured concurrency with hierarchical cancellation scopes (task / end task).
  • Deterministic by default: uncontrolled data races are a compile‑time error; shared mutable state must sit behind sync‑annotated types with statically provable hand‑off patterns.

3. Interaction with LLMs

3.1 Generation‑Guiding Pragmas

LLMs can embed generation hints that do not affect semantics but shape future completions:

pragma lm_hint:
    style = "prefer_recursive"
    complexity_budget = "O(log n)"
end pragma

Humans can delete or override these without touching logic.

3.2 “Round‑trip Delimiters”

Every top‑level entity is bracketed by stable markers so tooling can surgically update just one region:

###<Clarion:func id=sortVersions v=1.0>###
    ... implementation ...
###</Clarion:func id=sortVersions>###

An LLM patching the function must preserve the outer marker and increment the v field; diff reviews become trivial.


4. Tooling & Verification Pipeline

  1. clc (Clarion compiler)

    • Single pass, deterministic.
    • Emits LLVM IR or WebAssembly.
  2. clarion‑lint

    • Style, naming, cyclomatic complexity budgets.
  3. clarion‑prove

    • Generates VCs (verification conditions) from contracts.
    • Delegates to back‑ends (Z3, Coq, Daphne).
    • Embeds proof outlines back into source for audit.
  4. clarion‑trace

    • Traces run‑time values against contracts during testing; produces counter‑example captures for LLM fine‑tuning.
  5. clarion‑doc

    • Extracts spec headers + contracts into human‑readable HTML, hyperlinked to source, tests and proofs.

5. Example Module

### spec:
# module: Payments.Core
# requirement: PAY‑CLR‑002
# author: GPT‑4o
# reviewer: Alice.T
###

import std/crypto.Hash
import std/time.Utc

type Cents = Int where value >= 0

record Invoice:
    id:        Hash256
    issued_at: Utc.Timestamp
    amount:    Cents
end record

enum SettlementStatus:
    | Pending
    | Settled(at: Utc.Timestamp, ref: Hash256)
    | Failed(reason: String)
end enum

func settle(invoice: Invoice, tx_ref: Hash256) 
    -> (status: SettlementStatus)
pre   invoice.amount > 0
post  match status:
          | Settled(at, _) => at >= invoice.issued_at
          | Failed(_)      => true
          | Pending        => false
      end match
cap   net, db
begin
    db.begin_tx()
    let ok = BankApi.sendFunds(invoice.id, invoice.amount, tx_ref)
    if ok then
        db.recordSettlement(invoice.id, tx_ref)
        return Settled(now(), tx_ref)
    else
        db.rollback()
        return Failed("transfer rejected")
    end if
end func

A human can audit:

  • Preconditions/postconditions are explicit.
  • External side effects (net, db) are called out.
  • Failure modes are exhaustively enumerated.

6. Why Humans Can Trust It

Mechanism Benefit for reviewer
Structural regularity Easy to diff; little “action at a distance.”
Contracts and capability lists Immediate visibility into safety & security boundaries.
Machine‑checked proofs Eliminates gap between design and implementation.
Round‑trip delimiters & version tags Changes are traceable; no silent regeneration.
Self‑describing metadata Links each line of code to higher‑level requirement IDs.

7. Why LLMs Can Write It Well

  • Grammar fits context‑free rules → simpler token‑level generation.
  • No semantic dependence on whitespace → fewer accidental errors.
  • Explicit block terminators → models need not balance indentation.
  • Generation pragmas let prompts steer style and complexity targets.
  • Stable markers allow fine‑grained edits without reconstructing the file.

8. Relationship to Existing Languages

  • Ada/SPARK inspired contracts and determinism, but Clarion is more ergonomic for “everyday” coding.
  • Rust influenced ownership; Clarion lifts capability control to the type system.
  • F★, Dafny supply the verification lineage.
  • Go lent the structured‑concurrency philosophy.
  • Python readability goals remain, but ambiguity is removed.

Final Thoughts

Clarion deliberately sacrifices some brevity and syntactic sugar in exchange for:

  • Audit clarity – humans must see exactly what the AI meant.
  • Mechanical soundness – every compile target, proof obligation and capability is machine‑checkable.
  • Collaborative workflows – the language is equally hospitable to deterministic tooling, continuous integration and regenerative AI agents.

This balance aims to turn AI‑generated code from a black box into a transparently engineered artifact that real teams can rely on—while still letting language models move fast.

Opinions

That func -> end func syntax is ugly, but ChatGPT implicitly states that it’s not designed for “brevity and syntactic sugar”. I’m almost curious enough to see how long it would take the AI to create a complete language spec and compiler. Almost.