GitHub
GitHub API integration with managed OAuth. Access repositories, issues, pull requests, commits, branches, and users. Use this skill when users want to interact with GitHub reposito…
byungkyu
@byungkyu
Install
$ openclaw skills install @byungkyu/github-apiGitHub
Access the GitHub REST API with managed OAuth authentication. Manage repositories, issues, pull requests, commits, branches, users, and more.
Quick Start
CLI:
maton github repo list --sort updated
maton api '/github/user/repos?sort=updated&per_page=10'
Python:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/github/user/repos?sort=updated&per_page=10')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Base URL
https://api.maton.ai/github/{native-api-path}
Maton proxies requests to api.github.com and automatically injects your OAuth token.
Installation
NPM:
npm install -g @maton/cli
Homebrew:
brew install maton-ai/cli/maton
Authentication
CLI:
maton login # Opens browser for API key
maton login --interactive # Skip browser, paste API key directly
maton whoami # Show current auth state
Manual:
- Sign in or create an account at maton.ai
- Go to maton.ai/settings
- Copy your API key
- Set your API key as
MATON_API_KEY:
export MATON_API_KEY="YOUR_API_KEY"
Connection Management
Manage your GitHub OAuth connections at https://api.maton.ai.
List Connections
CLI:
maton connection list github --status ACTIVE
maton api -X GET /connections -f app=github -f status=ACTIVE
Python:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections?app=github&status=ACTIVE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Create Connection
CLI:
maton connection create github
maton api /connections -f app=github
Python:
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'github'}).encode()
req = urllib.request.Request('https://api.maton.ai/connections', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Get Connection
CLI:
maton connection view {connection_id}
maton api /connections/{connection_id}
Python:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Open the returned url in a browser to complete OAuth authorization.
Delete Connection
CLI:
maton connection delete {connection_id}
maton api -X DELETE /connections/{connection_id}
Python:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}', method='DELETE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Specifying Connection
If you have multiple GitHub connections, specify which one to use:
CLI:
maton github user --connection {connection_id}
maton api /github/user --connection {connection_id}
Python:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/github/user')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Maton-Connection', '{connection_id}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
If you have multiple connections, always specify the connection to ensure requests go to the intended account.
Security & Permissions
- Access is scoped to repositories, issues, pull requests, commits, branches, and users within the connected GitHub account.
- All write operations require explicit user approval. Before executing any create, update, or delete call:
- Confirm the exact target (owner/repo, issue number, branch name) with the user.
- Verify the correct connection ID when multiple connections exist.
- State whether the action is reversible or destructive.
- Irreversible / high-risk operations (require extra caution):
- Deleting repositories, branches, or releases
- Force-pushing or rewriting history
- Merging pull requests (cannot be unmerged)
- Removing collaborators or transferring ownership
- Scope boundaries:
- Only operate on repositories the user explicitly names. Never enumerate or modify repositories outside the current task context.
- Organization-level actions (creating repos, managing members) require the user to confirm the target organization.
- Do not request or use OAuth scopes beyond what the current task requires.
API Reference
Users
Get Authenticated User
GET /github/user
Example:
maton github whoami
Get User by Username
GET /github/users/{username}
List Users
GET /github/users?since={user_id}&per_page=30
Repositories
List User Repositories
GET /github/user/repos?per_page=30&sort=updated
Query parameters: type (all, owner, public, private, member), sort (created, updated, pushed, full_name), direction (asc, desc), per_page, page
Example:
maton github repo list --sort updated
List Organization Repositories
GET /github/orgs/{org}/repos?per_page=30
Example:
maton github repo list {org}
Get Repository
GET /github/repos/{owner}/{repo}
Example:
maton github repo view --repo {owner}/{repo}
Create Repository (User)
POST /github/user/repos
Content-Type: application/json
{
"name": "my-new-repo",
"description": "A new repository",
"private": true,
"auto_init": true
}
Example:
maton github repo create my-new-repo --description "A new repository" --visibility private
Create Repository (Organization)
POST /github/orgs/{org}/repos
Content-Type: application/json
{
"name": "my-new-repo",
"description": "A new repository",
"private": true
}
Example:
maton github repo create {org}/my-new-repo --visibility private
Update Repository
PATCH /github/repos/{owner}/{repo}
Content-Type: application/json
{
"description": "Updated description",
"has_issues": true,
"has_wiki": false
}
Example:
maton github repo edit --repo {owner}/{repo} --description "Updated description" --enable-issues --enable-wiki=false
Repository Contents
List Contents
GET /github/repos/{owner}/{repo}/contents/{path}
Get File Contents
GET /github/repos/{owner}/{repo}/contents/{path}?ref={branch}
Create or Update File
PUT /github/repos/{owner}/{repo}/contents/{path}
Content-Type: application/json
{
"message": "Create new file",
"content": "SGVsbG8gV29ybGQh",
"branch": "main"
}
Note: content must be Base64 encoded.
Delete File
DELETE /github/repos/{owner}/{repo}/contents/{path}
Content-Type: application/json
{
"message": "Delete file",
"sha": "{file_sha}",
"branch": "main"
}
Branches
List Branches
GET /github/repos/{owner}/{repo}/branches?per_page=30
Get Branch
GET /github/repos/{owner}/{repo}/branches/{branch}
Rename Branch
POST /github/repos/{owner}/{repo}/branches/{branch}/rename
Content-Type: application/json
{
"new_name": "new-branch-name"
}
Merge Branches
POST /github/repos/{owner}/{repo}/merges
Content-Type: application/json
{
"base": "main",
"head": "feature-branch",
"commit_message": "Merge feature branch"
}
Commits
List Commits
GET /github/repos/{owner}/{repo}/commits?per_page=30
Query parameters: sha (branch name or commit SHA), path (file path), author, committer, since, until, per_page, page
Get Commit
GET /github/repos/{owner}/{repo}/commits/{ref}
Compare Two Commits
GET /github/repos/{owner}/{repo}/compare/{base}...{head}
Issues
List Repository Issues
GET /github/repos/{owner}/{repo}/issues?state=open&per_page=30
Query parameters: state (open, closed, all), labels, assignee, creator, mentioned, sort, direction, since, per_page, page
Example:
maton github issue list --repo {owner}/{repo} --state open
Get Issue
GET /github/repos/{owner}/{repo}/issues/{issue_number}
Example:
maton github issue view {issue_number} --repo {owner}/{repo}
Create Issue
POST /github/repos/{owner}/{repo}/issues
Content-Type: application/json
{
"title": "Found a bug",
"body": "Bug description here",
"labels": ["bug"],
"assignees": ["username"]
}
Example:
maton github issue create --repo {owner}/{repo} --title "Found a bug" --body "Bug description here" --label bug --assignee username
Update Issue
PATCH /github/repos/{owner}/{repo}/issues/{issue_number}
Content-Type: application/json
{
"state": "closed",
"state_reason": "completed"
}
Example:
maton github issue close {issue_number} --repo {owner}/{repo} --reason completed
Lock Issue
PUT /github/repos/{owner}/{repo}/issues/{issue_number}/lock
Content-Type: application/json
{
"lock_reason": "resolved"
}
Example:
maton github issue lock {issue_number} --repo {owner}/{repo} --reason resolved
Unlock Issue
DELETE /github/repos/{owner}/{repo}/issues/{issue_number}/lock
Example:
maton github issue unlock {issue_number} --repo {owner}/{repo}
Issue Comments
List Issue Comments
GET /github/repos/{owner}/{repo}/issues/{issue_number}/comments?per_page=30
Example:
maton github issue view {issue_number} --repo {owner}/{repo} --comments
Create Issue Comment
POST /github/repos/{owner}/{repo}/issues/{issue_number}/comments
Content-Type: application/json
{
"body": "This is a comment"
}
Example:
maton github issue comment {issue_number} --repo {owner}/{repo} --body "This is a comment"
Update Issue Comment
PATCH /github/repos/{owner}/{repo}/issues/comments/{comment_id}
Content-Type: application/json
{
"body": "Updated comment"
}
Delete Issue Comment
DELETE /github/repos/{owner}/{repo}/issues/comments/{comment_id}
Labels
List Labels
GET /github/repos/{owner}/{repo}/labels?per_page=30
Example:
maton github label list --repo {owner}/{repo}
Create Label
POST /github/repos/{owner}/{repo}/labels
Content-Type: application/json
{
"name": "priority:high",
"color": "ff0000",
"description": "High priority issues"
}
Example:
maton github label create "priority:high" --repo {owner}/{repo} --color ff0000 --description "High priority issues"
Milestones
List Milestones
GET /github/repos/{owner}/{repo}/milestones?state=open&per_page=30
Create Milestone
POST /github/repos/{owner}/{repo}/milestones
Content-Type: application/json
{
"title": "v1.0",
"state": "open",
"description": "First release",
"due_on": "2026-03-01T00:00:00Z"
}
Pull Requests
List Pull Requests
GET /github/repos/{owner}/{repo}/pulls?state=open&per_page=30
Query parameters: state (open, closed, all), head, base, sort, direction, per_page, page
Example:
maton github pr list --repo {owner}/{repo} --state open
Get Pull Request
GET /github/repos/{owner}/{repo}/pulls/{pull_number}
Example:
maton github pr view {pull_number} --repo {owner}/{repo}
Create Pull Request
POST /github/repos/{owner}/{repo}/pulls
Content-Type: application/json
{
"title": "New feature",
"body": "Description of changes",
"head": "feature-branch",
"base": "main",
"draft": false
}
Example:
maton github pr create --repo {owner}/{repo} --base main --head feature-branch --title "New feature" --body "Description of changes"
Update Pull Request
PATCH /github/repos/{owner}/{repo}/pulls/{pull_number}
Content-Type: application/json
{
"title": "Updated title",
"state": "closed"
}
Example:
maton github pr edit {pull_number} --repo {owner}/{repo} --title "Updated title"
List Pull Request Commits
GET /github/repos/{owner}/{repo}/pulls/{pull_number}/commits?per_page=30
List Pull Request Files
GET /github/repos/{owner}/{repo}/pulls/{pull_number}/files?per_page=30
Example:
maton github pr diff {pull_number} --repo {owner}/{repo}
Check If Merged
GET /github/repos/{owner}/{repo}/pulls/{pull_number}/merge
Merge Pull Request
PUT /github/repos/{owner}/{repo}/pulls/{pull_number}/merge
Content-Type: application/json
{
"commit_title": "Merge pull request",
"merge_method": "squash"
}
Merge methods: merge, squash, rebase
Example:
maton github pr merge {pull_number} --repo {owner}/{repo} --squash --delete-branch
Pull Request Reviews
List Reviews
GET /github/repos/{owner}/{repo}/pulls/{pull_number}/reviews?per_page=30
Create Review
POST /github/repos/{owner}/{repo}/pulls/{pull_number}/reviews
Content-Type: application/json
{
"body": "Looks good!",
"event": "APPROVE"
}
Events: APPROVE, REQUEST_CHANGES, COMMENT
Example:
maton github pr review {pull_number} --repo {owner}/{repo} --approve --body "Looks good!"
Note: GitHub does not allow approving your own pull requests; --approve returns 422 Can not approve your own pull request in that case. Use --comment or --request-changes instead.
Search
Search Repositories
GET /github/search/repositories?q={query}&per_page=30
Example queries:
tetris+language:python- Repositories with "tetris" in Pythonreact+stars:>10000- Repositories with "react" and 10k+ stars
Example:
maton github repo search tetris --language python
Search Issues
GET /github/search/issues?q={query}&per_page=30
Example queries:
bug+is:open+is:issue- Open issues containing "bug"author:username+is:pr- Pull requests by author
Example:
maton github issue search "bug" --state open
Search Code
GET /github/search/code?q={query}&per_page=30
Example queries:
addClass+repo:facebook/react- Search for "addClass" in a specific repofunction+extension:js- JavaScript functions
Note: Code search may timeout on broad queries.
Search Users
GET /github/search/users?q={query}&per_page=30
Organizations
List User Organizations
GET /github/user/orgs?per_page=30
Note: Requires read:org scope.
Get Organization
GET /github/orgs/{org}
List Organization Members
GET /github/orgs/{org}/members?per_page=30
Rate Limit
Get Rate Limit
GET /github/rate_limit
Pagination
GitHub uses page-based pagination. The CLI automatically paginates with '--paginate'.
Example:
maton github repo list --paginate
Code Examples
CLI
# Get repos as JSON (full objects)
maton github repo list --json
# Project specific fields with jq
maton github repo list --json --jq '.[] | {name, full_name, private}'
# Filter — e.g., only public repos
maton github repo list --json --jq '.[] | select(.private == false) | .name'
# Extract a single field
maton github issue list --repo owner/repo --json --jq '.[].title'
JavaScript
const response = await fetch(
'https://api.maton.ai/github/repos/owner/repo/issues?state=open&per_page=10',
{
headers: {
'Authorization': `Bearer ${process.env.MATON_API_KEY}`
}
}
);
const issues = await response.json();
Python
import os
import requests
response = requests.get(
'https://api.maton.ai/github/repos/owner/repo/issues',
headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'},
params={'state': 'open', 'per_page': 10}
)
issues = response.json()
Notes
- Repository names are case-insensitive but the API preserves case
- Issue numbers and PR numbers share the same sequence per repository
- Content must be Base64 encoded when creating/updating files
- Rate limits: 5000 requests/hour for authenticated users, 30 searches/minute
- Search queries may timeout on very broad patterns
- Some endpoints require specific OAuth scopes (e.g.,
read:orgfor organization operations). If you receive a scope error, contact Maton support at support@maton.ai with the specific operations/APIs you need and your use-case - IMPORTANT: When using curl commands, use
curl -gwhen URLs contain brackets to disable glob parsing - IMPORTANT: When piping curl output to
jqor other commands, environment variables like$MATON_API_KEYmay not expand correctly in some shell environments
Error Handling
| Status | Meaning |
|---|---|
| 400 | Missing GitHub connection |
| 401 | Invalid or missing Maton API key |
| 403 | Forbidden - insufficient permissions or scope |
| 404 | Resource not found |
| 408 | Request timeout (common for complex searches) |
| 422 | Validation failed |
| 429 | Rate limited |
| 4xx/5xx | Passthrough error from GitHub API |
Troubleshooting: API Key Issues
CLI:
- Check your auth state:
maton whoami
- Verify the API key is valid by listing connections:
maton connection list
Manual:
- Check that the
MATON_API_KEYenvironment variable is set:
echo $MATON_API_KEY
- Verify the API key is valid by listing connections:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Troubleshooting: Invalid App Name
- Ensure your URL path starts with
github. For example:
- Correct:
https://api.maton.ai/github/user - Incorrect:
https://api.maton.ai/api.github.com/user
Resources
Related skills
Linear
@byungkyuLinear API integration with managed OAuth. Query and manage issues, projects, teams, cycles, and labels using GraphQL. Use this skill when users want to create, update, or query Linear issues, search for tasks, manage projects, or track work. For other third party apps, use the api-gateway skill (ht
GitHub
@hith3shWork with GitHub repositories, issues, pull requests, commits, branches, releases, and workflows via the GitHub REST and GraphQL APIs. Use this skill when us...
Monday.com
@byungkyuMonday.com API integration with managed OAuth. Manage boards, items, columns, groups, and workspaces using GraphQL. Use this skill when users want to create,...
Google Slides
@byungkyuGoogle Slides API integration with managed OAuth. Create presentations, add slides, insert content, and manage slide formatting. Use this skill when users wa...
Claude Code Integration
@hw10181913Claude Code integration for OpenClaw. This skill provides interfaces to: - Query Claude Code documentation from https://code.claude.com/docs - Manage subagents and coding tasks - Execute AI-assisted coding workflows - Access best practices and common workflows Use this skill when users want to: - Get help with coding tasks - Query Claude Code documentation - Manage AI-assisted development workflows - Execute complex programming tasks
OpenClaw GitHub Assistant
@conorkennQuery and manage GitHub repositories - list repos, check CI status, create issues, search repos, and view recent activity.