agentleFS
datalayerdatalayer/agent-codemode/skills/github/SKILL.md

github

Skill7 starsChanged 47 days agoBSD-3-ClauseView on GitHub

GitHub API toolkit for listing repositories, managing issues, pull requests, and interacting with GitHub resources. Requires a GITHUB_TOKEN environment variable for authentication.

  • Reads credentials

166 other projects use a version of this.

Adopted by

Most recently taken up by

Used with

Projects with it also use taskflow-inbox-triage, BlueBubbles and 10 more.

Other files people use alongside this one.

Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
  • AtomicBot-aiSkill

    taskflow-inbox-triage

    Also in 6 projects that use this

  • jiulingyunSkill

    BlueBubbles

    为Clawdbot构建或更新BlueBubbles外部通道插件(扩展包,REST发送/探测,webhook入站)。

    Also in 20 projects that use this

  • hkyutongSkill

    node-connect

    Diagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps. Use when QR/setup code/manual connect fails, local Wi-Fi works but VPS/tailnet does not, or errors mention pairing required, unauthorized, bootstrap token invalid or expired, gateway.bind, gateway.remote.url, Tailscale, or plugins.entries.device-pair.config.publicUrl.

    Also in 18 projects that use this

  • molt-botSkill

    discord-e2e

    Test Discord with Convex-leased QA bots: check credentials without a Gateway, exercise owned messages, or prove OpenClaw replies, files, threads, reactions, streaming, and typing. Distinguish API and Gateway evidence from manual user interactions.

    Also in 10 projects that use this

  • molt-botSkill

    openclaw-repair-sweep

    Run scoped OpenClaw issue/PR repair campaigns: coordinate workers, prove root causes, and land or close verified work under the requested authority.

    Also in 10 projects that use this

  • clawdbotSkill

    openclaw-performance

    Performance work in OpenClaw: a slow or heavy flow (latency, CPU, memory, SQL, RPC, renders), writing or reviewing a perf PR, or adding a cache. Count the work, delete waste first, cache last.

    Also in 7 projects that use this

  • +2 more from molt-bot
  • Other versions166 projects use a version of this.

    Word for word · 0

    None found.

    Edited · 0

    None found.

    Wrote their own version · 166

    1. moltbot/clawdbot★ 394ksame name
    2. steipete/warelay★ 394ksame name
    3. steipete/clawdis★ 394ksame name
    4. moltbot/moltbot★ 394ksame name
    5. clawdbot/clawdbot★ 394ksame name
    6. openclaw/openclaw★ 394ksame name
    7. molt-bot/clawdbot★ 391ksame name
    8. NousResearch/hermes-agent★ 262ksame name
    9. spinabot/brigade★ 11ksame name
    10. the-open-agent/openagent★ 5.7ksame name

    156 more not listed

    How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.

  • In this repository2 other files it gives its agents.

The file

We split this skill into the rules it gives an agent

10 rules. 0 are common, 6 are distinctive, and 4 are very specific to this project.

  • 0

    Common

    Most of the 151 edited versions we read keep these.

  • 6

    Distinctive

    This author's own choices. Worth a look.

  • 4

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    When connecting your GitHub account, ensure the following scopes are granted:

    line 36
  2. Very specific:

    If not using OAuth, you can set the GITHUB_TOKEN environment variable manually:

    line 44
  3. Distinctive:

    Check your rate limit status:

    line 345
  4. Very specific:

    Ensure GITHUB_TOKEN is set correctly

    line 405
  5. Distinctive:

    Check if the token has expired

    line 406
  6. Distinctive:

    Verify the token has required scopes

    line 407
  7. Distinctive:

    Verify you have access to the repository

    line 412
  8. Very specific:

    Wait for the rate limit to reset (check X-RateLimit-Reset header)

    line 416
  9. Very specific:

    Use conditional requests with If-None-Match header

    line 417
  10. Distinctive:

    Consider using GraphQL API for complex queries (higher limits)

    line 418

“Common” is measured: kept by at least 6 in 10 of the 151 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

GitHub API Guide

Overview

This skill provides tools to interact with the GitHub API using Python. It enables listing repositories (public and private), retrieving repository details, and more.

Authentication

OAuth Authentication (Recommended)

This skill uses GitHub OAuth authentication through the Datalayer identity system. When you connect your GitHub account via the "Connect GitHub" button in the agent configuration form, the OAuth token is automatically available to this skill.

How it works:

  1. Click the GitHub connect button in the Agent Configuration form
  2. Complete the OAuth authorization flow
  3. Your GitHub access token is securely stored and automatically provided to skill scripts

The token is retrieved from the identity store and made available as the GITHUB_TOKEN environment variable when scripts are executed.

Required OAuth Scopes

When connecting your GitHub account, ensure the following scopes are granted:

  • repo - Full control of private repositories (required for private repos)
  • read:user - Read user profile data
  • read:org - Read organization data (if listing org repos)

Manual Token (Fallback)

If not using OAuth, you can set the GITHUB_TOKEN environment variable manually:

export GITHUB_TOKEN="ghp_your_token_here"

To create a Personal Access Token:

  1. Go to GitHub Settings > Developer settings > Personal access tokens
  2. Click "Generate new token" (classic)
  3. Select the scopes listed above
  4. Generate and copy the token

Token Permissions

ScopeDescriptionRequired For
repoFull control of private repositoriesPrivate repos, creating issues/PRs
public_repoAccess public repositories onlyPublic repos only (limited)
read:userRead user profile dataUser information
read:orgRead org membershipOrganization repos

Note: The OAuth flow requests repo, read:user, and read:org scopes by default.

Quick Start

import os
import httpx

token = os.environ.get("GITHUB_TOKEN")
headers = {
    "Authorization": f"Bearer {token}",
    "Accept": "application/vnd.github+json",
    "X-GitHub-Api-Version": "2022-11-28",
}

# List your repositories
response = httpx.get(
    "https://api.github.com/user/repos",
    headers=headers,
    params={"per_page": 100, "type": "all"},
)
repos = response.json()

for repo in repos:
    visibility = "🔒" if repo["private"] else "🌐"
    print(f"{visibility} {repo['full_name']}")

Python Libraries

httpx - GitHub API Client

List All User Repositories

import os
import httpx

def get_github_headers() -> dict:
    """Get headers for GitHub API requests."""
    token = os.environ.get("GITHUB_TOKEN")
    if not token:
        raise ValueError("GITHUB_TOKEN environment variable is required")
    return {
        "Authorization": f"Bearer {token}",
        "Accept": "application/vnd.github+json",
        "X-GitHub-Api-Version": "2022-11-28",
    }

def list_repos(
    visibility: str = "all",
    sort: str = "updated",
    per_page: int = 100,
) -> list[dict]:
    """List repositories for the authenticated user.

    Args:
        visibility: Filter by visibility - 'all', 'public', or 'private'
        sort: Sort by 'created', 'updated', 'pushed', or 'full_name'
        per_page: Number of results per page (max 100)

    Returns:
        List of repository dictionaries.
    """
    headers = get_github_headers()
    repos = []
    page = 1

    while True:
        response = httpx.get(
            "https://api.github.com/user/repos",
            headers=headers,
            params={
                "visibility": visibility,
                "sort": sort,
                "per_page": per_page,
                "page": page,
            },
            timeout=30.0,
        )
        response.raise_for_status()
        page_repos = response.json()

        if not page_repos:
            break

        repos.extend(page_repos)
        page += 1

    return repos

Get Repository Details

def get_repo(owner: str, repo: str) -> dict:
    """Get details for a specific repository.

    Args:
        owner: Repository owner (username or organization)
        repo: Repository name

    Returns:
        Repository details dictionary.
    """
    headers = get_github_headers()
    response = httpx.get(
        f"https://api.github.com/repos/{owner}/{repo}",
        headers=headers,
        timeout=30.0,
    )
    response.raise_for_status()
    return response.json()

List Organization Repositories

def list_org_repos(org: str, type: str = "all") -> list[dict]:
    """List repositories for an organization.

    Args:
        org: Organization name
        type: Filter by type - 'all', 'public', 'private', 'forks', 'sources', 'member'

    Returns:
        List of repository dictionaries.
    """
    headers = get_github_headers()
    repos = []
    page = 1

    while True:
        response = httpx.get(
            f"https://api.github.com/orgs/{org}/repos",
            headers=headers,
            params={"type": type, "per_page": 100, "page": page},
            timeout=30.0,
        )
        response.raise_for_status()
        page_repos = response.json()

        if not page_repos:
            break

        repos.extend(page_repos)
        page += 1

    return repos

Working with Issues

List Repository Issues

def list_issues(owner: str, repo: str, state: str = "open") -> list[dict]:
    """List issues for a repository.

    Args:
        owner: Repository owner
        repo: Repository name
        state: Issue state - 'open', 'closed', or 'all'

    Returns:
        List of issue dictionaries.
    """
    headers = get_github_headers()
    response = httpx.get(
        f"https://api.github.com/repos/{owner}/{repo}/issues",
        headers=headers,
        params={"state": state, "per_page": 100},
        timeout=30.0,
    )
    response.raise_for_status()
    return response.json()

Create an Issue

def create_issue(
    owner: str,
    repo: str,
    title: str,
    body: str = "",
    labels: list[str] = None,
) -> dict:
    """Create a new issue.

    Args:
        owner: Repository owner
        repo: Repository name
        title: Issue title
        body: Issue body (markdown)
        labels: List of label names

    Returns:
        Created issue dictionary.
    """
    headers = get_github_headers()
    data = {"title": title, "body": body}
    if labels:
        data["labels"] = labels

    response = httpx.post(
        f"https://api.github.com/repos/{owner}/{repo}/issues",
        headers=headers,
        json=data,
        timeout=30.0,
    )
    response.raise_for_status()
    return response.json()

Working with Pull Requests

List Pull Requests

def list_pull_requests(
    owner: str,
    repo: str,
    state: str = "open",
) -> list[dict]:
    """List pull requests for a repository.

    Args:
        owner: Repository owner
        repo: Repository name
        state: PR state - 'open', 'closed', or 'all'

    Returns:
        List of pull request dictionaries.
    """
    headers = get_github_headers()
    response = httpx.get(
        f"https://api.github.com/repos/{owner}/{repo}/pulls",
        headers=headers,
        params={"state": state, "per_page": 100},
        timeout=30.0,
    )
    response.raise_for_status()
    return response.json()

Error Handling

import httpx

def safe_github_request(url: str, headers: dict) -> dict | None:
    """Make a GitHub API request with error handling."""
    try:
        response = httpx.get(url, headers=headers, timeout=30.0)
        response.raise_for_status()
        return response.json()
    except httpx.HTTPStatusError as e:
        if e.response.status_code == 401:
            print("Error: Invalid or expired GITHUB_TOKEN")
        elif e.response.status_code == 403:
            print("Error: Rate limit exceeded or insufficient permissions")
        elif e.response.status_code == 404:
            print("Error: Resource not found")
        else:
            print(f"HTTP error: {e.response.status_code}")
        return None
    except httpx.RequestError as e:
        print(f"Request failed: {e}")
        return None

Rate Limiting

GitHub API has rate limits:

  • Authenticated requests: 5,000 requests per hour
  • Unauthenticated requests: 60 requests per hour

Check your rate limit status:

def check_rate_limit() -> dict:
    """Check GitHub API rate limit status."""
    headers = get_github_headers()
    response = httpx.get(
        "https://api.github.com/rate_limit",
        headers=headers,
        timeout=30.0,
    )
    response.raise_for_status()
    return response.json()

Common Patterns

Filter Repositories by Language

def list_repos_by_language(language: str) -> list[dict]:
    """List user repositories filtered by primary language."""
    repos = list_repos()
    return [r for r in repos if r.get("language") == language]

Get Recent Activity

def get_recent_repos(days: int = 30) -> list[dict]:
    """Get repositories updated in the last N days."""
    from datetime import datetime, timedelta

    cutoff = datetime.now() - timedelta(days=days)
    repos = list_repos(sort="updated")

    recent = []
    for repo in repos:
        updated = datetime.fromisoformat(repo["updated_at"].replace("Z", "+00:00"))
        if updated.replace(tzinfo=None) > cutoff:
            recent.append(repo)
    return recent

Scripts

This skill includes the following executable scripts in the scripts/ directory:

ScriptDescriptionUsage
list_repos.pyList all repositories for the authenticated userpython list_repos.py [--visibility all|public|private] [--format table|json]
get_repo.pyGet details for a specific repositorypython get_repo.py <owner>/<repo>
list_issues.pyList issues for a repositorypython list_issues.py <owner>/<repo> [--state open|closed|all]
list_prs.pyList pull requests for a repositorypython list_prs.py <owner>/<repo> [--state open|closed|all]
search_repos.pySearch GitHub repositoriespython search_repos.py <query> [--language python]

Troubleshooting

"Bad credentials" Error

  • Ensure GITHUB_TOKEN is set correctly
  • Check if the token has expired
  • Verify the token has required scopes

"Not Found" Error for Private Repos

  • The token needs repo scope for private repository access
  • Verify you have access to the repository

Rate Limit Exceeded

  • Wait for the rate limit to reset (check X-RateLimit-Reset header)
  • Use conditional requests with If-None-Match header
  • Consider using GraphQL API for complex queries (higher limits)

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

Reviews can't be read right now.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.