#!/usr/bin/env python3 """ Print the nixosConfigurations defined in flake.nix. Parses flake.nix directly (no `nix eval`, so it works without nix tooling and is fast). Brace-matches to find the closing `}` of nixosConfigurations so it handles nested attrsets correctly. """ import re import sys from pathlib import Path def list_hosts(flake_path: Path) -> list[str]: src = flake_path.read_text() m = re.search(r"nixosConfigurations\s*=\s*\{", src) if not m: return [] # Brace-match to find the matching closing }. depth, i, close = 0, m.end() - 1, None while i < len(src): c = src[i] if c == "{": depth += 1 elif c == "}": depth -= 1 if depth == 0: close = i break i += 1 block = src[m.end():close] if close is not None else "" return re.findall( r"^[ \t]*([A-Za-z_][\w-]*)\s*=\s*nixpkgs\.lib\.nixosSystem", block, re.M, ) def main() -> int: flake = Path(sys.argv[1]) if len(sys.argv) > 1 else Path("flake.nix") if not flake.is_file(): print(f"[-] not a file: {flake}", file=sys.stderr) return 1 for name in list_hosts(flake): print(name) return 0 if __name__ == "__main__": sys.exit(main())