Leave the clouds
without losing a byte.

Bring your Takeout, your 20 years of email and your unsorted photos. With undo.

What this actually is

What's missing from self-hosting today is the layer that deals with your past: two decades of email, a Google Takeout export, a phone full of unsorted photos, a decade of bank statements — digested once, reversibly, into one normalized database you can actually query, instead of ten apps each holding a fenced-off slice of your life.

Reversibility is the point

Leaving a cloud is a one-way door for most people: you export, you import, and whatever got mangled on the way is gone. Here the pipeline that got your data in can always be run backward.

Snapshot first

Every database write goes through an append-only ledger that snapshots before it touches anything. Any change can be restored.

Nothing vanishes

Nothing is permanently deleted without confirmation. Uninstalling an app quarantines its tables — it doesn't drop them.

Glass box

Curation runs on an explicit vocabulary of reversible operations, not an opaque classifier. You can see why a file ended up where it did.

Every bulk change, however it was triggered, is a sequence of ops drawn from six primitives — COPY MOVE ANNOTATE RECORD LINK DELETE — each with an exact inverse. One of them dating a photo, with its reasoning attached, and undone with one command:

# dating_enrich.py moves + tags a photo, and says why run.move("Sink/IMG_0453.jpg", "Photos/1994/beach.jpg", because="EXIF date + neighbor-photo evidence, high confidence") # any op, any time — undo is never a special case $ nocloud journal revert a1e3f9 ✓ reverted: MOVE Photos/1994/beach.jpg → Sink/IMG_0453.jpg

The rules that decide *what* an op should be have their own small vocabulary, one level up — a RULE proposes a fact, a CONSTRAINT vetoes one, never the reverse. You write them, or say them in plain language and approve what comes out:

# a rule you wrote — or said out loud and approved: # "grandpa and both my uncles are there, but not my father — # it's before he was born" RULE grandpa_and_uncles_without_father MATCH photo WHERE depicts(grandpa) AND depicts(uncle_1) AND depicts(uncle_2) AND NOT depicts(father) PROPOSE date(photo) < father.born SOURCE "coaching: grandpa + both uncles, no father yet" # constraints only ever veto — never propose: CONSTRAINT lifespan REJECT date(photo) > person.died WHERE depicts(person) # before it runs anywhere, see what it would actually change: >>> curation.impact("grandpa_and_uncles_without_father", rule, corpus, ctx) 23 photos would be reclassified — reviewable before you approve it

Local-first, literally

Not a slogan — the mechanism. Your data lives on hardware you own (a Mac and a Raspberry Pi) and is reachable only over your own VPN. There is no account, no tenant, and nothing of yours leaves the house.

Status

NoCloud is being built in the open-ish: it runs, every day, on the author's own Mac and Raspberry Pi. The install command exists (see Getting started), but the source repo it pulls from is still private, so it doesn't work for anyone else yet. No tagged release exists either — installing today means pulling the repo's current state directly.