Hacker News
Show HN: Unfucked – version every change between commits - local-first
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).
notfried
|next
[-]
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
|root
|parent
|next
[-]
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 can get that done by Tuesday assuming no one reports big issues I'd like to hot fix in the current setup before the migration.
Side note: It would be awesome if YC had a semi-automated security review you could submit your product to before releasing on show.
wazzaps
|next
|previous
[-]
its-kostya
|root
|parent
|next
[-]
Thought I'd share the data point to support jetbrains
overcrowd8537
|next
|previous
[-]
ifh-hn
|next
|previous
[-]
monster_truck
|next
|previous
[-]
cyrusradfar
|root
|parent
[-]
mplanck
|next
|previous
[-]
cyrusradfar
|root
|parent
[-]
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)
datawars
|root
|parent
[-]
Writing this, I wanted to ask if the desktop app includes the CLI, but there it says it on your website :-) Thanks for thinking ahead so far, but then picking us up here and now so we can easily follow along into an unf* future!
Looking forward to try it.
cyrusradfar
|root
|parent
[-]
> unf watch
# reboot
> unf list
it should say watching on your directory still, if it stays crashed or something else. ping me at support at v1.coJust one human, two machines at my home can't replicate all configurations...
mpalmer
|next
|previous
[-]
cyrusradfar
|root
|parent
[-]
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.
- UNF* works alongside git, jj, or no VCS at all
- No workflow change. You don't adopt a new tool, it just runs in the background
- Works on files outside any repo (configs, scratch dirs, notes) as it doesn't require git.
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.
s0a
|next
|previous
[-]
williamstein
|next
|previous
[-]
cyrusradfar
|root
|parent
[-]
bananapub
|next
|previous
[-]
cyrusradfar
|root
|parent
[-]
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.
OutOfHere
|next
|previous
[-]
dang
|root
|parent
[-]
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
|previous
[-]
cyrusradfar
|root
|parent
[-]
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.