Scan your GitHub or GitLab org — generates metadata JSON for service, feature, and ownership discovery
Project description
Org21 Git Scanner
Scan your GitHub or GitLab organization to discover services, features, and code ownership — then upload the results to the Org21 platform for automatic knowledge graph enrichment.
Supports GitHub, GitLab.com, and self-hosted GitLab instances.
What It Does
The scanner reads your Git organization's metadata only — it never accesses source code content. It collects:
| Data | How It's Used |
|---|---|
| Repository names & descriptions | Identifies your services |
| README first paragraph | Helps name services accurately |
| Sub-module structure (build files) | Identifies features within services |
| Domain directory structure | Identifies capability areas |
| Contributor commit counts | Determines code ownership |
| Contributor emails | Bridges identity across tools (Jira, HiBob, Git) |
| CODEOWNERS file | Maps explicit ownership declarations |
| Collaborator permissions | Identifies repo admins (strongest ownership signal) |
| First commit author | Identifies who created each repo |
| File extension counts | Identifies IaC, deployment, and language patterns |
| AI SDK usage | Detects repos using OpenAI, Anthropic, Gemini, etc. |
| Visibility (private/public/internal) | Privacy-aware processing |
| Archived status | Tracks inactive services |
No source code is read, stored, or transmitted. Only repository metadata.
Quick Start
1. Install
pip install org21-git-scan
Requires Python 3.9+.
2. Set Up Authentication
The scanner supports two authentication methods: token (recommended) or username/password (for Enterprise and self-hosted setups).
Option A — Access Token (recommended)
For GitHub:
- Go to github.com/settings/tokens
- Click Generate new token (fine-grained)
- Select your organization under Resource owner
- Set Repository access → All repositories (or select specific ones)
- Under Permissions → Repository permissions, grant:
- Contents → Read-only
- Metadata → Read-only
- Click Generate token and copy it
For GitLab (Personal Access Token):
- Go to gitlab.com/-/user_settings/personal_access_tokens
- Create a token with scopes:
read_api,read_repository - Copy the token (
glpat-xxxx)
For GitLab (Group Access Token — fine-grained, recommended):
- Go to your group → Settings → Access Tokens
- Create a token with only these permissions (all read-only):
| Category | Permission | Why |
|---|---|---|
| Repository | Read | CODEOWNERS, README, directory tree, file extensions |
| Group | Read | List projects in group (including subgroups) |
| Member | Read | Collaborator permission levels (admin/write/read) |
| Global Search | Read | AI usage detection (searches for openai/anthropic/etc.) |
- Set role to Reporter (minimum needed)
- Copy the token (
glpat-xxxx)
Important: The scanner only reads metadata — it never creates, modifies, or deletes anything. No write permissions are needed. Do NOT grant Branch, Merge Request, Pipeline, CI/CD, Work Item, or Enterprise User permissions.
Option B — Username & Password
For GitHub Enterprise or self-hosted GitLab with local accounts, you can use username and password instead of a token.
Note: GitHub.com requires a token (password auth is deprecated for github.com). Username/password works for GitHub Enterprise Server and self-hosted GitLab.
3. Run the Scanner
GitHub with token:
org21-git-scan --provider github --org YourOrgName --token ghp_your_token
GitHub Enterprise with username/password:
org21-git-scan --provider github --org YourOrgName --username your_user --password your_pass
GitLab.com with token:
org21-git-scan --provider gitlab --org YourGroupName --token glpat_your_token
Self-hosted GitLab with token:
org21-git-scan --provider gitlab --org YourGroupName --token glpat_your_token --url https://gitlab.internal.company.com
Self-hosted GitLab with username/password:
org21-git-scan --provider gitlab --org YourGroupName --username your_user --password your_pass --url https://gitlab.internal.company.com
This produces a git-metadata.json file in your current directory.
4. Upload to Org21
Upload the git-metadata.json file to your Org21 dashboard:
- Log into your Org21 dashboard
- Go to Settings → Integrations → Git
- Click Upload Scan Results
- Select your
git-metadata.jsonfile
Your services, features, and ownership data will appear in the knowledge graph within minutes.
Options
org21-git-scan --help
usage: org21-git-scan [-h] [--provider {github,gitlab}] --org ORG
[--token TOKEN] [--username USERNAME]
[--password PASSWORD] [--url URL] [--output OUTPUT]
[--max-repos MAX_REPOS] [--verbose]
options:
--provider {github,gitlab} Git provider (default: github)
--org ORG GitHub organization or GitLab group name (required)
--token TOKEN Access token (or set GITHUB_TOKEN / GITLAB_TOKEN env var)
--username USERNAME Username for basic auth (or set GIT_USERNAME env var)
--password PASSWORD Password for basic auth (or set GIT_PASSWORD env var)
--url URL GitLab instance URL for self-hosted (default: https://gitlab.com)
--output, -o OUTPUT Output file path (default: git-metadata.json)
--max-repos MAX_REPOS Maximum repos to scan (default: 100)
--verbose, -v Show detailed scanning progress
Authentication: Use either --token OR --username + --password. Not both.
Using Environment Variables
# GitHub with token
export GITHUB_TOKEN=ghp_your_token
org21-git-scan --provider github --org YourOrgName
# GitLab with token
export GITLAB_TOKEN=glpat_your_token
org21-git-scan --provider gitlab --org YourGroupName
# Any provider with username/password
export GIT_USERNAME=your_user
export GIT_PASSWORD=your_pass
org21-git-scan --provider gitlab --org YourGroupName --url https://gitlab.internal.com
Provider Comparison
| Feature | GitHub | GitLab |
|---|---|---|
| List repos | ✓ (org repos) | ✓ (group projects, including subgroups) |
| Contributors + commits | ✓ | ✓ (includes email directly) |
| CODEOWNERS | ✓ (3 standard locations) | ✓ (3 standard locations) |
| Collaborator permissions | ✓ (admin/maintain/write/read) | ✓ (Owner/Maintainer/Developer/Reporter/Guest) |
| README parsing | ✓ | ✓ |
| Sub-module detection | ✓ | ✓ |
| File extensions | ✓ | ✓ |
| AI usage search | ✓ (Code Search API) | ✓ (Group Search API) |
| First commit author | ✓ | ✓ |
| Self-hosted | ✗ (GitHub Enterprise only) | ✓ (any GitLab instance via --url) |
| Visibility levels | private / public | private / internal / public |
What Gets Scanned
For each non-forked repository in your organization:
| Item | API Calls | Notes |
|---|---|---|
| Repository info | 1 per page | Name, description, language, last push, visibility, archived status |
| Contributors | 1 per repo | Login, display name, commit count, email |
| Languages | 1 per repo | Language breakdown |
| CODEOWNERS | Up to 3 per repo | Ownership patterns and assigned owners |
| README | 1 per repo | Heading + first paragraph (for service naming) |
| Collaborators | 1 per repo | Permission levels (admin/write/read) |
| First commit | 1 per repo | Proxy for repo creator |
| Directory tree | 1 per repo | Build manifests, sub-modules, domain directories, file extensions |
| Sub-READMEs | 1 per documented dir | Subdirectory documentation |
| AI usage | ~10 per org | Code search for AI SDK keywords |
Typical scan time: 2-3 minutes for a 50-repo organization.
Output Format
The scanner produces a single JSON file with identical format regardless of provider:
{
"org": "YourOrgName",
"scanned_at": "2026-04-09T10:30:00Z",
"provider": "github",
"repos": [
{
"name": "auth-service",
"description": "Authentication and authorization service",
"readme_heading": "Auth Service",
"readme_summary": "Multi-tenant authentication with OAuth2, PKCE, and session management.",
"language": "Python",
"languages": {"Python": 45000, "Shell": 2000},
"file_extensions": {".py": 120, ".yaml": 15, ".md": 8},
"last_push": "2026-04-07T15:30:00Z",
"visibility": "private",
"archived": false,
"contributors": [
{"login": "alice", "name": "Alice Smith", "commits": 142, "email": "alice@company.com"}
],
"collaborators": [
{"login": "alice", "name": "Alice Smith", "permission": "admin"}
],
"codeowners": [
{"pattern": "/src/oauth/", "owners": ["@alice", "@bob"]}
],
"sub_modules": [
{"path": "api-gateway", "name": "api-gateway", "build_file": "package.json"}
],
"created_by": "alice",
"admins": ["alice"],
"uses_ai": true,
"ai_references": ["openai", "langchain"]
}
]
}
Privacy & Security
- No source code is accessed — only repository metadata (names, structure, contributors)
- No data leaves your machine — the JSON file is generated locally
- You control what's shared — review the JSON before uploading
- Fine-grained token — only read permissions needed, no write access
- Credentials stay local — tokens and passwords are never sent to Org21, only used for Git API calls on your machine
- Revoke anytime — delete the token or change the password to revoke access immediately
- Basic auth supported — for environments where token generation is restricted (e.g., self-hosted GitLab with LDAP)
- Self-hosted GitLab — for organizations that can't use cloud Git, the scanner runs entirely within your network
How Org21 Uses This Data
Once uploaded, Org21 analyzes the metadata to enrich your knowledge graph:
| Input | Output |
|---|---|
| Repositories | Services with human-readable names |
| Sub-modules & domain directories | Features within services |
| Contributors, CODEOWNERS, admins | Ownership — who owns which service |
| Contributor emails | Identity bridging across Jira, Git, and HR systems |
| File extensions | Service classification (IaC, deployment, application) |
| AI references | AI stack discovery (which services use AI) |
This data cross-references with other connectors (Jira, HiBob, NetSuite) to build a complete picture of your organization's technology landscape.
Scheduling Regular Scans
# Crontab (daily at 2am)
0 2 * * * GITHUB_TOKEN=ghp_xxx org21-git-scan --provider github --org YourOrg -o /path/to/git-metadata.json
# Or run manually after significant changes
org21-git-scan --provider github --org YourOrg
Then upload the updated file to your Org21 dashboard.
Troubleshooting
| Error | Solution |
|---|---|
Error: Access token required |
Set --token or the appropriate env var |
403 Forbidden |
Token doesn't have required permissions — check scopes |
404 Not Found |
Organization/group name is wrong or token doesn't have access |
Rate limit exceeded |
Wait and retry, or use a token with higher limits |
| Scan takes too long | Use --max-repos 50 to limit scope |
| Self-hosted GitLab SSL error | Ensure your GitLab URL uses a valid certificate |
Support
For questions or issues: Contact your Org21 account team
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 org21_git_scan-1.0.1.tar.gz.
File metadata
- Download URL: org21_git_scan-1.0.1.tar.gz
- Upload date:
- Size: 20.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c62fbe2e062c7b8d4b0fa3fec6fff66532e128d3696de79635d9a15ad19d4f47
|
|
| MD5 |
d7535b9f4dc6d7ae13dffb5f6b854d08
|
|
| BLAKE2b-256 |
6b393970350352e42252e6fedfd05824c4033e97e80669586078dfb6cd08cabf
|
Provenance
The following attestation bundles were made for org21_git_scan-1.0.1.tar.gz:
Publisher:
publish-pypi.yml on Org21-ai/src-ingest-github-collector
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
org21_git_scan-1.0.1.tar.gz -
Subject digest:
c62fbe2e062c7b8d4b0fa3fec6fff66532e128d3696de79635d9a15ad19d4f47 - Sigstore transparency entry: 1284854769
- Sigstore integration time:
-
Permalink:
Org21-ai/src-ingest-github-collector@90f342cafb8ca55cec6f4a6c30127abbfd26f480 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Org21-ai
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@90f342cafb8ca55cec6f4a6c30127abbfd26f480 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file org21_git_scan-1.0.1-py3-none-any.whl.
File metadata
- Download URL: org21_git_scan-1.0.1-py3-none-any.whl
- Upload date:
- Size: 24.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
715a8593aeee7e153042bf205b853ed2aed5b13724915c7d642c4fcec4c36496
|
|
| MD5 |
e380a75bd72529e24c22369ebbc67dc0
|
|
| BLAKE2b-256 |
f5861a989d7f8be93439d79bfda2a61a1e6565b66994ed14a9640950c5581852
|
Provenance
The following attestation bundles were made for org21_git_scan-1.0.1-py3-none-any.whl:
Publisher:
publish-pypi.yml on Org21-ai/src-ingest-github-collector
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
org21_git_scan-1.0.1-py3-none-any.whl -
Subject digest:
715a8593aeee7e153042bf205b853ed2aed5b13724915c7d642c4fcec4c36496 - Sigstore transparency entry: 1284854894
- Sigstore integration time:
-
Permalink:
Org21-ai/src-ingest-github-collector@90f342cafb8ca55cec6f4a6c30127abbfd26f480 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Org21-ai
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@90f342cafb8ca55cec6f4a6c30127abbfd26f480 -
Trigger Event:
workflow_dispatch
-
Statement type: