MCPcopy Index your code
hub / github.com/Glistix/glistix

github.com/Glistix/glistix @v0.8.0

Chat with this repo
repository ↗ · DeepWiki ↗ · release v0.8.0 ↗ · + Follow
7,208 symbols 18,162 edges 279 files 491 documented · 7% updated 9mo agov0.8.0 · 2025-04-21★ 22112 open issues
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

Glistix ❄️

The power of Nix meets the simplicity and type-safety of Gleam

GitHub release

Try it in your browser!

Join our Zulip chat!

Read the Glistix book here!

Mirrors: GitHub | Codeberg

 

Glistix is a fork of the Gleam compiler which adds a Nix backend, so that you can compile Gleam code into Nix and use it in your configurations!

This allows you to leverage Gleam's type-safety and simplicity to write reasonable and more correct code. You will also be able to use Gleam's tooling in your favor, such as unit tests and easy package management.

For more information on Gleam, including tutorials, please check the Gleam language's website and its language tour. Likewise, to learn more about the Nix language, check the NixOS website as well.

NOTE: Glistix is beta software, and may have breaking changes. You shouldn't rely on it on production just yet, but feel free to give it a shot on personal or smaller projects and report any issues and bugs you find. It should be functional, but we still need people to try it out and report any bugs.

NOTE: Glistix's latest stable version currently tracks Gleam v1.8.1, meaning features and fixes from up to that Gleam version are available.

NOTE: Glistix is an unofficial project and is therefore not affiliated with the Gleam project.

Project Status

  • Overall status: Usable, but still missing easy bindings (to Nixpkgs, NixOS, Home Manager) and usage examples. Please contribute!

  • Codegen (Gleam -> Nix): Pretty much done (only a few bit array options aren't supported)

  • FFI (use Nix in Gleam and vice-versa): Done
  • Use @external(nix, "file.nix", "function_name") to import a Nix function in Gleam
  • Use (import ./glistix/project/dir).lib.loadGlistixPackage { module = ... } to import a Gleam module in Nix
  • Gleam package support: Basic packages OK, other packages may need manual porting
  • Gleam stdlib: Basic functionality ported to Nix (maintained under glistix/stdlib), still missing important functions
  • Gleeunit, Json, Birl: Maintained under the Glistix org
  • Bindings: Lacking
  • Basic Nix language bindings available on Hex: glistix_nix
  • No Nixpkgs bindings
  • No NixOS module system bindings
  • No NixOS config bindings
  • No Home Manager bindings
  • No bindings for Flakes

Sponsors

Please consider supporting the team behind Gleam on GitHub. Without their awesome project, Glistix wouldn't exist!

If you also want to support the Glistix project directly, feel free to support me on GitHub as well!

We need help!

If you like the project and know some Nix, consider contributing! At the time of writing, we have a few important issues open at glistix/stdlib which could use some help. Additionally, feel free to explore issues at the Glistix compiler's repository (make sure to read the "Contributing" section below).

Getting in touch

You can talk to us at:

  1. Zulip
    • Preferred medium for structured discussions, as it is public and properly organized for that.
    • Especially encouraged for prospective contributors.
  2. Gleam's Discord, in the Glistix thread
    • This medium can be used for quick questions and general chatting.

Installation

Glistix officially supports Linux, MacOS and Windows. (Note, however, that Nix doesn't support Windows yet, so you won't be able to test your projects, but glistix build should work at least.)

You can install Glistix in one of the following ways.

  1. From GitHub Releases: If you're using Linux (any distro, including NixOS), MacOS or Windows, you can install Glistix by downloading the latest precompiled binary for your platform at https://github.com/glistix/glistix/releases.

  2. With Nix flakes: Invoke the command below in the command line to download, compile and run a specific release of Glistix - here the latest at the time of writing (v0.8.0).

    sh nix run 'github:Glistix/glistix/v0.8.0' -- --help

    To install permanently, you can either add github:Glistix/glistix/v0.8.0 as an input to your system/Home Manager configuration, or use nix profile:

    sh nix profile install 'github:Glistix/glistix/v0.8.0'

  3. With Cargo: You can use Cargo to compile and install Glistix's latest release (v0.8.0 at the time of writing):

    sh cargo install --git https://github.com/glistix/glistix --tag v0.8.0 --locked

Table of Contents

Motivation

Glistix was initially conceived in an attempt to improve the development experience of working with more complex Nix code. Whereas Nix can be fairly straightforward to use at its core (the language itself is tiny in terms of syntax), it can be observed in reality that writing more involved Nix code can take considerable time and/or effort to get right due to the lack of type-safety in Nix, which leads to limitations in Nix LSPs and often hard to understand errors which could have been avoided with static type-checking - that is, checking the correctness of your Nix code before you even try to evaluate it.

Personally, I (author of Glistix) have faced this kind of problem while writing my own NixOS and Home Manager modules - oftentimes the configuration logic can get more involved and become particularly hard to debug and/or expand on without some form of static type-checking (and thus proper autocomplete and so on), which leads to a worse development experience.

While there have been several attempts to add some form of static type-checking to Nix, very few have had great amounts of success so far. It always seemed like Nix needed some quite large (and thus unfeasible) changes to make it possible.

That's where Gleam comes in. Gleam is a functional and statically-typed language with friendly syntax and great tooling (including the compiler and its helpful errors, great support for unit testing, good LSP support across editors, and so on). What's more, Gleam was designed for transpilation to other dynamically-typed languages (namely Erlang and JavaScript). So, it was the perfect match: we could leverage the Gleam compiler and its tooling to write more complicated logic with Gleam, transpile that to Nix, and attempt to keep complexity of actual Nix source code at a minimum - the Nix code would then focus on calling the transpiled Gleam code as much as possible.

Thus Glistix was born: it adds a Nix backend to the Gleam compiler, alongside auxiliary features and tooling to make Gleam easier to use within the Nix ecosystem. The main goal is precisely to integrate Gleam and Nix together as much as possible, so that you may write Gleam code and use it within Nix, and vice-versa (Gleam code can invoke Nix functions through FFI).

Importantly, this is very much inspired by PureNix's approach. That project, which allows compiling PureScript to Nix, was one of the options considered before settling on Glistix's design, and has similar goals regarding type-checking and tooling. The main difference in our approach is the usage of Gleam, whose simplicity in syntax, concepts and usage makes it stand out among other languages (in our opinion). Nevertheless, make sure to check out PureNix as well if you're interested in learning more about alternatives - it is an awesome project as well!

We hope you will enjoy using Glistix for your Nix and NixOS projects!

Features

Glistix provides the following features on top of Gleam's compiler and tooling:

Compiling Gleam to Nix

You can write Gleam code and have Glistix produce equivalent Nix code. Almost all of the base language's features are supported (bar a few BitArray specifics).

The generated Nix code aims to be as readable as possible, and attempts to follow common formatting standards within the Nix ecosystem. In particular, we have taken a few concepts from Nix RFC 0166 and plan to be more conformant with said RFC in the future.

This also allows using packages from the Gleam ecosystem within Nix. Note that pure Gleam packages are instantly usable, while packages which require Erlang/JS FFI need to be manually ported.

  • These ports are made possible thanks to the function attributes @external(nix, "./file.nix", "functionName") and @target(nix). The first one allows importing a function declared in Nix (see the next section for an example), while the second allows specializing a function's implementation for each target supported by Glistix (one implementation for @target(erlang), one for @target(javascript) and another for @target(nix)).

Consider this example code in src/example.gleam, added after running glistix new example:

pub type Time {
  Seconds(Int)
  Minutes(amount: Int)
}

pub fn as_seconds(time: Time) -> Int {
  case time {
    Seconds(amount) -> amount
    Minutes(amount) -> 60 * amount
  }
}

pub fn main() {
  let example1 = Seconds(5)
  let example2 = Minutes(30)
  let seconds: Int = as_seconds(example1)
  let minutes = as_seconds(example2)

  #(seconds, minutes)
}

Running glistix build, Glistix will compile this to:

let
  Seconds = x0: { __gleamTag = "Seconds"; _0 = x0; };

  Minutes = amount: { __gleamTag = "Minutes"; inherit amount; };

  as_seconds =
    time:
    if time.__gleamTag == "Seconds" then let amount = time._0; in amount
    else let amount = time.amount; in 60 * amount;

  main =
    { }:
    let
      example1 = Seconds 5;
      example2 = Minutes 30;
      seconds = as_seconds example1;
      minutes = as_seconds example2;
    in
    [ seconds minutes ];
in
{ inherit Seconds Minutes as_seconds main; }

We can use glistix run (in this case with -- --strict so the tuple is fully evaluated), which runs nix-instantiate, to verify that main { } evaluates to [ 5 1800 ].

Note that: - Generated Nix code is formatted and readable; - Gleam records can be easily created and manipulated from Nix code through the generated constructor functions and the resulting attribute sets (the field names are preserved, and have the form _INDEX when strictly positional); - Gleam's built-in types are adequately mapped to Nix's built-in types where possible (there are notable non-obvious exceptions, such as List and BitArray - check the relevant book page for more info); - By convention, functions without arguments take an empty set { } as argument (you'd call main { } for example), whereas functions with one or more arguments take them positionally (for example, f(a, b, c) in Gleam translates to f a b c in Nix).

Make sure to check out the chapter on the Nix target of the official Glistix book for more information!

Using Nix code from Gleam via FFI

You can add .nix files to your src and import them from Gleam. For example, consider the Gleam code below at src/example.gleam:

// We will need some help from Nix to check
// if a string contains a comma. (In practice,
// you'd use Gleam's stdlib for this.)
@external(nix, "./ffi.nix", "containsComma")
fn contains_comma(string: String) -> Bool

/// Converts True/False to "Yes"/"No"
fn yes_or_no(boolean: Bool) -> String {
  case boolean {
    True -> "Yes"
    False -> "No"
  }
}

pub fn main() {
  let text = "abc,d"

  // Yes, you can use piping!
  contains_comma(text)
  |> yes_or_no
}

Also consider that we add src/ffi.nix as follows:

let
  containsComma = s: builtins.match ".*,.*" s != null;
in
{ inherit containsComma; }

With glistix run (which uses nix-instantiate to evaluate the main function), we get the expected output of "Yes" (text does indeed contain a comma).

Nix tools t

Extension points exported contracts — how you extend this code

Documentable (Interface)
Coerce a value into a Document. Note we do not implement this for String as a slight pressure to favour str over String. [19 …
compiler-core/src/pretty.rs
FileSystemReader (Interface)
A trait used to read files. Typically we use an implementation that reads from the file system, but in tests and in othe [5 …
compiler-core/src/io.rs
CommandExecutor (Interface)
A trait used to run other programs. [5 implementers]
compiler-core/src/io.rs
FileSystemWriter (Interface)
A trait used to write files. Typically we use an implementation that writes to the file system, but in tests and in othe [5 …
compiler-core/src/io.rs
BeamCompiler (Interface)
A trait used to compile Erlang and Elixir modules to BEAM bytecode. [4 implementers]
compiler-core/src/io.rs

Core symbols most depended-on inside this repo

map
called by 614
compiler-core/src/build.rs
append
called by 549
compiler-core/src/pretty.rs
to_doc
called by 433
compiler-core/src/format.rs
expect
called by 341
compiler-core/src/build.rs
len
called by 267
compiler-core/src/ast.rs
as_ref
called by 253
compiler-core/src/config.rs
to_string
called by 252
compiler-core/src/config.rs
unwrap
called by 229
compiler-core/src/build.rs

Shape

Function 4,632
Method 2,062
Class 334
Enum 155
Interface 25

Languages

Rust97%
TypeScript3%

Modules by API surface

compiler-core/src/type_/tests/errors.rs321 symbols
compiler-core/src/language_server/tests/action.rs297 symbols
compiler-core/generated/schema_capnp.rs291 symbols
compiler-core/src/format/tests.rs244 symbols
compiler-core/src/type_/tests/warnings.rs231 symbols
compiler-core/src/type_/tests.rs164 symbols
compiler-core/src/parse/tests.rs145 symbols
compiler-core/src/ast/visit.rs125 symbols
compiler-core/src/language_server/tests/completion.rs109 symbols
compiler-core/src/parse.rs108 symbols
compiler-core/src/language_server/code_action.rs108 symbols
compiler-core/src/format.rs108 symbols

For agents

$ claude mcp add glistix \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact