invoking-github — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited invoking-github (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Programmatically interact with GitHub repositories from Claude.ai chat: read files, commit changes, create PRs, and persist state across sessions.
Primary use cases:
Trigger patterns:
Not needed for:
Create a GitHub Personal Access Token and add to Project Knowledge:
repo (or public_repo for public repos only)GITHUB_API_KEYghp_abc123...)from invoking_github import commit_file
result = commit_file(
repo="username/repo-name",
path="README.md",
content="# Updated README\n\nNew content here...",
branch="main",
message="Update README with new instructions"
)
print(f"Committed: {result['commit_sha']}")from invoking_github import read_file
content = read_file(
repo="username/repo-name",
path="config.json",
branch="main"
)
print(content)from invoking_github import commit_files
files = [
{"path": "src/main.py", "content": "# Python code..."},
{"path": "README.md", "content": "# Updated docs..."},
{"path": "tests/test.py", "content": "# Tests..."}
]
result = commit_files(
repo="username/repo-name",
files=files,
branch="feature-branch",
message="Add new feature implementation",
create_branch_from="main" # Create branch if it doesn't exist
)
print(f"Committed {len(files)} files: {result['commit_sha']}")from invoking_github import create_pull_request
pr = create_pull_request(
repo="username/repo-name",
head="feature-branch",
base="main",
title="Add new feature",
body="## Changes\n- Implemented feature X\n- Updated docs\n- Added tests"
)
print(f"PR created: {pr['html_url']}")read_file()Read a file from repository:
read_file(
repo: str, # "owner/name"
path: str, # "path/to/file.py"
branch: str = "main" # Branch name
) -> strReturns: File content as string Raises: GitHubAPIError if file not found or access denied
commit_file()Commit a single file (create or update):
commit_file(
repo: str, # "owner/name"
path: str, # "path/to/file.py"
content: str, # New file content
branch: str, # Target branch
message: str, # Commit message
create_branch_from: str = None # Create branch from this if doesn't exist
) -> dictReturns: Dict with commit_sha, branch, file_path Raises: GitHubAPIError on conflicts or auth failures
commit_files()Commit multiple files in a single commit:
commit_files(
repo: str, # "owner/name"
files: list[dict], # [{"path": "...", "content": "..."}]
branch: str, # Target branch
message: str, # Commit message
create_branch_from: str = None # Create branch from this if doesn't exist
) -> dictReturns: Dict with commit_sha, branch, files_committed Raises: GitHubAPIError on failures
Note: Uses Git Trees API for efficiency - atomic commit of all files.
create_pull_request()Create a pull request:
create_pull_request(
repo: str, # "owner/name"
head: str, # Source branch (your changes)
base: str, # Target branch (where to merge)
title: str, # PR title
body: str = "" # PR description (supports markdown)
) -> dictReturns: Dict with number, html_url, state Raises: GitHubAPIError if branches invalid or PR exists
This skill requires a GitHub Personal Access Token. Two configuration methods:
Best for Claude.ai chat users (mobile/web):
GITHUB_API_KEYPermissions required:
repo scopeAlternatively, use combined credentials file:
API_CREDENTIALS.json in project knowledge{"github_api_key": "ghp_your-token-here"}Auto-persist DEVLOG.md to GitHub for cross-session continuity:
# In your DEVLOG update function
from invoking_github import commit_file
from pathlib import Path
def update_devlog_with_sync(data, repo="user/project", branch="devlog"):
"""Update DEVLOG.md locally and sync to GitHub"""
# Update local DEVLOG
update_devlog(data) # Your existing function
# Auto-sync to GitHub
try:
devlog_content = Path("DEVLOG.md").read_text()
result = commit_file(
repo=repo,
path="DEVLOG.md",
content=devlog_content,
branch=branch,
message=f"DEVLOG: {data['title']}",
create_branch_from="main"
)
print(f"✓ DEVLOG synced to GitHub ({repo}:{branch})")
return result
except Exception as e:
print(f"⚠ DEVLOG sync failed: {e}")
# Continue anyway - local DEVLOG.md still updated
return NoneBenefits:
See references/iterating-integration.md for complete patterns.
All functions raise GitHubAPIError with descriptive messages:
from invoking_github import commit_file, GitHubAPIError
try:
result = commit_file(
repo="user/repo",
path="file.py",
content="...",
branch="main",
message="Update"
)
except GitHubAPIError as e:
if e.status_code == 404:
print("Repository or branch not found")
elif e.status_code == 401:
print("Authentication failed - check your token")
elif e.status_code == 403:
print("Access denied - check token permissions")
elif e.status_code == 409:
print("Conflict - file was modified since last read")
else:
print(f"GitHub API error: {e}")Common errors:
commit_files() for related changescreate_branch_from="main" parameterOnly commit if file content changed:
from invoking_github import read_file, commit_file, GitHubAPIError
try:
current_content = read_file(repo, path, branch)
if current_content != new_content:
commit_file(repo, path, new_content, branch, "Update file")
else:
print("No changes detected, skipping commit")
except GitHubAPIError as e:
if e.status_code == 404:
# File doesn't exist, create it
commit_file(repo, path, new_content, branch, "Create file")
else:
raiseAvoid conflicts with unique branch names:
import datetime
session_id = datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
branch_name = f"devlog-{session_id}"
commit_file(
repo="user/project",
path="DEVLOG.md",
content=devlog_content,
branch=branch_name,
message="Session progress",
create_branch_from="main"
)Work across multiple repos:
repos = ["user/frontend", "user/backend", "user/docs"]
for repo in repos:
commit_file(
repo=repo,
path="VERSION",
content="2.0.0\n",
branch="release-2.0",
message="Bump version to 2.0.0"
)This skill uses ~800 tokens when loaded but provides essential GitHub operations for claude.ai chat environments where native git access isn't available. Enables persistent state management and cross-session workflows.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.