fsnotify

A Go library that delivers cross-platform filesystem change notifications through a single Watcher API backed by native OS event mechanisms.

Library
Go
vv1.10.1
10,805 stars
BSD 3-Clause License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
51 /100 Fair
Development Activity 8
Maintenance 20
Community 76
Maturity 60
Momentum 40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
83 /100 Excellent
Architecture 85
Code Quality 85
Innovation 82
Learning Curve 80

fsnotify wraps the filesystem-change primitives of Linux (inotify), macOS/BSD (kqueue), Windows (ReadDirectoryChangesW), and illumos (FEN) behind one consistent Go API: create a Watcher, add paths, and read Create/Write/Remove/Rename/Chmod events off a channel. It has been the de facto standard for filesystem watching in the Go ecosystem for over a decade and sits as an indirect dependency inside a huge share of the Go tooling landscape — build tools, hot-reloaders, config watchers, and CLI utilities.

The library deliberately stays small: no recursive watching, no polling fallback, no bundled debouncing. Instead it gives callers a thin, predictable layer over what each operating system actually reports, along with extensive documentation of the platform-specific quirks (rename cookies, Chmod-before-Remove ordering on Linux, kqueue file-descriptor limits) that trip up naive implementations. Consumers who need higher-level behavior like recursive watches or event coalescing are expected to build it on top.

What You Get

  • A Watcher type with Add/AddWith/Remove/Close/WatchList methods and buffered or unbuffered Events/Errors channels
  • A unified Op bitmask (Create, Write, Remove, Rename, Chmod) that normalizes each OS’s native event vocabulary
  • Per-platform backends (inotify, kqueue, ReadDirectoryChangesW, FEN) selected automatically at build time via Go build tags
  • AddWith/WithBufferSize for tuning the Windows event buffer when large bursts risk overflow
  • FSNOTIFY_DEBUG=1 environment-variable support that prints every raw platform event to stderr for troubleshooting
  • Extensive documented platform notes covering rename-cookie pairing, Linux’s Chmod-before-Remove ordering, and kqueue file-descriptor exhaustion

Common Use Cases

  • Hot-reloading build tools - watch source files and trigger a rebuild or live-reload on Write/Create events, the pattern used by many Go-based dev servers and static-site generators
  • Configuration hot-reload - watch a config file’s parent directory and re-read settings when editors atomically replace the file via a Rename
  • File-sync and backup daemons - detect Create/Remove/Rename events in a watched tree to queue sync operations without polling
  • Log and data pipeline tailers - notice when new files appear in a spool directory and start processing them immediately
  • Editor and IDE tooling - detect external file changes (e.g. git checkout, formatter output) to refresh in-memory buffers or trigger diagnostics

Under The Hood

Architecture

fsnotify is organized around one exported Watcher struct that embeds a backend interface (Add, AddWith, Remove, WatchList, Close, xSupports) defined in fsnotify.go; the concrete implementation is chosen entirely at compile time through Go build tags, with backend_inotify.go (//go:build linux), backend_kqueue.go (macOS/BSD), backend_windows.go, and backend_fen.go (illumos) each providing their own struct that satisfies that interface and embeds a shared *shared helper type for common bookkeeping like watch bookkeeping and channel wiring. This keeps the public surface (NewWatcher, Add, Events, Errors, Close) identical across platforms while letting each backend manage OS-specific state — inotify’s rename-cookie LRU cache, kqueue’s per-file descriptor table, Windows’s overlapped I/O buffer — internally. Because the abstraction boundary is a plain Go interface rather than a runtime dispatch table, swapping or extending a backend only touches its own file; the core fsnotify.go and internal/ package never need to know which OS backend is active.

Tech Stack

The module (go.mod) targets Go 1.23+ and declares a single external dependency, golang.org/x/sys, used for the raw syscalls each backend needs (unix.InotifyInit1, kqueue’s Kevent, and Windows’s ReadDirectoryChangesW bindings). Everything else — event dispatch, the Op bitmask, buffer management — is standard library only (os, path/filepath, sync, errors). There is no build system beyond go build/go test; CI (.github/workflows/test.yml and staticcheck.yml) runs the test suite and staticcheck linting across the supported platforms rather than relying on any bundled task runner.

Code Quality

Each backend ships its own dedicated test file (backend_inotify_test.go, backend_kqueue_test.go, backend_windows_test.go, backend_fen_test.go) alongside shared cross-platform tests in fsnotify_test.go, helpers_test.go, and a synctest_test.go that exercises timing-sensitive event ordering. Error handling favors typed sentinel errors (ErrNonExistentWatch, ErrClosed, ErrEventOverflow) returned explicitly rather than panics or swallowed failures, and public functions/types carry substantial godoc comments explaining platform edge cases inline. A staticcheck.conf plus a dedicated CI lint workflow enforce static analysis on every push, and naming is consistently idiomatic Go (exported Watcher/Event/Op, unexported watchFlag, koekje cookie helper).

API Design The public surface is deliberately minimal: construct a Watcher, call Add(path), and range over two channels — there’s no configuration object to assemble and no callback registration boilerplate. Op is a bitmask with a Has() helper so callers avoid brittle equality checks against multi-flag events, and the one platform-specific knob (WithBufferSize for Windows) is opt-in via a functional-options pattern (AddWith) rather than cluttering the common path. The tradeoff for this simplicity is that callers must implement their own recursion and debouncing, which the README states explicitly rather than leaving undocumented — the FAQ and platform-notes sections in the docs preempt the most common integration mistakes (watching individual files, NFS/FUSE limitations, Chmod noise).

Used by 24 apps in this directory

Go
83%
MIT

Gitea

Developer Tools · Devops · Project Management

58,668

Self-hosted DevOps in a single Go binary — Git hosting, GitHub Actions-compatible CI/CD, and 30+ package registries without any SaaS dependency.

View details
93
Repo Health
79
Technical
64
Dependency
Built with
Go 83%
Updated 6 days ago
Go
89%
Apache 2.0

Glasskube

Developer Tools · Devops

3,487

A next-generation Kubernetes package manager with a GUI, CLI, and native GitOps integration that makes deploying cluster workloads 20x faster than Helm.

View details
52
Repo Health
74
Technical
74
Dependency
Built with
Go 89%
Updated 4 months ago
TypeScript
47%
AGPL 3.0

Grafana

Analytics · Monitoring

77,469

The open-source observability platform that unifies metrics, logs, and traces from any data source into dynamic, queryable dashboards.

View details
95
Repo Health
91
Technical
63
Dependency
Built with
TypeScript 47%
Go 47%
Updated 6 days ago
Go
87%
MIT

Hatchet

AI Development · Automation · Developer Tools

8,174

A Postgres-backed orchestration engine for background tasks, AI agents, and durable workflows that replaces Redis queues and multi-datastore durable execution platforms with a single self-hostable service.

View details
88
Repo Health
83
Technical
67
Dependency
Built with
Go 87%
Updated 1 weeks ago
Go
95%
Other

NetBird

Security

30,175

Replace your VPN with a zero-trust WireGuard overlay network that auto-connects devices, enforces SSO and posture checks, and deploys in under 5 minutes.

View details
92
Repo Health
82
Technical
66
Dependency
Built with
Go 95%
Updated 6 days ago
Go
48%
GPL 3.0

Netdata

Devops · Monitoring

81,111

Real-time per-second metrics, ML-powered anomaly detection, and zero-config observability for any infrastructure.

View details
93
Repo Health
86
Technical
70
Dependency
Built with
Go 48%
C 29%
Rust 15%
Updated 6 days ago
Go
99%
Apache 2.0

Okteto

Developer Tools · Devops

3,554

Develop applications directly inside your Kubernetes cluster with real-time file sync and instant hot-reload — no more docker build/redeploy cycles.

View details
91
Repo Health
79
Technical
69
Dependency
Built with
Go 99%
Updated 1 weeks ago
Go
91%
Apache 2.0

Ory Kratos

Authentication

13,933

API-first identity and user management that handles login, registration, MFA, and recovery so your application never has to.

View details
69
Repo Health
78
Technical
65
Dependency
Built with
Go 91%
Updated 3 months ago
Go
69%
MIT

PocketBase

Authentication · Databases · Ecommerce

61,570

Open Source realtime backend in 1 file — embedded SQLite, auth, file storage, and admin UI as a single Go binary.

View details
90
Repo Health
87
Technical
77
Dependency
Built with
Go 69%
JavaScript 24%
Updated 1 weeks ago

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers