Skip to content
Composable file system watcher for Go

Watch files like a pro.

A high-performance, composable file system watcher built on fsnotify. Automatic recursion, 17+ filters, 18 middleware, and production-grade resilience.

18
Middleware
17+
Filters
4
Dependencies
MIT
License
main.go
package main

import (
    "context"
    "fmt"
    "log"
    "time"

    filewatcher "github.com/larsartmann/go-filewatcher/v2"
)

func main() {
    w, err := filewatcher.New(
        []string{"./src"},
        filewatcher.WithExtensions(".go"),
        filewatcher.WithDebounce(500*time.Millisecond),
    )
    if err != nil { log.Fatal(err) }
    defer w.Close()

    events, _ := w.Watch(context.Background())
    // channel of Event{Path, Op, Timestamp, ...}

    for ev := range events {
        fmt.Printf("%s: %s\n", ev.Op, ev.Path)
    }
}
Features

Everything you need to watch files.

17+ composable filters, 18 production middleware, and resilience built for large-scale filesystems.

Zero Boilerplate

Start watching in 5 lines of code. Sensible defaults, automatic recursion, context-aware cancellation.

17+ Built-in Filters

Extensions, globs, regex, size, age, content hash, gitignore, generated-code detection. Compose with AND/OR/NOT.

18 Middleware

Logging, recovery, rate limiting, circuit breaker, metrics, batching, error correlation, exponential backoff.

Resilient by Default

Self-healing watches, inotify budget awareness, graceful ENOSPC handling, and .gitignore-aware walking.

Full Observability

Built-in Stats(), Prometheus collector, OpenTelemetry tracing middleware, and structured debug logging.

NFS/FUSE Friendly

Optional polling mode supplements OS-native events for network filesystems, Docker volumes, and FUSE mounts.

How it works

Create. Watch. Consume.

Four steps from zero to streaming file events. No boilerplate, no manual goroutine management.

1

Create

Initialize with paths and options. Functional options configure filters, middleware, debounce.

w, _ := filewatcher.New(paths, filewatcher.WithExtensions(".go"), )
2

Watch

Call Watch(ctx) to start. Returns a read-only event channel. Goroutines handle the rest.

events, _ := w.Watch(ctx)
3

Pipeline

Events pass through your filter chain and middleware. 17+ filters, 18 middleware, composable.

// filters + middleware applied automatically
4

Consume

Range over the channel. Each event carries path, op, timestamp, size, modtime, and optional hash.

for ev := range events { fmt.Println(ev.Op, ev.Path) }
Comparison

Why go-filewatcher?

Raw fsnotify gives you events and nothing else. Other wrappers give you some convenience. go-filewatcher gives you production-grade infrastructure.

Raw fsnotify Other wrappers go-filewatcher
Recursive watching ~
Built-in filters ~
Middleware chains
Debouncing ~
.gitignore-aware
ENOSPC resilience
NFS/FUSE polling
Prometheus + OTel
Self-healing
Use Cases

Built for real workloads.

Drop it into any system that needs to react to filesystem changes.

Hot Reload

Dev servers, build systems, and live-reload tools that trigger on file changes

Log Monitoring

Tail and process log files in real-time with debouncing and rate limiting

CI/CD Triggers

Watch for changes and trigger pipelines, tests, or deployments automatically

Get Started

Start watching in minutes.

One import. Zero boilerplate. Production-ready.