| ---
|
| title: Repo Summarizer
|
| emoji: π
|
| colorFrom: blue
|
| colorTo: indigo
|
| sdk: gradio
|
| sdk_version: "6.0.2"
|
| python_version: "3.11"
|
| app_file: app.py
|
| pinned: false
|
| short_description: Summarize GitHub repos β purpose, tech stack, layout.
|
| ---
|
|
|
| # Repo Summarizer
|
|
|
| A FastAPI service that takes a GitHub repository URL, fetches key files (README, `main.py`, requirements, directory tree), and returns an AI-generated **summary**, **technologies** list, and **structure** description using the Anthropic Claude API.
|
|
|
| ---
|
|
|
| ## Features
|
|
|
| - **POST /summarize** β Accepts a GitHub repo URL and returns:
|
| - **summary** β Short project description (from README, `main.py`, and the 10 longest Python files).
|
| - **technologies** β List of technologies/dependencies (from `requirements*.txt` and file extensions in the repo).
|
| - **structure** β One paragraph describing the project layout (from the repoβs directory tree).
|
| - **GET /** β Web UI to paste a GitHub URL or local path and see the summary result (`index.html`).
|
| - **`app.py`** β Gradio UI with the same behavior as the HTML page (for [Hugging Face Spaces](https://huggingface.co/docs/hub/spaces) and local runs).
|
| - **GET /health** β Health check (`{"status": "ok"}`).
|
| - Unified **error responses** in JSON: `{"status": "error", "message": "..."}`.
|
| - Optional **GITHUB_TOKEN** for higher GitHub API rate limits.
|
| - **Entry-point logging** via `log_entry()` (filename, line, function name) for tracing.
|
|
|
| ---
|
|
|
| ## Project structure
|
|
|
| ```
|
| NebiusTest/
|
| βββ main.py # FastAPI app, /summarize, /health, /, GitHub fetch, LLM calls
|
| βββ app.py # Gradio UI (Space entry point); reuses main.py summarization logic
|
| βββ logger.py # log_entry() for request/function tracing
|
| βββ constants.py # FILE_EXTENSIONS (used for repo analysis)
|
| βββ index.html # Frontend form for GitHub URL/local path β summarize
|
| βββ requirement.txt # Python dependencies
|
| βββ README.md # This file
|
| βββ .gitignore
|
| ```
|
|
|
| ---
|
|
|
| ## Setup
|
|
|
| ### 1. Install dependencies
|
|
|
| ```bash
|
| pip install -r requirement.txt
|
| ```
|
|
|
| ### 2. Environment variables
|
|
|
| | Variable | Required | Description |
|
| |----------|----------|-------------|
|
| | `ANTHROPIC_API_KEY` | Yes | API key for Anthropic (Claude). Used for all summarization. |
|
| | `GITHUB_TOKEN` | No | GitHub personal access token. Raises API rate limit (e.g. 5000/hr vs 60/hr without). |
|
| | `SSL_CERT_FILE` / `REQUESTS_CA_BUNDLE` / `SSL_CA_BUNDLE` | No | PEM path with extra CAs (e.g. corporate HTTPS inspection). Overrides the default Mozilla bundle (`certifi`) used for GitHub + Anthropic `httpx` clients. |
|
| | `HTTPX_VERIFY` | No | Set to `0`, `false`, or `no` to **disable TLS verification** (insecure; debugging only). |
|
|
|
| Example (PowerShell):
|
|
|
| ```powershell
|
| $env:ANTHROPIC_API_KEY = "sk-ant-..."
|
| $env:GITHUB_TOKEN = "ghp_..." # optional
|
| ```
|
|
|
| ### 3. Run the server
|
|
|
| ```bash
|
| python main.py
|
| ```
|
|
|
| Server runs at **http://127.0.0.1:8000**.
|
|
|
| Or with uvicorn:
|
|
|
| ```bash
|
| uvicorn main:app --reload --host 127.0.0.1 --port 8000
|
| ```
|
|
|
| ### 4. Gradio UI (`app.py`)
|
|
|
| `app.py` opens a Gradio interface that matches `index.html`: one text field for a **GitHub URL** or **local directory path**, a **Summarize** button, and sections for **Summary**, **Technologies**, and **Structure**, with errors shown at the top of the result area.
|
|
|
| Run locally after installing dependencies (including Gradio from `requirement.txt`):
|
|
|
| ```bash
|
| python app.py
|
| ```
|
|
|
| Gradio prints a local URL in the terminal (defaults may differ by version). The underlying logic is shared with `main.py` (same GitHub vs. local detection and LLM pipeline).
|
|
|
| **Hugging Face Spaces**
|
|
|
| - Create a Space with the **Gradio** SDK and point it at this repo, or set the Spaceβs **App file** to `app.py` and ensure Gradio finds the global `demo` object (this project exposes `demo` at module level in `app.py`).
|
| - Add **Secrets** for `ANTHROPIC_API_KEY` (required) and optionally `GITHUB_TOKEN`, same as for the FastAPI app.
|
| - Spaces default to a `requirements.txt` file name. If your Space only sees `requirement.txt`, either add a `requirements.txt` mirroring those dependencies or configure the Space build to use `requirement.txt`.
|
| - **Local paths** only work when Gradio runs on a machine that can read that folder. On Hugging Face, use **GitHub URLs** only.
|
|
|
| ---
|
|
|
| ## API
|
|
|
| ### POST /summarize
|
|
|
| **Request body (JSON):**
|
|
|
| ```json
|
| {
|
| "github_url": "https://github.com/owner/repo"
|
| }
|
| ```
|
|
|
| **Success response (200):**
|
|
|
| ```json
|
| {
|
| "summary": "**ProjectName** is a ...",
|
| "technologies": ["Python", "FastAPI", "httpx"],
|
| "structure": "Main code lives in `src/`, tests in `tests/`, ..."
|
| }
|
| ```
|
|
|
| **Error response (4xx/5xx):**
|
|
|
| All errors return JSON:
|
|
|
| ```json
|
| {
|
| "status": "error",
|
| "message": "Description of what went wrong"
|
| }
|
| ```
|
|
|
| Example: repository not found, invalid URL, no text files, or LLM/rate-limit errors.
|
|
|
| ---
|
|
|
| ## Usage
|
|
|
| ### Browser (FastAPI + `index.html`)
|
|
|
| 1. Open http://127.0.0.1:8000/
|
| 2. Enter a GitHub repository URL or a local repository path.
|
| 3. Click **Summarize** and view summary, technologies, and structure.
|
|
|
| ### Gradio (`app.py`)
|
|
|
| 1. Run `python app.py`.
|
| 2. Open the URL shown in the terminal.
|
| 3. Enter the same kind of repository source (GitHub URL or local path) and submit.
|
|
|
| ### cURL
|
|
|
| ```bash
|
| curl -X POST http://127.0.0.1:8000/summarize \
|
| -H "Content-Type: application/json" \
|
| -d "{\"github_url\": \"https://github.com/psf/requests\"}"
|
| ```
|
|
|
| ### Python client
|
|
|
| From the repo root:
|
|
|
| ```python
|
| from main import call_summarize
|
|
|
| result = call_summarize("https://github.com/psf/requests")
|
| print(result["summary"])
|
| print(result["technologies"])
|
| print(result["structure"])
|
| ```
|
|
|
| ---
|
|
|
| ## How summarization works
|
|
|
| 1. **Parse URL** β Extract `owner`/`repo` from the GitHub URL.
|
| 2. **Fetch repo data** (GitHub API):
|
| - Default branch and recursive file tree.
|
| - Contents of: README.md, `main.py`, the 10 longest other `.py` files, and `requirements*.txt`.
|
| 3. **Three sequential LLM calls** (to stay within Anthropic rate limits):
|
| - **Summary** β From README + main.py + 10 longest Python files (Claude). Used the model claude-opus-4-6, since it works better with code
|
| - **Technologies** β From requirements content + file extensions found in the project (`constants.FILE_EXTENSIONS`). Used the model claude-haiku-4-5 since it's liteweight and fast (the task here is pretty simple)
|
| - **Structure** β From the directory tree (paths list). Used the model claude-sonnet-4-6, because this was the default model and I didn't see much difference from other models, and I guess this one is best for tree of structure.
|
| 4. **Response** β JSON with `summary`, `technologies` (one-line array), and `structure`.
|
|
|
| ---
|
|
|
| ## Dependencies
|
|
|
| - **fastapi** β Web framework.
|
| - **uvicorn** β ASGI server.
|
| - **httpx** β Async HTTP client (GitHub API).
|
| - **pydantic** β Request/validation.
|
| - **anthropic** β Claude API client.
|
| - **gradio** β Gradio UI in `app.py` (Spaces / local).
|
| - **python-dotenv** β Loads `.env` for local development (used by `main.py`).
|
| - **certifi** β Default CA bundle for TLS (used when custom CA env vars are not set).
|
|
|
| ---
|
|
|
| ## Logging
|
|
|
| - **logger.py** provides `log_entry()`, which prints `[filename:line] Entering function_name()` for the caller.
|
| - Used at entry of main request handlers and helpers to trace execution.
|
|
|
| ---
|
|
|
| ## License
|
|
|
| Use and modify as needed for your project.
|
|
|