作者:互联网 时间: 2026-07-30 10:30:01
Openclaw Skills 的 GitHub 技能使开发人员和 AI 代理能够直接与 GitHub REST API 交互,而无需手动管理复杂的 OAuth 流程。通过安全网关代理请求,此技能可以无缝管理版本控制资产、团队协作工具和仓库数据。
此集成是构建自动化编码工作流、智能仓库助手或自定义 CI/CD 工具的重要组件。它处理了身份验证的繁重工作,让您可以专注于使用标准 HTTP 请求构建与庞大 GitHub 生态系统交互的功能。
下载入口:https://github.com/openclaw/skills/tree/main/skills/byungkyu/github-api
从源直接安装技能的最快方式。
npx clawhub@latest install github-api
将技能文件夹复制到以下位置之一
全局模式~/.openclaw/skills/
工作区
<project>/skills/
优先级:工作区 > 本地 > 内置
将此提示词复制到 OpenClaw 即可自动安装。
请帮我使用 Clawhub 安装 github-api。如果尚未安装 Clawhub,请先安装(npm i -g clawhub)。
要开始使用 Openclaw Skills 的这项技能,请按照以下步骤操作:
export MATON_API_KEY="YOUR_API_KEY"
curl -X POST https://ctrl.maton.ai/connections r
-H "Authorization: Bearer $MATON_API_KEY" r
-H "Content-Type: application/json" r
-d '{"app": "github"}'
url,以在 GitHub 上授权该应用程序。curl https://gateway.maton.ai/github/user r
-H "Authorization: Bearer $MATON_API_KEY"
该技能使用标准 GitHub REST API 模式组织数据。响应以 JSON 格式提供,通常遵循以下结构:
| 资源 | 描述 | 常用字段 |
|---|---|---|
| Repositories | 代码项目的元数据 | name, full_name, private, owner, html_url |
| Issues | 任务跟踪项 | number, title, state, labels, assignee |
| Pull Requests | 代码合并提案 | title, state, merged, head, base |
| Contents | 文件和目录数据 | path, sha, size, content (Base64) |
| Search Results | 分页查询匹配项 | total_count, items, score |
注意:创建或更新文件时,根据 GitHub 的要求,content 字段必须经过 Base64 编码。
name: github
description: |
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 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).
compatibility: Requires network access and valid Maton API key
metadata:
author: maton
version: "1.0"
clawdbot:
emoji: ??
requires:
env:
- MATON_API_KEY
Access the GitHub REST API with managed OAuth authentication. Manage repositories, issues, pull requests, commits, branches, users, and more.
# Get authenticated user
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/github/user')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
https://gateway.maton.ai/github/{native-api-path}
Replace {native-api-path} with the actual GitHub API endpoint path. The gateway proxies requests to api.github.com and automatically injects your OAuth token.
All requests require the Maton API key in the Authorization header:
Authorization: Bearer $MATON_API_KEY
Environment Variable: Set your API key as MATON_API_KEY:
export MATON_API_KEY="YOUR_API_KEY"
Manage your GitHub OAuth connections at https://ctrl.maton.ai.
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.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
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'github'}).encode()
req = urllib.request.Request('https://ctrl.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
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.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
Response:
{
"connection": {
"connection_id": "83e7c665-60f6-4a64-816c-5e287ea8982f",
"status": "ACTIVE",
"creation_time": "2026-02-06T03:00:43.860014Z",
"last_updated_time": "2026-02-06T03:01:06.027323Z",
"url": "https://connect.maton.ai/?session_token=...",
"app": "github",
"metadata": {}
}
}
Open the returned url in a browser to complete OAuth authorization.
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.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 with the Maton-Connection header:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/github/user')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Maton-Connection', '83e7c665-60f6-4a64-816c-5e287ea8982f')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
If omitted, the gateway uses the default (oldest) active connection.
GET /github/user
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
GET /github/orgs/{org}/repos?per_page=30
GET /github/repos/{owner}/{repo}
POST /github/user/repos
Content-Type: application/json
{
"name": "my-new-repo",
"description": "A new repository",
"private": true,
"auto_init": true
}
POST /github/orgs/{org}/repos
Content-Type: application/json
{
"name": "my-new-repo",
"description": "A new repository",
"private": true
}
PATCH /github/repos/{owner}/{repo}
Content-Type: application/json
{
"description": "Updated description",
"has_issues": true,
"has_wiki": false
}
DELETE /github/repos/{owner}/{repo}
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
GET /github/repos/{owner}/{repo}/issues/{issue_number}
POST /github/repos/{owner}/{repo}/issues
Content-Type: application/json
{
"title": "Found a bug",
"body": "Bug description here",
"labels": ["bug"],
"assignees": ["username"]
}
PATCH /github/repos/{owner}/{repo}/issues/{issue_number}
Content-Type: application/json
{
"state": "closed",
"state_reason": "completed"
}
PUT /github/repos/{owner}/{repo}/issues/{issue_number}/lock
Content-Type: application/json
{
"lock_reason": "resolved"
}
DELETE /github/repos/{owner}/{repo}/issues/{issue_number}/lock
GET /github/repos/{owner}/{repo}/issues/{issue_number}/comments?per_page=30
POST /github/repos/{owner}/{repo}/issues/{issue_number}/comments
Content-Type: application/json
{
"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
POST /github/repos/{owner}/{repo}/labels
Content-Type: application/json
{
"name": "priority:high",
"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
GET /github/repos/{owner}/{repo}/pulls/{pull_number}
POST /github/repos/{owner}/{repo}/pulls
Content-Type: application/json
{
"title": "New feature",
"body": "Description of changes",
"head": "feature-branch",
"base": "main",
"draft": false
}
PATCH /github/repos/{owner}/{repo}/pulls/{pull_number}
Content-Type: application/json
{
"title": "Updated title",
"state": "closed"
}
GET /github/repos/{owner}/{repo}/pulls/{pull_number}/commits?per_page=30
GET /github/repos/{owner}/{repo}/pulls/{pull_number}/files?per_page=30
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
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
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+ starsGET /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 authorGET /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
Response:
{
"rate": {
"limit": 5000,
"remaining": 4979,
"reset": 1707200000
},
"resources": {
"core": { "limit": 5000, "remaining": 4979 },
"search": { "limit": 30, "remaining": 28 }
}
}
GitHub uses page-based and link-based pagination:
GET /github/repos/{owner}/{repo}/issues?per_page=30&page=2
Response headers include pagination links:
Link: <url>; rel="next", <url>; rel="last"Common pagination parameters:
per_page: Results per page (max 100, default 30)page: Page number (default 1)Some endpoints use cursor-based pagination with since parameter (e.g., listing users).
const response = await fetch(
'https://gateway.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://gateway.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 [email protected] 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 |
MATON_API_KEY environment variable is set:echo $MATON_API_KEY
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.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://gateway.maton.ai/github/userhttps://gateway.maton.ai/api.github.com/user