Agent skill

Portfolio Auto

by EliasOulkadi in EliasOulkadi/shokunin

Auto-sync GitHub repos to portfolio website. An agent skill from EliasOulkadi/shokunin.

MITAuto-check passedTesting & QA

Install Portfolio Auto

skills CLI
$ npx skills add EliasOulkadi/shokunin --skill portfolio-auto -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install EliasOulkadi/shokunin portfolio-auto --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/EliasOulkadi/shokunin.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.pack/skills/portfolio-auto .claude/skills/portfolio-auto && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
portfolio-auto
GitHub stars
114
Token cost
~2.6k tokens
SKILL.md length
891 words
Files
1
Skills in repo
49
Repo updated
First seen
Licence
MIT

At a glance

Auto-sync GitHub repos to portfolio website. An agent skill from EliasOulkadi/shokunin.

  • Works in 7 steps: Gather configuration → Fetch repos via GitHub API → Detect changes → …
  • User asks to update portfolio
  • SKILL.md covers Workflow, Notes, Error Handling and GitHub API Patterns, plus 3 more sections
  • Calls npx; reaches api.github.com; needs GITHUB_TOKEN

What it does

Portfolio Auto is an agent skill from EliasOulkadi/shokunin. Auto-sync GitHub repos to portfolio website. Scans GitHub repos, captures screenshots with Playwright, generates project entries, and updates projects-data.js or Supabase DB. Use when user asks to "update portfolio", "sync projects", "add my repos to portfolio", or "refresh portfolio projects". Do NOT use for one-time project additions — batch sync only.

Its SKILL.md is about 2.6k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts. Compatibility notes: opencode

It sits in Testing & QA, covering Browser testing. It works with GitHub, Playwright and Supabase. The repository describes itself as: 職人 Shokunin 62 AI agent skills for OpenCode, Claude Code, Cursor, Windsurf. ChromaDB memory, MCP servers, declarative self-updates. Multi-model, open source, zero cost. The licence is MIT.

When your agent uses it

  • User asks to update portfolio
  • Add my repos to portfolio
  • Refresh portfolio projects
  • One-time project additions — batch sync only

Example prompts

  • “update portfolio”
  • “sync projects”
  • “add my repos to portfolio”
  • “/portfolio-auto”

Requirements

  • Python 3
  • Node.js
  • A credential in GITHUB_TOKEN
  • Compatibility (from SKILL.md): opencode

Workflow steps

7 steps, taken from the step headings in SKILL.md.

  1. Gather configuration
  2. Fetch repos via GitHub API
  3. Detect changes
  4. Capture screenshots
  5. Update portfolio data
  6. Save sync state
  7. Report results

What it can do on your machine

Read from SKILL.md and the folder at commit 4c68e5b. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • npx

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Hosts in commands or code, which the agent is likely to contact:

    • api.github.com

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names these keys or tokens, usually read from environment variables:

    • GITHUB_TOKEN

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

  • Compatibility

    opencode

    From compatibility in the SKILL.md frontmatter.

Context cost

Portfolio Auto loads about 2.6k tokens when it runs. Until then it costs about 93 tokens; SKILL.md has 891 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~93
When it runs · the whole SKILL.md, loaded when a task matches
~2.6k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from EliasOulkadi/shokunin at commit 4c68e5b, republished under its MIT licence (© EliasOulkadi). 891 words, ~2,611 tokens.

Download SKILL.mdSave it as .claude/skills/portfolio-auto/SKILL.md (or your agent's skills folder).
name
portfolio-auto
description
Auto-sync GitHub repos to portfolio website. Scans GitHub repos, captures screenshots with Playwright, generates project entries, and updates projects-data.js or Supabase DB. Use when user asks to "update portfolio", "sync projects", "add my repos to portfolio", or "refresh portfolio projects". Do NOT use for one-time project additions — batch sync only.
compatibility
opencode
triggers
update portfolio, sync projects, add my repos, refresh portfolio, portfolio automation, GitHub sync, project screenshots
negatives
one-time project, manual addition, design portfolio, PDF portfolio
license
MIT
metadata.workflow
automation
metadata.audience
developers
metadata.version
2.0.0

Note: last-sync.json state file is auto-created on first successful sync. Ignore "missing file" warnings on first run.

Portfolio Auto-Sync

Automatically sync GitHub repositories to your portfolio website.

Workflow

Step 1: Gather configuration

Ask the user:

  • GitHub username: (default from git config)
  • Portfolio type: static (projects-data.js) or supabase (API)
  • Portfolio directory: Path to portfolio project
  • Filters: Exclude repos (archived, forks, specific names)
Step 2: Fetch repos via GitHub API
GET /users/{username}/repos?per_page=100&sort=updated&direction=desc

Extract: name, description, html_url, homepage, language, topics, updated_at

Filter out:

  • Forks (unless user opts in)
  • Profile repos ({username}/{username})
  • Archived repos
Step 3: Detect changes

Compare against last-sync.json (stored in skill directory).

  • New repos: Not in last sync → full process
  • Updated repos: updated_at changed → re-screenshot
  • Unchanged repos: Skip
Step 4: Capture screenshots

For repos with a homepage or deploy URL:

javascript
const { chromium } = require('playwright');
const browser = await chromium.launch({ headless: true });
const page = await browser.newPage();
await page.setViewportSize({ width: 1280, height: 800 });
await page.goto(process.env.URL, { waitUntil: 'networkidle', timeout: 15000 });
await page.screenshot({ path: `/tmp/portfolio-${name}.png`, fullPage: false });
await browser.close();

Save to portfolio's screenshot directory.

Step 5: Update portfolio data
Static (projects-data.js)
javascript
{
  title: '{repo.name}',
  description: 'Auto-generated: {description}',
  tech: '{language},{topics}',
  github_url: '{html_url}',
  live_url: '{homepage || ""}',
  featured: false
}
Supabase
javascript
const res = await fetch('https://your-site.com/api/projects', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer {token}' },
  body: JSON.stringify(projectData)
});
Step 6: Save sync state
json
{
  "lastSync": "2026-05-12T18:30:00Z",
  "repos": {
    "example-repo": { "updated_at": "2026-04-20T10:00:00Z", "screenshot": true }
  }
}
Step 7: Report results
Sync complete:
+ 2 new (Cyberian, Image Enhancer)
+ 1 screenshot captured
+ 1 updated (Portfolio)
- 0 errors

Notes

  • Screenshots require Playwright + valid URL. Skip if no homepage.
  • Never change featured: true on existing projects — only user can promote.
  • Schedule via cron/GitHub Actions for weekly sync.

Error Handling

CauseFix
GitHub API returns 401 UnauthorizedNo token or expired token. Set GITHUB_TOKEN environment variable. Generate a new Personal Access Token at github.com/settings/tokens with public_repo scope.
GitHub API rate limit exceeded (403)Unauthenticated requests are limited to 60/hour. Authenticated: 5000/hour. Add token. If already authenticated, wait for reset (check X-RateLimit-Reset header).
Repository has no homepage field and no deploy URLCannot capture a screenshot. Mark the repo as "no live preview" in the output. Use the GitHub URL as fallback link.
Playwright browser fails to launchChromium not installed. Run npx playwright install chromium. On headless server, add --no-sandbox flag: chromium.launch({ headless: true, args: ['--no-sandbox'] }).
Screenshot URL returns 404 or times out after 15sDeploy URL is stale or site is down. Skip screenshot for this repo. Log the URL and error to a failed-screenshots.json file for manual review.
projects-data.js has custom formatting that auto-generation would breakA regex-based insert could corrupt handwritten code. Read the file first to detect non-standard structure. If detected, append a comment block with the new entries and ask user to merge manually.
Supabase API insert fails with foreign key or schema constraintPortfolio schema might differ from the auto-generated payload shape. Read the Supabase table schema first. Map fields explicitly (not spread operator). Validate with a dry-run POST that returns 200 before committing.
last-sync.json is corrupted or manually editedParse as JSON in a try-catch. On failure, rename to last-sync.json.bak and start fresh sync from scratch. Warn user that incremental detection is lost.

GitHub API Patterns

Repository Discovery
python
import requests, os

headers = {"Authorization": f"token {os.environ['GITHUB_TOKEN']}"}

# Fetch all repos (paginated)
repos = []
page = 1
while True:
    r = requests.get(f"https://api.github.com/user/repos?per_page=100&page={page}&sort=updated", headers=headers)
    batch = r.json()
    if not batch: break
    repos.extend(batch)
    page += 1

# Filter: only non-fork, non-archived, has description
candidates = [r for r in repos if not r["fork"] and not r["archived"] and r["description"]]
Rate Limiting
  • GitHub API: 5,000 requests/hour (authenticated). Check X-RateLimit-Remaining header.
  • For repos with 500+ repos: use conditional requests (If-None-Match with ETag)
  • Sleep 1s between screenshot captures (avoid GitHub rate limit on assets)
Playwright Screenshot Pattern
python
from playwright.sync_api import sync_playwright

def capture(url, output_path):
    with sync_playwright() as p:
        browser = p.chromium.launch()
        page = browser.new_page(viewport={"width": 1280, "height": 800})
        page.goto(url, timeout=15000, wait_until="networkidle")
        page.screenshot(path=output_path, full_page=False)
        browser.close()
Error Recovery
  • Timeout on page load -> retry once, skip if still fails (mark in output)
  • Private repo -> skip (cannot screenshot without auth)
  • Page crashes -> capture error state as screenshot
  • DNS failure -> skip with log message
Caching Strategy
python
import hashlib, json, os
cache_file = ".sync-cache.json"
cache = json.load(open(cache_file)) if os.path.exists(cache_file) else {}

for repo in repos:
    key = hashlib.md5(f"{repo['full_name']}:{repo['pushed_at']}".encode()).hexdigest()
    if cache.get(repo['full_name']) == key:
        continue  # Skip: no changes since last sync
    # ... capture screenshot, update entry ...
    cache[repo['full_name']] = key

json.dump(cache, open(cache_file, 'w'))

Checklist

  • GitHub token has correct scopes (repo, read:user) before fetching repos
  • Screenshot runs only for repos with valid homepage URLs (HEAD check first)
  • Playwright browser closed in finally block to prevent orphan processes
  • Existing portfolio customizations preserved before upserting new entries
  • Dry-run mode available to preview changes without executing
Show full SKILL.md (336 more words)Show less

Sources

  • GitHub REST API v3 documentation (docs.github.com/en/rest/repos/repos) — repository listing, filtering, and pagination
  • Playwright documentation (playwright.dev/docs/api/class-playwright) — headless browser launch, screenshot, and viewport configuration
  • Supabase JavaScript client documentation (supabase.com/docs/reference/javascript) — API insert, upsert, and auth patterns
  • Node.js fs module documentation (nodejs.org/api/fs.html) — file read/write with atomic rename for sync state safety
  • Personal Access Token best practices (docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) — scopes, expiration, and secure storage
  • GitHub Actions cron scheduling (docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#schedule) — weekly sync automation pattern
  • "Automate the Boring Stuff with Python" by Al Sweigart (No Starch Press, 2nd Edition, 2019) — automation reliability patterns applicable to JavaScript automation tasks

Anti-Patterns

PatternProblemFix
Syncing without checking for existing customizationsAuto-generated entries may overwrite handcrafted project descriptions, featured flags, or custom ordering set by the user.Read the target file first. Detect non-standard structure. For featured: true entries, preserve all fields. Only upsert new or changed repos.
Capturing screenshots for every repo indiscriminatelyRepos without live demos waste Playwright launch time (~3s each). Repos with broken URLs produce useless error screenshots.Pre-filter: only screenshot repos where homepage field is non-empty and returns 200 on a HEAD request.
Running sync on a metered or slow connectionCloning or screenshotting dozens of repos can consume significant bandwidth and time.Run in batches of 10. Add a --dry-run flag that lists what would change without executing.
Using the Supabase anon key instead of service_role key for writesAnon key has row-level security restrictions that block upserts.Use service_role key with caution. Store in environment variable, never in code. Add table-level RLS policies for the sync function.
Not cleaning up Playwright browser processes after syncEach chromium.launch() spawns a process. Orphaned processes accumulate memory and can exhaust system resources.Always call browser.close() in a finally block. Track launched browsers in an array and force-close on SIGINT/SIGTERM.
Hardcoding the portfolio data path instead of reading from configPaths change between projects. A hardcoded path breaks on first use on a different machine.Ask for portfolio directory in Step 1. Derive projects-data.js path from that base. Store in sync state for reuse.

© EliasOulkadi, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .pack/skills/portfolio-auto of EliasOulkadi/shokunin.

Open the folder on GitHubat commit 4c68e5b

Compare with similar skills

Portfolio Auto next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Portfolio Auto compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Portfolio Auto this skillEliasOulkadi/shokunin114—~2.6kAutomated safety check: PassMIT
Studio E2E Testssupabase/supabase111k—~2.8kAutomated safety check: PassApache-2.0
Reprovaadin/web-components582—~1.3kAutomated safety check: PassNone
Reprovaadin/flow-components129—~1.3kAutomated safety check: PassNone
Site Bugfixdebs-obrien/debbie.codes142—~960Automated safety check: PassNone
Hlive TestingSamHennessy/hlive101—~1.2kAutomated safety check: PassMIT

Similar skills

  • Studio E2E Tests

    supabase/supabase

    Official

    Write and run Playwright E2E tests for Supabase Studio (e2e/studio).

    111k GitHub stars~2.8k tokensUpdated yesterday
    Testing & QAAuto-check passed
  • Repro

    vaadin/web-components

    Reproduce a Vaadin web component bug from a GitHub issue in vaadin/web-components.

    582 GitHub stars~1.3k tokensUpdated yesterday
    Testing & QAAuto-check passed
  • Repro

    vaadin/flow-components

    Reproduce a Vaadin Flow component bug from a GitHub issue in vaadin/flow-components or a component-specific issue in vaadin/flow.

    129 GitHub stars~1.3k tokensUpdated yesterday
    Testing & QAAuto-check passed
  • Site Bugfix

    debs-obrien/debbie.codes

    Reproduce and fix a debbie.codes site bug with browser proof and a Playwright regression when useful.

    142 GitHub stars~960 tokensUpdated 3 days ago
    Testing & QAAuto-check passed
  • Hlive Testing

    SamHennessy/hlive

    Write browser tests for HLive pages using the hlivetest package (github.com/SamHennessy/hlive/hlivetest) and Playwright.

    101 GitHub stars~1.2k tokensUpdated 3 mo ago
    Testing & QAAuto-check passed
  • Handsontable Performance Testing

    handsontable/handsontable

    Guide to Handsontable's performance-tests package: Playwright scenarios measured through CDP traces and compared against golden baselines taken from the develop branch.

    22k GitHub stars~3.4k tokensUpdated yesterday
    Testing & QAAuto-check passed

More from EliasOulkadi/shokunin

All 49 skills in this repo
  • CI CD

    EliasOulkadi/shokunin

    Design CI/CD pipelines for GitHub Actions, GitLab CI, and CircleCI with matrix builds, test sharding, caching, Docker layer caching, OIDC auth, deployment strategies (rolling, blue-green, canary)…

    114 GitHub stars~3.4k tokensUpdated 6 days ago
    Auto-check: notes
  • Component Forge

    EliasOulkadi/shokunin

    Build production-grade components for React, Vue 3, and Svelte 5 with all states (loading, empty, error, success, idle), TypeScript strict, WCAG 2.2 accessibility, server components (RSC), and…

    114 GitHub stars~3.6k tokensUpdated 6 days ago
    Auto-check: notes
  • DB Admin

    EliasOulkadi/shokunin

    PostgreSQL database administration — backup/restore (pgdump, PITR, WAL archiving), health monitoring (connections, bloat, cache hit ratio, dead tuples), connection pooling (PgBouncer), replication…

    114 GitHub stars~2k tokensUpdated 6 days ago
    Auto-check: notes
  • DB Sculptor

    EliasOulkadi/shokunin

    Design database schemas with Prisma/Drizzle, PostgreSQL index strategy (B-tree, GIN, GiST, BRIN, Hash), query optimization (EXPLAIN ANALYZE), migration safety (expand/contract, zero-downtime), and…

    114 GitHub stars~3.1k tokensUpdated 6 days ago
    Auto-check: notes
  • Docker

    EliasOulkadi/shokunin

    Optimize Docker images with multi-stage builds, distroless bases, BuildKit cache mounts, multi-arch builds, compose watch, security hardening (non-root, seccomp, capabilities drop), and…

    114 GitHub stars~3.8k tokensUpdated 6 days ago
    Auto-check: notes
  • Error Handler

    EliasOulkadi/shokunin

    Design error handling, structured logging, and observability with OpenTelemetry (traces, metrics, logs), error classification, recovery patterns (retry with jitter, circuit breaker, bulkhead…

    114 GitHub stars~3.6k tokensUpdated 6 days ago
    Auto-check: notes

Categories

Questions about Portfolio Auto

What does Portfolio Auto do?

Auto-sync GitHub repos to portfolio website. An agent skill from EliasOulkadi/shokunin. Portfolio Auto is an agent skill from EliasOulkadi/shokunin. Auto-sync GitHub repos to portfolio website.

When should I use Portfolio Auto?

Portfolio Auto fits situations like: user asks to update portfolio; add my repos to portfolio; refresh portfolio projects; one-time project additions — batch sync only.

How do I install Portfolio Auto in Claude Code?

Run `npx skills add EliasOulkadi/shokunin --skill portfolio-auto -a claude-code`. Or copy the skill folder (.pack/skills/portfolio-auto in EliasOulkadi/shokunin) into .claude/skills/portfolio-auto in your project. Claude Code loads it when a task matches its description.

How do I install Portfolio Auto in Codex?

Run `npx skills add EliasOulkadi/shokunin --skill portfolio-auto -a codex`. Or copy the skill folder (.pack/skills/portfolio-auto in EliasOulkadi/shokunin) into .agents/skills/portfolio-auto in your project. Codex loads it when a task matches its description.

Can I use Portfolio Auto in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add EliasOulkadi/shokunin --skill portfolio-auto -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/portfolio-auto, .gemini/skills/portfolio-auto, .github/skills/portfolio-auto and .opencode/skills/portfolio-auto in your project.

What does Portfolio Auto need to run?

Going by SKILL.md and its folder, Portfolio Auto needs the command-line tools its instructions call (npx) and credentials named GITHUB_TOKEN. Our summary lists: Python 3; Node.js; A credential in GITHUB_TOKEN. Compatibility (from SKILL.md): opencode.

Does Portfolio Auto access the network?

SKILL.md names 1 domain. In commands or code: api.github.com; the agent is likely to contact it when it follows the instructions. This is read from the text; nothing was executed.

Is Portfolio Auto safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Portfolio Auto use?

Portfolio Auto is published under the MIT licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Portfolio Auto use?

About 2.6k tokens (SKILL.md is roughly 10k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Portfolio Auto?

Skills that share tags, products or a category with Portfolio Auto: Studio E2E Tests (supabase/supabase, 111k stars), Repro (vaadin/web-components, 582 stars), Repro (vaadin/flow-components, 129 stars) and Site Bugfix (debs-obrien/debbie.codes, 142 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Portfolio Auto?

EliasOulkadi (a GitHub user) maintains it in EliasOulkadi/shokunin, which has 114 GitHub stars. The repository holds 49 skills in this directory. The repository was last updated on October 5, 2026.

Source: EliasOulkadi/shokunin on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.