Install
$ agentstack add skill-atypical-consulting-githubskills-ghs-profile ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
GitHub Profile Viewer
Display a full 360-degree view of a GitHub user: profile, repos, contributions, open work, orgs, and activity.
References:
- ../shared/references/gh-cli-patterns.md
- ../shared/references/output-conventions.md
- ../shared/references/ui-brand.md
- ../shared/references/argument-parsing.md
Purpose: Read-only profile renderer that fetches and displays GitHub user data via the gh CLI.
Roles:
- Profile Renderer (you) — fetches user data via gh CLI, formats the display, suggests next actions
No sub-agents — this is a read-only skill that renders API data.
Shared References
| Reference | Path | Purpose | |-----------|------|---------| | GH CLI Patterns | ../shared/references/gh-cli-patterns.md | Auth checks, API calls, error handling (404/403) | | Output Conventions | ../shared/references/output-conventions.md | Status indicators, progress bars, table patterns |
Anti-Patterns
| Do NOT | Do Instead | Why | |--------|-----------|-----| | Use raw curl to api.github.com | Use gh api for all GitHub API calls | gh api handles auth and rate limits automatically | | Use GraphQL $variables in shell commands | Inline values directly in the query | $var gets eaten by the shell and String! triggers zsh history expansion | | Run all API calls in one parallel batch | Split into 2-3 batches | A GraphQL failure can cascade-cancel REST calls | | Fail hard when viewing another user's private data | Set ISVIEWER flag; show [INFO] for non-@me targets | Private data is expected to be unavailable for other users | | Show all repositories in the terminal | Cap at top 5 by stars; note total count | Terminal output becomes unreadable with too many repos | | Show absolute timestamps for events | Use relative timestamps (e.g., "2d ago") or short dates (YYYY-MM-DD) | Relative times are more scannable | | Paginate through all events | Fetch first page only (up to 30), slice to 10 with --jq '.[:10]' | Avoids unnecessary API calls and output bloat | | Call viewer GraphQL queries for other users | Gate contribution stats and review requests behind ISVIEWER flag | viewer queries only work for the authenticated user | | Render rows for null/empty profile fields | Only render non-null fields — skip empty rows | Empty rows add noise without information |
Display a comprehensive GitHub profile report with the following sections:
- Profile Header — username, name, bio, company, location, blog, member since, follower/following counts
- Repository Portfolio — top 5 repos by stars, language breakdown, fork ratio, popular topics
- Pinned Repositories — up to 6 pinned repos (if any)
- Contribution Stats — commits, PRs, issues, reviews for current year (IS_VIEWER only)
- Open Work — open PRs authored, issues assigned, review requests (IS_VIEWER only)
- Organizations — org memberships with descriptions
- Recent Activity — last 10 public events
- Next Steps — routing suggestions to other skills
Next routing:
- Suggest
/ghs-repo-scan {user}/{top-repo}to scan the user's top repository - Suggest
/ghs-issue-triage {user}/{repo}if the user has repos with open issues - Suggest
/ghs-backlog-boardfor cross-repo overview
No prerequisites.
Input
Optional argument: a GitHub username (e.g., phmatray, torvalds).
- If no username provided, default to the authenticated user (
@me) - Accept formats:
username,@username,@me
Phase 1 — Auth & User Resolution
- Verify authentication:
``bash gh auth status ` If this fails, tell the user to run gh auth login` and stop.
- Resolve the authenticated user's login:
``bash gh api user --jq '.login' ``
- Determine the target user:
- If no argument or
@me: target = authenticated user - If a username is provided: target = that username
- Set the IS_VIEWER flag:
IS_VIEWER = truewhen target login matches the authenticated user's loginIS_VIEWER = falseotherwise
> Rule: Always set ISVIEWER before making any data calls. > > Trigger: Every invocation — needed to decide which queries to run. > > Example: User says "show profile for torvalds" → target = torvalds, ISVIEWER = false → skip contribution stats and review requests.
API Call Batching Strategy
Split API calls into batches to prevent a single failure from cascading and cancelling all sibling calls:
| Batch | Calls | Why separate | |-------|-------|-------------| | Batch 1 (Phase 1) | gh auth status, gh api user | Must complete before anything else — sets IS_VIEWER flag | | Batch 2 (Phases 2-4) | Profile data, repo list, pinned repos (GraphQL), contribution stats (GraphQL) | Can run in parallel; GraphQL calls may fail but REST calls should survive | | Batch 3 (Phases 6-8) | Open PRs, assigned issues, review requests, orgs, events | All REST calls — safe to parallelize |
If a GraphQL call fails in Batch 2, show a [WARN] for that section and continue — do not retry or re-run the entire batch.
Phase 2 — Profile Data
Fetch the user's profile information:
# For @me (IS_VIEWER = true)
gh api user --jq '{login, name, bio, company, location, blog, twitter_username, followers, following, public_repos, public_gists, created_at}'
# For other users (IS_VIEWER = false)
gh api users/{username} --jq '{login, name, bio, company, location, blog, twitter_username, followers, following, public_repos, public_gists, created_at, type}'
Render the profile header. Only include non-null, non-empty fields:
## GitHub Profile: @{username}
{username} ({name})
Bio: {bio}
Company: {company}
Location: {location}
Blog: {blog}
Twitter: @{twitter_username}
Member since: {YYYY-MM-DD} ({N} years)
Followers: {N} | Following: {N} | Public repos: {N} | Gists: {N}
https://github.com/{username}
Phase 3 — Repository Portfolio
Fetch the user's repositories (up to 30 for analysis, display top 5):
gh repo list {username} --limit 30 --json name,nameWithOwner,description,stargazerCount,forkCount,primaryLanguage,isFork,isArchived,updatedAt --jq 'sort_by(-.stargazerCount)'
Top Repos by Stars
Display the top 5 non-fork, non-archived repos sorted by stars:
### Repository Portfolio — {total_count} public repos
Top by Stars:
★ {N} {owner}/{repo} — {description}
★ {N} {owner}/{repo} — {description}
...
If total repos > 5, add: ... and {N} more repos
Language Breakdown
Aggregate primaryLanguage across all fetched repos. Display as a 16-char bar:
Language Breakdown:
C#: ████████░░░░░░░░ {N} repos ({pct}%)
TypeScript: ████░░░░░░░░░░░░ {N} repos ({pct}%)
Python: ██░░░░░░░░░░░░░░ {N} repos ({pct}%)
...
Bar width: 16 characters. Filled: █ (U+2588). Empty: ░ (U+2591). Show top 5 languages.
Additional Stats
Forks: {N} of {total} repos are forks ({pct}%)
Archived: {N} repos archived
Only show fork/archived lines if count > 0.
Phase 4 — Pinned Repositories
Fetch pinned repos via GraphQL. Inline the username directly in the query — do NOT use GraphQL $variables because $ gets eaten by the shell and String! triggers zsh history expansion:
gh api graphql -f query='{ user(login: "{username}") { pinnedItems(first: 6, types: REPOSITORY) { nodes { ... on Repository { nameWithOwner description stargazerCount primaryLanguage { name } } } } } }' --jq '.data.user.pinnedItems.nodes'
Display if any pinned repos exist:
### Pinned Repositories
1. {owner}/{repo} ★ {N} — {description} ({lang})
2. {owner}/{repo} ★ {N} — {description} ({lang})
...
If no pinned repos, skip this section entirely (do not show an empty heading).
Phase 5 — Contribution Stats (IS_VIEWER only)
> Rule: Only fetch contribution stats when ISVIEWER = true. > > Trigger: Target user is the authenticated user. > > Example: ISVIEWER = false → display [INFO] Contribution stats are only available for the authenticated user (@me) and skip this phase.
gh api graphql -f query='{ viewer { contributionsCollection { totalCommitContributions totalPullRequestContributions totalIssueContributions totalPullRequestReviewContributions restrictedContributionsCount } } }' --jq '.data.viewer.contributionsCollection'
Display with relative progress bars (largest value gets full 16-char bar, others scale proportionally):
### Contribution Stats — {year}
Commits: ████████████████ {N}
PRs: ████████░░░░░░░░ {N}
Issues: ████░░░░░░░░░░░░ {N}
Reviews: ██░░░░░░░░░░░░░░ {N}
If all values are 0, show: No contributions recorded for {year} yet.
Phase 6 — Open Work (IS_VIEWER only)
> Rule: Only fetch open work when IS_VIEWER = true. > > Trigger: Target user is the authenticated user.
Open PRs Authored
gh search prs --author=@me --state=open --json number,title,repository,createdAt --limit 10
Issues Assigned
gh search issues --assignee=@me --state=open --json number,title,repository,createdAt --limit 10
Review Requests
gh search prs --review-requested=@me --state=open --json number,title,repository --limit 10
Display:
### Open Work
Open PRs authored ({N}):
[OPEN] #{N} {title} {repo} ({age})
...
Issues assigned ({N}):
[OPEN] #{N} {title} {repo} ({age})
...
Review requests ({N}):
[OPEN] #{N} {title} {repo}
...
If IS_VIEWER = false, display:
### Open Work
[INFO] Open work details are only available for the authenticated user (@me)
Phase 7 — Organizations
# For @me
gh api user/orgs --jq '.[] | {login, description}'
# For other users
gh api users/{username}/orgs --jq '.[] | {login, description}'
Display:
### Organizations ({N})
@{org} — {description}
@{org} — {description}
...
If no organizations, show: No public organization memberships.
Phase 8 — Recent Activity
Fetch the last 10 public events (first page only, no pagination):
gh api users/{username}/events --jq '[.[:10][] | {type, repo: .repo.name, created_at}]'
Display:
### Recent Activity (last 10 events)
{date} {EventType} {repo} {summary}
{date} PushEvent user/repo pushed {N} commits
{date} CreateEvent user/repo created branch {ref}
{date} IssuesEvent user/repo opened issue #{N}
{date} PullRequestEvent user/repo opened PR #{N}
{date} WatchEvent user/repo starred
{date} ForkEvent user/repo forked to user/fork
...
Event Type Summaries
| Event Type | Summary Format | |-----------|---------------| | PushEvent | pushed {size} commits | | CreateEvent | created {ref_type} {ref} | | DeleteEvent | deleted {ref_type} {ref} | | IssuesEvent | {action} issue #{number} | | PullRequestEvent | {action} PR #{number} | | WatchEvent | starred | | ForkEvent | forked to {forkee} | | IssueCommentEvent | commented on #{number} | | ReleaseEvent | released {tag_name} | | Other | {type} (raw event type) |
If no events found, show: No recent public activity.
Phase 9 — Render Report & Next Steps
Assemble all sections from Phases 2–8 into the final report. Then add routing suggestions:
---
### Next Steps
/ghs-repo-scan {username}/{top-repo} — scan the top repository for health issues
/ghs-backlog-board — view backlog dashboard across all audited repos
If IS_VIEWER = true, also suggest:
/ghs-issue-triage {username}/{top-repo} — triage issues on the top repository
Edge Cases
| Scenario | Behavior | |----------|----------| | User not found (404) | [FAIL] User "{username}" not found on GitHub. — stop gracefully | | Bot/org account (type: "Bot" or type: "Organization") | [INFO] @{username} is a {type} account. — show available data, skip contribution stats | | No pinned repos | Skip the Pinned Repositories section entirely | | No public repos | Show No public repositories. in the portfolio section | | Rate limit hit (403/429) | [WARN] GitHub API rate limit reached. Try again in a few minutes. — show whatever data was already fetched | | Null profile fields (bio, company, twitter, blog) | Skip those rows — do not render empty lines | | GraphQL errors for pinned repos | [WARN] Could not fetch pinned repositories. — continue with other sections |
Troubleshooting
| Problem | Cause | Fix | |---------|-------|-----| | gh auth status fails | Not logged in | Run gh auth login | | Contribution stats show [INFO] for @me | IS_VIEWER flag not set correctly | Ensure the target matches gh api user --jq '.login' | | Recent activity is empty | User has no public events | Normal for private-only users — show informational message | | Organizations list is empty | User has no public org memberships, or orgs are hidden | Show No public organization memberships. | | Pinned repos query fails | User may have no pinned items, or GraphQL permission issue | Show [WARN] and continue |
Routing Suggestions
| After ghs-profile | Suggest | |-------------------|---------| | User viewed own profile | /ghs-repo-scan {user}/{top-repo}, /ghs-issue-triage, /ghs-backlog-board | | User viewed another profile | /ghs-repo-scan {user}/{top-repo}, /ghs-backlog-board | | User says "scan that repo" | Invoke /ghs-repo-scan {user}/{repo} | | User says "triage my issues" | Invoke /ghs-issue-triage |
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: Atypical-Consulting
- Source: Atypical-Consulting/GitHubSkills
- License: MIT
- Homepage: https://atypical-consulting.github.io/GitHubSkills/
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.