Back to Release Notes

cfire: C++23 Without the Ceremony

Batteries-included systems code that plays nice with agents.

I’ve always had a soft spot for programming languages and systems programming. There is something uniquely satisfying about writing code that sits close to the metal — knowing exactly how memory is laid out, feeling the raw speed, and seeing tangible performance materialize on real hardware.

For that kind of work, modern C++ (especially C++20 and C++23) is actually a remarkable language. Features like std::expected, std::span, std::format, and concepts have made the language fundamentally safer and more expressive than it was a decade ago.

The problem isn’t the core language anymore. The problem is everything around it.

The Tooling Tax (and the Agent Problem)

If you want to build a small, high-performance systems tool in C++, you immediately run into a familiar wall of ceremony:

  • You need CMake, Meson, or a multi-page Makefile just to link SQLite, zstd, or a JSON parser.
  • You spend half your afternoon writing header guards, forward declarations, and repetitive const T& signatures.
  • When something goes wrong, the compiler dumps four hundred lines of template tracebacks that scroll straight off your terminal screen.

And now, in the age of AI coding assistants and autonomous agents, this friction multiplies.

Agents are great at reasoning about algorithms and data structures, but traditional C++ toolchains actively fight them. An agent writes a clean function, but it fails to compile because a CMake target wasn’t exported properly, an include path was missing, or a subtle std::move hazard triggered an opaque compiler warning. The agent ends up in a hallucination loop trying to appease a convoluted build system instead of solving your problem.

Shrinking the Surface Area

When I built Tako, the guiding principle was simple: shrink the surface area. Your code already expresses what it wants to do, so you shouldn’t have to repeat your architectural intent across Dockerfiles, Terraform, and YAML.

cfire (.cf) comes from the exact same philosophy, applied to systems programming:

  1. Write clean, high-level intent.
  2. Batteries included.
  3. Lower 1:1 to zero-overhead, human-readable C++23.

No garbage collector. No hidden runtime penalty. Zero external build tool dependencies. You have one single binary — cfire — and it gives you a complete, self-contained development environment with a built-in compiler, test runner, formatter, doc generator, and LSP server.

Declaring Intent Cleanly

In cfire, you write clean structural code that feels like Go, Odin, or TypeScript, but lowers directly to idiomatic C++23:

import "core:fs"
import "core:json"
import "core:db/sqlite"

struct User {
    id: i64,
    username: str,
    email: str,
}

fn load_users(db_path: str) -> vector[User]! {
    let db = sqlite.open(db_path)?;
    defer db.close();

    let users = db.query[User]("SELECT id, username, email FROM users ORDER BY id ASC")?;
    return users;
}

fn main() -> i32 {
    let users = load_users("app.db") match {
        case Ok(val) => val,
        case Err(err) => {
            println("Failed to load users: {}", err);
            return 1;
        }
    };

    println("Loaded {} active users.", users.len());
    return 0;
}

Notice what isn’t there:

  • No build scripts: You import core:db/sqlite or core:compress/zstd, and cfire automatically includes the headers and links the native engine (-lsqlite3, -lzstd).
  • No pointer anxiety: Parameters are read-only (in) by default. When you need mutability, you say mut. When you pass ownership, you say move.
  • First-class errors: T! is simply std::expected<T, cfire::Error>. The ? operator unwraps the value or returns early, and pattern matching handles errors without exception overhead.

Why It Plays Nice With Agents

When agents write code, they thrive on fast feedback loops and deterministic interfaces. Because cfire bundles everything into a single tool with no external dependencies, an agent has a predictable pair-programming flow:

  • Run in one shot: cfire run main.cf compiles, links, and runs without touching CMake.
  • Built-in unit tests: Write test "validates email" { ... } directly in any file and verify it with cfire test.
  • Deterministic formatting: cfire fmt ensures syntax remains canonical.
  • Localized errors: Syntax and type diagnostics point straight to the source line with clear error messages, keeping the context window clean.

Eating My Own Cooking

cfire itself is written in pure C++23 with zero external dependencies, compiling itself and running across macOS and Linux.

I’ve been using it to build small, high-performance command-line tools and audio experiments that I can actually finish and share without losing an entire weekend to build configuration.

If you want to take it for a spin:

git clone https://github.com/gsandoval/cfire.git
cd cfire && make
./cfire run examples/01-hello-core/main.cf

The interactive documentation and complete standard library catalog are live at cfire.memo.engineer.

At the end of the day, I build things because I like seeing impact materialize. I hope cfire makes writing fast, low-level code a little simpler and a lot more approachable for you and your agents too.