Show HN: Unfucked - version all changes (by any tool) - local-first/source avail
133 points| cyrusradfar | 3 days ago |unfudged.io
unf is a background daemon that watches directories you choose (via CLI) and snapshots every text file on save. It stores file contents in an object store, tracks metadata in SQLite, and gives you a CLI to query and restore any version. The install includes a UI, as well to explore the history through time.
The tool skips binaries and respects `.gitignore` if one exists. The interface borrows from git so it should feel familiar: unf log, unf diff, unf restore.
I say "UN-EF" vs U.N.F, but that's for y'all to decide: I started by calling the project Unfucked and got unfucked.ai, which if you know me and the messes I get myself into, is a fitting purchase.
The CLI command is `unf` and the Tauri desktop app is titled "Unfudged" (kids safe name).
How it works: https://unfucked.ai/tech (summary below)
The daemon uses FSEvents on macOS and inotify on Linux. When a file changes, `unf` hashes the content with BLAKE3 and checks whether that hash already exists in the object store — if it does, it just records a new metadata entry pointing to the existing blob. If not, it writes the blob and records the entry. Each snapshot is a row in SQLite. Restores read the blob back from the object store and overwrite the file, after taking a safety snapshot of the current state first (so restoring is itself reversible).
There are two processes. The core daemon does the real work of managing FSEvents/inotify subscriptions across multiple watched directories and writing snapshots. A sentinel watchdog supervises it, kept alive and aligned by launchd on macOS and systemd on Linux. If the daemon crashes, the sentinel respawns it and reconciles any drift between what you asked to watch and what's actually being watched. It was hard to build the second daemon because it felt like conceding that the core wasn't solid enough, but I didn't want to ship a tool that demanded perfection to deliver on the product promise, so the sentinel is the safety net.
Fingers crossed, I haven’t seen it crash in over a week of personal usage on my Mac. But, I don't want to trigger "works for me" trauma.
The part I like most: On the UI, I enjoy viewing files through time. You can select a time section and filter your projects on a histogram of activity. That has been invaluable in seeing what the agent was doing.
On the CLI, the commands are composable. Everything outputs to stdout so you can pipe it into whatever you want. I use these regularly and AI agents are better with the tool than I am:
# What did my config look like before we broke it?
unf cat nginx.conf --at 1h | nginx -t -c /dev/stdin
# Grep through a deleted file
unf cat old-routes.rs --at 2d | grep "pub fn"
# Count how many lines changed in the last 10 minutes
unf diff --at 10m | grep '^[+-]' | wc -l
# Feed the last hour of changes to an AI for review
unf diff --at 1h | pbcopy
# Compare two points in time with your own diff tool
diff <(unf cat app.tsx --at 1h) <(unf cat app.tsx --at 5m)
# Restore just the .rs files that changed in the last 5 minutes
unf diff --at 5m --json | jq -r '.changes[].file' | grep '\.rs$' | xargs -I{} unf restore {} --at 5m
# Watch for changes in real time
watch -n5 'unf diff --at 30s'
What was new for me: I came to Rust in Nov. 2025 honestly because of HN enthusiasm and some FOMO. No regrets. I enjoy the language enough that I'm now working on custom clippy lints to enforce functional programming practices. This project was also my first Apple-notarized DMG, my first Homebrew tap, and my second Tauri app (first one I've shared).Install & Usage:
> brew install cyrusradfar/unf/unfudged
Then unf watch in a directory. unf help covers the details (or ask your agent to coach).EDIT: Folks are asking for the source, if you're interested watch https://github.com/cyrusradfar/homebrew-unf -- I'll migrate there if you want it.
notfried|2 days ago
I love the idea; definitely something I ran into a few times before and wish I had.
Unfortunately, I am not installing a closed-source daemon with access to the filesystem from an unknown (to me) developer. I will bookmark this and revisit in a few weeks and hope you had published the source. :)
cyrusradfar|2 days ago
I didn't open up the source for this as I have a mono-repo with several experiments (and websites).
Happy to open the source up and link it from the existing website.
I've started to have an Agent migrate it out, and will review it before calling it done. Watch https://github.com/cyrusradfar/homebrew-unf
Edit: You can download the current version now: https://github.com/cyrusradfar/homebrew-unf/archive/refs/tag...
popalchemist|2 days ago
wazzaps|2 days ago
its-kostya|2 days ago
Thought I'd share the data point to support jetbrains
gschrader|2 days ago
heeen2|2 days ago
mpalmer|2 days ago
cyrusradfar|2 days ago
If an AI agent rewrites 30 files and you haven't touched jj yet, jj has the before-state but none of the intermediate states. UNF* captured every save as it happened, at filesystem level.
jj is a VCS. UNF is a safety net that sits below your VCS.
They're complementary, not competing.W.r.t. to the histogram, this is my fav feature of the app as well. Session segmentation (still definitely not perfect) creates selectable regions to make it easier, too. The algo is in the CLI as well for the Agent recap (rebuilding context) features.
benoitg|1 day ago
jj wouldn’t help with that as it would be gitignored.
ghrl|22 hours ago
I really like the website design and content-wise, as well as the detailed writeup here on HN. Certainly impressive work for an individual.
I've never used Time Machine but I do have kopia set up for frequent backups of important places, like the entire Documents folder. It does use a CAS as well and last time/size/hashes for determining what to save.
Coming from that I'm curious about a few aspects. Would this work well for larger folders/files? You mentioned deduplication, but does that happen on the file level or on chunks of the file, so that small changes don't store an entire new version of the file? Additionally, are the stored files compressed somehow, probably a fast compression algorithm? I think that could make it work for more than just source code.
Great project though, so far. I could see it becoming a lot more popular given an open source code base. Maybe a pricing model like the one Mac Mouse Fix uses would work, being open source and charging a fee so small it still reaches a large audience. That would likely be fair considering the developer time/agent cost of just a single unf'd problem as ROI.
gavinray|1 day ago
Odds are, one or more people have had this problem in the past and there's probably a nifty solution that does what you want.
cyrusradfar|1 day ago
I think it would be dishonest if I didn't share that your approach to discourse here isn't a productive way of asking what insights I'm bringing.
If that's your concern, I agree I can't claim that nothing exists to solve pieces of the puzzle in different ways. I did my research and was happy that I could get a domain that explained the struggle -- namely unfucked.ai/unfudged.io -- moreover I do feel there are many pieces and nuances to the experience which give pause to folks who create versioning tools.
I'm open to engaging if you have a question or comment that doesn't diminish my motives, assumes I must operate in your world view "problems can only be solved once", and discourages people to try new things and learn.
Look, I'm grateful that you stopped by and hope you'll recognize I'm doing my best to manage my own sadness that my children have to exist in a world where folks think this is how we should address strangers.
amadeuspagel|1 day ago
gavinray|1 day ago
https://gavinray97.github.io/blog/llm-build-cheaper-than-sea...
My comment is not meant as a shallow dismissal of the authors work but rather what seems to be a growing, systemic issue
oftenwrong|1 day ago
https://www.vim.org/scripts/script.php?script_id=89
It is comparatively unsophisticated, but I need it so infrequently that it has been good enough.
I do like the idea of maintaining a complete snapshot of all history.
This is a good application for virtual filesystems. The virtual fs would capture every write in order to maintain a complete edit history. As I understand it, Google's CitC system and Meta's EdenFS work this way.
https://cacm.acm.org/research/why-google-stores-billions-of-...
https://github.com/facebook/sapling/blob/main/eden/fs/docs/O...
mplanck|2 days ago
cyrusradfar|2 days ago
I spent a bit of time being baffled nothing existed that does this. Then I realized that, until Agents, the velocity of changes wasn't as quick and errors were rare(er)
rusty-jules|1 day ago
Keep it up!
ncr100|1 day ago
Alternative - version files and catalog those versions (most of the work, with "Unfucked", appears to be catalog management), building it on top of a Versioning File System.
E.g. NILFS logging file system, logs every block-change (realtime)
more:
- NILFS https://en.wikipedia.org/wiki/NILFS
- topic https://en.wikipedia.org/wiki/Versioning_file_system
rishabhaiover|2 days ago
cyrusradfar|2 days ago
ifh-hn|2 days ago
dpe82|1 day ago
jona-f|1 day ago
dataflow|1 day ago
cyrusradfar|1 day ago
It doesn't read the file the instant the OS fires the event. It accumulates events and waits for 3 seconds of silence before reading. So if an editor does write-tmp → rename (atomic save), or a tool writes in chunks, we only read after the dust settles.
I accept there are cases if the editor crashes mid-state that you have a corrupted state but there was never a good state to save, so, arguably you'd just restore to what's on file and remove the corrupt partial write.
It's not bulletproof against a program that holds a file open and writes to it continuously for more than 3 seconds, but in practice that doesn't happen with text files by Agent tools or IDEs.
Feel free to follow up for clarity.
s0a|3 days ago
teo_zero|1 day ago
cyrusradfar|1 day ago
sourcegrift|1 day ago
pasc1878|1 day ago
Why not just use TRime Machine?
otterley|1 day ago
atmanactive|1 day ago
cyrusradfar|1 day ago
I could build an extension for the UI vs a Tauri app, and it could help you install the CLI if you don't have it. Would that meet your needs?
That said, the fidelity of OS-level daemon can't really be replicated from within an app process.
overcrowd8537|2 days ago
cyrusradfar|2 days ago
mellosouls|1 day ago
+1 for the open source comments.
In your examples the framing of use cases against agent screw-ups is contemporary and well-chosen.
Best of luck with the project as you make it more useable.
monster_truck|2 days ago
cyrusradfar|2 days ago
alunchbox|2 days ago
imiric|1 day ago
But I'm amused by the people asking for the source code. You trust a tool from a giant corporation with not only your local data, but with all your data on external services as well, yet trusting a single developer with a fraction of this is a concern? (:
urbandw311er|1 day ago
williamstein|2 days ago
cyrusradfar|2 days ago
bananapub|2 days ago
cyrusradfar|2 days ago
From what I know (correct me) magit-wip-mode hooks into editor saves. UNF hooks into the filesystem.
magit-wip-mode is great if your only risk is your own edits in Emacs. UNF* exists because that's no longer the only risk; agents are rewriting codebases/docs and they don't use Emacs.
mrorigo|1 day ago
8n4vidtmkvmk|1 day ago
I do this but i certainly see the appeal of something better
riteshyadav02|1 day ago
[deleted]
zack2722|2 days ago
[deleted]
unknown|3 days ago
[deleted]
schainks|1 day ago
cyrusradfar|1 day ago
UNF is one install command + unf watch to protect a repo on every file change, takes 30s.
Time Machine snapshots hourly, not on every change, so you can lose real work between snapshots. This may have changed or I missed something but I reviewed that app to see if it was possible.
And while tmutil exists, it wasn’t designed to be invoked mid-workflow by an agent. UNF* captures every write and is built to be part of the recovery loop
OutOfHere|2 days ago
[deleted]
dang|2 days ago
https://news.ycombinator.com/newsguidelines.html
Edit: you did it more than once in this thread - the other case was https://news.ycombinator.com/item?id=47183957. Can you please stop posting like this? It's not what this site is for, and destroys what it is for.
OutOfHere|2 days ago
[deleted]
cyrusradfar|2 days ago
I am more interested in testing if folks have the problem and like the shape of the solution, before I try to decide on the model to sustain it. Open Source to me is saying -- "hey do you all want to help me build this?"
I'm not even at the point of knowing if it should exist, so why start asking people to help without that validation.
I work(ed) with OSS projects that have terrible times sustaining themselves and don't default to it bc of that trauma.
Thanks for stopping by.