Sigil Releases
0.14.0
The compiler, runtime, build system, and standard libraries have been split into their own repositories. codeberg:sigil/sigil is the user-facing CLI; codeberg:sigil/sigil-lang is the compiler and runtime; codeberg:sigil/sigil-build is the build system; and twenty-plus standalone library repos make up the rest of the ecosystem. To match this, packages declare a single sigil: field that the build system uses to specify which version range of Sigil they are compatible with. Most package manifests get smaller as a result.
This is a breaking change for the ecosystem. Existing packages that pull from the old monorepo URLs (e.g. (from-git url:"codeberg:sigil/sigil" package:"sigil-stdlib" ...)) need to migrate to the new extracted-repo URLs (codeberg:sigil/sigil-lang, codeberg:sigil/sigil-build, codeberg:sigil/sigil-X for individual libraries). The new URL conventions are listed in the extraction table below. Going forward, packages target the extracted repos directly and bump them on their own cadence; the monorepo no longer hosts library code.
The sigil: package field
Every Sigil package now declares which language version it targets:
(package
name: "my-app"
version: "0.1.0"
sigil: "^0.14"
...)The sigil: field is load-bearing build-system input. From it, the build system derives:
sigil-stdlib(always, for any package that imports anything from(sigil ...))sigil-lib(when the package declaresc-sources:, for the C runtime headers)
Existing packages that explicitly declare those deps continue to work; the auto-derive only injects when no explicit declaration is present. The win is in new packages and library refreshes: a typical pure-Scheme package.sgl no longer needs the (from-git url:"codeberg:sigil/sigil-lang" package:"sigil-stdlib" version:"^0.13.1") boilerplate every previous version required.
The field is now required for every package. Build commands fail loudly if a package manifest is missing sigil:; the error names the file and suggests the fix.
For multi-package workspaces, sigil: ranges across member packages must intersect. The build system pairwise-intersects member ranges and reports an honest error when they conflict, naming both members and their declared ranges.
The default-package: workspace field
Multi-package workspace repos can now declare a default package for cross-repo dependency references:
(workspace
default-package: "sigil-build"
packages: (list
"packages/sigil-package"
"packages/sigil-deps"
"packages/sigil-build"))When a downstream package writes (from-git url: "codeberg:sigil/sigil-build") without a package: selector, the resolver picks up the workspace's default-package: and uses it to disambiguate which sub-package to install. This makes single-package consumers of multi-package repos look like single-package consumers of single-package repos: no package: keyword needed for the common case.
The field is explicit-only; the build system does not infer a default. If a downstream package refers to a multi-package workspace via from-git without package: and the workspace doesn't declare default-package:, resolution errors loudly with the list of member packages so the consumer can pick.
The completed extraction
The package set extracted from codeberg:sigil/sigil over 0.12.x and 0.13.x is now closed. What stays in the monorepo (for now):
sigil-cli(the user-facing tool)sigil-run(the bytecode runtime ship unit)sigil-web-run(the WASM runtime variant)
What lives in its own repo:
| Repository | Contents |
|---|---|
codeberg:sigil/sigil-lang | sigil-lib (C runtime), sigil-stdlib (standard library), compiler |
codeberg:sigil/sigil-build | sigil-package, sigil-deps, sigil-build (build system + manifest + dep resolver) |
codeberg:sigil/sigil-ansi | terminal styling |
codeberg:sigil/sigil-args | command-line argument parsing |
codeberg:sigil/sigil-crypto | cryptography primitives (vendored mbedTLS) |
codeberg:sigil/sigil-docs | documentation generation |
codeberg:sigil/sigil-ffi | foreign function interface |
codeberg:sigil/sigil-format | code formatting |
codeberg:sigil/sigil-git | git integration |
codeberg:sigil/sigil-hooks | lifecycle hooks |
codeberg:sigil/sigil-http | HTTP client + server |
codeberg:sigil/sigil-json | JSON parsing + encoding |
codeberg:sigil/sigil-log | structured logging |
codeberg:sigil/sigil-lsp | language server |
codeberg:sigil/sigil-mcp | MCP (Model Context Protocol) library |
codeberg:sigil/sigil-nrepl | network REPL protocol |
codeberg:sigil/sigil-repl | REPL library |
codeberg:sigil/sigil-socket | socket primitives |
codeberg:sigil/sigil-sqlite | SQLite (vendored amalgamation) |
codeberg:sigil/sigil-store | content-addressed storage |
codeberg:sigil/sigil-test | test runner |
codeberg:sigil/sigil-tls | TLS layer (consumes sigil-crypto) |
codeberg:sigil/sigil-version | version helpers |
codeberg:sigil/sigil-web | web framework |
Each library now releases on its own cadence. Mixed-version ecosystems are by design: sigil-http at v0.14.0 may pin sigil-stdlib at ^0.13, and that is fine. The extraction was about decoupling release cadences, not enforcing lockstep.
sigil cli upgrade and sigil cli use
sigil cli upgrade is faster, more reliable, and verifies binary integrity. Downloads now ship with mandatory sha256 checks; mismatched downloads are rejected and cleaned up. sigil cli use <version> lets you pin to a specific historical version on demand. The upgrade flow is now decoupled from any specific release-repo URL, so future hosting moves won't require a new sigil binary.
init templates refreshed
sigil init templates were updated for the post-pivot ecosystem. Each template's package.sgl now references the new extracted-repo URLs (codeberg:sigil/sigil-args, codeberg:sigil/sigil-http, codeberg:sigil/sigil-mcp, etc.) rather than the previous codeberg:sigil/sigil#vX.Y.Z + package: shape. The default *sigil-version* baked into newly-scaffolded projects bumped from v0.7.0 (badly stale) to ^0.14 and tracks current stable going forward.
Hygienic macros: syntax-case and quasisyntax
Sigil's hygienic macro implementation is now feature-complete enough to use as the primary macro system for any project. R6RS syntax-case with full hygiene, ellipsis patterns, and quasisyntax templates all work end-to-end. This matters because hygienic macros are the difference between "macros that occasionally surprise you with variable-capture bugs" and "macros that compose cleanly without a thought" — and well-written code in this style relies on the corner cases being correct.
- Quasisyntax shorthand — the reader now accepts `
#`,#,, and#,@as shorthand prefixes forquasisyntax,unsyntax, andunsyntax-splicing` (matching R6RS). - Quasisyntax expansion — full hygienic template expansion lands. Templates can use
unsyntaxto splice values back into a syntax object during macro expansion. syntax-local-value— R6RS compile-time environment query, available inside macros.syntax/#'outsidesyntax-case/with-syntax— fixed; previously raised an "unbound variable" error when used at the top of a macro body without an enclosing pattern matcher.syntax-caseellipsis patterns — fixed a long-standing bug where the ellipsis bound to the wrong template variable in nested patterns.
Build system and dependency resolver
The dep resolver fails loudly where it used to fail silently. The 0.13.x resolver had several "report success and break the consumer at build time" failure modes; those are gone. New behavior is loud and named: when a fetch errors, when a lockfile entry diverges from the manifest, when a config name doesn't exist. The motivating goal: turn unreproducible build mysteries into immediate, actionable errors at the source.
- Lock-entry staleness —
sigil deps installnow invalidates a lock entry when itsfrom-gitURL or package selector drifts from the manifest, not just when its version range changes. Previously, swapping a from-git dep's URL while keeping the same name would silently reuse the old SHA from the lockfile. - Loud-fail on any fetch error —
sigil deps installnow exits non-zero when any fetch errors out. Previous behavior printed the error in red but still returned success and wrote the lockfile. --configvalidation —sigil build --config <name>now fails loudly when the config name is undeclared inpackage.sgl. Previously the command silently fell through to the default config.- Improved diagnostic on path-resolve failures — the "Failed to resolve redirected path" error now names the missing package and suggests the fix.
Native codegen
Native builds are smaller, faster, and more visible. The CPS variable-declaration packing alone took the worst-case per-module zig-cc compile from "stuck at 24 minutes" to "completes cleanly," which makes native builds practical at the upper end of module size. Cumulative effect: native is now a comfortable default, not a "use at your own risk" path.
- CPS variable declaration packing — emitted C now packs CPS variable declarations 8 per line instead of 1 per line. On large modules (e.g. the
live-craftertheme module) this reduced emitted C from ~109k lines to ~77k lines, taking the per-module zig-cc compile time from "stuck after 24 minutes" to "completes cleanly." PUSH_BINDINGcache-miss path factored out of line — the binding-cache miss path was inlined into every binding access; pulling it out of line cut both binary size and per-binding hot-path code size.- Case-lambda runtime workaround retired — 332 lines of C in
packages/sigil-lib/src/macro.cwere removed after the underlyingcase-lambdahygiene bug was fixed in the syntax-case path. - Visible
libsigil.abuild progress — sigil-build's libsigil compile path now prints one line per call (libsigil.a: cache hit (...)orBuilding libsigil.a from source (...)) so users can see the C runtime being processed during native builds. Previously this was guarded behind--verbose.
Bug fixes
dep-namefalls back tofrom-git-package— previously, deps installed via(from-git url: ... package: ...)shape resolved to a name of#fin error messages.fetch-sglsymlink race —create-package-symlinknow tolerates the dangling-symlink edge where a previousdelete-fileraced withfile-exists?returning true.- WASM-incompatible code excluded from WASM builds —
sigil-lib'ssetjmp-based exception scaffolding andtzset()-based time code are now#ifndef __wasm__-gated so WASM-musl cross-compiles cleanly. - Stale lock reuse on version-range change — fixed the case where
sigil deps installwould reuse a lockfile entry whose pinned SHA no longer matches the new version range.
0.13.0
Sigil ships as a native binary. The release CLI is compiled end-to-end through the native C backend — no bytecode, no interpreter loop, no runtime-compile on startup. Every sigil invocation on 0.13.0 exercises the native runtime. This release also introduces a full Language Server Protocol implementation (sigil lsp serve), restructures the native compile pipeline for visibility and parallelism, and lands the cell-elision and escape-analysis codegen optimizations default-on.
Native sigil CLI
sigil build sigil-cli -c release produces a fully native binary. No extra flags required — the workspace release config declares backend: 'native. All shippable configs (release, prerelease, and every cross-compile target) now declare backend: 'native; the WASM target keeps the bytecode VM.
Linux x86_64 ships in two variants:
sigil-linux-amd64— dynamic glibc, cross-compiled via zig. The default download for normal distro users: smaller, faster startup, plays with system libc.sigil-linux-amd64-static— static musl. Self-contained bootstrap binary for unknown distros, containers, and downstream CI that needs "runs anywhere."
Showcase: Cinder Cantata
Cinder Cantata v0.2.0 — a music-reactive bullet-hell built on Sigil — ships alongside this release as a demonstration of the native backend's performance. The full game loop runs on the 0.13.0 runtime: native codegen for the per-frame hot path, goroutines for audio streaming, FFI for graphics/audio sokol bindings, and the motif audio composition engine driving enemy bullet patterns in lockstep with the soundtrack. Download a playable binary for Linux x86_64 from the release page.
Language Server (sigil lsp serve)
Sigil now ships a full LSP 3.17 implementation, invoked as sigil lsp serve. Editors and coding agents can wire it up over stdio for:
- Diagnostics — reader errors, compile errors, and lint warnings reported inline with source spans
- Hover — signature + full docstring for any binding at point, with fallback to the runtime spec when source isn't available
- Completion — context-aware completion items with proper
filterTextandtextEditfor editors like eglot - Go-to-definition — jumps to the exporting
.sglsource line; descends into library re-exports - Formatting — full-document and range formatting via
(sigil format) - Quick-fix code actions —
suggest-importproposes imports for undefined bindings andremove-unused-importcleans up lint warnings; both offered on cursor position, not just on diagnostics - Unused-import linter — detects unused imports with precise source spans, including inside re-exporting libraries
The server warms its docs index at initialized so first hover/completion is snappy. sigil lsp serve --log-file ... --log-level ... gives you traceable logs when debugging editor integrations.
Per-config backend: declarations
Build configs now declare their backend directly: (config name: 'release backend: 'native ...). Replaces the previous pattern where users had to use --backend native at build time. Each project's dev/release configs now declare their own backends (bytecode for fast iteration, native for shipping).
Per-package native compile pipeline
The native build pipeline was restructured to emit mod_*.c and compile to .o inside each package's build step instead of at the end in a silent 200K-line blob. Visible COMPILE mod_X.o per-package progress, parallelizable, better cache locality.
Cache correctness
Cache keys now include compiler identity + SGB version. Three caches (deps fetch, SGB auto-compile, runtime native) are keyed honestly against the exact compiler + runtime fingerprint they were produced with. Fresh checkouts and compiler rebuilds now produce consistent results instead of resurrecting phantom bytecode from a prior compiler version, eliminating a whole class of compiler errors.
Codegen optimizations (default-on)
- Escape analysis — closures whose captures don't escape the enclosing frame are now stack-allocated instead of heap-allocated. Includes a trampoline-frame fix for
TAIL_CALL.proc. - Cell elision v2 — post-conversion pass removes cells for variables that are read-only after definition. Register-allocator clobber bug that had blocked enabling cell elision by default (in 0.12.0) is fixed.
Both can be disabled via SIGIL_CPS_NO_CELL_ELISION=1 and similar env vars for the escape-analysis pass.
MCP server reliability
sigil-mcp (the Model Context Protocol server that lets Claude Code drive sigil) got a reliability pass:
- Subprocess isolation for the
sigil/testtool (was inheriting sigil-mcp's environment) - Per-server
--log/--log-levelflags for traceable multi-worker setups - JSON-RPC
id: nullcompliance for notification-shaped messages
Worker fleets running sigil-mcp across many concurrent Claude Code sessions are now stable.
Bug Fixes
- Self-rebuild trampoline crash — fixed a dangling
inline_argspointer in the native-bridge trampoline. The pointer referenced a stack slot that had already been unwound by the time the trampoline bounced back through it. Harmless in short-running programs, fatal on the self-rebuild cycle where the compiler recursively compiles itself. - Closure serialization across threads — cell elision could leave some captures as raw values while siblings remained upvalue cells. Value-level serialization now carries a per-capture is-cell flag, so deserialized closures rebuild with the exact capture shape the code expects. Fixes cross-thread closure passing under default codegen settings.
- Nested-guard codegen — exception-unwinding flag is now cleared after a tail handler fires, fixing a latent bug in deeply-nested
guardforms. - Compiler self-bootstrap — 0.12.0 compilers can now build 0.13.0 source without guarded-reference crashes (
SIGIL_ABI_VERSIONreference is#ifdef-gated).
0.12.0
Register VM stabilized, stack VM removed, and experimental native C codegen. This release makes the register-based virtual machine the sole execution backend — the legacy stack VM and direct compiler have been removed. The register VM is now battle-tested across production MCP servers (folio, courier, bureau) and the full Sigil ecosystem. This release also introduces an experimental C native code generation backend.
Stack VM Removal
The stack-based virtual machine and direct compiler have been removed. The CPS compiler and register VM are now the only toolchain — no opt-in flags needed.
- Removed stack VM interpreter, direct compiler, and CPS stack emitter
- Removed mixed-mode dispatch
- Renamed opcodes and headers (
ROP_→OP_,regvm.h→opcodes.h) - SGB format v8+ only (older binaries rejected)
Register VM Stabilization
The register VM introduced as opt-in in 0.11.0 is now the default and only backend. It has been stabilized through extensive testing and production use:
- All ecosystem tests pass (~2,700 tests across 23 repos)
- Running in production as the backend for MCP servers (folio, courier, bureau, minder)
- 20+ bug fixes addressing edge cases in exception handling, macro hygiene, continuations, and module loading
Experimental Native C Codegen
New --backend=native flag for sigil build compiles Sigil programs to C, then to native binaries via the Zig toolchain. This is opt-in and experimental.
The native codegen compiles CPS IR directly to C functions with a trampoline-based calling convention. All modules — entry and dependencies — are compiled to native C. Features:
- Full-program native compilation — all modules compiled to C, linked into a single binary
- Module system support — cross-module calls, binding caches, module initialization
- Delimited continuations — fiber-based C stack capture via ucontext (Linux/glibc)
- Async goroutines — native fibers for concurrent I/O (scheduler, stdin read loops)
- GC integration — shadow stack for local variables, conservative C stack scanning, trampoline closure rooting
- MCP server support — folio and courier run as native MCP servers through Claude Code
87 of 91 native differential test files pass (matching bytecode output). The native backend is functional for real applications and delivers significant performance improvements over the bytecode VM.
Platform Limitations
- Linux (glibc): Full support including async fibers
- Linux (musl): Builds and runs, but no fiber support (musl ucontext stubs return ENOSYS)
- macOS: Builds and runs, but no fiber support (ucontext is deprecated)
- Windows: Builds and runs, but no dynamic native module initialization
Async goroutines require fiber support. On platforms without it, persistent servers (MCP, HTTP) that use goroutines for I/O will not work in native mode.
Bug Fixes
- Fix macro hygiene: literal comparison and free identifier resolution
- Fix
let*variable scope leak causing GET_CELL crash - Fix
raise-continuablein tail position - Fix GC use-after-free in compile-file for dependency builds
- Fix register VM parallel arg move clobbering in tail calls
- Fix
define-librarybody defines leaking to top level - Fix
guard/with-exception-handleracross eval boundaries and tail calls - Fix
collect_internal_definesand capture analysis for module bodies - Fix MCP server crash on
resources/templates/listrequests
0.11.0
Register VM and self-hosting CPS compiler. This release adds a register-based virtual machine as an alternative backend for the CPS compiler introduced in 0.10.0. The new toolchain is opt-in via SIGIL_NEXT=1 and is 7-57% faster than the direct compiler across all benchmark categories. It is fully self-hosting — the CPS compiler running on the register VM can compile itself.
Register VM
Enable with SIGIL_NEXT=1. This activates both the CPS compiler and the register VM together. All stdlib modules compile, all ecosystem tests pass (zero regvm-specific failures across ~2,700 tests in 23 repos).
The register VM uses 32-bit fixed-width instructions with 3-address register operands. Key design features:
- Liveness-aware register allocation via CFG-based backward dataflow analysis
- Register coalescing eliminates redundant moves between registers
- Self-tail-call loop optimization converts recursive tail calls to JMP instructions
- Call window optimization overlaps caller/callee register frames
- Full continuation support — call/cc, delimited continuations, abort-to-prompt
- Exception handling — raise, guard, with-exception-handler
New source files:
regvm.c-- register VM interpreter (90+ opcodes)regvm.h-- register VM instruction encoding and opcodescps-emit-reg.c-- CPS IR to register bytecode emission
Performance
Benchmarks across 60+ tests (ratio = register VM time / direct compiler time, lower is faster):
| Category | Ratio | Improvement |
|---|---|---|
| Compute (fib, tak, ack) | 0.79-0.93x | 7-21% faster |
| Closures | 0.56-1.03x | Up to 44% faster |
| Tail calls | 0.76-0.96x | Up to 24% faster |
| String processing | 0.43-0.90x | Up to 57% faster |
| Allocation/trees | 0.80-1.01x | Up to 20% faster |
| Higher-order functions | 0.72-1.03x | Up to 28% faster |
| JSON encode/decode | ~1.0x | Parity (stdlib-bound) |
The register VM went from 3.3x slower (initial prototype) to consistently faster than the direct compiler through register allocation, coalescing, and call window optimizations.
Self-Hosting Bootstrap
The CPS compiler + register VM can compile itself. A two-stage bootstrap (stack VM binary compiles regvm binary, regvm binary recompiles itself) produces byte-identical output for 43/44 stdlib modules. This proves the new toolchain is correct enough to replace the direct compiler.
CPS Compiler Improvements
Fixes and enhancements to the CPS compiler from 0.10.0:
- Forward-referenced macro expansion during CPS conversion
- CFG-based liveness analysis for register and slot allocation
- Rest parameter slot allocation fix (was dropping the rest param)
- GC rooting for import set datums during module loading
- Module context save/restore across nested module loads
- call/cc stack reservation for lambda locals
- CPS emitter abort-to-prompt continuation routing for delimited continuations
- 19 primitive operation fallbacks added to register emitter
- Syntax transparency for register VM type predicates (car, cdr, null?, pair?, symbol?)
- Bignum arithmetic operations (mod, rem, neg, abs, number->string)
Other Changes
SIGIL_NEXT=1flag activates CPS + register VM togetherSIGIL_MODULE_MAX_MACROSincreased from 64 to 256- Benchmark suite added at
benchmarks/for release-to-release comparison
0.10.0
Experimental CPS compiler with optimization passes. This release adds a continuation-passing style intermediate representation to the compiler pipeline, sitting between macro expansion and bytecode generation. The CPS path is opt-in and does not change default compiler behavior.
CPS Compiler
Enable with SIGIL_USE_CPS=1. The CPS pipeline converts expanded S-expressions into CPS IR, runs optimization passes, then emits bytecode. All existing tests pass through the CPS path.
New source files:
cps.h-- CPS IR data structures and arena allocatorcps-convert.c-- S-expression to CPS conversioncps-emit.c-- CPS to bytecode emissioncps-opt.c-- optimization pass pipelinecps-dump.c-- CPS IR pretty-printer for debugging
Optimization Passes
Control the optimization level with SIGIL_OPT_LEVEL (0, 1, or 2). Individual passes can be disabled with environment variables.
-O1 (contification + dead code elimination):
- Contification: converts single-call closures in tail position into continuation jumps, eliminating closure allocation. Non-tail contification enabled for pure callees.
- Dead code elimination: removes unreachable continuations via BFS reachability analysis.
-O2 (adds inlining, constant propagation, capture minimization):
- Beta reduction / inlining: inlines small functions (10 or fewer CPS terms, called at most twice) at tail call sites.
- Constant propagation: folds fixnum arithmetic and boolean operations at compile time, eliminates constant branches. Overflow-safe using compiler builtins.
- Capture minimization: removes unused captures from closures after dead code elimination.
Pass ordering: contification, inlining, constant propagation, DCE, capture minimization. At -O2, the pipeline iterates up to 3 times for cascading opportunities.
Debugging
SIGIL_DUMP_CPS=1-- dump CPS IR before optimizationSIGIL_DUMP_CPS_OPT=1-- dump CPS IR after optimization- Individual pass toggles:
SIGIL_CPS_NO_CONTIFY=1,SIGIL_CPS_NO_DCE=1,SIGIL_CPS_NO_INLINE=1,SIGIL_CPS_NO_CONSTPROP=1,SIGIL_CPS_NO_CAPMIN=1
Other Changes
cond-expandimplemented as an expression form in the CPS convertercase-lambdaCPS expansion bypasses hygiene interaction bug in syntax-rules dispatch- Fix
sigil_apply{0,1,2,3}to reserve stack space for locals - Fix module context inheritance for closures created inside
define-librarybody - Fix
make-vectorto use native call instead of primitive opcode makedefault target now builds stdlib (previously requiredmake stdlib)
0.9.1
Transitive dependency resolution, version ranges, and lockfile support. The package manager now recursively resolves the full dependency tree — projects only need to declare their direct dependencies, and everything else is fetched automatically. This is the feature that makes the extracted ecosystem from 0.9.0 practical to use at scale.
Transitive Dependency Resolution
sigil deps install now recursively follows from-git dependencies. When a package is fetched, its package.sgl is read and its own dependencies are queued for fetching. Deduplication by package name prevents redundant fetches and cycles.
Before (0.9.0): if your project depends on press, and press depends on sigil-markdown, sigil-sxml, sigil-fp, and 7 other packages, you had to declare all of them manually in your package.sgl.
After (0.9.1): declare press and everything else resolves transitively. sigil-site went from 4 declared dependencies to 2, with 12 more resolved automatically.
Version Ranges
The from-git dependency form now supports an optional version: field with Cargo-style semver ranges:
(from-git url: "codeberg:sigil/sigil-sxml" version: "^0.9.0")Supported range syntax:
^0.9.0— minor-compatible:>=0.9.0, <0.10.0~0.9.0— patch-only:>=0.9.0, <0.9.1- Exact version:
0.9.0 *or omitted — any version (latest tag)
Resolution happens after cloning the bare repo: available tags are listed and the highest matching version is selected.
Lockfile
sigil deps install now writes sigil.lock with the exact commit hash for every resolved dependency (direct and transitive):
;; Auto-generated by sigil deps install. Do not edit.
(lock
(package name: "press" url: "codeberg:sigil/press" ref: "v0.1.0" sha: "abc123...")
(package name: "sigil-stdlib" url: "codeberg:sigil/sigil" ref: "v0.9.0" sha: "def456...")
...)sigil deps installreads the lockfile and uses pinned refs for reproducible installssigil deps updateignores the lockfile, re-resolves frompackage.sglranges, and writes a fresh lockfile--redirectsskips the lockfile entirely (neither read nor written) since local development overrides everything
Version Conflict Detection
When a transitive dependency requires a version range incompatible with an already-resolved version, sigil deps install errors with an actionable message suggesting you add an explicit pin in your package.sgl.
Bug Fixes
- Added
sigil/deps/semverandsigil/deps/lockto Makefile bootstrap modules
0.9.0
Lean core, ecosystem split, Zig everywhere. Sigil's monorepo sheds over 25,000 lines as libraries move to independent repositories with their own release cycles. The standard library is streamlined for AI-native development — pattern matching, transducers, R7RS compatibility, and functional programming utilities move to optional packages. Zig replaces GCC as the default C compiler for native builds, and Emscripten is replaced entirely by Zig + WASI for WebAssembly, enabling the Sigil REPL to run in browsers without heavyweight toolchain dependencies.
Ecosystem Split
The monorepo shrinks from 39 packages to 26. Extracted libraries are now independent repositories on Codeberg under the sigil/ organization, each with their own version tags, CI, and release cycle.
| Extracted Package | Repository | Description |
|---|---|---|
| sigil-peg | codeberg.org/sigil/sigil-peg | PEG parser combinators |
| sigil-sxml | codeberg.org/sigil/sigil-sxml | SXML to HTML/XML conversion |
| sigil-markdown | codeberg.org/sigil/sigil-markdown | CommonMark parser with YAML front matter |
| sigil-web | codeberg.org/sigil/sigil-web | Web application framework |
| sigil-css | codeberg.org/sigil/sigil-css | Programmatic CSS generation |
| sigil-match | codeberg.org/sigil/sigil-match | Pattern matching |
| sigil-fp | codeberg.org/sigil/sigil-fp | Functional programming utilities (compose, pipe, partial, threading macros) |
| sigil-transducers | codeberg.org/sigil/sigil-transducers | Composable transducers |
| sigil-r7rs | codeberg.org/sigil/sigil-r7rs | R7RS-small compatibility (scheme *) modules and SRFI-9 records |
| sigil-web-repl | codeberg.org/sigil/sigil-web-repl | Browser-based REPL (was sigil-playground) |
| press | codeberg.org/sigil/press | Static site generator (was sigil-publish) |
| sigil-site | codeberg.org/sigil/sigil-site | Official Sigil website |
| sigil-web-demo | codeberg.org/sigil/sigil-web-demo | Demo web application |
Extracted packages use from-git dependencies and dev-redirects.sgl for local development. All existing functionality is preserved — packages just live in their own repos.
AI-Native Standard Library
The standard library is streamlined based on a comprehensive audit of how AI agents actually use Sigil across 12 production codebases (117 libraries). Features with zero AI usage were moved to optional packages:
- Pattern matching (
match,match-let) — moved tosigil-match - Transducers (
mapping,filtering,transduce) — moved tosigil-transducers - Functional combinators (
compose,pipe,curry,partial,cut/cute) — moved tosigil-fp - Threading macros (
chain,->,some->) — moved tosigil-fp - R7RS compatibility (
(scheme base),(scheme write), etc.) — moved tosigil-r7rs - SRFI-9 records (
define-record-type) — moved tosigil-r7rs
The core language retains what AI agents naturally reach for: when/unless, keyword arguments, define-struct, guard/error, map/filter/apply/find, dicts, broadcast channels, and go concurrency.
Zig as Default Compiler
Zig is now the preferred C compiler across all build paths:
- Native builds:
detect-default-compilerandcompile-native-testspreferzig ccwhen available, falling back to systemcc/gcc - Cross-compilation: All eight platform targets use Zig (unchanged from 0.8)
- CI: Test and GC stress jobs use Zig via
with-zigwrapper - WebAssembly: New
webbuild config useszig cc -target wasm32-wasi(see below)
WebAssembly Without Emscripten
The web build target is completely rewritten. Emscripten is replaced by Zig targeting wasm32-wasi with a browser WASI polyfill:
- All 34 C source files compile with
zig cc -target wasm32-wasi - 3.3MB WASM binary (comparable to Emscripten output)
- Uses
@bjorn3/browser_wasi_shimfor WASI polyfill in browsers - New
__SIGIL_WEB__platform define replaces__EMSCRIPTEN__guards - Web build config:
sigil build sigil-web-repl --config web - Sigil REPL runs fully in the browser — expression evaluation, module loading, interactive input
sigil-docs Trimmed
sigil-docs is now a lightweight JSON lookup package for REPL inline help:
- Removed
(sigil docs commands)— thesigil docsCLI subcommand. Press handles all doc site generation now. - Removed
(sigil docs execute)— code block execution for doc validation - Removed dependencies on
sigil-markdownandsigil-sxml - Remaining:
(sigil docs lookup),(sigil docs search),(sigil docs types)— just reads the JSON files the compiler generates
sigil-cli Slimmed
The CLI drops several optional command modules and dependencies:
- Removed
sigil docscommand (handled by press) - Removed
sigil publishcommand (handled by press) - Removed
sigil changescommand (package deleted) - Removed dependencies:
sigil-docs,sigil-web,sigil-changes
0.8.0
Dynamic FFI and portable foundations. Sigil gains the ability to call any C library at runtime without writing glue code, a content-addressable build cache for faster incremental builds, and seven new packages spanning graphics, game development, calendar sync, and messaging. Cross-compilation now passes across all eight platform targets, and a new app management system makes it easy to install and run Sigil applications from git repos. With this release, Sigil reaches a stability point that enables us to begin decoupling libraries from the monorepo for independent releases and faster iteration.
Dynamic FFI
The headline feature. sigil-ffi lets you call C library functions directly from Scheme without writing any C glue code. Load shared libraries with ffi-open, look up symbols with ffi-ref, define call signatures, and invoke — all at runtime.
(import (sigil ffi))
(define lib (ffi-open "libm.so.6"))
(define c-sqrt (ffi-ref lib "sqrt" '(double) 'double))
(c-sqrt 144.0) ; => 12.0- Callbacks:
c-callbackcreates function pointers that call back into Scheme, enabling integration with event-driven C APIs like GUI toolkits - Pointer finalizers:
set-pointer-finalizer!attaches GC-triggered cleanup to foreign pointers (pass#fto clear) - dyncall backend: Replaced pure-C trampolines with dyncall for portable calling convention support, including mixed int/double argument signatures used by Cairo and similar libraries
Content-Addressable Build Store
A new sigil-store package provides content-addressable storage for build artifacts. C compilation results and static libraries are cached by content hash, so unchanged native code is never recompiled. Build outputs are properly rooted for GC, and the store integrates transparently with the existing build system.
App Management
New sigil app commands for installing, updating, and removing Sigil applications from git repositories:
sigil app install— clone a repo, resolve dependencies, bundle the app, and register any MCP serverssigil app list— show installed applicationssigil app update— pull latest changes and rebuildsigil app remove— clean up installed app and deregister MCP serverssigil app rollback— revert to the previous version
Supports --scope for MCP server registration, --env and secret-env for configuration, and graceful handling of missing environment variables.
New Packages
| Package | Description |
|---|---|
sigil-ffi | Dynamic FFI for calling C libraries at runtime via dyncall |
sigil-cairo | Cairo 2D graphics bindings — paths, transforms, surfaces, PNG loading, compositing operators, glyph rendering |
sigil-freetype | FreeType font loading and glyph metrics via FFI |
sigil-harfbuzz | HarfBuzz text shaping via FFI |
sigil-raylib | Raylib game development bindings — 2D shapes, text, input, collision, audio |
sigil-caldav | CalDAV calendar client with iCalendar parsing, event CRUD, recurrence expansion, timezone handling |
sigil-telegram | Telegram Bot API client with bot framework, MarkdownV2 formatting, inline keyboards, file uploads |
MCP Server Improvements
- Channel servers: New
(sigil mcp channel)module with helpers for building MCP channel-based servers (stdin/stdout transport) - Server-initiated notifications: MCP servers can now push notifications to clients, declare custom capabilities, and provide instructions
- Structured logging: MCP message handling uses
sigil-logwithlog-configure-from-args!for CLI integration - Better error reporting: Stack traces included in MCP tool error responses
HTTP Improvements
/jsonroute helpers now return JSON bodies on all HTTP status codes, not just 2xxurl-encode-valueandbuild-query-stringfor proper URL query parameter encoding- Fixed UTF-8 split across HTTP read chunk boundaries
- Fixed chunked transfer decoding for non-ASCII UTF-8 content
- Fixed
Content-Lengthusing character count instead of byte length - Fixed partial socket writes truncating large HTTP responses
- Unix domain socket server support via
unix-listen
CalDAV and iCalendar
Beyond the new sigil-caldav package, significant improvements to calendar handling:
- Timezone-aware datetime parsing with correct DST offset calculation via
mktime - Attendee parameter support for event creation
- Calendar name and timezone fields on
ical-event - RRULE recurrence expansion with
RECURRENCE-IDexception suppression - Date range filtering for non-recurring events in recurrence expansion
Formatter Performance
The code formatter was optimized from 30 seconds to under 2 seconds on large files (2800+ lines):
- Replaced struct-based tokens with raw vectors
- Inlined tokenizer hot loops with delimiter lookup table
- Zero-allocation form type matching
- Fixed tokenizer mishandling of delimiter character literals
Build System
- Content-addressable store for cached C compilation and static libraries
- Fixed build cache ignoring dependency changes
- Fixed false source file matches in module dependency resolution
- Fixed test runner dependency resolution for external packages
- Fixed build store hard-link self-copy corruption
- Hardened test runner against load errors
- Default release/prerelease configs switched to glibc dynamic linking (supporting FFI and dlopen)
- Static build configs available as
release-staticandprerelease-static
JMAP Improvements
jmap-email-countfor lightweight email counting without fetching messagesjmap-download-blobfor downloading JMAP blobs to files- Batch email move support
- Fixed send compatibility issues
Performance and Code Quality
- Fixed quadratic
string-join— now uses linear accumulation - Improved
list-unzipto use simultaneous traversal - Deduplicated
inspect-vectorandinspect-arraywith shared helper - Dict-based lookups in diagnostic module and watch module for faster type-guard and mtime resolution
Bug Fixes
- Fixed crash when
formatdisplays bignum values - Fixed segfault from unbounded macro export recursion
- Fixed preemptive yield escaping through
sigil_applyboundaries - Fixed
string->listto properly decode UTF-8 characters - Fixed
string-joinoverflow with large lists - Fixed double-encoded UTF-8 in build output and diagnostics
- Fixed YAML encoder to handle Sigil arrays
- Raised module binding limit from 2048 to 4096
- Fixed async stdin handling for MCP servers (pipe detection, fd-waiter integration)
- Fixed
char-ready?for pipes with async-aware stdin polling - Added Scheme module definition for
sigil-tlspackage - Fixed Windows cross-compilation:
fcntl/FD_CLOEXECguards replaced withSetHandleInformation - Fixed OpenBSD cross-compilation:
setvbufworkaround for opaqueFILEstruct in Zig headers - Fixed OpenBSD executable path resolution, poll fd limit, and partial write handling
- Set
FD_CLOEXECon TCP sockets to prevent child process inheritance
0.7.0
Parallelism and production readiness. Sigil gains multi-core execution, better I/O scalability, proper exception semantics, machine-readable procedure specifications, structured logging, and four new packages. With the stability and DX foundations from 0.5.0 and 0.6.0, this release focuses on the features needed to build and run serious applications.
Multi-VM Threading
The headline feature. Each thread-spawn creates a new VM with its own stack, heap, GC, symbol table, and module registry — zero shared mutable state, no locks needed. Threads communicate by message passing with automatic serialization/deserialization. parallel-map provides a high-level API for data-parallel workloads, partitioning work across N workers and collecting results.
Tail-Optimized Exception Handling
Replaced prompt-based exception handling with a dedicated VM-level handler stack. guard bodies now execute in true tail position, eliminating the 512-prompt practical limit. Deep recursive guard patterns (10,000+ iterations) work without overflow. Closure arity errors are now catchable by guard. Cross-context exception propagation works correctly through eval and load boundaries.
I/O Multiplexing
Replaced select(2) with epoll (Linux) and kqueue (macOS/BSD) behind the existing socket-select and fd-select APIs. Purely internal change with no Scheme API impact. Handles 200+ concurrent file descriptors efficiently.
Preemptive Yield Points
Yield checks at loop back-edges prevent CPU-bound tasks from starving other coroutines in the async scheduler. Default disabled — only activates when running inside with-async. Configurable interval via SIGIL_YIELD_INTERVAL environment variable.
Procedure Specifications
Machine-readable specs for procedure parameters and return values using real Scheme predicates. Specs use the inline (: ...) syntax placed as the first expression in a define or lambda body:
(define (add a b)
(: number? number? -> number?)
(+ a b))- Runtime checking: Optional predicate checks gated by the
sigil-checksfeature — zero cost in release builds - Predicate combinators:
any-of,maybe,list-of,none-offor expressive type constraints - Struct field annotations:
define-structfields accept type predicates, auto-generating specs for constructors, accessors, and mutators - Full coverage: 330+ specs across 35+ modules, all audited against conventions
- Tooling: Specs displayed in MCP search/exports output and generated API documentation
define-native Compiler Form
Declares bindings provided by native C code at runtime. Scheme modules can document and export native functions without fallback implementations, with optional specs and docstrings. Uses the new OP_DEFINE_IF_UNBOUND opcode to avoid overwriting native bindings registered at VM startup.
New Packages
| Package | Description |
|---|---|
sigil-tui | Immediate-mode terminal UI toolkit with native C grid, layout system, components, event parsing, and text input |
sigil-jmap | JMAP email client (RFC 8620/8621) with session discovery, mailbox operations, email query/send |
sigil-yaml | YAML parsing and serialization with block/flow collections, block scalars, anchors/aliases, multi-document |
sigil-log | Structured logging with levels, text/JSON output, configurable targets, and lazy macros |
sigil-tui-demo provides a chat client simulation exercising all TUI components.
HTTP Improvements
- Streaming HTTP download support with binary-safe reads
- File serving with Range request support and port positioning
Developer Tooling
- MCP server: Procedure specs shown in search and exports output
- API docs:
sigil docs apifixed and now displays spec signatures in generated documentation - Build system: Test compilation propagates build config features (e.g.,
sigil-checks)
Bug Fixes
- Fixed false positive capture corruption check in serializer
- Fixed Windows build: mingw macro collision with
_inlinefield name - Fixed Windows build: use
define-nativeforunix-connect(not available on Windows) - Fixed exception handler double-pop causing test runner segfault
- Fixed bootstrap compilation: replaced
whenwithifin%set-spec!
0.6.0
This release brings Sigil much closer to full R7RS compliance, adds a complete web development workflow with live browser reloading, and introduces three new packages: a PEG parsing library, an Org Mode parser, and an XMPP client. Developer tooling improves significantly with rich error diagnostics, an enhanced MCP server, and watch mode for incremental builds.
R7RS Compliance
The biggest area of work in this release. Sigil now supports nearly all of R7RS Small:
- Control flow:
dynamic-wind,dosyntax,guardprompt limit raised for deeper exception handling - Macros:
let-syntax,letrec-syntax - Modules:
include,include-ci, import set modifiers (only,except,prefix,rename) - I/O: Bytevector ports,
read-bytevector!,char-ready?,u8-ready? - Output:
write-sharedwith datum labels for circular structure printing - Feature detection:
features,cond-expand,syntax-error - Libraries:
(scheme time),(scheme process-context),(scheme repl)withinteraction-environment - Literals:
#u8(...)bytevector literal syntax in compiler and reader
Web Development
A full live-development workflow for web applications:
- Live reloading: nREPL server with SSE-based browser reload — edit code, see changes instantly
- Higher-level UI components: Expanded component library for sigil-web
- API refinements: Improved ergonomics for routing, form handling, and GET requests
- CSS generation:
css-selfor compound selectors - MCP browser tools: 7 new tools for live browser control (morph, navigate, execute JS, reload CSS, error overlay)
- Demo application: Vinyl Vault, a full CRUD demo showcasing the web stack
New Packages
| Package | Description |
|---|---|
sigil-peg | Parsing Expression Grammars with S-expression DSL, backtracking, and captures |
sigil-org | Org Mode parser producing SXML (headlines, metadata, source blocks, tables, lists) |
sigil-xmpp | XMPP client with STARTTLS, SASL (SCRAM-SHA-1/PLAIN), roster, presence, and MUC |
Supporting packages: sigil-crypto gains HMAC-SHA1 and PBKDF2-SHA1, sigil-tls adds tls-upgrade for STARTTLS.
Developer Tooling
- Rich error diagnostics: Structured error type hierarchy with Levenshtein-based "did you mean?" suggestions, source snippets with caret indicators in stack traces
- MCP server: Package-provided tool discovery, multi-form eval, format auto-fix, runtime doc fallback for undocumented exports, nREPL
describeandmodulesoperations - Watch mode:
sigil build --watchandsigil test --watchwith--format jsonsupport - Value inspection: New
(sigil inspect)module for structured introspection via nREPL and MCP - Project templates:
sigil initgainsweb-app,api-service, andmcp-tooltemplates - Docstring collection: Variable definitions now collect docstrings; native docs propagate through re-exports
Performance
- Dict lookup: FNV-1a hash cached on string keys, avoiding repeated computation
Library Improvements
- sigil-markdown: Inline parser rewritten using PEG grammars (~120 fewer lines, same behavior)
- sigil-json: Handle UTF-16 surrogate pairs in unicode escapes per RFC 8259
- sigil-docs: Re-export descriptions resolved from source module entries
Bug Fixes
- Fixed
SIGIL_NATIVES_MAXlimit (increased to 2048) for projects with many native bindings - Fixed
--no-colorflag in test runner - Fixed
git-fetchto include tags when updating cached bare repos - Fixed binary-safe nREPL wire protocol and SIGPIPE handling
- Fixed MCP format tool crash
0.5.0
This release is all about stability and correctness. A comprehensive audit of the garbage collector uncovered and fixed a critical write barrier gap, and GC stress testing now runs across the entire compiler pipeline. The HAMT dict implementation is complete, arbitrary-precision integers (bignums) are fully integrated, and every open issue has been resolved. Performance improves with inline caching and superinstructions, and the multimedia packages have been reorganized for flexibility.
GC Correctness
The most impactful change in this release: the tri-color write barrier was implemented but never called. Every mutation site that writes a heap pointer into an existing object could violate the tri-color invariant during incremental marking. This was the root cause of several hard-to-reproduce crashes.
- Write barriers: Added
sigil__gc_write_barrier()calls to all 13 heap mutation sites across vm.c and natives.c - Compiler rooting: Removed the
SIGIL_GC_DISABLE_DURING_COMPILATIONworkaround entirely. Fixed 46+ unrooted allocation sites in the compiler through systematic audit - GC stress testing:
SIGIL_GC_STRESS=1forces GC on every allocation, maximizing the window for bugs. All tests pass under stress
Performance
- Inline caching: Module binding lookups now use per-code cache arrays. On benchmarks, 3.3M hash lookups reduced to ~38K cold-start misses, with 100% steady-state cache hit rate
- Superinstructions: Peephole optimizer fuses 8 common opcode patterns (e.g., PUSHLOCAL+PUSHLOCAL, PUSH_CONST+ADD). Compiler-level fusion merges source location tracking with call opcodes
Arbitrary-Precision Integers
Integers larger than 2^47 now automatically promote to bignums instead of raising an error:
- Full arithmetic operations (add, subtract, multiply, divide, modulo, GCD)
- Comparison and bitwise operations
- Transparent promotion and demotion (bignum results that fit in a fixnum automatically demote)
- Serialization support in bytecode files
Dict Completeness
The HAMT (Hash Array Mapped Trie) implementation is now feature-complete:
- Printing: HAMT dicts display all entries with
displayandwrite - Equality:
equal?walks HAMT nodes for structural comparison - Collision handling: Fixed silent key dropping when hash collisions occur at the same node
- Removal: Proper structural
dict-removewith sharing, branch collapse, and HAMT-to-array demotion when count drops below 8
Error Handling
- Three
exit(1)calls in the module system replaced withsigil__vm_error()so the Scheme-level exception system handles them gracefully OP_ABORT_TO_PROMPTnow extracts real error messages from exception objects- Macro expansion errors propagate properly to the compiler
matchraises an error instead of printing a warning when no clauses match
Stack Traces
Procedures now track where they were defined. Stack traces show definition locations, making it easier to identify which function failed:
Stack trace (most recent call first):
0: my-helper
at utils.sgl:42:5Multimedia Packages
sigil-studio has been split into three independent packages for more flexible dependency management:
| Package | Description |
|---|---|
sigil-app | Windowing, input, application lifecycle (sokol_app) |
sigil-graphics | 2D rendering, image loading, font rendering (sokol_gfx, stb) |
sigil-audio | Sound effects and music streaming (sokolaudio, stbvorbis) |
sigil-studio remains as a meta-package that pulls in all three. New: playlist support with wait-music-end and play-playlist.
Build System
- Test harness generation for packages with native C dependencies
c-flagsfield on library definitions--profileflag for opcode-level performance analysis- Build safety: warns when replacing the running binary, errors on 0-byte output or missing target package
Test Coverage
Added test suites for 15+ packages that previously had none, including sigil-crypto, sigil-tls, sigil-web (routing, middleware, cookies, SSE, security), sigil-socket, sigil-process, sigil-mcp, sigil-jwt, sigil-websocket, sigil-markdown, sigil-format, and sigil-sxml. Error path tests added across the standard library.
Bug Fixes
- Fixed
assq-refto return values instead of aliasingassq; addedassv-ref - Fixed
number->stringprecision for exact IEEE 754 roundtrip (was losing digits on large flonums) - Fixed REPL
string-lengtherror after exception recovery - Fixed cross-module symbol resolution corruption
- Fixed bundle directory listing for bundled applications (VFS)
- Fixed
sigil-runre-import of(sigil core)before calling entry main - Fixed process port caching for stable repeated access
- Removed dead opcodes (
OP_LOAD_BYTECODE,OP_MAKE_CLOSURE_RT,OP_WRITE_BYTECODE_FILE)
0.4.0
This release makes Sigil leaner and faster. Native list operations cut compilation time in half, release binaries are 44% smaller, and a new profiling module helps you find bottlenecks in your own code. Macro authors get full hygiene support, and error handling improves with catchable VM errors and cleaner stack traces.
Breaking Changes
- sigil-web: Renamed UI components from
sigil-*tosg-*prefix (e.g.,sigil-buttonbecomessg-button) to mirrordata-sg-*attributes
Performance
Profiling revealed hotspots in list operations during macro expansion. Native C implementations of assoc, assq, assv, member, memq, and memv deliver significant speedups:
- Test suite runs 2x faster (33s → 15s)
- Module compilation 50% faster
- Release binaries 44% smaller (3.2MB → 1.8MB)
Macro Hygiene
Full hygienic macro support for syntax-rules and syntax-case. Macros now properly respect lexical scope, preventing accidental variable capture:
- Local and module-level hygiene
free-identifier=?for comparing identifiers during expansion#'reader shorthand for(syntax ...)expressions- New
(sigil syntax)module withsyntax->datum,datum->syntax,generate-temporaries
Error Handling
- Catchable VM errors:
guardcan now catch type errors, division by zero, and out-of-bounds access. Use the newvm-error?predicate in(sigil error). - Better stack traces: Errors display file paths with line and column positions. Anonymous lambda frames are filtered by default for cleaner output.
Profiling
New (sigil profile) module for performance analysis:
(with-profiling
(my-expensive-operation))
(profile-report) ; Shows call counts, timing, allocationsLibrary Improvements
- sigil-http: Keyword arguments for
make-http-serverandhttp-serve(port:,host:,handler:) - sigil-sxml: New
sxml->htmlfor converting SXML trees to HTML strings - sigil-version: New package for semantic version parsing and comparison
Bug Fixes
- Fixed source file names in error stack traces
- Fixed socket API consistency across platforms
- Fixed
with-api-docspath resolution in sigil-publish - Fixed sigil-irc package dependency declaration
0.3.0
This release focuses on modular compilation and improved application bundling. Native dependencies like SQLite, TLS, and crypto are now separate packages, so applications only compile what they actually use. The new sigil publish command provides a complete static site generation pipeline, and bundling gains script mode support for simpler deployments.
Breaking Changes
- sigil-http: API review changes including lazy TLS loading for compile-time independence
Modular Native Packages
Heavy native dependencies have been extracted from sigil-lib into separate packages:
| Package | Description |
|---|---|
sigil-sqlite | SQLite database bindings |
sigil-tls | TLS/SSL support |
sigil-crypto | Cryptographic functions |
Applications that don't use these features no longer compile them, resulting in smaller binaries and faster builds.
Application Bundling
- Script mode: Bundle single-file scripts with
sigil bundle script.sgl - Custom runtimes: Build tailored runtimes with only needed native modules
- Native package detection: Automatic entrypoint generation for native dependencies
- Production runtime (
sigil-run): Script mode support for bundled applications
New Command: sigil publish
Static site generation with a pipeline-based architecture:
(site output-dir: "dist"
pipeline: (list markdown-processor syntax-highlighter)
watch-patterns: '("content/**/*.md" "templates/**/*.html"))Site operators integrate with the threading macro for composable pipelines.
Library Improvements
- sigil-json: Added
json-get-infor nested access - sigil-stdlib: New conveniences and predicates from API review
- sigil-args: New features and comprehensive documentation
- sigil-test: Native test build integration and new assertions
- sigil-build: Consolidated shared code and improved test support
Bug Fixes
- Fixed temp file creation on Windows (
sigil-lib)
0.2.0
This release focuses on improving the idiomatic functional programming style of Sigil. New modules for sequences and function composition make it easier to write clean, composable code. Pattern matching gains dict, vector, and struct support, and several APIs have been refined for consistency.
Breaking Changes
- Module renamed:
(sigil exceptions)→(sigil error) - API changes:
mapandfor-eachnow operate on single lists only. Uselist-mapandlist-for-eachfor multi-list operations. - Renamed functions:
remove-directory→delete-directory,channel-close→channel-close!
New Modules
| Module | Description |
|---|---|
(sigil random) | Random number generation, shuffling, and sampling |
(sigil seq) | Polymorphic sequences and transducers |
(sigil array) | Efficient fixed-size collections |
(sigil fn) | Function composition: compose, pipe, partial, juxt |
Pattern Matching Improvements
- Dict pattern matching:
(match d ((dict a: x b: y) ...)) - Vector literal syntax:
#(a b c)patterns - New forms:
match-lambda,match-lambda* - Struct and vector pattern support
Other Enhancements
- Unicode case conversion:
char-upcase,char-downcase,string-upcase,string-downcasewith full Unicode support - HTTP client: Added chunked transfer encoding support
- CLI:
sigil cli upgradenow uses native HTTP client (no curl dependency) - Dict utilities:
dict-select,dict-rename-keys,dict-get-infor nested access - Threading:
some->macro for nil-short-circuiting pipelines
0.1.0
The first public release of Sigil, a practical Scheme for building standalone applications.
NOTE: Sigil is still highly experimental and changing fast, but don't let that stop you from trying it out and providing feedback!
Highlights
- Standalone executables: Bundle your application with all dependencies into a single binary (~1-2MB base size)
- Fast startup: Bytecode VM with incremental garbage collection
- Hygienic macros: Full
syntax-ruleswithsyntax-casesupport - Batteries included: JSON, HTTP client/server, sockets, process management, and more
Core Runtime (sigil-lib)
The foundation: bytecode VM, S-expression reader, incremental mark-sweep GC, and native bindings for I/O, filesystem, networking, and process management.
Standard Library (sigil-stdlib)
Nearly complete R7RS base with practical extensions:
(sigil core)- Pattern matching, records, delimited continuations, array/dict utilities(sigil math)- Trigonometric, exponential, and bitwise operations(sigil string)- String manipulation utilities(sigil path)- Cross-platform path handling(sigil fs)- Filesystem operations(sigil io)- Extended I/O primitives(sigil process)- Process spawning and pipes(sigil time)- Date/time operations(sigil exceptions)- Exception handling(scheme *)- R7RS compatibility modules
Build System (sigil-build)
Package-based workspace architecture with:
- Dependency resolution across workspace packages
- Multiple build configurations (dev, debug, release)
- Executable bundling with embedded bytecode archives
CLI Tools (sigil-cli)
Development workflow commands:
sigil build- Compile packages and dependenciessigil bundle- Create standalone executablessigil test- Run test suitessigil repl- Interactive developmentsigil format- Code formattingsigil changes- Release managementsigil cli- Install and manage Sigil installations
Libraries
| Package | Description |
|---|---|
| sigil-json | JSON parsing and serialization |
| sigil-http | HTTP/1.1 client and server with TLS support |
| sigil-socket | TCP/UDP networking |
| sigil-websocket | WebSocket client and server |
| sigil-sqlite | SQLite database bindings |
| sigil-git | Git repository operations |
| sigil-repl | Interactive REPL with readline |
| sigil-nrepl | Network REPL for editor integration |
| sigil-test | Test framework with assertions |
| sigil-format | S-expression code formatter |
| sigil-markdown | Markdown parsing with frontmatter |
| sigil-sxml | SXML document construction |
| sigil-ansi | Terminal colors and formatting |
| sigil-args | Command-line argument parsing |
| sigil-hooks | Extensible hook system |
| sigil-mcp | Model Context Protocol server |
| sigil-jwt | JWT token encoding and verification |
| sigil-docs | Documentation generation |
| sigil-web | Web application framework |
| sigil-publish | Static site generation pipeline |
| sigil-irc | IRC client |
| sigil-css | CSS generation from Sigil code |
Note: Library APIs may change between minor releases until 1.0. Core modules (sigil-lib,sigil-stdlib) aim for stability.
Platform Support
| Platform | Architecture | Status |
|---|---|---|
| Linux | x86_64, aarch64 | Primary development platform |
| macOS | arm64, x86_64 | Builds and runs, not yet extensively tested |
| Windows | x86_64 | Builds and runs, not yet extensively tested |
| FreeBSD | x86_64 | Cross-compiles, not yet tested on real hardware |
| OpenBSD | x86_64 | Cross-compiles, not yet tested on real hardware |
| NetBSD | x86_64 | Cross-compiles, not yet tested on real hardware |
| Web/WASM | - | Runs in browser via Emscripten |
Known Limitations
- R7RS Small coverage is not yet complete; full compliance planned for a future release
- Limited SRFI coverage
Getting Started
See the Getting Started guide for installation and first steps.