FScript: a strongly typed language designed to be embedded

FScript: a strongly typed language designed to be embedded

July 17, 2026

Terrabuild’s extensions are powered by FScript, a small, open-source language built at Magnus Opera. We created it for a specific reason: applications sometimes need logic that can evolve independently, without giving up the guarantees and boundaries of the host system.

FScript is not only a command-line scripting tool. It is an embeddable language runtime for .NET and JavaScript applications. A host can load a script in-process, type-check it, inspect its exported functions, and invoke them by name. No sidecar service or RPC layer is required.

ML-style, with strong static typing

FScript belongs to the ML family of languages and will feel familiar to F# and OCaml developers. Its language model includes:

  • immutable bindings and expression-oriented code;
  • records and discriminated unions;
  • options, lists, tuples, and maps;
  • functions, pipelines, and pattern matching;
  • Hindley–Milner type inference.

The last point matters. FScript is strongly and statically typed, but most types do not need to be written explicitly. The language infers them and checks the program before evaluation. Type annotations remain available wherever an interface should be made explicit.

Here is the pricing example from the FScript home page:

type Customer =
  { Name: string
    Plan: string
    Seats: int }

[<export>] let quote (customer: Customer) =
  let basePrice =
    match customer.Plan with
    | "scale" -> 29
    | "team" -> 19
    | _ -> 9

  basePrice * customer.Seats

The Customer record defines the input contract. Pattern matching makes the pricing rule explicit, and the type checker infers that quote returns an integer. The [<export>] annotation makes the function visible to the embedding host; everything else stays internal to the script.

This is the balance FScript aims for: concise enough for rules and automation, while retaining the structure expected from application code.

The host stays in control

Embedding a language is also about deciding what scripts are allowed to do.

FScript uses a capability-based model. The core language has no ambient access to the filesystem, network, database, or process environment. The host explicitly registers typed external functions, and scripts can use only the capabilities they receive.

The boundary works in both directions:

  • the host defines typed functions available to scripts;
  • scripts expose only bindings marked with [<export>];
  • scripts are parsed and type-checked before execution;
  • the host controls source loading, imports, timeouts, and operational limits.

This makes FScript suitable for product rules, workflows, build integrations, and other extension points where flexibility must remain reviewable and constrained.

Why Terrabuild uses FScript

A Terrabuild extension translates a target action such as build, test, or publish into the shell operations that Terrabuild schedules. Built-in extensions for .NET, npm, pnpm, Docker, Terraform, and other tools are FScript programs, and workspaces can provide their own .fss extensions without recompiling Terrabuild.

The language and the host protocol complement each other:

  • FScript provides typed records, unions, options, functions, and pattern matching.
  • Terrabuild provides typed build contexts and extension contracts.
  • The extension returns data describing commands instead of running arbitrary processes directly.
  • Terrabuild remains responsible for scheduling, containers, caching, artifacts, and failure handling.

Because the protocol is strongly typed, an extension’s inputs and outputs are checked when the script is loaded. Because capabilities are host-controlled, Terrabuild can restrict filesystem access and omit functions that do not fit deterministic graph evaluation.

The result is an extension system that is easier to read and change than compiled plugins, without falling back to unstructured shell scripting.

Explore FScript

FScript can be used as a standalone CLI, embedded through NuGet packages, or loaded in a JavaScript application through @magnusopera/fscript.

You can try FScript in the browser, read the language manual, or explore the project on GitHub.

Last updated on