A native desktop app that catches GitHub repositories the moment they vanish, and tries to recover their history before it's gone for good.
GitHub never tells you when a public repository gets deleted — it just stops responding with a 404, exactly like one made private. ForkForensics watches the repositories it has seen, notices when one goes silent, and automatically searches forks and orphan commits for anything still recoverable.

owner/repo entries that stay in the re-verification queue permanently,
whether or not they ever reappear in public GitHub activity. They're
rechecked on the same 14-day cadence as everything else.api.github.com, raw.githubusercontent.com, and github.com
for git operations) and to data.gharchive.org for the public archive.
No telemetry of any kind.Requires Python 3.11+ and Git.
git clone https://github.com/siris9476/forkforensics.git
cd forkforensics
python -m venv .venv
Windows
.venv\Scripts\pip install -r requirements.txt -r requirements-desktop.txt
.venv\Scripts\pythonw -m desktop.main
macOS / Linux
.venv/bin/pip install -r requirements.txt -r requirements-desktop.txt
.venv/bin/python -m desktop.main
On Windows, pythonw runs the app without a console window alongside it;
everything still goes to the log file. Use python -m desktop.main on any
platform to watch the log live in a terminal.
GITHUB_TOKEN /
GH_TOKEN environment variable), then save.Token scopes: a classic PAT needs no scopes ticked at all — the tool only reads public repository metadata. A fine-grained PAT needs "Public Repositories (read-only)" and no account permissions. The token is required because GitHub's GraphQL API has no anonymous access, and it raises the REST rate limit. You can enter multiple tokens separated by commas; both the REST and GraphQL clients rotate between them automatically as each approaches its limit.
Where your data lives: running from source, in data/ next to the
repository. In the standalone executable, in %APPDATA%\ForkForensics\ on
Windows (or your home directory elsewhere) — the log, the SQLite database
and downloaded archives all live there.
Closing the window doesn't quit the app. It minimizes to the system tray so the nightly cycle can still run; quit from the tray menu or with Ctrl+Q. On desktops with no system tray (common on GNOME/Wayland), closing the window quits for real instead.
No Python installation required on the target machine. Build on the platform you're targeting — PyInstaller does not cross-compile.
Windows (verified):
.venv\Scripts\pip install -r requirements-build.txt
.venv\Scripts\pyinstaller --name ForkForensics --onefile --windowed --icon desktop/resources/icon.ico ^
--add-data "desktop/theme.qss;desktop" --add-data "desktop/resources/icon.ico;desktop/resources" ^
--paths . desktop/main.py
The result is dist/ForkForensics.exe.
macOS / Linux (untested — note the : data separator instead of ;,
and that macOS wants an .icns icon):
.venv/bin/pip install -r requirements-build.txt
.venv/bin/pyinstaller --name ForkForensics --onefile --windowed \
--add-data "desktop/theme.qss:desktop" \
--add-data "desktop/resources/icon.ico:desktop/resources" \
--paths . desktop/main.py
If the logo changes, regenerate the icon with
python desktop/resources/make_icon.py (requires Pillow, already in
requirements-build.txt).
Automatic daily cycle (internal scheduler at 03:00, with a desktop notification when it's done):
Recovery investigation, for a given repository:
git fetch.Everything above is also reachable manually from the Investigate tab, for one-off checks on a specific repository.
This project grew out of manually recovering historical data for a quantitative trading project, after a repository it depended on was re-initialized and appeared to have lost years of history. The recovery was done by hand: ranking forks by depth to find one that had preserved the missing years, then tracking down orphan commits to close the remaining gap. ForkForensics automates that process end to end.
As a validation test, the tool was later run against that same real case:
its fork ranking reproduced — automatically, with no hints given — the
exact same ranking that had been found by hand months earlier, deepest
fork first, down to correctly flagging the one fork that had itself since
gone. The exercise also surfaced and fixed a real bug: the fork-of-fork
recursion relied on pushed_at > created_at, but a fork's pushed_at
inherits its source's last-commit timestamp and can predate created_at
for a fork that was never touched again. It was fixed using forks_count,
which GitHub's API already provides.
Built with Claude (Anthropic) as a coding assistant, under direct human direction and review at every step — including the live, real-token end-to-end tests described above.
Declared here rather than discovered the hard way:
tests/test_github_graphql.py) but not guaranteed by GitHub for every
repository.settings table). The Settings field hides it from view after saving,
but anyone able to read that file can read the token. On Windows it sits
under your per-user %APPDATA%; on macOS/Linux the file is created with
owner-only permissions. Use a token with the minimum scopes (see above),
and revoke it if the machine is
shared or compromised.api.github.com and
raw.githubusercontent.com. The GH Archive downloads are unauthenticated
and never see it.data/ is gitignored..venv\Scripts\pip install -r requirements-dev.txt
.venv\Scripts\pytest
requirements-dev.txt pulls in the desktop requirements too — some tests
import PySide6.
230 tests, almost all running against mocks and synthetic fixtures with no
real network calls. tests/test_rescue_integration.py is the deliberate
exception: it runs a real git binary against a real local repository (no
network involved) to verify the recovery mechanism against actual git
behavior rather than a mocked subprocess.
docs/index.html is a static, backend-free presentation page meant for
GitHub Pages — enable it from the repository settings once this project is
published. It explains what the tool does and how to get it; it doesn't
replace the desktop app itself.
MIT — see SECURITY.md for how the tool handles your token and what it talks to over the network.
1 commits
Python
100.0%
A native desktop app that catches GitHub repositories the moment they vanish, and tries to recover their history before it's gone for good.
GitHub never tells you when a public repository gets deleted — it just stops responding with a 404, exactly like one made private. ForkForensics watches the repositories it has seen, notices when one goes silent, and automatically searches forks and orphan commits for anything still recoverable.

owner/repo entries that stay in the re-verification queue permanently,
whether or not they ever reappear in public GitHub activity. They're
rechecked on the same 14-day cadence as everything else.api.github.com, raw.githubusercontent.com, and github.com
for git operations) and to data.gharchive.org for the public archive.
No telemetry of any kind.Requires Python 3.11+ and Git.
git clone https://github.com/siris9476/forkforensics.git
cd forkforensics
python -m venv .venv
Windows
.venv\Scripts\pip install -r requirements.txt -r requirements-desktop.txt
.venv\Scripts\pythonw -m desktop.main
macOS / Linux
.venv/bin/pip install -r requirements.txt -r requirements-desktop.txt
.venv/bin/python -m desktop.main
On Windows, pythonw runs the app without a console window alongside it;
everything still goes to the log file. Use python -m desktop.main on any
platform to watch the log live in a terminal.
GITHUB_TOKEN /
GH_TOKEN environment variable), then save.Token scopes: a classic PAT needs no scopes ticked at all — the tool only reads public repository metadata. A fine-grained PAT needs "Public Repositories (read-only)" and no account permissions. The token is required because GitHub's GraphQL API has no anonymous access, and it raises the REST rate limit. You can enter multiple tokens separated by commas; both the REST and GraphQL clients rotate between them automatically as each approaches its limit.
Where your data lives: running from source, in data/ next to the
repository. In the standalone executable, in %APPDATA%\ForkForensics\ on
Windows (or your home directory elsewhere) — the log, the SQLite database
and downloaded archives all live there.
Closing the window doesn't quit the app. It minimizes to the system tray so the nightly cycle can still run; quit from the tray menu or with Ctrl+Q. On desktops with no system tray (common on GNOME/Wayland), closing the window quits for real instead.
No Python installation required on the target machine. Build on the platform you're targeting — PyInstaller does not cross-compile.
Windows (verified):
.venv\Scripts\pip install -r requirements-build.txt
.venv\Scripts\pyinstaller --name ForkForensics --onefile --windowed --icon desktop/resources/icon.ico ^
--add-data "desktop/theme.qss;desktop" --add-data "desktop/resources/icon.ico;desktop/resources" ^
--paths . desktop/main.py
The result is dist/ForkForensics.exe.
macOS / Linux (untested — note the : data separator instead of ;,
and that macOS wants an .icns icon):
.venv/bin/pip install -r requirements-build.txt
.venv/bin/pyinstaller --name ForkForensics --onefile --windowed \
--add-data "desktop/theme.qss:desktop" \
--add-data "desktop/resources/icon.ico:desktop/resources" \
--paths . desktop/main.py
If the logo changes, regenerate the icon with
python desktop/resources/make_icon.py (requires Pillow, already in
requirements-build.txt).
Automatic daily cycle (internal scheduler at 03:00, with a desktop notification when it's done):
Recovery investigation, for a given repository:
git fetch.Everything above is also reachable manually from the Investigate tab, for one-off checks on a specific repository.
This project grew out of manually recovering historical data for a quantitative trading project, after a repository it depended on was re-initialized and appeared to have lost years of history. The recovery was done by hand: ranking forks by depth to find one that had preserved the missing years, then tracking down orphan commits to close the remaining gap. ForkForensics automates that process end to end.
As a validation test, the tool was later run against that same real case:
its fork ranking reproduced — automatically, with no hints given — the
exact same ranking that had been found by hand months earlier, deepest
fork first, down to correctly flagging the one fork that had itself since
gone. The exercise also surfaced and fixed a real bug: the fork-of-fork
recursion relied on pushed_at > created_at, but a fork's pushed_at
inherits its source's last-commit timestamp and can predate created_at
for a fork that was never touched again. It was fixed using forks_count,
which GitHub's API already provides.
Built with Claude (Anthropic) as a coding assistant, under direct human direction and review at every step — including the live, real-token end-to-end tests described above.
Declared here rather than discovered the hard way:
tests/test_github_graphql.py) but not guaranteed by GitHub for every
repository.settings table). The Settings field hides it from view after saving,
but anyone able to read that file can read the token. On Windows it sits
under your per-user %APPDATA%; on macOS/Linux the file is created with
owner-only permissions. Use a token with the minimum scopes (see above),
and revoke it if the machine is
shared or compromised.api.github.com and
raw.githubusercontent.com. The GH Archive downloads are unauthenticated
and never see it.data/ is gitignored..venv\Scripts\pip install -r requirements-dev.txt
.venv\Scripts\pytest
requirements-dev.txt pulls in the desktop requirements too — some tests
import PySide6.
230 tests, almost all running against mocks and synthetic fixtures with no
real network calls. tests/test_rescue_integration.py is the deliberate
exception: it runs a real git binary against a real local repository (no
network involved) to verify the recovery mechanism against actual git
behavior rather than a mocked subprocess.
docs/index.html is a static, backend-free presentation page meant for
GitHub Pages — enable it from the repository settings once this project is
published. It explains what the tool does and how to get it; it doesn't
replace the desktop app itself.
MIT — see SECURITY.md for how the tool handles your token and what it talks to over the network.
1 commits
Python
100.0%