Monitor GitHub fork constellations with AI-powered analysis
Project description
ForkHub
Monitor GitHub fork constellations with AI-powered analysis.
ForkHub watches the forks around your GitHub repositories, uses a Claude AI agent to classify what changed and why, and surfaces interesting divergences through digest notifications. Think of it as a satellite view of all the gardens growing from your code — whether the gardeners sent a letter or not.
Quickstart
Prerequisites
- Python 3.12+
- uv package manager
- A GitHub personal access token (for API access)
- An Anthropic API key (for AI-powered analysis)
Install
git clone https://github.com/joshuaoliphant/forkhub.git
cd forkhub
uv sync
Configure
The easiest way is to create a .env file in your project directory:
cp env.example .env
# Edit .env with your tokens
ForkHub automatically loads .env files at startup. You can also export environment variables directly:
export GITHUB_TOKEN="ghp_..."
export ANTHROPIC_API_KEY="sk-ant-..."
Or use a TOML config file:
mkdir -p ~/.config/forkhub
cp forkhub.toml.example ~/.config/forkhub/forkhub.toml
Authentication options for Anthropic:
ANTHROPIC_API_KEY— standard API keyCLAUDE_ACCESS_TOKEN— OAuth token fromclaude set-token(used by Claude Code)
Either works. If both are set, the API key takes precedence.
First run
# Discover and track your repos
uv run forkhub init --user your-github-username
# See what's tracked
uv run forkhub repos
# Sync fork data from GitHub
uv run forkhub sync
# View forks for a specific repo
uv run forkhub forks owner/repo
# Generate a digest of interesting changes
uv run forkhub digest
CLI Commands
| Command | Description |
|---|---|
forkhub init --user <username> |
Discover and track your GitHub repos |
forkhub track <owner> <repo> |
Track a repository you don't own |
forkhub untrack <owner> <repo> |
Stop tracking a repository |
forkhub exclude <owner> <repo> |
Exclude a repo from tracking |
forkhub include <owner> <repo> |
Re-include an excluded repo |
forkhub repos |
List tracked repositories |
forkhub forks <owner> <repo> |
List forks of a tracked repo |
forkhub inspect <owner> <repo> |
Detailed view of a single fork |
forkhub clusters <owner> <repo> |
Show signal clusters (similar changes across forks) |
forkhub sync |
Sync fork data from GitHub |
forkhub digest |
Generate and deliver a change digest |
forkhub config show |
Show current configuration |
Library Usage
ForkHub is a library first. The CLI is a thin consumer.
import asyncio
from forkhub import ForkHub
async def main():
async with ForkHub() as hub:
# Discover your repos
repos = await hub.init("your-username")
# Sync fork data
result = await hub.sync()
print(f"Synced {result.repos_synced} repos, {result.total_changed_forks} changed forks")
# Get forks for a repo
forks = await hub.get_forks("owner", "repo", active_only=True)
# Generate and deliver a digest
digest = await hub.generate_digest()
await hub.deliver_digest(digest)
asyncio.run(main())
Custom providers
All extension points use Python Protocol classes, so you can inject your own implementations:
from forkhub import ForkHub
hub = ForkHub(
git_provider=my_custom_provider, # implements GitProvider protocol
notification_backends=[my_slack_backend], # implements NotificationBackend protocol
embedding_provider=my_embeddings, # implements EmbeddingProvider protocol
)
How It Works
Tracking modes
| Mode | Description |
|---|---|
| owned | Your repos, auto-discovered via init. Forks are monitored. |
| watched | Repos you don't own but want to observe via track. |
| upstream | Repos you've forked. Tracks upstream changes you might want. |
Signals
When ForkHub syncs, a Claude AI agent analyzes what changed in each fork and produces signals — classified changes with a significance score (1-10):
| Category | Description |
|---|---|
feature |
New functionality added |
fix |
Bug fix not yet in upstream |
refactor |
Structural/architectural change |
config |
Configuration or deployment change |
dependency |
Dependency swap or version change |
removal |
Feature or code removed |
adaptation |
Platform or environment adaptation |
release |
A new tagged release |
Clusters
When multiple forks independently make similar changes, ForkHub detects these as clusters using vector similarity of signal embeddings. Clusters reveal community-wide trends — if three forks all swap the same dependency, that's a signal worth knowing about.
Data flow
forkhub sync -> Discover forks (GitHub API)
-> Compare HEAD SHAs (skip unchanged)
-> AI agent classifies changes -> store signals
-> Update clusters via embedding similarity
forkhub digest -> Query recent signals
-> AI agent composes readable summary
-> Deliver via notification backends
Configuration
ForkHub looks for forkhub.toml in ~/.config/forkhub/ or the current directory. Environment variables override TOML values.
| Setting | Env Var | Default |
|---|---|---|
| GitHub token | GITHUB_TOKEN |
— |
| Anthropic API key | ANTHROPIC_API_KEY |
— |
| OAuth token | CLAUDE_ACCESS_TOKEN |
— |
| Analysis budget | — | $0.50 per sync |
| Analysis model | — | sonnet |
| Digest model | — | haiku |
| Sync interval | — | 6h |
| Digest frequency | — | weekly |
| Min significance | — | 5 |
| DB path | — | ~/.local/share/forkhub/forkhub.db |
ForkHub loads .env files automatically. See env.example for all supported variables.
See forkhub.toml.example for all options.
Architecture
ForkHub is a library first — the CLI is a thin consumer. The core library (src/forkhub/) exposes the ForkHub class as its public API.
Extension points (Protocol-based, swappable at runtime):
GitProvider— fetches repo/fork data (default: GitHub via githubkit)NotificationBackend— delivers digests (default: Rich console output)EmbeddingProvider— text embeddings for clustering (default: local sentence-transformers)
AI analysis uses the Claude Agent SDK with a coordinator + subagent pattern:
- Coordinator agent gets tools to explore forks (list, summarize, diff)
- diff-analyst subagent deep-dives individual forks
- digest-writer subagent composes human-readable summaries
Storage: SQLite + sqlite-vec for vector similarity search.
Development
# Install with dev dependencies
uv sync
# Run tests (450 tests)
uv run pytest
# Lint and format
uv run ruff check src/ tests/
uv run ruff format src/ tests/
# Type check
uv run mypy src/forkhub/
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file forkhub-0.1.0.tar.gz.
File metadata
- Download URL: forkhub-0.1.0.tar.gz
- Upload date:
- Size: 272.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6a91e3db0a8d8ac9912de57915d36bcc72036a9bff17d797e01b1111a738e36a
|
|
| MD5 |
8ef4303a0daf47a92bb8afd294802860
|
|
| BLAKE2b-256 |
c1a46ee1270875fb9b908d090aa3b7f603a8bec509d06a70c7af66ba0e87c646
|
Provenance
The following attestation bundles were made for forkhub-0.1.0.tar.gz:
Publisher:
publish.yml on JoshuaOliphant/forkhub
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
forkhub-0.1.0.tar.gz -
Subject digest:
6a91e3db0a8d8ac9912de57915d36bcc72036a9bff17d797e01b1111a738e36a - Sigstore transparency entry: 1140607425
- Sigstore integration time:
-
Permalink:
JoshuaOliphant/forkhub@16910cdb1cb2cdf6942d05519e78c76920217174 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/JoshuaOliphant
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@16910cdb1cb2cdf6942d05519e78c76920217174 -
Trigger Event:
push
-
Statement type:
File details
Details for the file forkhub-0.1.0-py3-none-any.whl.
File metadata
- Download URL: forkhub-0.1.0-py3-none-any.whl
- Upload date:
- Size: 59.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1b397e389571488eb16d7755ddd7c5c2b532ce3cc3650f9f57e1ed71148df992
|
|
| MD5 |
3ed801980d3197ce28326e04840baeda
|
|
| BLAKE2b-256 |
c5ac82d4fc1eac9224f8e7fd4f776a36af2fb24b93e26c7d9ebe16be4523ef6e
|
Provenance
The following attestation bundles were made for forkhub-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on JoshuaOliphant/forkhub
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
forkhub-0.1.0-py3-none-any.whl -
Subject digest:
1b397e389571488eb16d7755ddd7c5c2b532ce3cc3650f9f57e1ed71148df992 - Sigstore transparency entry: 1140607588
- Sigstore integration time:
-
Permalink:
JoshuaOliphant/forkhub@16910cdb1cb2cdf6942d05519e78c76920217174 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/JoshuaOliphant
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@16910cdb1cb2cdf6942d05519e78c76920217174 -
Trigger Event:
push
-
Statement type: