CLS is designed around a strict separation of concerns: language logic, execution, and deployment environment are three fully decoupled layers that never reach across each other’s boundaries.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/elfrask/cls/llms.txt
Use this file to discover all available pages before exploring further.
cls-core knows only about tokens, ASTs, types, and diagnostics — it has no filesystem access and no opinion about where code comes from. cls-runtime knows how to execute an AST and what a Value is, but it never reads a file or opens a socket directly. The nodes — clx and clxr — are the narrow integration points that wire everything together for a specific environment by injecting resolvers, stdlib modules, and I/O capabilities.
Layer Diagram
cls-core, becomes an AST, travels to cls-runtime for execution, and the node provides everything the runtime cannot see — which files to read, which network calls to allow, and where to print errors.
cls-core
cls-core is the pure language crate. It accepts source text, produces tokens and an AST, and optionally runs middleware passes. It has zero filesystem or network I/O.
Crate layout:
Frontend
Lexer converts source text to a
SpannedToken stream, handling string delimiters, CMX markup, and # comments inline.Parser is a recursive-descent parser that builds typed AST nodes (Module, Statement, Expression) from the token stream.Middleware
TypeChecker validates type annotations, resolves generics, and reports diagnostics without modifying the AST.NameResolver ensures every identifier is declared before use.Optimizer performs AST-level rewrites (constant folding infrastructure is present, though the folding pass is planned).
cls-runtime
cls-runtime is the execution crate. It contains the tree-walker interpreter, the Value enum, the scoped Environment, and the core standard library. Like cls-core, it has no direct I/O — every capability is injected by the node.
Crate layout:
ModuleResolver trait is the key abstraction: the runtime calls it to resolve import "module" paths, but it never knows whether the resolver reads from a file, a zip archive, an in-memory map, or a registry. That decision belongs entirely to the node.
Nodes: clx and clxr
A node is a binary that configures the runtime for a specific environment. It:- Registers intrinsics (
print,input,exit, etc.) in the initial environment. - Configures a ModuleResolver that knows how to locate
.clsxsource files,.clsappzips, and standard library modules. - Injects node-local modules (
fs,http,Lib) that the runtime and core never reference directly. - Decides where and how to report errors (console, JSON, HTML).
clx — Development CLI
clx is the full development toolchain. Its subcommands:
| Subcommand | Description |
|---|---|
new <name> | Scaffold a new CLS project |
run [file] | Execute a .clsx file |
check [file|dir] | Run type checker and name resolver |
build [file] | Package into a .clsapp zip |
maptype [path] | Generate .type.json type maps |
ast <file> --json | Dump AST as JSON |
repl | Interactive REPL |
add / remove / install | Dependency management |
lsp | Start the LSP server |
clxr — Lightweight Runtime
clxr is the production executor. It can run .clsx source files and .clsapp packaged applications, but exposes none of the development tooling. It is the binary you distribute alongside a .clsapp.
Module System Architecture
CLS has two orthogonal module systems that coexist without interfering:System A — Source Modules
import "mod" loads .clsx source or a stdlib name. Resolved by the pluggable ModuleResolver. During clx build, all resolved module ASTs are serialised into the .clsapp zip and accessible at runtime via the res:// VFS protocol.System B — Compiled Libraries
Lib.load("./lib.clslib") loads a .clslib zip containing .clbin WASM bytecode (planned). Resolved by a separate ClsLibResolver. A .clslib ships alongside a .clsapp, not inside it — equivalent to a .dll or .so.Workspace Crate Structure
cargo build -p clx and the runtime executor with cargo build -p clxr.