Install
openclaw skills install github-apiGitHub API integration with managed OAuth. Access repositories, issues, pull requests, commits, branches, and users. Use this skill when users want to interact with GitHub repositories, manage issues and PRs, search code, or automate workflows. For other third party apps, use the api-gateway skill (https://clawhub.ai/byungkyu/api-gateway).
openclaw skills install github-apiAccess the GitHub REST API with managed OAuth authentication. Manage repositories, issues, pull requests, commits, branches, users, and more.
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
https://api.maton.ai/github/{native-api-path}
Maton proxies requests to api.github.com and automatically injects your OAuth token.
NPM:
npm install -g @maton-ai/cli
Homebrew:
brew install maton-ai/cli/maton
CLI:
maton login # Opens browser for API key
maton login --interactive # Skip browser, paste API key directly
maton whoami # Show current auth state
Manual:
MATON_API_KEY:export MATON_API_KEY="YOUR_API_KEY"
Manage your GitHub OAuth connections at https://api.maton.ai.
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
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
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.
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
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.
GET /github/user
Example:
maton github whoami
GET /github/users/{username}
GET /github/users?since={user_id}&per_page=30
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
GET /github/orgs/{org}/repos?per_page=30
Example:
maton github repo list {org}
GET /github/repos/{owner}/{repo}
Example:
maton github repo view --repo {owner}/{repo}
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
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
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
GET /github/repos/{owner}/{repo}/contents/{path}
GET /github/repos/{owner}/{repo}/contents/{path}?ref={branch}
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 /github/repos/{owner}/{repo}/contents/{path}
Content-Type: application/json
{
"message": "Delete file",
"sha": "{file_sha}",
"branch": "main"
}
GET /github/repos/{owner}/{repo}/branches?per_page=30
GET /github/repos/{owner}/{repo}/branches/{branch}
POST /github/repos/{owner}/{repo}/branches/{branch}/rename
Content-Type: application/json
{
"new_name": "new-branch-name"
}
POST /github/repos/{owner}/{repo}/merges
Content-Type: application/json
{
"base": "main",
"head": "feature-branch",
"commit_message": "Merge feature branch"
}
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 /github/repos/{owner}/{repo}/commits/{ref}
GET /github/repos/{owner}/{repo}/compare/{base}...{head}
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 /github/repos/{owner}/{repo}/issues/{issue_number}
Example:
maton github issue view {issue_number} --repo {owner}/{repo}
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
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
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
DELETE /github/repos/{owner}/{repo}/issues/{issue_number}/lock
Example:
maton github issue unlock {issue_number} --repo {owner}/{repo}
GET /github/repos/{owner}/{repo}/issues/{issue_number}/comments?per_page=30
Example:
maton github issue view {issue_number} --repo {owner}/{repo} --comments
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"
PATCH /github/repos/{owner}/{repo}/issues/comments/{comment_id}
Content-Type: application/json
{
"body": "Updated comment"
}
DELETE /github/repos/{owner}/{repo}/issues/comments/{comment_id}
GET /github/repos/{owner}/{repo}/labels?per_page=30
Example:
maton github label list --repo {owner}/{repo}
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"
GET /github/repos/{owner}/{repo}/milestones?state=open&per_page=30
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"
}
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 /github/repos/{owner}/{repo}/pulls/{pull_number}
Example:
maton github pr view {pull_number} --repo {owner}/{repo}
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"
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"
GET /github/repos/{owner}/{repo}/pulls/{pull_number}/commits?per_page=30
GET /github/repos/{owner}/{repo}/pulls/{pull_number}/files?per_page=30
Example:
maton github pr diff {pull_number} --repo {owner}/{repo}
GET /github/repos/{owner}/{repo}/pulls/{pull_number}/merge
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
GET /github/repos/{owner}/{repo}/pulls/{pull_number}/reviews?per_page=30
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.
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+ starsExample:
maton github repo search tetris --language python
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 authorExample:
maton github issue search "bug" --state open
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 functionsNote: Code search may timeout on broad queries.
GET /github/search/users?q={query}&per_page=30
GET /github/user/orgs?per_page=30
Note: Requires read:org scope.
GET /github/orgs/{org}
GET /github/orgs/{org}/members?per_page=30
GET /github/rate_limit
GitHub uses page-based pagination. The CLI automatically paginates with '--paginate'.
Example:
maton github repo list --paginate
# 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'
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();
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()
read:org for 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-casecurl -g when URLs contain brackets to disable glob parsingjq or other commands, environment variables like $MATON_API_KEY may not expand correctly in some shell environments| 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 |
CLI:
maton whoami
maton connection list
Manual:
MATON_API_KEY environment variable is set:echo $MATON_API_KEY
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
github. For example:https://api.maton.ai/github/userhttps://api.maton.ai/api.github.com/user