# GitHub Repo Analyzer — Repository Metrics & Health (`perryay/github-repo-analyzer`) Actor

Extract comprehensive repository metrics from public GitHub repos. Supports single-repo lookup, batch analysis (up to 10 repos), and topic/keyword search. Returns stars, forks, language, topics, license, contributors, open issues, README preview, and timestamps. No authentication required.

- **URL**: https://apify.com/perryay/github-repo-analyzer.md
- **Developed by:** [Perry AY](https://apify.com/perryay) (community)
- **Categories:** Developer tools, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.05 / actor start

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## GitHub Repo Analyzer — Extract Repository Metrics and Analysis Data

Analyze public GitHub repositories without authentication. Get stars, forks, primary language, topics, license, contributor counts, open issue counts, and README previews — all from one clean output. Supports single repositories, batch lists of up to 10, and topic-based keyword search.

Built with async HTTPX and the plain Apify SDK. No Playwright, no browser automation, no authentication secrets to manage. Just point it at a GitHub URL (or a list of them) and the actor returns structured data for every repository it finds.

---

### What does it do?

GitHub Repo Analyzer is a lightweight Apify actor that reads the public GitHub REST API and returns a consistent, structured dataset of repository metrics. It handles three common workflows:

- **Single repo** — paste one URL and get a full breakdown.
- **Batch list** — provide up to 10 repos and get them all back in one run, fetched concurrently for speed.
- **Topic search** — give it a keyword like `machine-learning` and it finds the top starred repos in that topic, then fetches detailed metrics for each.

The actor is designed for developers, data analysts, researchers, and anyone who needs to inventory or compare GitHub repositories programmatically.

---

### Who is it for?

| Persona | What They Need | How This Actor Helps |
|---|---|---|
| Open-source maintainer | Track adoption metrics across their own repos and similar projects | Batch-analyze related repos side by side to compare stars, forks, contributor activity |
| Data analyst / researcher | Gather repository metadata for analysis, dashboards, or academic studies | Search by topic and export structured JSON into datasets for further processing |
| Recruiter / talent sourcer | Evaluate a candidate's open-source activity | Single-repo mode returns contributor counts, language, and recent issue activity |
| Developer evaluating dependencies | Assess the health and community of a library before adopting it | Quick access to stars, open issues, license, and last update date |
| Tech blogger / content creator | Gather facts for comparison articles or round-up posts | Search or batch mode collects data for "Top 10 ML repos" style articles |
| Product manager | Benchmark competitor or peer project adoption | Batch-analyze repos from multiple organisations and compare metrics |
| DevOps / platform engineer | Automate repo discovery and monitoring as part of infrastructure tooling | Integrate the actor into a CI pipeline or Apify webhook workflow |
| Open-source researcher | Study patterns in the GitHub ecosystem (languages, licenses, topics) | Topic search with configurable limits provides focused, structured samples |

---

### Why use this?

| Concern | GitHub API (direct) | GitHub Repo Analyzer |
|---|---|---|
| Rate limits | 60 req/hr unauthenticated | Same limit applies, but results are structured and batched to maximise every request |
| Output format | Raw JSON with varying structure per endpoint | Consistent schema across all output rows — every field is always present |
| Multi-repo workflows | Requires manual loops, pagination, and error handling | Batch mode handles concurrency, semaphores, and error isolation automatically |
| Error handling | Raw HTTP errors must be caught and parsed per endpoint | Typed error messages per exception (404, 403, 5xx, timeout, network) |
| README extraction | Separate endpoint, base64 decoding required | Built-in decode and truncation to 500 characters |
| Dataset integration | None | Pushes directly to Apify dataset with every row |
| Cost tracking | N/A | Charge events at startup, per-repo, per-search, and batch completion |
| Contributor counting | Requires pagination via Link header parsing | Automatic last-page detection from Link header |

---

### Features

- **Three analysis modes** — Single, Batch (up to 10), Search by topic
- **Async concurrent fetching** — Semaphore-limited parallel requests in batch mode (max 3 concurrent) for good throughput without hammering rate limits
- **Structured output** — Every row contains: repo name, stars, forks, language, topics list, license, description, open issues, contributors, created/updated timestamps, README preview, and error field
- **No authentication required** — Uses the public GitHub REST API v3 with no token needed. Ready to run with zero configuration.
- **Graceful error isolation** — A failed repo never blocks the rest. Errors are recorded per row with descriptive messages (rate limited, not found, network error, server error, parse error).
- **Input validation** — Mode checks, URL parsing, array length limits, and integer bounds run before any API call.
- **Safe charging** — `charge_safe()` wrapper ensures charging errors never crash the actor.
- **No Playwright** — Zero browser dependencies. The Docker image stays lean (`apify/actor-python:3.13` base).
- **Event hooks** — Push events fire at meaningful lifecycle points: `apify-actor-start`, `apify-default-dataset-item` (per row), `batch-analysis` (batch/search summary). Charge events fire for `apify-actor-start`, `repo-analysis`, `search-execute`, and `batch-report`.

---

### Input Parameters

| Field | Type | Required | Description |
|---|---|---|---|
| `mode` | string (enum) | Yes | `single`, `batch`, or `search` |
| `repo` | string | If mode=single | Repository URL or owner/name |
| `repos` | array of strings | If mode=batch | List of repo identifiers (max 10) |
| `topic` | string | If mode=search | Keyword to search repositories by topic |
| `limit` | integer | No | Max results for search mode (1–20, default 10) |

#### Accepted Repository Identifier Formats

- `owner/name` — e.g. `example/example-repo`
- `https://github.com/owner/name`
- `http://github.com/owner/name`
- `github.com/owner/name`
- All of the above with trailing `.git`

---

### Output Format

Each row in the default dataset contains the following fields:

| Field | Type | Description |
|---|---|---|
| `repo_name` | string | Repository identifier in `owner/name` format |
| `stars` | number | Stargazers count |
| `forks` | number | Forks count |
| `language` | string | Primary programming language detected by GitHub |
| `topics` | array of strings | Topic tags associated with the repo |
| `license` | string | SPDX license identifier or key |
| `description` | string | Repository description text |
| `open_issues` | number | Number of open issues |
| `contributors` | number | Approximate total contributors |
| `created_at` | string | ISO 8601 creation timestamp |
| `updated_at` | string | ISO 8601 last-update timestamp |
| `readme_preview` | string | First ~500 characters of decoded README content |
| `error` | string | Error message if data could not be fetched (empty on success) |

---

#### Example Input

**Example 1 — Single Repository**

**Input:**
```json
{
  "mode": "single",
  "repo": "https://github.com/example/example-repo"
}
````

**Output row:**

```json
{
  "repo_name": "example/example-repo",
  "stars": 42,
  "forks": 12,
  "language": "Python",
  "topics": ["data-science", "example"],
  "license": "MIT",
  "description": "An example repository for demonstration purposes.",
  "open_issues": 5,
  "contributors": 10,
  "created_at": "2020-01-15T10:30:00Z",
  "updated_at": "2024-06-01T14:22:00Z",
  "readme_preview": "# Example Repository\n\nThis is an example...",
  "error": ""
}
```

**Example 2 — Batch Mode (3 Repositories)**

**Input:**

```json
{
  "mode": "batch",
  "repos": [
    "https://github.com/example/example-repo",
    "https://github.com/example/another-repo",
    "example/third-repo"
  ]
}
```

**Output — three rows** in the dataset, one per repository. Each row follows the same schema as Example 1. Repos are fetched concurrently (up to 3 at a time) so total runtime is approximately the slowest single request plus overhead.

**Example 3 — Topic Search**

**Input:**

```json
{
  "mode": "search",
  "topic": "machine-learning",
  "limit": 5
}
```

**Output — up to 5 rows**, each representing a repository matched by the topic search, sorted by stars descending. Each row contains the full schema including README preview and contributor counts.

**Example 4 — Repository Not Found (Graceful Error)**

**Input:**

```json
{
  "mode": "single",
  "repo": "example/nonexistent-repo-xyz"
}
```

**Output row:**

```json
{
  "repo_name": "example/nonexistent-repo-xyz",
  "stars": 0,
  "forks": 0,
  "language": "",
  "topics": [],
  "license": "",
  "description": "",
  "open_issues": 0,
  "contributors": 0,
  "created_at": "",
  "updated_at": "",
  "readme_preview": "",
  "error": "Repository 'example/nonexistent-repo-xyz' not found on GitHub."
}
```

**Example 5 — Invalid Input**

**Input:**

```json
{
  "mode": "single",
  "repo": ""
}
```

**Outcome:** The actor fails immediately with `status_message` set to `"Mode 'single' requires a 'repo' value (owner/name or full URL)."` No dataset rows are written.

**Example 6 — Search with Rate Limit**

If the GitHub API returns a 403 with `X-RateLimit-Remaining: 0`, the actor produces a single error row:

```json
{
  "repo_name": "search:machine-learning",
  "error": "Search rate limited (remaining: 0).",
  ...
}
```

***

### Use Cases

#### 1. Open-Source Portfolio Auditing

Maintainers can batch-analyze all their organisation's public repos to track star growth, fork activity, and contributor trends over time. Export the dataset into a spreadsheet or dashboard for quarterly reviews.

#### 2. Dependency Health Checks

Before adding a library to a project, run the actor against its repository to check: stars (community confidence), open issues / contributors ratio (maintenance activity), last update date (abandonment risk), and license (compatibility with your project).

#### 3. Competitive Landscape Research

Gather data on 10 competitor or peer project repositories in a single run. Compare stars, language choice, topic tags, and contributor communities side by side to understand market positioning.

#### 4. Topic-Based Discovery

Use search mode with keywords like `static-site-generator`, `database-driver`, or `ci-cd` to discover the most-starred projects in any category. The actor fetches full metadata for each, making it easy to evaluate options without opening GitHub tabs.

#### 5. Academic Research on Open Source

Researchers studying the GitHub ecosystem can use topic search to collect structured samples of repositories by topic, language, or other characteristics. The consistent output schema simplifies statistical analysis and avoids per-endpoint parsing.

#### 6. Recruitment and Candidate Assessment

When evaluating a candidate's GitHub activity, run the actor against their repositories to see contributor counts, primary languages, and recent update activity. Get an objective snapshot without manual browsing.

#### 7. Content and Blog Post Research

Tech writers preparing comparison articles or "Top N" lists can search by topic and get structured data on the top repositories — stars, license, description — all in one export. No manual data entry required.

#### 8. Infrastructure Automation

DevOps teams can trigger the actor via Apify webhooks or API calls as part of a CI/CD pipeline. Repository metrics become data points in monitoring dashboards, Slack alerts, or automated reports.

***

### FAQ

#### 1. Do I need a GitHub token or authentication?

No. The actor uses the unauthenticated GitHub REST API v3. Without a token you are limited to 60 requests per hour. If you need higher limits, modify the `headers` dict in `main.py` to include an `Authorization` header with a personal access token.

#### 2. What happens if one repository in a batch fails?

It is isolated. The repository gets a row with an `error` field describing the failure. The other repositories complete normally.

#### 3. How many repositories can I analyze in one run?

- **Batch mode:** up to 10.
- **Search mode:** up to 20 (configurable via the `limit` field, default 10).
- **Single mode:** 1.

#### 4. Does the actor handle paginated results (e.g. all contributors)?

The actor reads contributor and issue header pagination by parsing the `Link` header to find the last page number. This gives an approximate total without fetching every page. For most repos this is accurate to within a few units.

#### 5. What does the README preview include?

The actor fetches the repository's README via the GitHub API, base64-decodes the content, and truncates it to approximately 500 characters. If the repo has no README or the request fails, the field is an empty string.

#### 6. Does this actor work with private repositories?

No. The actor uses the public GitHub REST API without authentication, so it can only read public repositories.

#### 7. What happens when the rate limit is hit?

The actor detects a 403 response with `X-RateLimit-Remaining: 0` and returns an informative error row. No dataset is corrupted; you can retry once the rate limit resets (typically one hour).

#### 8. Can I run this actor locally with Apify CLI?

Yes. Clone the actor directory, run `apify run` in the project root. Make sure you have Python 3.13+ and the dependencies from `requirements.txt` installed.

#### 9. What's the difference between `open_issues` and `contributors`?

- `open_issues`: number of currently open GitHub issues on the repo. Calculated from the `Link` header of the issues endpoint, falling back to `open_issues_count` from the repo API.
- `contributors`: approximate total number of unique committers. Calculated from the `Link` header of the contributors endpoint.

Both are approximations when the count exceeds the first page (30 items).

#### 10. Are there plans to add more modes (e.g. user repos, organisation repos)?

The current architecture makes it straightforward to add new fetch modes by extending the `mode` enum and adding a fetch function. Community contributions and feature requests are welcome.

***

### Related Tools

- **[Website Tech Stack Detector](https://apify.com/perryay/website-tech-stack-detector)** — Detect the technology stack used by any website. Complementary to repository analysis: use the Tech Stack Detector to identify tools and frameworks on live sites, then use Repo Analyzer to examine their source repositories.

- **[Article to Markdown Converter](https://apify.com/perryay/article-to-markdown-converter)** — Convert web articles and blog posts to clean Markdown. Use alongside Repo Analyzer to capture technical blog content about repositories you discover, or to convert README content into formatted documentation.

***

### API Usage

#### Via cURL

```bash
curl -X POST "https://api.apify.com/v2/acts/perryay~github-repo-analyzer/runs" \
  -H "Content-Type: application/json" \
  -d '{
    "mode": "single",
    "repo": "https://github.com/example/example-repo"
  }'
```

#### Via Python (Apify Client)

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_API_TOKEN")
run = client.actor("perryay/github-repo-analyzer").call(
    run_input={
        "mode": "single",
        "repo": "https://github.com/example/example-repo",
    }
)
dataset_items = client.dataset(run["defaultDatasetId"]).list_items().items
for item in dataset_items:
    print(f"{item['repo_name']}: {item['stars']} stars, {item['language']}")
```

#### Via JavaScript (Apify Client)

```javascript
const ApifyClient = require('apify-client').ApifyClient;
const client = new ApifyClient({ token: 'YOUR_API_TOKEN' });

const run = await client.actor('perryay/github-repo-analyzer').call({
    mode: 'single',
    repo: 'https://github.com/example/example-repo',
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach(item => console.log(`${item.repo_name}: ${item.stars} stars`));
```

***

### MCP Integration

Add this actor to your MCP (Model Context Protocol) server configuration:

```json
{
  "mcpServers": {
    "apify-github-analyzer": {
      "command": "npx",
      "args": [
        "-y",
        "@apify/mcp-server-actors",
        "--actors=perryay/github-repo-analyzer"
      ]
    }
  }
}
```

This enables AI assistants to analyze GitHub repositories through your MCP client.

***

### SEO Keywords

GitHub repo analyzer, repository metrics, GitHub stars tracker, open source analytics, repository health check, GitHub API scraper, repo analysis tool, batch repo analyzer, GitHub topic search, repository metadata extraction, open source project analysis, developer analytics tool

# Actor input Schema

## `mode` (type: `string`):

Choose how to target repositories: single repo, batch list, or topic search.

## `repo` (type: `string`):

The GitHub repository to analyze. Accepts full URL (https://github.com/owner/name), short URL (github.com/owner/name), or owner/name format.

## `repos` (type: `array`):

List of repository URLs or owner/name pairs to analyze (max 10).

## `topic` (type: `string`):

Search for repositories matching this topic keyword. Uses GitHub topic search.

## `limit` (type: `integer`):

Maximum number of repositories to return in search mode (1–20).

## Actor input object example

```json
{
  "mode": "single",
  "repo": "https://github.com/example/example-repo",
  "repos": [
    "https://github.com/example/example-repo",
    "https://github.com/example/another-repo"
  ],
  "topic": "machine-learning",
  "limit": 10
}
```

# Actor output Schema

## `results` (type: `string`):

Repository analysis results delivered via the default dataset

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "mode": "single",
    "repo": "https://github.com/example/example-repo",
    "repos": [
        "https://github.com/example/example-repo",
        "https://github.com/example/another-repo"
    ],
    "topic": "machine-learning",
    "limit": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("perryay/github-repo-analyzer").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "mode": "single",
    "repo": "https://github.com/example/example-repo",
    "repos": [
        "https://github.com/example/example-repo",
        "https://github.com/example/another-repo",
    ],
    "topic": "machine-learning",
    "limit": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("perryay/github-repo-analyzer").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "mode": "single",
  "repo": "https://github.com/example/example-repo",
  "repos": [
    "https://github.com/example/example-repo",
    "https://github.com/example/another-repo"
  ],
  "topic": "machine-learning",
  "limit": 10
}' |
apify call perryay/github-repo-analyzer --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=perryay/github-repo-analyzer",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "GitHub Repo Analyzer — Repository Metrics & Health",
        "description": "Extract comprehensive repository metrics from public GitHub repos. Supports single-repo lookup, batch analysis (up to 10 repos), and topic/keyword search. Returns stars, forks, language, topics, license, contributors, open issues, README preview, and timestamps. No authentication required.",
        "version": "1.0",
        "x-build-id": "8EkPQmUmg8tc9f7xG"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/perryay~github-repo-analyzer/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-perryay-github-repo-analyzer",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/perryay~github-repo-analyzer/runs": {
            "post": {
                "operationId": "runs-sync-perryay-github-repo-analyzer",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/perryay~github-repo-analyzer/run-sync": {
            "post": {
                "operationId": "run-sync-perryay-github-repo-analyzer",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "mode"
                ],
                "properties": {
                    "mode": {
                        "title": "Analysis Mode",
                        "enum": [
                            "single",
                            "batch",
                            "search"
                        ],
                        "type": "string",
                        "description": "Choose how to target repositories: single repo, batch list, or topic search.",
                        "default": "single"
                    },
                    "repo": {
                        "title": "Repository URL or Owner/Name",
                        "pattern": "^https?://github\\.com/[^/]+/[^/]+|^github\\.com/[^/]+/[^/]+|^[^/]+/[^/]+$",
                        "type": "string",
                        "description": "The GitHub repository to analyze. Accepts full URL (https://github.com/owner/name), short URL (github.com/owner/name), or owner/name format.",
                        "default": ""
                    },
                    "repos": {
                        "title": "Repository List (Batch Mode)",
                        "type": "array",
                        "description": "List of repository URLs or owner/name pairs to analyze (max 10).",
                        "items": {
                            "type": "string",
                            "pattern": "^https?://github\\.com/[^/]+/[^/]+|^github\\.com/[^/]+/[^/]+|^[^/]+/[^/]+$"
                        },
                        "default": []
                    },
                    "topic": {
                        "title": "Topic / Keyword (Search Mode)",
                        "type": "string",
                        "description": "Search for repositories matching this topic keyword. Uses GitHub topic search.",
                        "default": ""
                    },
                    "limit": {
                        "title": "Result Limit",
                        "minimum": 1,
                        "maximum": 20,
                        "type": "integer",
                        "description": "Maximum number of repositories to return in search mode (1–20).",
                        "default": 10
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
