An opinionated import organizer for Zig. Sorts, groups, and hoists @import
declarations, similar to isort for Python or
goimports for Go.
Note
Requires Zig 0.15.2 or newer (including 0.16) on Linux or macOS. On Windows, use WSL2.
brew tap mstdokumaci/zsort
brew install mstdokumaci/zsort/zsortDownload from GitHub Releases,
unpack, and add to your PATH.
Add to build.zig.zon:
.zsort = .{
.url = "https://github.com/mstdokumaci/zsort/archive/refs/tags/v0.7.0.tar.gz",
// .hash
.lazy = true,
},Wire up build steps in build.zig:
const zsort = b.lazyDependency("zsort", .{
.target = b.graph.host,
.optimize = .ReleaseFast,
});
if (zsort) |dep| {
const zsort_exe = dep.artifact("zsort");
const check_imports = b.addRunArtifact(zsort_exe);
check_imports.setCwd(b.path("."));
check_imports.addArgs(&.{ "check", "src", "--ban-prefix", "./", "--ban-prefix", "src/" });
b.step("check-imports", "Run zsort check on this project").dependOn(&check_imports.step);
const run_fix = b.addRunArtifact(zsort_exe);
run_fix.setCwd(b.path("."));
run_fix.addArgs(&.{ "fix", "src", "--ban-prefix", "./", "--ban-prefix", "src/" });
b.step("fix-imports", "Fix Zig import ordering in this project").dependOn(&run_fix.step);
}See test/consumer/ for a working example.
zig build -Doptimize=ReleaseFast # → zig-out/bin/zsortUsage: zsort [check|fix] <dir|file>... [options]
Modes:
check Verify import ordering (exit 1 if changes needed)
fix Rewrite files in place
Options:
--ban-prefix <p> Reject imports starting with <p> (repeatable)
--bottom Place the import block at the end of the file
-h, --help Show help
--version Print version
zsort check src/ # verify a directory
zsort fix . # fix everything
zsort check src/ build.zig # mixed targets
zsort check . --ban-prefix ./ --ban-prefix src/ # ban relative paths
zsort fix . --bottom # imports at the end of the filecheckprints unified diffs for files that need changes.// zsort: skipanywhere in a file excludes it from processing.- Directories are scanned recursively.
.gitignoreentries,.git,.zig-cache,zig-cache, andzig-outare skipped automatically.
zsort groups imports into four bands, separated by blank lines:
- std / builtin — the
stdandbuiltinmodules - Third-party — other module names (
httpz,sqlite, …), including@cImport - Local — paths containing
/or ending in.zig, plus Zig's package-level modulesroot(the package's own root source file) andbuild_root(the build runner's root module) - Aliases —
const X = module.Member;wheremoduleresolves to an import above;const X = @This();sorts first in this band
Within each band, plain imports come before member imports, then both are sorted
by path (byte-wise). If two imports share the same path, the full line of code
breaks the tie (e.g. const Foo = @import("x.zig").Foo; before
const bar = @import("x.zig").bar;). The output is deterministic regardless
of input order.
Before zsort fix:
const std = @import("std");
const Config = auth.Config;
const Router = @import("router.zig").Router;
const httpz = @import("httpz");
// Handles request authentication.
const auth = @import("auth.zig");After:
const std = @import("std");
const httpz = @import("httpz");
// Handles request authentication.
const auth = @import("auth.zig");
const Router = @import("router.zig").Router;
const Config = auth.Config;- Sorts and groups top-of-file imports into the bands above
- Hoists stray imports and aliases from deeper in the file into their proper band
- Keeps preceding comments attached to their import
- Ensures a blank line between the import block and the following code
- Preserves
//!doc comments and original line endings (LF / CRLF)
With --bottom, the whole block instead moves to the end of the file (the
layout used by zig init templates): //! doc comments and comments
detached by a blank line stay at the top, comments directly attached to an
import travel with it, and comments after the last import stay with the
body. The sort order and bands are unchanged.
Add to .pre-commit-config.yaml:
repos:
- repo: https://github.com/mstdokumaci/zsort
rev: v0.7.0
hooks:
- id: zsort # check mode (fail on unsorted)
# - id: zsort-fix # fix mode (rewrite in place)Requires zsort on $PATH (language: system). Pass extra flags via args,
e.g. args: [--ban-prefix, 'src/']. Only .zig files are checked.
- CONTRIBUTING.md — development setup and lint gates
- CHANGELOG.md — release history
MIT