GitHub: github.com/srijanshukla18/vigil
Most file watching tools are good enough until you have an LLM changing your codebase for you. Then the gap becomes obvious very quickly. You do not just want to know that a file changed. You want to know what changed, where it changed, and whether the agent is doing something sensible without constantly flipping back to your editor or git diff.
That was the real reason I built Vigil. I had LLMs working autonomously, and I wanted a live way to see the codebase breathe while they were making changes. Not after the fact. Not one commit later. While it was happening.
The obvious thought was: this must already exist. Something like watch ., but for directories. Recursive file events, inline diffs, and a terminal UI that stays pinned to the stream. Clear the screen when you want. Follow new events when you want. Scroll back when something interesting happens.
It did not exist in the shape I wanted. So I vibe coded it.
The short version is this: the individual building blocks already existed, but no single tool combined file events, diffs, and a usable TUI into one command. Once I saw that clearly, the project got much smaller. I was not inventing a new category. I was just stitching together the thing that should already have been there.
Let’s get into it.
The Existing Tools Were Close, Not Correct
The problem was not a total lack of tools. The problem was that each tool solved only one slice of the workflow.
The landscape looked roughly like this:
fswatch -r .gives you file eventsentrgives you file-triggered executionwatchreruns a command on an intervalviddygives you a nicer watch-style TUIlazygitgives you git-aware diffswatchmangives you strong file event plumbing
That sounds fine until you ask a slightly different question:
What if I want to stand in one directory and see all file-level and directory-level changes, plus inline diffs, in one terminal UI, without requiring git?
That is where the tools stop lining up.
The closest workaround looked like this:
fswatch -r . | xargs -I{} sh -c 'echo "--- {} ---" && git diff {}'
That is clever. It is also janky.
It assumes git. It is not a TUI. It is not pleasant to leave running. And it is not built for the specific workflow of watching an autonomous coding agent continuously mutate a working tree.
That framing matters. I was not trying to build a general-purpose file event daemon. I was trying to build an operator console for code changes.
Why This Problem Shows Up Once Agents Get Real
If you are editing code manually, your editor already gives you most of what you need.
- you know what file you touched
- you know what line you changed
- you know why you changed it
- diffs are local in your head
Once an agent is driving, that changes.
Now the questions are different:
- what files is it touching right now?
- is it thrashing across the tree or working cleanly?
- did it just create a useful file or dump scaffolding everywhere?
- is this a tiny patch or a cascading rewrite?
- should I interrupt it?
That one decision explains most of Vigil’s shape. It is not just a filesystem watcher. It is a visibility tool for agentic development.
The UX I Wanted
The target interaction was simple:
vigil .
And from there:
- recursive directory watch
- stream events live
- show inline diffs when files change
- support create, modify, and delete events
- stay in follow mode by default
- let me clear the stream and just watch fresh changes
- avoid flooding on save storms
- ignore obvious junk by default
That is the whole product.
No browser. No daemon dashboard. No git dependency. No extra service. Just a terminal UI that tells me what changed.
What Vigil Actually Does
At a high level, Vigil combines three things:
- filesystem events
- text diffs
- terminal UI
The implementation is small because the boundaries are small.
notifyhandles cross-platform filesystem eventssimilarhandles text diffingratatuihandles the UIcrosstermhandles terminal interactionclaphandles CLI parsing
That boundary is doing most of the work. I did not need a fancy backend. I needed a good event loop and sane defaults.
The current behavior is straightforward:
- watch the current directory or a provided path
- optionally filter by extension
- optionally ignore paths by substring
- show file events in a scrollable stream
- show inline diffs for text files
- skip binary files
- skip very large files
- debounce rapid event bursts
- auto-follow new events until the user scrolls up
The keybindings are intentionally boring:
qquitscclears the event streamdtoggles inline diffsj/kscrollGjumps to the bottomgjumps to the top
That is exactly the kind of tool I want while an agent is editing code. I do not want to learn a product. I want a pane of visibility.
The Defaults Matter More Than The UI
The most important part of a watcher like this is not the box drawing. It is the policy.
Vigil ignores noisy directories by default:
.gitnode_modulestarget__pycache__.DS_Store
It also debounces event storms and caches baselines so the first time it sees a file it establishes a reference point, and the next time it can show a real diff instead of pretending every file was always under observation.
That one decision does a lot of work.
Without baseline caching, the tool becomes noisy. Without debounce, editor saves become spam. Without ignore rules, the stream becomes unreadable the moment you open a JavaScript or Rust project.
The TUI is the visible part. The defaults are what make it usable.
Why I Did Not Just Make This Git-Only
It would have been easier to say:
- require git
- shell out to
git diff - call it done
But that would have been the wrong tool.
The whole point was to watch a directory, not a repository.
Sometimes the code is not committed yet. Sometimes the agent is generating files before they ever become part of git history. Sometimes you want to point the tool at a scratch workspace, a generated output directory, or a temp project.
Git is a great history system. It is not the right primitive for every live visibility problem.
What I Learned Building It
I learned two things.
First, the tool gap was real. This was not me failing to search properly. The workflow really was split across too many half-solutions.
Second, this kind of project becomes much easier once you stop trying to make it broader than it needs to be. Vigil does not need to be an IDE. It does not need collaboration features. It does not need remote streaming. It just needs to answer one question well:
What is changing in this directory right now?
That is enough.
Why This Tool Exists
The README says it plainly: watch your codebase breathe.
That is exactly the right description.
Once agents are doing real work, live change visibility stops being a nice-to-have. It becomes part of how you trust the system. You do not want to inspect every edit manually, but you also do not want the agent operating in the dark.
Vigil sits in that middle layer.
- not intervention
- not full review
- just awareness
That is the job.
The Rule I Would Use Again
If I had to compress the whole project into one line, it would be this:
Once code changes become autonomous, observability for local file mutation becomes its own product surface.
watch was built for rerunning commands.
kubectl -w was built for streaming resource state.
Vigil was built for watching an active codebase while something else is driving.
That distinction is the whole point.