**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
Find a file
CJ van den Berg 3554794234
fix(kqueue): add per-file watches to detect modifications and fix rename ordering
kqueue's NOTE_WRITE on a directory fires only when directory entries are
added or removed, not when file contents change. This meant writes to
existing files were never reported as 'modified' events on macOS/FreeBSD.

Fix by maintaining a second set of kqueue watches on individual files
(file_watches), registered with NOTE_WRITE|NOTE_EXTEND. When either flag
fires on a file fd, a 'modified' event is emitted. File watches are
registered in take_snapshot (for files already present when watch() is
called) and in scan_dir (for newly created files), and deregistered when
files are deleted or the directory is unwatched.

Also fix two related bugs:
- NOTE_DELETE was incorrectly defined as 0x04 (NOTE_EXTEND); the correct
  value is 0x01. This could cause NOTE_EXTEND events on watched directories
  to be misreported as directory-deleted events.
- scan_dir emitted created events before deleted events, so a rename
  (old name disappears, new name appears) reported the destination before
  the source. Swapped the order so deletions are always emitted first.

Simplify thread_fn/arm to pass *KQueueBackend directly now that the backend
lives at a stable heap address inside the heap-allocated Interceptor.

All 10 integration tests now pass on FreeBSD.
2026-03-07 20:18:05 +01:00
docs build: add initial zig package 2026-02-22 20:44:20 +01:00
src fix(kqueue): add per-file watches to detect modifications and fix rename ordering 2026-03-07 20:18:05 +01:00
.gitignore build: add initial zig package 2026-02-22 20:44:20 +01:00
build.zig build: install test executables 2026-02-26 14:47:07 +01:00
build.zig.zon build: add flags and xcode-frameworks deps 2026-02-26 13:42:14 +01:00
README.md build: add initial zig package 2026-02-22 20:44:20 +01:00

     _   _ _       _     _     _       _     _       _         
    | \ | (_)     | |   | |   | \     / |   | |     | |        
    |  \| |_  __ _| |__ | |_  \  \ _ /  /_ _| |_  __| |___     
    | . ` | |/ _` | '_ \| __|  \  ` '  / _` | __|/ _| '_  \    
    | |\  | | (_| | | | | |_    \     / (_| | |_| (_| | | |    
    |_| \_|_|\__, |_| |_|\__|    \_|_/ \__,_|\__|\__|_| |_|    
              __/ |                                            
             |___/                                             
                   T H E   N I G H T   W A T C H               

nightwatch

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.