Tuesday, August 18, 2026

Late Night Heavy Thoughts

The current temperature of the universe is 2.72548 Kelvin.

By Landauer's principle, the minimum amount of energy required to erase or alter one bit of information is kT ln(2), where k is Boltzmann's constant and T is the temperature in Kelvin. At 2.72548 K, this energy is approximately 2.6 x 10-23 Joules.

By Einstein's mass-energy equivalence, E = mc2, this energy corresponds to a mass of approximately 2.9 x 10-40 kilograms.

According to the IDC, the total amount of data stored on the internet is approximately 79 zettabytes (7.9 x 1022 bytes, or 6.32 x 1023 bits). The total mass of all that information is approximately 1.83 x 10-16 kilograms. This is the mass above and beyond the mass of the physical media on which the information is stored. The mass of the information is negligible compared to the mass of the physical media, but it is not zero. (A full disk weighs a tiny bit more than an unformatted one).

The entire internet - Wikipedia, the cat videos, porn, instagram, etc. - weighs about 183 femtograms, which is roughly one-fifth the mass of a single typical bacterium.

passes the doobie...


Monday, August 17, 2026

Coding with an East Coast Vibe

I'm apparently doing it wrong.

According to Andrej Karpathy,

There's a new kind of coding I call 'vibe coding', where you fully give in to the vibes, embrace exponentials, and forget that the code even exists. You just talk to the AI and the app appears.

That sounds way too California to me, too much prompt-and-pray. I'm not going to kick back, grab a kombucha, and tell my model to `Create me an SaaS app, bro`. What I do is more akin to `Dialectical Software Engineering`, but that rolls trippingly off the tongue like peanut butter, so I'm going to call it `East Coast Vibing`.

I work with two LLMs to vibe code my application. I start with Gemini as my high-level `sparring partner` LLM. Its role is to be the `general contractor` for the project. I present an architecture to it and it takes an adversarial approach and challenges my ideas. It asks questions about the requirements and specific design decisions. It pokes holes in my design and makes sure that I have considered all of the relevant factors and edge cases. It will also consider the broader context of the project, including design patterns, user requirements, and long-term maintainability.

I'll spend a couple of hours with `general contractor` arguing design points until we are both satisfied. Only then do I move to the step of actual code generation using a different LLM, GitHub Copilot, which is the `code monkey`. The role of the `code monkey` is to write the actual application code. Its context isn't the broad architectural design I hammered out with the `general contractor`, but specific and detailed knowledge of the codebase, the design patterns, and the style of the code.

I `meta-prompt` the `general contractor` to generate a detailed prompt for the `code monkey` to carry out. The prompt generated for the `code monkey` is quite detailed and specific. It includes the requirements, the design decisions, and the specific code that needs to be written. A typical meta-prompt would be something like this:

Provide an OpenAPI discovery binding for servers who want to discover our API.

This is naturally far too vague a prompt for an LLM to directly carry out, but the `general contractor` has the context of the project and arguments about the design decisions that we just hammered out, so it can generate a detailed prompt for the `code monkey` to carry out. It generates a prompt that looks something like this:

  I am adding an OpenAPI 3.0 discovery document to a Common Lisp Hunchentoot
API. Act as an expert Common Lisp developer.

  Write a Lisp file (or function) that defines and serves a static OpenAPI spec.

**1. The OpenAPI Specification (YAML or JSON):**
Define a global variable (e.g., `*openapi-spec*`) containing the raw OpenAPI 3.0 text. The spec must define:
*   **Info:** Title: "JRM Code Project API", Version: "1.0.0".
*   **Servers:** URL: `https://jrm-code-project.com`.
*   **Paths:**
    *   `POST /api/v1/auth/token`:
        *   Description: "Exchange an API key for a short-lived JWT."
        *   Request Body (required, application/json): `email` (string) and `api_key` (string).
        *   Responses: 
            *   `200`: Success. Returns `access_token` (string), `expires_in` (integer), and `token_type` (string).
            *   `400`: Bad Request.
            *   `401`: Unauthorized (Invalid credentials).
            *   `429`: Too Many Requests.
*   **Components/SecuritySchemes:**
    *   Define a `BearerAuth` scheme (type: `http`, scheme: `bearer`, bearerFormat: `JWT`).
*   **Security:** Apply `BearerAuth` globally (optional, but good for future endpoints).

**2. The Hunchentoot Route:**
Write a Hunchentoot handler (e.g., `define-easy-handler`) for `GET /openapi.yaml` (or `.json` depending on how you formatted the string).
*   It should set the appropriate `content-type` (`application/yaml` or `application/json`).
*   It should return the contents of `*openapi-spec*`.
*   Ensure this route is *not* protected by the JWT or restrictive rate limiting, as it must be publicly discoverable by machines.

  Write clean, idiomatic Lisp. Just embed the spec as a string literal to keep
dependencies minimal; we don't need a heavy YAML parsing library just to serve a
static document.

This detailed prompt is then handed to Copilot, which writes the actual Common Lisp code that implements the specified endpoints and updates the OpenAPI specification. Copilot focuses on extending the existing codebase and ensuring that the new code adheres to the existing architecture and coding standards. It does not need to worry about the broader context of the project, as that is the responsibility of the `general contractor`. The prompt given to the `code monkey' is detailed and specific enough that it can write the code without hallucinations and test the code it has written to ensure that it meets the requirements.

You can get away with a few rounds of this back-and-forth with the `general contractor` and `code monkey` but technical debt will accumulate quickly. The `code monkey` will write working code, but it will take shortcuts and make decisions that are expedient in the short term but will cause problems in the long term. This is the point where we need to go in and refactor the code to make it more maintainable and extensible.

We go directly to the `code monkey` and prompt it to analyze the code and identify the technical debt. We prompt the LLM to rank the technical debt in order of severity and impact and write it to a file. Then we iterate with the simple prompt of `Select the most important element of technical debt and address it.` We burn down the P0 and P1 technical debt and address a number of the P2 items. Attempting to address all of the P2 items tends to lead to code churn and diminishing returns, but the P0 and P1 items are absolutely worth addressing. Every few rounds of feature development, we return to addressing the technical debt. This is important to keep the codebase from becoming a tangled mess of spaghetti code.

Left to its own devices, the LLM will write imperative, procedural code. That is because the bulk of the code it has been trained on is imperative, procedural code. This kind of code is easy to write, but it is hard to maintain and extend. State tends to creep into the code base and the LLM will find it difficult to reason about the code because it has to keep track of the state of the system across multiple functions and modules.

The solution is to prompt the LLM to write functional code. Functional code is easier to reason about because it is stateless and the output of a function depends only on its input. With functional code, the LLM can reason locally and does not need to keep track of implicit time. If the code is largely written in a functional style, the LLM will find it easier to continue to extend the code in a functional style, but it will occasionally slip back into imperative, procedural code. When that happens, we prompt the LLM to refactor the code to be more functional.

Early on in the project, we prompt the LLM to do a full functional refactoring of the codebase. This is a big job and takes multiple steps. If the code fundamentally models side effects, then it is difficult to refactor it to be fully functional. If this is the case, we prompt the LLM to move the side effects to the edges of the codebase and keep the core of the codebase functional through use of functional/reactive programming and monadic programming techniques.

Pure functional code is easier to test and debug because each function can be written and tested in isolation. The LLM can limit the scope of the code it is writing to a single function and at a time. It can reason about the function and its inputs and outputs without having to reason about the state of the code that calls the function.

Taking a disciplined approach to software development will prevent the LLM from writing fragile code that collapses under the weight of its own complexity. It will allow the LLM to write code that is maintainable and extensible.

Conclusion

East Coast Vibing is a disciplined approach to software development that involves these steps:

  • Use two LLMs, one a `general contractor` with a high-level view and the other a `code monkey` down in the trenches .
  • Work with the `general contractor` in an adversarial way to define the architecture and design of the application. Only begin coding when you are satisfied with the design.
  • Use the `general contractor` to generate detailed prompts for the `code monkey` to write the actual code.
  • Frequently perform cycles of technical debt reduction to keep the code clean.
  • Early on in the project, perform a full functional refactoring of the codebase to keep the core of the codebase functional and move side effects to the edges.

No doubt people will argue that this is the wrong way to do things and that I have completely misunderstood what Karpathy meant by `vibe coding`. Perhaps I have, but I have found it an effective way to build software. If you want to kick back with a kombucha and "give in to the exponentials" while the AI hallucinates a brittle Jenga tower, go right ahead. But I suggest you grab a strong black coffee and try the East Coast Vibing approach and engineer a solution.


Sunday, August 16, 2026

SDK for jrm-code-project.com

A few of you have noticed the OpenAPI spec floating around the site lately. Rather than watching everyone write the same HTTP boilerplate from scratch to talk to the server, I went ahead and bundled up a set of official client bindings.

If you want to programmatically hit the pastebin or mess with the other endpoints, the jrm-code-client repository is live.

Right now, it includes complete SDKs for:

  • Common Lisp (obviously)
  • Emacs Lisp (naturally)
  • Python (seriously?)
  • Go (ugh)

They all handle the JWT authentication handshake natively and deserialize the JSON responses into proper language-specific structs/objects. You can stop raw-dogging it with curl (unless that's your thing).

Source is up on GitHub: jrm-code-project/jrm-code-client

Play nice with the rate limits.


Saturday, August 15, 2026

OpenAPI Access to jrm-code-project.com

It's a web site! It's a service! jrm-code-project.com has an OpenAPI specification and you can use it to generate client code in your favorite programming language (which is Lisp, right?). The OpenAPI specification is available at https://jrm-code-project.com/openapi.yaml. There are the following endpoints:

  • GET /api/v1/ping - Returns a simple "pong" response to test connectivity and verify your authentication tier.
  • POST /api/v1/echo - Accepts a JSON payload and returns the same payload in the response. For testing your client.
  • POST /api/v1/auth/token - Exchange your long-lived programmatic API key for a short-lived JWT Bearer token to authenticate secure requests.
  • GET /api/v1/pastes - Retrieve a paste's content by its ID (Publicly readable, no auth required).
  • POST /api/v1/pastes - Create a new code snippet paste (Requires JWT).
  • DELETE /api/v1/pastes - Delete a specific paste you own (Requires JWT).
  • GET /api/v1/user/pastes - List all non-expired pastes associated with your authenticated account (Requires JWT).
  • POST /api/v1/chef - Programmatic access to The Chef. Submit your raw Lisp code to be mercilessly roasted. (Requires JWT and a x-goog-api-key header with your Gemini API key).

I invite you to explore the API and see what you can build with it. If you have any questions or feedback, please don't hesitate to reach out to me at eval.apply@gmail.com.


Friday, August 14, 2026

Pics or it Didn't Happen

An anonymous reader said it out loud: "Alright, it's a simple website… can we see its sources though?"

I started going through the sources and parameterizing the secrets so that there weren't any hard-coded sensitive strings. It's a royal pain because the secrets then have to be injected via environment variables, which means reconfiguring the server on the host and the development environment on the local machine, and let's face it, no one is going to actually run the server, they just want to see what the vibe coded lisp looks like. So I punted and did this instead.

jrm-code-public is a copy of the website repository with the secrets redacted. IT won't run as a standalone web site without some development work. (Although I bet you could sic a high-end model on it have it massage the code into a running state.) I'm releasing it as a snopshot of the source code so you can see the kind of code that the LLM has written for the web site. As you can see, it is a little bit more complex than your standard static web site.

The Lisp code isn't bad for machine generated. There is a lot to critique, sure, but a lot is pretty good, too. I've seen worse code in production.

As usual, I put this under an MIT license, so feel free to use any or all of it in your own projects. You could even use this as the skeleton for nibe coding your own site.


Thursday, August 13, 2026

A Web Site in Vibe Coded Common Lisp

I believe that vibe coding is the future. This is crazy because last year I was a skeptic. Last year LLMs couldn't write large Lisp programs. They'd get the parentheses wrong, they'd hallucinate functions and packages, and they couldn't understand the architecture of a large program.

This is all in the past.

A SOTA frontier LLM absoulely can write large lisp programs. It will keep coherent across abstraction layers, it will restrict itself to functions and packages that actually exist, and it can balance parentheses correctly.

I put my money where my mouth is. jrm-code-project.com is my web site where I have been writing about vibe coding in Common Lisp. The site is written in 100% Common Lisp and it is 100% vibe coded. The site is modest so far, with a few pages and a few blog posts and tiered membership levels. It isn't pretty; neither I nor my LLM is a graphic designer. As a pedagogic exercise I added a Lisp pastebin to the site. I invite people to create a free account and try it out. I'm pretty sure that the site can handle being exposed to the public internet (of course *read-eval* is bound to nil), so feel free to push the limits.


Sunday, August 9, 2026

llambda.lisp on linux

A reader named Madhu sent me a patch for running llambda.lisp under linux. This patch uses mmap to pull the weights into the lisp address space outside the heap.

In addition, he tried to use a hugging face model that needed some default values, so he added them.

He reports that he was able to get the model to do inference on his linux box with about an hour of hacking. I have incorporated his patches and pushed the update to GitHub.