graphsloth View on GitHub

Your Desktop/Project folder stopped being yours to understand.

GraphSloth scans a folder of old projects, pulls real disk size, real git history, a real code graph, and real deploy signals, then asks a local Gemma model for a two-line verdict it has to justify with those facts. It never deletes anything.

29folders audited 29.4Greclaimable, verified 3real bugs caught by dogfooding
GraphSloth's audit report, showing real project folders sorted into archive-candidate, dormant, and active, each with a one-sentence reason citing real facts.

How it actually decides

Five steps, in order. Each one only adds facts; the model at the end can't skip to a conclusion without them.

1sizedisk usage via du -sk, no opinion yet
2gitlast commit age, branch, dirty state — checked one level into subfolders too, for folders that hold a repo rather than being one
3graphifya real tree-sitter structural graph: node/edge counts, most-referenced symbol, zero LLM cost
4deployvercel.json, docker-compose.yml, a live URL in the README — cheap, local, no-network signals that something might still be running
5gemmareads only the facts above and returns ACTIVE, DORMANT, or ARCHIVE-CANDIDATE with a one-sentence reason — a deterministic code check overrides it if it ignores a deploy signal

Caught lying to itself

All three of these were found by running GraphSloth on the author's own live, production folders — not in a test suite.

ARCHIVE-CANDIDATE (wrong)

Srijan Saree, a live store with real orders, came back as safe to archive.

Cause: the deploy-signal check only looked at the folder's top level. The store's actual code, and its .vercel config, sat one folder down. A shallow scan saw nothing and called it quiet.

ACTIVE (wrong)

OSS, 26.8G holding 34 separate git clones, was one busy clone away from being called ACTIVE as a whole.

Cause: the first nested-repo fix picked whichever single clone was touched most recently and judged the entire folder by it. Only 10 of the 34 clones had moved in the last 30 days. The fix now reports the real distribution and caps the verdict instead of trusting one busy repo.

raw exception (almost shipped)

A single Ollama timeout, right after a restart, nearly shipped as a verdict reading [Gemma call failed after 3 attempts: timed out].

Cause: the model thinks before it answers, and a tangled prompt pushed that past a 300s timeout on CPU-only inference. Fixed with think: false and a token cap — plus a check that catches and retries that shape of error before anything publishes.

Good things take their time

A sloth doesn't rush, and neither does this. Click in and type — space cuts the stem, backspace withers it.

type something slow 0 characters grown

Dies without losing its place

The first plain-Python run got killed mid-way through 29 folders by an OS memory-pressure reaper. Gemma sits at 8G resident; the machine ran low on RAM in the background. Recovering meant hand-parsing a log file.

So the audit loop now runs as a Temporal workflow, one durable activity per folder. Proven live, not claimed:

$ temporal_audit.py start [1/5] fieldcast ... done [2/5] karmacompass ... done [3/5] ocr-pipeline ... running $ kill -9 <worker pid> worker dies mid-activity $ temporal workflow describe ... 2 activities completed, state intact on the server $ temporal_audit.py worker (restarted) resumes at folder 3 — never redoes 1 or 2