Zigspinner: minimal terminal spinners for Zig (timed, ticked, no-std friendly)

Hi everyone, I built Zigspinner, a small spinner library for Zig focused on clean API, compile-time friendly presets, and cross-platform terminal output.

Screen Recording 2026-04-21 043045

What it includes:

- Timed spinners based on elapsed nanoseconds

- Ticked spinners for manual frame driving

- Reverse direction and offset support

- Presets: arrows, ascii, braille, emoji

- Works in no-std style loops

Quick install:

zig fetch --save git+https://github.com/Andrew-Velox/Zigspinner.git

Build integration:

const dep = b.dependency("Zigspinner", .{});

const zigspinner_mod = dep.module("Zigspinner");

exe.root_module.addImport("Zigspinner", zigspinner_mod);


Minimal usage:

const std = @import("std");

const sp = @import("Zigspinner");




pub fn main() !void {

    const spinner = sp.presets.ascii.simple_dots_scrolling();

    const start = std.time.nanoTimestamp();




    while (true) {

        const elapsed: u64 = @intCast(std.time.nanoTimestamp() - start);

        std.debug.print("\r{s}", .{spinner.frameAt(elapsed)});



        std.Thread.sleep(30_000_000);

    }




    std.debug.print("\rDone\n", .{});

}

Repo: https://github.com/Andrew-Velox/Zigspinner

Would love feedback on API shape, naming, and missing presets.

12 Likes

Given the recent release of Zig 0.16.0, I suggest indicate whether this works with that version or not (yet). Or what part can be used c.q. is tested with 0.16.

I looked at the source online and did see std.fs.File, so I suspected errors with Zig 0.16, and
when cloned, the source would not build out-of-the-box with Zig 0.16 (on the macOS M1 machine where I tried this). I am not complaining that it failed, as that is perfectly understandable, but I assume that others would want to know whether they can use it in 0.16, or not, before trying.

3 Likes

I guess you can look at the .minimum_zig_version = "0.15.2", in the build.zig.zon as an indicator (but not full confirmation) that it might only support 0.15.2 currently.

There are some packages that support multiple versions of Zig at the same time, for those Zig 0.16.0 might work too. Or some packages might just happen to work with newer Zig versions because they weren’t affected by the changes.

I also think it makes sense to use the version tags of ziggit.

3 Likes

I want to throw in a plug for @marler8997’s anyzig, which has made this upgrade (which I’ve barely started) so much more pleasant than it would otherwise have been.

Picks the Zig binary for a project based on the .minimum_zig_version string. Brilliant stuff.

3 Likes

I just played around a bit with it.

Looks great.

Also, it does work with 0.16.0 too since, at least the stuff related to the library, not the calls to nanoTimestamp, sleep and the example.

But if there’s a specific release for 0.16.0, a change from a raw number to std.Io.Timestamp and std.Io.Duration would be a nice touch.

Also, there’s an empty braile.zig file (one l instead of two) next to the braille.zig file in the repository.

1 Like

Great point, and thanks for raising it.
You were right that compatibility needed to be explicit. I’ve now validated both Zig 0.15.2 and Zig 0.16.0 with build + tests, and updated the project docs so users can see support status before trying.

1 Like

Thanks, this is a really good clarification.
I agree that .minimum_zig_version should be treated as a lower bound, not full confirmation. I now test against both 0.15.2 and 0.16.0, and I updated the README to reflect verified versions more clearly. Also agreed on Ziggit version tags, I’ll follow that.

That looks super useful, thanks for sharing this.
Using anyzig with .minimum_zig_version is a great workflow for reducing version friction, especially while supporting multiple Zig versions. I’ll mention this approach for others too.

1 Like

Thanks for testing and for the detailed notes.
Good catch on the duplicate empty braile.zig file, that has been removed.
And yes, I agree on your std.Io.Timestamp / std.Io.Duration suggestion for a cleaner 0.16-focused pass.