{"id":49585827,"url":"https://github.com/jexp/github4j","last_synced_at":"2026-05-03T22:35:13.664Z","repository":{"id":346815909,"uuid":"1191743339","full_name":"jexp/github4j","owner":"jexp","description":"Vibe coded GitHub wrapped with Neo4j","archived":false,"fork":false,"pushed_at":"2026-03-26T00:31:08.000Z","size":17298,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-26T17:29:01.516Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://jexp.github.io/github4j","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jexp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-03-25T14:44:52.000Z","updated_at":"2026-03-26T00:31:11.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/jexp/github4j","commit_stats":null,"previous_names":["jexp/github4j"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/jexp/github4j","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jexp%2Fgithub4j","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jexp%2Fgithub4j/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jexp%2Fgithub4j/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jexp%2Fgithub4j/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jexp","download_url":"https://codeload.github.com/jexp/github4j/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jexp%2Fgithub4j/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32587821,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-03T22:12:39.696Z","status":"ssl_error","status_checked_at":"2026-05-03T22:09:10.534Z","response_time":103,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-05-03T22:35:13.059Z","updated_at":"2026-05-03T22:35:13.656Z","avatar_url":"https://github.com/jexp.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🎸 github4j — GitHub Wrapped × Neo4j\n\n\u003e *Your year (or quarter, or sprint) in code. Spotify Wrapped, but make it graphs.*\n\nBuilt at the Neo4j hackathon 🦾. Six CSVs of GitHub activity go in — contributor glory, collaboration graphs, and bug-slaying leaderboards come out. Vibe coded with Claude + Neo4j.\n\n---\n\n## 🗺️ What's inside\n\n| Layer | What it does |\n|---|---|\n| 🕸️ **Graph import** | 6 CSVs → Neo4j AuraDB property graph (persons, repos, PRs, reviews, files, labels) |\n| 📊 **NeoDash dashboard** | 10 pre-built panels — top contributors, PR velocity, hottest files, label heatmap |\n| 🌐 **Web app** | GitHub Pages site with Wrapped-style hero stats + NVL interactive collaboration graph |\n| 🔬 **GDS notebook** | Louvain community detection + PageRank — do the informal teams match the org chart? |\n| 🤖 **MCP server** | FastAPI endpoint Claude can query: *\"who fixed the most bugs?\"* |\n\n---\n\n## ⚡ Quickstart\n\n### 1. 🌩️ Get an AuraDB instance\n\nFree tier at [neo4j.com/cloud/aura](https://neo4j.com/cloud/aura) — takes 2 minutes. Save your **Bolt URI** (`neo4j+s://...`) and password.\n\n### 2. 🌱 Seed the database\n\n```bash\n# install uv if you don't have it\ncurl -LsSf https://astral.sh/uv/install.sh | sh\n\ngit clone https://github.com/jexp/github4j\ncd github4j\n\nNEO4J_URI=neo4j+s://xxxx.databases.neo4j.io \\\nNEO4J_USER=neo4j \\\nNEO4J_PASSWORD=your-password \\\nuv run seed.py\n\n# AuraDB Free tier? Skip the large TOUCHES import:\nuv run seed.py --skip-touches\n```\n\nReads from local `data/` — no remote CSV fetching, fast batched Python.\n\n\u003e ⚠️ **AuraDB Free tier note:** Full import creates ~507k relationships. `--skip-touches` drops 206k `TOUCHES` rels to stay under the 400k limit. All hero stats still work!\n\n### 3. 🌐 Open the web app\n\n```bash\ncd docs \u0026\u0026 python3 -m http.server 8080\n# → http://localhost:8080\n```\n\nEnter your AuraDB **Bolt URI** (`neo4j+s://...`) on first load — stored in `localStorage`, never committed.\n\nOr open the live demo:\n\n\u003e **🌐 Live demo: [https://www.jexp.de/github4j/](https://www.jexp.de/github4j/)**\n\nThe app uses the **Neo4j JS driver over WebSocket (Bolt)**, so there are no CORS issues — Bolt runs over `wss://` (WebSocket), which is not subject to the HTTP CORS policy. No AuraDB allowlist configuration is needed. 🎉\n\nTo host your own fork on GitHub Pages: Settings → Pages → Source: `docs/` folder, branch `main`.\n\n### 4. 📊 Load the NeoDash dashboard\n\n![NeoDash dashboard](dashboards/github4j-wrapped-dashboard.png)\n\n1. Go to [neodash.graphapp.io](https://neodash.graphapp.io) (or AuraDB → Apps → NeoDash)\n2. New dashboard → Import → paste `dashboards/github-wrapped.json`\n3. Connect to your AuraDB instance\n\n### 5. 📜 Run the LOAD CSV scripts (alternative to seed.py)\n\nIf you prefer Cypher directly in AuraDB Browser or cypher-shell:\n\n```\nimport/01_persons.cypher\nimport/02_repos.cypher\nimport/03_files.cypher\nimport/04_prs.cypher\nimport/05_reviews.cypher\nimport/06_files_touched.cypher   ← optional, see note above\n```\n\nCSVs fetched from `raw.githubusercontent.com/jexp/github4j/main/data/`.\n\n### 6. ✅ Verify the import\n\nPaste `import/verify.cypher` into AuraDB Browser — checks node counts, relationship counts, and runs the hero stat queries.\n\n---\n\n## 🏆 Hero stats\n\n**🗑️ The Great Deleter** — who deleted the most lines of code? Sometimes the best PR is the one that removes 10,000 lines. A true hero of maintainability.\n\n**🐛 Bug Slayer** — ranked by merged PRs carrying the `bug` label. The unsung heroes keeping production alive.\n\n---\n\n## 🕸️ Graph schema\n\n```\n(:Person)-[:AUTHORED]-\u003e(:PullRequest)-[:IN_REPO]-\u003e(:Repo)\n(:Person)-[:REVIEWED]-\u003e(:PullRequest)\n(:Person)-[:MERGED]-\u003e(:PullRequest)\n(:PullRequest)-[:HAS_LABEL]-\u003e(:Label)\n(:PullRequest)-[:TOUCHES {additions, deletions}]-\u003e(:File)\n(:File)-[:IN_DIR]-\u003e(:Directory)\n```\n\n---\n\n## 🔬 GDS notebook (community detection)\n\n```bash\nuv sync --extra notebook   # first time only — installs graphdatascience, neo4j-viz, python-dotenv\nuv run --extra notebook jupyter notebook notebooks/github_gds.ipynb\n```\n\nCredentials are loaded automatically from `integration.env` in the project root (same file used by `seed.py` and `verify.py`):\n\n```\nNEO4J_URI=neo4j+s://xxxx.databases.neo4j.io\nNEO4J_USERNAME=neo4j\nNEO4J_PASSWORD=your-password\n```\n\nRuns **Louvain community detection** on the collaboration graph (who reviews whose PRs) and compares detected communities against `team-*` labels. Are the informal teams the same as the org chart? Probably not. 👀\n\nVisualised with `neo4j-viz`. Community IDs written back to `Person.community` in AuraDB.\n\n---\n\n## 🤖 MCP server (Claude integration)\n\n### Run locally\n\n```bash\ncd mcp_server\nNEO4J_URI=... NEO4J_PASSWORD=... uv run uvicorn main:app --reload\n```\n\n### Deploy to Railway (recommended)\n\n1. Install the [Railway CLI](https://docs.railway.app/develop/cli): `npm i -g @railway/cli`\n2. Log in: `railway login`\n3. From `mcp_server/`:\n\n```bash\ncd mcp_server\nrailway init          # creates a new project\nrailway variables set NEO4J_URI=neo4j+s://xxxx.databases.neo4j.io\nrailway variables set NEO4J_USERNAME=neo4j\nrailway variables set NEO4J_PASSWORD=your-password\nrailway variables set NEO4J_DATABASE=neo4j\nrailway up            # deploys — get the public URL from the dashboard\n```\n\nRailway auto-detects `pyproject.toml` + `uv.lock` via Nixpacks and builds with uv.\nThe `mcp_server/railway.toml`, `Procfile`, and `nixpacks.toml` are already configured.\n\n### Deploy to Vercel (alternative)\n\n```bash\ncd mcp_server\nnpm i -g vercel\nvercel env add NEO4J_URI\nvercel env add NEO4J_USERNAME\nvercel env add NEO4J_PASSWORD\nvercel env add NEO4J_DATABASE\nvercel --prod\n```\n\nConfiguration is in `mcp_server/vercel.json`.\n\n### Use with Claude\n\nAdd `\u003cyour-public-url\u003e/openapi.json` as a tool in Claude Projects and ask:\n\n- 💬 *\"Who are the top 5 bug fixers?\"*\n- 💬 *\"Which file is touched by the most PRs?\"*\n- 💬 *\"What communities did Louvain detect?\"*\n- 💬 *\"Who should review my PR in the kernel team?\"*\n\nSmoke-test the deployment:\n```bash\ncurl https://\u003cyour-public-url\u003e/\ncurl https://\u003cyour-public-url\u003e/openapi.json | jq '.info.title'\ncurl \"https://\u003cyour-public-url\u003e/tools/get_top_contributors?metric=prs\u0026limit=5\"\n```\n\n\u003e **Note:** No AuraDB credentials are stored in any committed file. All secrets are configured as environment variables in the hosting platform.\n\n---\n\n## 📁 Data files\n\n| File | Rows | Description |\n|---|---|---|\n| `data/persons.csv` | 348 | 👤 GitHub users |\n| `data/repos.csv` | 14 | 📦 Repositories |\n| `data/prs.csv` | 32,252 | 🔀 Pull requests |\n| `data/reviews.csv` | 92,721 | 👀 PR reviews |\n| `data/files.csv` | 52,996 | 📄 Files in repos |\n| `data/files_touched.csv` | 206,196 | ✏️ Files changed per PR |\n\n---\n\n## 🛠️ Built with\n\n- [Neo4j AuraDB](https://neo4j.com/cloud/aura) 🌩️ — managed graph database\n- [NeoDash](https://neodash.graphapp.io) 📊 — no-code graph dashboards\n- [NVL](https://neo4j.com/docs/nvl/current/) 🕸️ — Neo4j Visualization Library (JS)\n- [neo4j-viz](https://neo4j.com/docs/python-graph-visualization/current/) 🐍 — Python graph viz wrapper\n- [neo4j-rust-ext](https://pypi.org/project/neo4j-rust-ext/) ⚡ — fast Neo4j Python driver (Rust-backed)\n- [graphdatascience](https://neo4j.com/docs/graph-data-science/current/python-client/) 🔬 — GDS Python client\n- [uv](https://astral.sh/uv) 🚀 — Python package manager\n- [Claude](https://claude.ai) 🤖 — vibe coded the whole thing\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjexp%2Fgithub4j","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjexp%2Fgithub4j","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjexp%2Fgithub4j/lists"}