mcpField
A
accessing-github-repos

accessing-github-repos

github.com/oaustegard開発15768 回インストール1 日前に更新
リポジトリ

accessing-github-repos について

git cloneがブロックされたコンテナ型AI環境でGitHubリポジトリにアクセスするスキルです。GitHub REST APIとrawファイルURLを使い、PATによるプライベートリポジトリへのアクセスや書き込みにも対応します。

主な機能

  1. 01raw URLまたはAPIでファイル取得
  2. 02リポジトリツリーの表示とアーカイブ取得
  3. 03環境変数やプロジェクトファイルからPATを検出
  4. 04ファイル、ブランチ、Issue、Pull Requestを作成
  5. 05PATを使ったプライベートリポジトリアクセス

活用シーン

  1. 01git cloneなしで公開リポジトリのファイルを読む
  2. 02PATでプライベートリポジトリにアクセス
  3. 03API経由でリポジトリのファイルを更新
  4. 04制限環境でIssue管理やPull Request作成

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/oaustegard/claude-skills --skill accessing-github-repos

インストール後、Claude Code で/accessing-github-reposを入力して読み込まれたか確認します。

同梱ファイルCHANGELOG.md

詳細

GitHub リポジトリへのアクセス

コンテナ化された AI 環境では Git clone がブロックされます(例:外向きプロキシが CONNECT トンネルを拒否します)が、GitHub REST API と raw ファイル URL を使えば、リポジトリに完全にアクセスできます。

クイックスタート

パブリックリポジトリ(設定不要)
# Individual file via raw URL
curl -sL "https://raw.githubusercontent.com/OWNER/REPO/BRANCH/path/file"

# Directory tree via API
curl -sL "https://api.github.com/repos/OWNER/REPO/git/trees/BRANCH?recursive=1"
プライベートリポジトリまたは書き込みアクセス

GitHub Personal Access Token(PAT)が必要です。以下のセットアップセクションを参照してください。

セットアップ

認証情報の設定

このスキルは、環境変数またはプロジェクトファイルから PAT を自動的に検出します。

環境変数(以下の順に確認):

  • GITHUB_PAT
  • GH_PAT
  • GITHUB_TOKEN
  • GH_TOKEN

プロジェクトファイル(Claude.ai):

  • /mnt/project/.env
  • /mnt/project/github.env

形式:

GITHUB_PAT=github_pat_11AAAAAA...
GitHub PAT の作成
  1. GitHub → Settings → Developer settings → Fine-grained tokens
  2. 必要なリポジトリを対象にトークンを作成します
  3. 権限を設定します:
    • Contents: Read - プライベートリポジトリへのアクセス用
    • Contents: Write - ファイルのプッシュ用
    • Issues: Write - Issue の管理用
    • Pull requests: Write - PR の作成用
ネットワークアクセス(Claude.ai Projects)

ネットワーク許可リストに追加します:

  • api.github.com
  • raw.githubusercontent.com

認証レベル別の機能

機能PAT なし(パブリックのみ)PAT(読み取り)PAT(書き込み)
パブリックファイルの取得✅✅✅
プライベートファイルの取得❌✅✅
tarball のダウンロード✅ パブリック✅✅
ファイルの作成/更新❌❌✅
ブランチの作成❌❌✅
Issue の管理❌❌✅
PR の作成❌❌✅

Python ヘルパー関数

認証情報の検出
import os

def get_github_auth():
    """Returns (token, source) or (None, None)"""
    # Check environment variables
    for var in ['GITHUB_PAT', 'GH_PAT', 'GITHUB_TOKEN', 'GH_TOKEN']:
        if token := os.environ.get(var):
            return token, var

    # Check project .env files
    env_paths = ['/mnt/project/.env', '/mnt/project/github.env']
    for path in env_paths:
        try:
            with open(path) as f:
                for line in f:
                    if '=' in line and not line.startswith('#'):
                        key, val = line.strip().split('=', 1)
                        if key in ['GITHUB_PAT', 'GH_PAT', 'GITHUB_TOKEN']:
                            return val.strip(), f'{path}:{key}'
        except FileNotFoundError:
            continue

    return None, None
単一ファイルの取得
import base64
import urllib.request
import json

def fetch_file(owner: str, repo: str, path: str, ref: str = 'main', token: str = None) -> str:
    """Fetch single file. Uses API if token provided, raw URL otherwise."""
    if token:
        # Use API (works for private repos)
        url = f'https://api.github.com/repos/{owner}/{repo}/contents/{path}?ref={ref}'
        req = urllib.request.Request(url, headers={
            'Authorization': f'Bearer {token}',
            'Accept': 'application/vnd.github+json'
        })
        with urllib.request.urlopen(req) as resp:
            data = json.load(resp)
            return base64.b64decode(data['content']).decode()
    else:
        # Use raw URL (public repos only)
        url = f'https://raw.githubusercontent.com/{owner}/{repo}/{ref}/{path}'
        with urllib.request.urlopen(url) as resp:
            return resp.read().decode()
リポジトリ tarball の取得
def fetch_repo_tarball(owner: str, repo: str, ref: str = 'main', token: str = None) -> bytes:
    """Download full repo as tarball. Requires token for private repos."""
    url = f'https://api.github.com/repos/{owner}/{repo}/tarball/{ref}'
    headers = {'Accept': 'application/vnd.github+json'}
    if token:
        headers['Authorization'] = f'Bearer {token}'

    req = urllib.request.Request(url, headers=headers)
    with urllib.request.urlopen(req) as resp:
        return resp.read()

# Usage:
tarball = fetch_repo_tarball('owner', 'repo', 'main', token)
with open('/tmp/repo.tar.gz', 'wb') as f:
    f.write(tarball)
# Extract: tar -xzf /tmp/repo.tar.gz
ファイルの作成または更新
def push_file(owner: str, repo: str, path: str, content: str,
              message: str, token: str, sha: str = None) -> dict:
    """Create/update file via API. Returns commit info.

    Args:
        sha: Required when updating existing file (get via contents API)
    """
    url = f'https://api.github.com/repos/{owner}/{repo}/contents/{path}'

    payload = {
        'message': message,
        'content': base64.b64encode(content.encode()).decode()
    }
    if sha:  # Update existing file
        payload['sha'] = sha

    req = urllib.request.Request(url,
        data=json.dumps(payload).encode(),
        headers={
            'Authorization': f'Bearer {token}',
            'Accept': 'application/vnd.github+json',
            'Content-Type': 'application/json'
        },
        method='PUT')

    with urllib.request.urlopen(req) as resp:
        return json.load(resp)
ファイル SHA の取得(更新用)
def get_file_sha(owner: str, repo: str, path: str, token: str, ref: str = 'main') -> str:
    """Get file SHA needed for updates."""
    url = f'https://api.github.com/repos/{owner}/{repo}/contents/{path}?ref={ref}'
    req = urllib.request.Request(url, headers={
        'Authorization': f'Bearer {token}',
        'Accept': 'application/vnd.github+json'
    })
    with urllib.request.urlopen(req) as resp:
        data = json.load(resp)
        return data['sha']

Bash の例

パブリックファイルの取得
curl -sL "https://raw.githubusercontent.com/owner/repo/main/path/file.py"
プライベートファイルの取得(PAT 使用)
curl -H "Authorization: Bearer $GITHUB_PAT" \
     -H "Accept: application/vnd.github+json" \
     "https://api.github.com/repos/owner/repo/contents/path/file.py" | \
     python3 -c "import sys,json,base64; print(base64.b64decode(json.load(sys.stdin)['content']).decode())"
リポジトリ tarball のダウンロード
# Public repo
curl -sL "https://api.github.com/repos/owner/repo/tarball/main" -o repo.tar.gz

# Private repo
curl -sL -H "Authorization: Bearer $GITHUB_PAT" \
     "https://api.github.com/repos/owner/repo/tarball/main" -o repo.tar.gz
tar -xzf repo.tar.gz
ファイルの作成/更新
# Encode content
CONTENT=$(cat file.txt | base64 -w0)

# Push (new file)
curl -X PUT \
     -H "Authorization: Bearer $GITHUB_PAT" \
     -H "Accept: application/vnd.github+json" \
     "https://api.github.com/repos/owner/repo/contents/path/file.txt" \
     -d "{\"message\":\"Add file\",\"content\":\"$CONTENT\"}"

# Push (update existing - need SHA first)
SHA=$(curl -s -H "Authorization: Bearer $GITHUB_PAT" \
           "https://api.github.com/repos/owner/repo/contents/path/file.txt" | \
           python3 -c "import sys,json; print(json.load(sys.stdin)['sha'])")

curl -X PUT \
     -H "Authorization: Bearer $GITHUB_PAT" \
     -H "Accept: application/vnd.github+json" \
     "https://api.github.com/repos/owner/repo/contents/path/file.txt" \
     -d "{\"message\":\"Update file\",\"content\":\"$CONTENT\",\"sha\":\"$SHA\"}"
ディレクトリツリーの一覧表示
curl -sL "https://api.github.com/repos/owner/repo/git/trees/main?recursive=1" | \
  python3 -c "import json, sys; [print(f['path']) for f in json.load(sys.stdin)['tree'] if f['type']=='blob']"

git clone が機能しない理由

コンテナの外向きプロキシは git プロトコルの操作をブロックします:

  • HTTPS clone:プロキシが CONNECT トンネルに対して 401 を返します
  • SSH:コンテナに ssh バイナリがありません
  • git:// protocol:DNS 解決がブロックされています

GitHub REST API は標準的な HTTPS を使用し、通常どおりプロキシ経由で通信します。

禁止事項

  • 絶対に git clone を試みないでください(時間の無駄であり、必ず失敗します)
  • git プロトコルが必要な回避策を絶対に提案しないでください
  • 別の git フラグや SSH URL で絶対に再試行しないでください
  • git submodules、git archive、その他の git プロトコル操作を絶対に推奨しないでください

レート制限

  • 認証済み:5,000 リクエスト/時間
  • 未認証:60 リクエスト/時間

大量に使用する場合は、必ず PAT を指定してください。

このスキルが適用されない場合

  • ネイティブの開発環境:Git に直接アクセスできるため、標準的な git コマンドを使用してください
  • ローカルマシン:git clone は通常どおり機能します
  • MCP GitHub サーバーがある環境:代わりに MCP ツールを使用してください

コメント