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

Getting Started

Install

Try without installing

The fastest way to try tix — no installation required:

nix run github:JRMurr/tix -- inspect my-file.nix

Add tix to your flake inputs:

{
  inputs.tix.url = "github:JRMurr/tix";
}

Then add the package to your system configuration:

# configuration.nix (NixOS)
{ inputs, pkgs, ... }:
{
  environment.systemPackages = [
    inputs.tix.packages.${pkgs.system}.default
  ];
}

Or add it to a dev shell:

{
  inputs.tix.url = "github:JRMurr/tix";

  outputs = { self, nixpkgs, tix, ... }:
    let
      pkgs = nixpkgs.legacyPackages.x86_64-linux;
    in {
      devShells.x86_64-linux.default = pkgs.mkShell {
        buildInputs = [
          tix.packages.x86_64-linux.default
        ];
      };
    };
}

Or install imperatively with nix profile:

nix profile install github:JRMurr/tix

Without flakes

Add to a traditional NixOS configuration via fetchTarball:

# configuration.nix
let
  tix = import (builtins.fetchTarball "https://github.com/JRMurr/tix/archive/main.tar.gz") {};
in
{
  environment.systemPackages = [
    tix.packages.${builtins.currentSystem}.default
  ];
}

Pin to a specific revision for reproducibility:

let
  tix = import (builtins.fetchTarball {
    url = "https://github.com/JRMurr/tix/archive/<rev>.tar.gz";
    sha256 = "<hash>";  # nix-prefetch-url --unpack <url>
  }) {};
in
  tix.packages.${builtins.currentSystem}.default

Or install imperatively with nix-env:

nix-env -f https://github.com/JRMurr/tix/archive/main.tar.gz -iA packages.x86_64-linux.default

Build from source

git clone https://github.com/JRMurr/tix
cd tix
cargo build --release
# Binary at target/release/tix

Or with nix:

nix build .#

Usage

Type-check a file

tix inspect my-file.nix

This prints the inferred type of each top-level binding and the root expression.

With stubs

tix inspect my-file.nix --stubs ./my-stubs/

--stubs accepts file paths or directories (recursively finds .tix files). Can be passed multiple times. The built-in nixpkgs stubs are loaded by default — use --no-default-stubs to disable.

Initialize a project

Scaffold a tix.toml by scanning your project for .nix files:

tix init

This classifies each file (NixOS module, Home Manager module, callPackage, overlay, etc.) and generates context sections automatically. Use --dry-run to preview without writing:

tix init --dry-run

Check a project

Type-check all files in a project using the tix.toml configuration:

tix check

This discovers all .nix files, applies context from tix.toml, and type-checks them in parallel using layered inference. Files are sorted by their import dependencies so that types flow between files — if a.nix imports b.nix, b.nix is inferred first and a.nix gets its real type. It also validates that file classifications match their configured contexts (e.g., warns if a NixOS module isn’t in any [context.nixos] section).

tix check --verbose    # Show file classifications
tix check --config path/to/tix.toml  # Explicit config path
tix check -j 4         # Limit to 4 parallel inference threads

Exit code is 1 if any type errors are found, 0 otherwise (config warnings don’t affect the exit code).

Machine-readable output

For CI pipelines and tool integration, use --format json to get structured JSON output on stdout:

tix inspect my-file.nix --format json
tix check --format json

The JSON schema includes diagnostics with file paths, 1-indexed line/column locations, severity, error codes, and documentation URLs. Single-file mode also includes inferred bindings and the root type.

{
  "version": 1,
  "files": [
    {
      "file": "my-file.nix",
      "diagnostics": [
        {
          "severity": "error",
          "code": "E001",
          "message": "type mismatch: expected `string`, got `int`",
          "line": 5,
          "column": 3,
          "end_line": 5,
          "end_column": 8,
          "url": "https://jrmurr.github.io/tix/diagnostics/e001.html"
        }
      ]
    }
  ],
  "summary": {
    "files_checked": 1,
    "errors": 1,
    "warnings": 0
  },
  "bindings": { "x": "int" },
  "root_type": "int"
}

The bindings and root_type fields are only present in single-file mode. The version field allows for future schema evolution.

Full type output

By default, large types are truncated for readability (fields, union members, nesting depth, and total characters are bounded). To see complete types without truncation:

tix inspect my-file.nix --full-types

Timing and profiling

Show per-phase timing and RSS memory usage:

tix inspect my-file.nix --timing
tix check --timing

This prints a breakdown of wall-clock time and memory for each pipeline phase (registry loading, parsing, name resolution, inference, diagnostics).

For detailed heap profiling, build with the dhat-heap feature:

cargo build --release --features dhat-heap
tix inspect my-file.nix    # produces dhat-heap.json

View the result at dhat-viewer.

Generate stubs

Generate typed stubs from your NixOS or Home Manager configuration:

# From a flake
tix stubs generate nixos --flake . --hostname myhost -o nixos.tix
tix stubs generate home-manager --flake . --username jr -o hm.tix

# From nixpkgs directly
tix stubs generate nixos --nixpkgs /path/to/nixpkgs -o nixos.tix

See the Stubs chapter for details.

LSP

tix lsp

Communicates over stdin/stdout. Works with any LSP-compatible editor. Stubs are loaded from tix.toml and editor settings.

Features: hover types, completions (dot access, function args, identifiers), go-to-definition, find references, rename, inlay hints, document symbols, semantic tokens, formatting (via nixfmt).