Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

nix-ast

A Nix library that parses, inspects, transforms, and evaluates Nix Abstract Syntax Trees (AST) using Haskell’s hnix parser.

nix-ast exposes a full Nix AST API directly in Nix itself (via IFD, Import From Derivation) and uses hnix’s Haskell parser and evaluator internally. You can parse any Nix expression into a structured AST, traverse and transform it with pure Nix functions, render it back to source code, and even evaluate it. All from within your Nix expressions.


Features

FeatureDescription
ParseParse any Nix expression (file, string, or stdin) into a structured, typed AST
RenderConvert an AST back to formatted, importable Nix code
EvalEvaluate ASTs using hnix’s evaluator and get the results as JSON values
toASTConvert native Nix values (ints, strings, lists, attrsets) to AST nodes (pure, no IFD)
fromASTConvert an AST back to a native Nix value, the inverse of toAST (pure, no IFD)
Pattern MatchingType-safe tag-based dispatch with match ast { Tag = handler; _ = fallback; }
TraversalRecursive transform, rewrite, universe, children/rebuild, and contexts
Type-checked ConstructorsAll mk* builders validate argument types at runtime with descriptive error messages
CLI Toolnix-ast eval / nix-ast parse / nix-ast render for shell/pipe workflows

Quick Start

Using the Nix Library (Flake)

Add nix-ast to your flake inputs:

inputs.nix-ast.url = "github:z1-0/nix-ast";

The library exposes three main API groups via inputs.nix-ast.lib:

APIDescription
lib.parse lib.render lib.evalIFD-based: bridge to hnix’s parser/evaluator
lib.toAST lib.fromASTPure Nix: convert between Nix values and ASTs
lib.match lib.syntax lib.traversalWork with AST nodes after construction
# Parse -> Transform -> Render
asts = lib.parse pkgs [./config.nix];
transformed = lib.traversal.transform (node: ...) (builtins.head asts);
outPaths = lib.render pkgs [transformed];
config = import (builtins.head outPaths);

# Parse -> Evaluate (skip rendering)
result = lib.eval pkgs asts;

CLI

# Parse from expression string
nix-ast parse --expr '{ x = 1; }' > ast.json

# Parse files from stdin (one path per line)
echo ./config.nix | nix-ast parse > ast.json

# Render AST back to Nix
nix-ast render --json '{"tag":"Set","recursive":false,"bindings":[...]}'

# Render batch to output directory
nix-ast render < asts.json --out-dir ./out

# Evaluate AST using hnix
nix-ast eval --json '{"tag":"Constant","contents":{"tag":"Int","contents":42}}'

# Pipe workflow: parse -> eval
nix-ast parse --expr '{ x = 1 + 2; }' | nix-ast eval

Architecture

┌─────────────────────────────────────────────────────────┐
│                     Nix (your flake)                     │
│                                                         │
│  lib.parse   lib.render   lib.eval                      │
│       │           │           │                         │
│       ▼           ▼           ▼                         │
│  ┌──────────────────────────────┐                       │
│  │  IFD: nix-ast CLI (Haskell)  │  <- hnix parser/eval  │
│  └──────────────────────────────┘                       │
│                                                         │
│  lib.toAST  lib.fromAST  (pure Nix, no IFD)             │
│  lib.match  lib.syntax  lib.traversal                   │
└─────────────────────────────────────────────────────────┘

parse/render/eval go through Haskell via IFD. toAST/fromAST/match/syntax/traversal run in pure Nix on the AST values.

Installation

# Run directly without installing
nix run github:z1-0/nix-ast -- parse --expr '{ x = 1; }'

# Or add to your flake inputs
inputs.nix-ast.url = "github:z1-0/nix-ast";

Binary Cache

Use the Cachix cache to skip building from source.

nix.settings = {
  substituters = [ "https://z1-0.cachix.org" ];
  trusted-public-keys = [ "z1-0.cachix.org-1:FS7lPgL0StRBOPrlu0RgdCL7LafUI23+U6Iivdw5QK8=" ];
};

Learn more

  • API Reference: parse, render, eval, construct, match, and traverse AST nodes
  • AST Reference: every node type with fields, JSON representation, and examples
    • Expr: 19 expression constructors
    • Atom: primitive constants (Bool, Int, Float, Null, Uri)
    • Binding: Inherit, NamedVar
    • KeyName: StaticKey, DynamicKey
    • Params: Param, ParamSet
    • String: DoubleQuoted, Indented
    • Antiquoted: Plain, Antiquoted, EscapedNewline
  • CLI Reference: nix-ast eval / nix-ast parse / nix-ast render

License

BSD-3-Clause: see LICENSE for details.