sigildocs

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 declares c-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:

RepositoryContents
codeberg:sigil/sigil-langsigil-lib (C runtime), sigil-stdlib (standard library), compiler
codeberg:sigil/sigil-buildsigil-package, sigil-deps, sigil-build (build system + manifest + dep resolver)
codeberg:sigil/sigil-ansiterminal styling
codeberg:sigil/sigil-argscommand-line argument parsing
codeberg:sigil/sigil-cryptocryptography primitives (vendored mbedTLS)
codeberg:sigil/sigil-docsdocumentation generation
codeberg:sigil/sigil-ffiforeign function interface
codeberg:sigil/sigil-formatcode formatting
codeberg:sigil/sigil-gitgit integration
codeberg:sigil/sigil-hookslifecycle hooks
codeberg:sigil/sigil-httpHTTP client + server
codeberg:sigil/sigil-jsonJSON parsing + encoding
codeberg:sigil/sigil-logstructured logging
codeberg:sigil/sigil-lsplanguage server
codeberg:sigil/sigil-mcpMCP (Model Context Protocol) library
codeberg:sigil/sigil-nreplnetwork REPL protocol
codeberg:sigil/sigil-replREPL library
codeberg:sigil/sigil-socketsocket primitives
codeberg:sigil/sigil-sqliteSQLite (vendored amalgamation)
codeberg:sigil/sigil-storecontent-addressed storage
codeberg:sigil/sigil-testtest runner
codeberg:sigil/sigil-tlsTLS layer (consumes sigil-crypto)
codeberg:sigil/sigil-versionversion helpers
codeberg:sigil/sigil-webweb 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 for quasisyntax, unsyntax, and unsyntax-splicing` (matching R6RS).
  • Quasisyntax expansion — full hygienic template expansion lands. Templates can use unsyntax to splice values back into a syntax object during macro expansion.
  • syntax-local-value — R6RS compile-time environment query, available inside macros.
  • syntax/#' outside syntax-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-case ellipsis 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 stalenesssigil deps install now invalidates a lock entry when its from-git URL 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 errorsigil deps install now exits non-zero when any fetch errors out. Previous behavior printed the error in red but still returned success and wrote the lockfile.
  • --config validationsigil build --config <name> now fails loudly when the config name is undeclared in package.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-crafter theme 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_BINDING cache-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.c were removed after the underlying case-lambda hygiene bug was fixed in the syntax-case path.
  • Visible libsigil.a build progress — sigil-build's libsigil compile path now prints one line per call (libsigil.a: cache hit (...) or Building 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-name falls back to from-git-package — previously, deps installed via (from-git url: ... package: ...) shape resolved to a name of #f in error messages.
  • fetch-sgl symlink racecreate-package-symlink now tolerates the dangling-symlink edge where a previous delete-file raced with file-exists? returning true.
  • WASM-incompatible code excluded from WASM buildssigil-lib's setjmp-based exception scaffolding and tzset()-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 install would 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 filterText and textEdit for editors like eglot
  • Go-to-definition — jumps to the exporting .sgl source line; descends into library re-exports
  • Formatting — full-document and range formatting via (sigil format)
  • Quick-fix code actionssuggest-import proposes imports for undefined bindings and remove-unused-import cleans 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/test tool (was inheriting sigil-mcp's environment)
  • Per-server --log / --log-level flags for traceable multi-worker setups
  • JSON-RPC id: null compliance 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_args pointer 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 guard forms.
  • Compiler self-bootstrap — 0.12.0 compilers can now build 0.13.0 source without guarded-reference crashes (SIGIL_ABI_VERSION reference 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.hopcodes.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-continuable in 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-library body defines leaking to top level
  • Fix guard/with-exception-handler across eval boundaries and tail calls
  • Fix collect_internal_defines and capture analysis for module bodies
  • Fix MCP server crash on resources/templates/list requests

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 opcodes
  • cps-emit-reg.c -- CPS IR to register bytecode emission

Performance

Benchmarks across 60+ tests (ratio = register VM time / direct compiler time, lower is faster):

CategoryRatioImprovement
Compute (fib, tak, ack)0.79-0.93x7-21% faster
Closures0.56-1.03xUp to 44% faster
Tail calls0.76-0.96xUp to 24% faster
String processing0.43-0.90xUp to 57% faster
Allocation/trees0.80-1.01xUp to 20% faster
Higher-order functions0.72-1.03xUp to 28% faster
JSON encode/decode~1.0xParity (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=1 flag activates CPS + register VM together
  • SIGIL_MODULE_MAX_MACROS increased 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 allocator
  • cps-convert.c -- S-expression to CPS conversion
  • cps-emit.c -- CPS to bytecode emission
  • cps-opt.c -- optimization pass pipeline
  • cps-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 optimization
  • SIGIL_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-expand implemented as an expression form in the CPS converter
  • case-lambda CPS 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-library body
  • Fix make-vector to use native call instead of primitive opcode
  • make default target now builds stdlib (previously required make 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 install reads the lockfile and uses pinned refs for reproducible installs
  • sigil deps update ignores the lockfile, re-resolves from package.sgl ranges, and writes a fresh lockfile
  • --redirects skips 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/semver and sigil/deps/lock to 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 PackageRepositoryDescription
sigil-pegcodeberg.org/sigil/sigil-pegPEG parser combinators
sigil-sxmlcodeberg.org/sigil/sigil-sxmlSXML to HTML/XML conversion
sigil-markdowncodeberg.org/sigil/sigil-markdownCommonMark parser with YAML front matter
sigil-webcodeberg.org/sigil/sigil-webWeb application framework
sigil-csscodeberg.org/sigil/sigil-cssProgrammatic CSS generation
sigil-matchcodeberg.org/sigil/sigil-matchPattern matching
sigil-fpcodeberg.org/sigil/sigil-fpFunctional programming utilities (compose, pipe, partial, threading macros)
sigil-transducerscodeberg.org/sigil/sigil-transducersComposable transducers
sigil-r7rscodeberg.org/sigil/sigil-r7rsR7RS-small compatibility (scheme *) modules and SRFI-9 records
sigil-web-replcodeberg.org/sigil/sigil-web-replBrowser-based REPL (was sigil-playground)
presscodeberg.org/sigil/pressStatic site generator (was sigil-publish)
sigil-sitecodeberg.org/sigil/sigil-siteOfficial Sigil website
sigil-web-democodeberg.org/sigil/sigil-web-demoDemo 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 to sigil-match
  • Transducers (mapping, filtering, transduce) — moved to sigil-transducers
  • Functional combinators (compose, pipe, curry, partial, cut/cute) — moved to sigil-fp
  • Threading macros (chain, ->, some->) — moved to sigil-fp
  • R7RS compatibility ((scheme base), (scheme write), etc.) — moved to sigil-r7rs
  • SRFI-9 records (define-record-type) — moved to sigil-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-compiler and compile-native-tests prefer zig cc when available, falling back to system cc/gcc
  • Cross-compilation: All eight platform targets use Zig (unchanged from 0.8)
  • CI: Test and GC stress jobs use Zig via with-zig wrapper
  • WebAssembly: New web build config uses zig 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_shim for 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) — the sigil docs CLI subcommand. Press handles all doc site generation now.
  • Removed (sigil docs execute) — code block execution for doc validation
  • Removed dependencies on sigil-markdown and sigil-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 docs command (handled by press)
  • Removed sigil publish command (handled by press)
  • Removed sigil changes command (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-callback creates 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 #f to 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 servers
  • sigil app list — show installed applications
  • sigil app update — pull latest changes and rebuild
  • sigil app remove — clean up installed app and deregister MCP servers
  • sigil 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

PackageDescription
sigil-ffiDynamic FFI for calling C libraries at runtime via dyncall
sigil-cairoCairo 2D graphics bindings — paths, transforms, surfaces, PNG loading, compositing operators, glyph rendering
sigil-freetypeFreeType font loading and glyph metrics via FFI
sigil-harfbuzzHarfBuzz text shaping via FFI
sigil-raylibRaylib game development bindings — 2D shapes, text, input, collision, audio
sigil-caldavCalDAV calendar client with iCalendar parsing, event CRUD, recurrence expansion, timezone handling
sigil-telegramTelegram 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-log with log-configure-from-args! for CLI integration
  • Better error reporting: Stack traces included in MCP tool error responses

HTTP Improvements

  • /json route helpers now return JSON bodies on all HTTP status codes, not just 2xx
  • url-encode-value and build-query-string for 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-Length using 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-ID exception 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-static and prerelease-static

JMAP Improvements

  • jmap-email-count for lightweight email counting without fetching messages
  • jmap-download-blob for 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-unzip to use simultaneous traversal
  • Deduplicated inspect-vector and inspect-array with shared helper
  • Dict-based lookups in diagnostic module and watch module for faster type-guard and mtime resolution

Bug Fixes

  • Fixed crash when format displays bignum values
  • Fixed segfault from unbounded macro export recursion
  • Fixed preemptive yield escaping through sigil_apply boundaries
  • Fixed string->list to properly decode UTF-8 characters
  • Fixed string-join overflow 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-tls package
  • Fixed Windows cross-compilation: fcntl/FD_CLOEXEC guards replaced with SetHandleInformation
  • Fixed OpenBSD cross-compilation: setvbuf workaround for opaque FILE struct in Zig headers
  • Fixed OpenBSD executable path resolution, poll fd limit, and partial write handling
  • Set FD_CLOEXEC on 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-checks feature — zero cost in release builds
  • Predicate combinators: any-of, maybe, list-of, none-of for expressive type constraints
  • Struct field annotations: define-struct fields 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

PackageDescription
sigil-tuiImmediate-mode terminal UI toolkit with native C grid, layout system, components, event parsing, and text input
sigil-jmapJMAP email client (RFC 8620/8621) with session discovery, mailbox operations, email query/send
sigil-yamlYAML parsing and serialization with block/flow collections, block scalars, anchors/aliases, multi-document
sigil-logStructured 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 api fixed 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 _inline field name
  • Fixed Windows build: use define-native for unix-connect (not available on Windows)
  • Fixed exception handler double-pop causing test runner segfault
  • Fixed bootstrap compilation: replaced when with if in %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, do syntax, guard prompt 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-shared with datum labels for circular structure printing
  • Feature detection: features, cond-expand, syntax-error
  • Libraries: (scheme time), (scheme process-context), (scheme repl) with interaction-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-sel for 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

PackageDescription
sigil-pegParsing Expression Grammars with S-expression DSL, backtracking, and captures
sigil-orgOrg Mode parser producing SXML (headlines, metadata, source blocks, tables, lists)
sigil-xmppXMPP 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 describe and modules operations
  • Watch mode: sigil build --watch and sigil test --watch with --format json support
  • Value inspection: New (sigil inspect) module for structured introspection via nREPL and MCP
  • Project templates: sigil init gains web-app, api-service, and mcp-tool templates
  • 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_MAX limit (increased to 2048) for projects with many native bindings
  • Fixed --no-color flag in test runner
  • Fixed git-fetch to 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_COMPILATION workaround entirely. Fixed 46+ unrooted allocation sites in the compiler through systematic audit
  • GC stress testing: SIGIL_GC_STRESS=1 forces 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 display and write
  • 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-remove with sharing, branch collapse, and HAMT-to-array demotion when count drops below 8

Error Handling

  • Three exit(1) calls in the module system replaced with sigil__vm_error() so the Scheme-level exception system handles them gracefully
  • OP_ABORT_TO_PROMPT now extracts real error messages from exception objects
  • Macro expansion errors propagate properly to the compiler
  • match raises 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:5

Multimedia Packages

sigil-studio has been split into three independent packages for more flexible dependency management:

PackageDescription
sigil-appWindowing, input, application lifecycle (sokol_app)
sigil-graphics2D rendering, image loading, font rendering (sokol_gfx, stb)
sigil-audioSound 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-flags field on library definitions
  • --profile flag 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-ref to return values instead of aliasing assq; added assv-ref
  • Fixed number->string precision for exact IEEE 754 roundtrip (was losing digits on large flonums)
  • Fixed REPL string-length error after exception recovery
  • Fixed cross-module symbol resolution corruption
  • Fixed bundle directory listing for bundled applications (VFS)
  • Fixed sigil-run re-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-* to sg-* prefix (e.g., sigil-button becomes sg-button) to mirror data-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 with syntax->datum, datum->syntax, generate-temporaries

Error Handling

  • Catchable VM errors: guard can now catch type errors, division by zero, and out-of-bounds access. Use the new vm-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, allocations

Library Improvements

  • sigil-http: Keyword arguments for make-http-server and http-serve (port:, host:, handler:)
  • sigil-sxml: New sxml->html for 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-docs path 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:

PackageDescription
sigil-sqliteSQLite database bindings
sigil-tlsTLS/SSL support
sigil-cryptoCryptographic 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-in for 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: map and for-each now operate on single lists only. Use list-map and list-for-each for multi-list operations.
  • Renamed functions: remove-directorydelete-directory, channel-closechannel-close!

New Modules

ModuleDescription
(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-downcase with full Unicode support
  • HTTP client: Added chunked transfer encoding support
  • CLI: sigil cli upgrade now uses native HTTP client (no curl dependency)
  • Dict utilities: dict-select, dict-rename-keys, dict-get-in for 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-rules with syntax-case support
  • 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 dependencies
  • sigil bundle - Create standalone executables
  • sigil test - Run test suites
  • sigil repl - Interactive development
  • sigil format - Code formatting
  • sigil changes - Release management
  • sigil cli - Install and manage Sigil installations

Libraries

PackageDescription
sigil-jsonJSON parsing and serialization
sigil-httpHTTP/1.1 client and server with TLS support
sigil-socketTCP/UDP networking
sigil-websocketWebSocket client and server
sigil-sqliteSQLite database bindings
sigil-gitGit repository operations
sigil-replInteractive REPL with readline
sigil-nreplNetwork REPL for editor integration
sigil-testTest framework with assertions
sigil-formatS-expression code formatter
sigil-markdownMarkdown parsing with frontmatter
sigil-sxmlSXML document construction
sigil-ansiTerminal colors and formatting
sigil-argsCommand-line argument parsing
sigil-hooksExtensible hook system
sigil-mcpModel Context Protocol server
sigil-jwtJWT token encoding and verification
sigil-docsDocumentation generation
sigil-webWeb application framework
sigil-publishStatic site generation pipeline
sigil-ircIRC client
sigil-cssCSS 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

PlatformArchitectureStatus
Linuxx86_64, aarch64Primary development platform
macOSarm64, x86_64Builds and runs, not yet extensively tested
Windowsx86_64Builds and runs, not yet extensively tested
FreeBSDx86_64Cross-compiles, not yet tested on real hardware
OpenBSDx86_64Cross-compiles, not yet tested on real hardware
NetBSDx86_64Cross-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.