← back to gallery

Antigravity Exit

Scan a public GitHub repo for Gemini CLI usage and get a migration plan before the June 18 cutoff.

dev-toolsmigrationgemini-cliantigravitygithub-scannerdeprecation
Open product ↗

antigravity-exit

Scan a public GitHub repo for Gemini CLI usage and emit a migration checklist to Antigravity CLI before the 2026-06-18 cutoff. Built for dev teams and indie hackers caught by Google's 30-day deprecation window.

What it does

  1. Paste owner/repo (or a github.com URL) → backend fetches the repo tree via GitHub REST, walks files matching package.json|.yml|.yaml|.sh|.bash|.zsh|.fish|.md|.gemini/*|Dockerfile|Makefile|*.toml (capped at 200 files / 4 MB / 30 s) and looks for known Gemini CLI signatures.
  2. Per finding, it joins to the curated mappings/known.json table to surface the Antigravity CLI replacement, or flags NO ANTIGRAVITY EQUIVALENT — escalate to Google if the surface has no published mapping yet.
  3. Each scan gets a stable, shareable URL with full per-file findings and a downloadable Markdown checklist.
  4. The home page renders a leaderboard of pre-scanned popular OSS repos by exposure score (0–100) plus a giant countdown to the 2026-06-18 cutoff and the current 7-day npm downloads of @google/gemini-cli (proof the at-risk user base is still huge).

No login, no payments, no LLM calls — deterministic scanning + table lookup against real-time public data.

Endpoints (all under /antigravity-exit)

| Method | Path | Purpose |
|---|---|---|
| GET | /health | Liveness — {ok:true} HTTP 200 |
| POST | /api/scan | Body {repo:"owner/name"} → runs scan synchronously (cap 30s), returns {id, exposureScore, findingsCount, …} |
| GET | /api/scan/:id | Full scan: findings grouped by file with mapping resolution |
| GET | /api/scan/:id/checklist.md | Markdown checklist download |
| GET | /api/leaderboard | Top N pre-scanned repos. Query ?sort=score\|stars\|updated&limit=50 |
| GET | /api/mappings | Gemini → Antigravity mapping table + announcement snapshot metadata |
| GET | /api/announcement | Latest scraped announcement (text + hash + history) |
| GET | /api/stats | {cutoffIso, daysLeft, npm7dRange, npm7dTotal, scansTotal, exposedReposTotal, announcement} |
| GET | / | SPA shell (leaderboard) |
| GET | /scan/:id | Static SPA — deep view of a scan |
| GET | /mappings | Static SPA — full mapping table |

Live data sources

| Source | URL | Refresh |
|---|---|---|
| GitHub REST — repo metadata | https://api.github.com/repos/{owner}/{repo} | per scan + nightly via popular-repos cron |
| GitHub REST — git tree | https://api.github.com/repos/{owner}/{repo}/git/trees/{sha}?recursive=1 | per scan |
| GitHub raw — file content | https://raw.githubusercontent.com/{owner}/{repo}/{branch}/{path} | per scan, only allow-listed extensions, capped 200 files / 4 MB |
| Google Developers Blog announcement | https://developers.googleblog.com/en/an-important-update-transitioning-gemini-cli-to-antigravity-cli/ | hourly (0 ) — diffed by SHA256 of normalized text |
| npm registry — downloads | https://api.npmjs.org/downloads/range/last-week/@google/gemini-cli | every 6h (0 /6 ) |
| npm registry — package metadata | https://registry.npmjs.org/@google/gemini-cli | every 6h |
| Popular-OSS re-scan | curated list in scrapers/popular-repos.list | nightly (15 4 *) |

A GITHUB_TOKEN from the vault lifts requests to the 5000/h authenticated rate limit; it never leaves the server. If you run unauthenticated you'll likely get rate-limited on the first big repo scan.

Mapping table

mappings/known.json is a curated reference table — equivalent to a dictionary, version-controlled with the code. The hourly scraper re-fetches the official announcement and stores a SHA256 — when the doc changes the mappings page surfaces a banner so a human knows to refresh the table. Entries without a known target are stored as replacement: null and rendered as red "NO MAPPING YET" rows. We do not fabricate replacements.

Run locally

npm install
PORT=4828 node server.js
# open http://localhost:4828/antigravity-exit/

The server creates data/antigravity-exit.db (SQLite, WAL). On boot it kicks off the announcement + npm fetchers immediately, plus the popular-repos scan after 5 seconds. Cron jobs continue afterwards.

Pattern set

| pattern_id | Matches | Severity |
|---|---|---|
| pkg.json.dep | "@google/gemini-cli" in package.json deps | high |
| pkg.json.script | gemini / gemini-cli token inside package.json scripts. | high |
| gh-actions.uses | uses: google-gemini/.+ or
gemini-cli in .github/workflows/.yml | high |
| gh-actions.run | run: step invoking gemini or npx gemini-cli | high |
| shell.gemini-bin | gemini / gemini-cli in shell scripts / Makefile / Dockerfile | high |
| dotgemini.dir | any path under .gemini/ | med |
| env.api-key | reference to GEMINI_API_KEY env var | med |
| docs.mention | README/markdown mentions of gemini-cli | info |
| agent.skills | .gemini/skills / .gemini/hooks / .gemini/subagents | high |

exposure_score (0–100) = 30 if any high, +5/extra high (cap 60), +5/distinct file (cap 30), +1/med (cap 10).

Layout

antigravity-exit/
├── server.js                # Express bootstrap, cron registration
├── db.js                    # better-sqlite3 init, migrations, WAL
├── config.js                # PORT, BASE_PATH, GITHUB_TOKEN, allowlist
├── routes/                  # health, scan, leaderboard, mappings, stats
├── scanners/                # github API client, regex patterns, orchestrator
├── scrapers/                # announcement (hourly), npm (6h), popular-repos (nightly)
├── mappings/known.json      # curated Gemini → Antigravity table
└── public/                  # vanilla SPA: index.html, scan.html, mappings.html, app.js, style.css

Out of scope (by spec)

Honesty notes