Open Compiler, Open Services: Beskid's Licensing Contract
Beskid uses Apache-2.0 for the compiler, runtime, tools, and reusable libraries, and AGPL-3.0-only for Beskid-authored network services. Programs built with Beskid remain yours.
Blog
Recent
Beskid uses Apache-2.0 for the compiler, runtime, tools, and reusable libraries, and AGPL-3.0-only for Beskid-authored network services. Programs built with Beskid remain yours.
Beskid now serves its public documentation from one main-site Docs surface. The separate Platform Spec application is retired.
The Beskid runtime journey -- from Pecan's gc-arena experiments through Rust handlers to ISLE-native stock Cranelift CLIF. Not a straight line. An honesty arc.
Most compilers hit a syntax error and give up. Beskid's parser recovers, finds more errors, and reports them all — because 'error on line 1' is a compiler crime and nobody has time for fix-one-error-rerun loops.
The Beskid platform spec has draft contexts — a staging area for spec changes that must pass validation before they go live. Community members can propose changes via PR. The git-sync/pr.ts pipeline validates them. If validation fails, the spec stays frozen.
From the archive
July 2026. The bun→pnpm migration across all sites and CI. Three days of broken pipelines, Docker images that wouldn't build, and the discovery that monorepo package managers are personality tests with consequences.
July 2026. Beskid CI learned to auto-promote production after staging passed. No manual approval gates. No 'someone should click the button.' If staging is green, production follows. The contract, the Coolify sync, and why this matters.
July 2026. Beskid's staging deploy broke because Coolify needed a service UUID that nobody had documented. Then GHCR accepted the login but rejected the push because the token had read:packages but not write:packages. Infrastructure is a distributed systems problem.
July 2026. Beskid's ABI hit v5. Capturing closures needed a runtime contract. Fiber spawn boundaries needed a convention. The current-root helper got migrated. ABI versioning is not engineering — it is diplomacy with consequences measured in linker errors.
The LSP wants syntax facts. Codegen wants lowering. They disagree on what the AST should look like. The syntax facade is how Beskid gives both of them what they need without duplicating the compiler.
Beskid's normative spec lives in OpenSpec. A catalog.json indexes every document, requirement, and decision. When the spec changes and the catalog doesn't, CI fails. The catalog is the immune system for documentation truth.
Windows CI for a language compiler is three shells, two architectures, one missing assembler, and a static-archive TLS provenance problem that only manifests when you link against the CRT in a specific way. Beskid v0.4 shipped it anyway.
Beskid added GitNexus — a code intelligence engine that indexes every symbol, every relationship, and every execution flow. Before any edit, run impact analysis. Before any commit, run changed-scope review. The graph doesn't guess. It traces.
The ISLE-native runtime migration is not just a technical decision -- it is a philosophical shift from claiming ownership to proving correctness.
The shift: instead of Rust handlers emitting machine code, ISLE rules emit stock Cranelift CLIF. No forking Cranelift. No custom opcodes. The same verifier that checks user code now checks the runtime.
June 2026. Beskid got a cross-platform installer pipeline and a distrib submodule. The compiler ran on three platforms. The installer had to work on all three. This is the story of CI matrices, shell scripts, and the unglamorous work of making a language available.
June 2026. We migrated CI from GitHub Actions to Dagger on Blacksmith Testbox. The Dagger engine segfaulted. We downgraded it twice. Node runtime crashed. This is the story of infrastructure mortality — and why CI should be boring.
June 2026. The compiler gate kept failing on generic enum constructors, contextual inference, and Result match provenance. The fix was not a patch — it was a type system refactor that touched lowering, syntax, and dispatch. Six days of commits. Green gates at the end.
June 2026. A corelib test passed against a Rust handler that was correct by the old spec but wrong by the new one. The CI gate was green. The behavior was silently wrong. This was the moment the Rust-first runtime died.
June 2026. The corelib test matrix was red. Not sometimes red — always red. Two weeks of commits: corelib testing optimizations, further work on corelib shapes, progress on full corelib test pass, fixes to concurrency stack, Generic Assertions. Then the gate went green. Then we had to keep it green.
v0.4 was the band where Beskid stopped being a compiler project and started being a platform. Auth, hosting, observability, CI, tracker. The compiler is the fun part. The infrastructure is what keeps the project alive.
v0.4 shipped the graph explorer for compiler architecture and execution flows, plus Grafana/Memgraph monitoring. The kind of thing that takes weeks and looks like it took hours.
v0.4 made the Beskid tracker a SQLite database — the real record of what shipped. GitHub Issues sync is scoped to active version and bugs only. If you want to know what's Done and what's Not Yet, you query the tracker.
Every Beskid service needs to know who you are. v0.4 shipped OAuth flows, session management, and webhook validation in a shared package — the kind of decision that saves years of duplicated auth bugs.
Most language projects ship features they shouldn't. They merge half-finished work, mark it 'experimental,' and hope the community finishes it. Beskid v0.3 did the opposite: this is what shipped, this is what didn't, and the cutoff is hard.
The abfall GC integration and runtime bridge tracks were the most honest failures of v0.3. The design was sound. The code existed. But the seam between Beskid-managed memory and Cranelift-generated code was not stable enough to ship.
Besid v0.3 was supposed to land compiler-mod execution, native DI, export FFI, foreign-library import, phase-B GC, corelib tiering, tooling package kinds, and CI hardening — all in one weekend. Here is what each track was, what landed, and what didn't.
The platform-spec cutover, trudoc, and api.json are not separate stories. They are the same story: from trust to verify. From 'we wrote this correctly' to 'the compiler proves this is correct.'
v0.2 surfaced runtime work that had been brewing since Pecan: fibers, channels, GC integration, the pipeline/services split. These were not finished features. They were declarations of intent — the compiler would verify what the spec said.
Documentation rots because humans maintain it. trudoc reads api.json from the compiler. One chain of truth: compiler semantic facts → api.json → trudoc → platform spec → website. Beskid v0.2 discovered that docs are compiler artifacts.
The Book was not supposed to be funny. It was supposed to be documentation. Then someone put in the 'my story' chapter, the trauma rant, the iceberg meme, and the GIF of a dog in a burning room saying 'this is fine.' That was when the Book stopped being a manual and started being a manifesto.
Before v0.2, tutorials and normative rules shared the same page. 'Here is how to write a loop' sat next to 'the compiler SHALL reject this pattern.' The cutover split them — and discovered that splitting documentation is a build pipeline problem.
The Beskid landing page has a comparison table: .NET vs Java vs Beskid. It has bullet lists of what .NET got right and what it got wrong. It has an 'already better' section. Every landing page lies. This one tells you exactly whose side it's on.
Besid v0.1 discovered the discipline that would become the project's immune system: every compiler bump is a deliberate pin to a tested commit. The release pipeline, VS Code extension, and Open VSX publishing.
Besid v0.1 shipped AOT compilation and beskid pack before the language was usable. Not because it was ready, but because we refused to build a runtime we'd have to undo later.
When the compiler became its own repository, the runtime model solidified: hand-written Rust handlers, frozen kernel exports, soft dispatch ops, and a registration chain threading through every crate. It worked. For a while.
Besid v0.1 shipped the compiler's nested corelib submodule as the single source of truth for the standard library. No forks. No drift. One canonical corelib, and the compiler gate ran against exactly that version.
Convention is not a module system. Beskid v0.1 made file boundaries explicit and compiler-enforced — and if you got it wrong, the diagnostic had a span and a code, not a Stack Overflow post from 2014.
The clean break at compiler handoff: how Beskid decided that the superrepo integrates and the compiler stands alone. The architectural decision that has held for every release since.
Beskid methods are not a separate concept from functions. They are functions with a receiver parameter named 'this' — and the impl block is just syntax for grouping them. This design decision saved the compiler from reinventing dispatch.
Beskid's first builtin symbols were print, println, and strlen. They are not functions in the standard library — they are compiler-known symbols that bridge language space and host space. Every builtin since traces back to this pattern.
Not an acronym. Not a myth. A mountain range in the Carpathians — and a metaphor for the language tier that Java, C#, and Ruby occupy. Why the rename from Pecan mattered.
18 February to 5 March 2026. The furious prototype period that established parsing, HIR, resolution, diagnostics, and GC research — and then threw half of it out when Beskid was born.
Before Beskid had a runtime, it had a research spike. The gc-arena crate asked: can we build a garbage collector out of Rust arena allocators? The answer was 'probably, but not yet' — and that pattern of honest retreat became the project's default stance.
February 2026. Before Beskid had a compiler, it had an architecture decision: trait-based lowering instead of a visitor pattern. The node-by-node implementation roadmap got retired. The trait-based architecture is still here.
The Blazor form renderer that broke me. Sixteen years of .NET. An architect who thought WinForms devs would jump to web. And the moment I stopped negotiating with frameworks and started writing my own rules.