**The Night Watch** is a file change tracker for directory trees, written
in **Zig**, cross platform and provides a CLI tool and a zig module
Three bugs caused all integration tests to fail with -Dmacos_fsevents=true: - FSEventStreamCreate was passed *CallbackContext directly as the context parameter, which expects *FSEventStreamContext (a struct with version=0, info=ptr, retain/release/copyDescription). The handler pointer landed in the version field (must be 0) and info received by callbacks was garbage, so the callback returned immediately on every event. - FSEvents coalesces operations into a single delivery with multiple flags set (e.g. ItemCreated|ItemModified, ItemRenamed|ItemModified). The callback used an if/else chain that only emitted the first matching event type, so a write coalesced with a create or rename produced no 'modified' event. Fixed by checking each flag independently. - FSEvents delivers spurious historical events for watched root directories at stream start (even with kFSEventStreamEventIdSinceNow), causing phantom dir_created events. Fixed by snapshotting the watched root paths in CallbackContext at arm() time and skipping events whose path exactly matches a root. Also: arm() is now a no-op when no paths are watched yet (stream starts on the first add_watch call), add_watch/remove_watch restart the stream so paths added or removed take effect immediately, and makeTempDir resolves /tmp to /private/tmp on macOS so test-constructed paths match FSEvents canonical output. |
||
|---|---|---|
| docs | ||
| src | ||
| .gitignore | ||
| build.zig | ||
| build.zig.zon | ||
| README.md | ||
| test_manual.ps1 | ||
| test_manual.sh | ||
_ _ _ _ _ _ _ _ _
| \ | (_) | | | | | \ / | | | | |
| \| |_ __ _| |__ | |_ \ \ _ / /_ _| |_ __| |___
| . ` | |/ _` | '_ \| __| \ ` ' / _` | __|/ _| '_ \
| |\ | | (_| | | | | |_ \ / (_| | |_| (_| | | |
|_| \_|_|\__, |_| |_|\__| \_|_/ \__,_|\__|\__|_| |_|
__/ |
|___/
T H E N I G H T W A T C H
The city sleeps. The files do not.
"FABRICATI DIEM, PVNC"
The Night Watch is a file change tracker for directory trees, written in Zig.
It provides:
- A standalone CLI for tracking filesystem changes
- A module for embedding change-tracking into other Zig programs
- Minimal dependencies and consistent, predictable, cross-platform behavior
It does not interfere. It does not speculate. It simply keeps watch.
Features
- Recursive directory tree tracking
- Deterministic multi-platform support (Linux, FreeBSD, MacOS, Windows)
- Lightweight and fast
- Embeddable Zig module API
- Standalone CLI executable
Installation
The Watch is written in Zig and built using the Zig build system.
Requirements
- Zig (currently zig-0.15.2)
Build CLI
zig build
The executable will be located in:
zig-out/bin/nightwatch
Install System-Wide
zig build install
Using as a Zig Module
The Night Watch exposes a reusable module that can be imported into other Zig programs.
In your build.zig:
const nightwatch = b.dependency("nightwatch", .{
.target = target,
.optimize = optimize,
});
exe.root_module.addImport("nightwatch", nightwatch.module("nightwatch"));
In your Zig source:
const nightwatch = @import("nightwatch");
You now have programmatic access to the tracking engine.
CLI Usage
nightwatch [{path}..]
Run:
nightwatch --help
for full command documentation.
Philosophy
Other tools watch files.
The Night Watch keeps watch over the peace.
It remembers what changed. It records what vanished. It notices what arrived at 2:14 AM.
And it writes it down.
