gitskins
v0.2.0
Published
Commit self-updating, themed GitHub profile widgets to your repo — no more hot-linking. Renders GitSkins cards to static SVG/PNG files via a GitHub Action.
Maintainers
Readme
gitskins
Self-updating GitHub profile widgets, committed to your repo.
Most profile-widget services (including plain GitSkins image URLs) hot-link an image on every README view. That means a broken image whenever the service is slow or down, render traffic that scales with your popularity, and animations that GitHub's sanitizer strips out.
This CLI takes the opposite approach — the same one that makes build-time SVG tools reliable: it renders your GitSkins widgets to static files and commits them into your repo, then a GitHub Action refreshes them on a schedule. Your README points at local files, so it always loads instantly and never breaks.
Quick start
npx gitskins initinit will:
- Ask for your GitHub username and theme.
- Write a
.gitskins.jsonconfig. - Add a GitHub Action at
.github/workflows/gitskins.yml. - Render your widgets once into
.gitskins/. - Print a Markdown snippet to paste into your README.
Commit the config, the .gitskins/ folder, and the workflow, then push. The
Action re-renders your widgets daily (and whenever you edit the config) and
commits the updated images automatically.
On GitHub, enable Settings → Actions → General → Workflow permissions → Read and write so the Action can commit refreshed widgets.
init also scaffolds the workflow pinned to the CLI version that generated it
(reproducible runs) and, if your .gitignore would exclude the output folder,
adds a negation rule so the generated widgets stay tracked.
Using the composite Action instead
If you'd rather not manage the workflow yourself, the package also ships a composite Action:
name: GitSkins
on:
schedule: [{ cron: "0 6 * * *" }]
workflow_dispatch:
permissions:
contents: write
jobs:
refresh:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: gitskins/gitskins/[email protected]
with:
version: "0.1.0" # npm version of the CLI to run
strict: "false" # fail the job on any widget errorIt exposes a changed output (true/false) so you can chain steps.
Resilience
Widget renders are fetched with retries. If GitSkins is briefly unreachable
during a scheduled run, the CLI keeps the previously committed image for
that widget instead of failing — your README never breaks, and the run stays
green. Pass --strict (or strict: "true" in the Action) to fail loudly
instead. A first run with no cached copy and no successful render exits non-zero.
Commands
| Command | What it does |
| --- | --- |
| gitskins init | Scaffold config + Action and render once |
| gitskins render | Re-render the widgets in .gitskins.json |
| gitskins portrait <image> | Convert a local photo to an ASCII-art SVG |
| gitskins template <action> | Build, validate and preview a community README template |
| gitskins help | Show help |
init options
| Flag | Default | Description |
| --- | --- | --- |
| --username <name> | (prompted) | GitHub username |
| --theme <name> | github-dark | Theme id (e.g. satan, neon, dracula) |
| --output-dir <dir> | .gitskins | Where widget files are written |
| --base-url <url> | https://gitskins.com | GitSkins instance to render from |
| --skip-render | | Scaffold without rendering |
| --force | | Overwrite an existing config |
render options
--username, --theme, and --base-url override the config for a single run
(useful in CI). Add --snippet to also print the README Markdown, or --strict
to fail the run on any widget error even when a cached copy was kept.
gitskins portrait
Turns a local photo into a clean, monochrome ASCII-art SVG that types itself in like a terminal — the subject isolated on a dark terminal window. It commits as a static file, so nothing is hot-linked.
npx gitskins portrait me.jpg --remove-bg --out .gitskins/portrait.svgQuality comes from three things, in order: background removal (so a busy background doesn't become ASCII noise), CLAHE local contrast (lifts a flatly lit face out of a grey blob), and a single ink color with a good density ramp.
For the cutout you have two options:
--remove-bgruns a background-removal model locally (first run downloads it, ~a minute), or- pass a transparent PNG you cut out yourself — its alpha channel is used directly as the mask.
Without either, the whole frame is rendered, so use a plain background.
| Flag | Default | Description |
| --- | --- | --- |
| <image> | (required) | Photo to convert (first argument) |
| --remove-bg | | Isolate the subject with the background-removal model |
| --cols / --rows | 96 / 51 | Grid size |
| --invert | | For light subjects on dark backgrounds |
| --out <file> | portrait.svg | Output path |
| --title <text> | me@github: ~$ ./portrait.sh | Terminal title line |
| --ink <hex> | #c9d1d9 | ASCII color |
The image tools are heavy and only used here, so they're optional — install them when you want the command:
npm install -g sharp @imgly/background-removal-nodesharp is required; @imgly/background-removal-node is only needed for
--remove-bg. (Prefer the always-available hosted version? The web app renders
one from your GitHub avatar at /api/section/portrait?username=<you>.)
gitskins template
Make a README template for the GitSkins gallery and get credited in every README built from it. A template is a JSON recipe (sections, order, headings, layouts, theme), never code.
npx gitskins template init # writes gitskins-template.json
npx gitskins template validate # checks it offline
npx gitskins template preview --user torvalds # renders README.preview.md| Action | Description |
| --- | --- |
| init [file] | Write a starter template (--example <name> to start from a ready-made one, --force to overwrite) |
| examples | List the ready-made examples |
| validate [file] | Check the template against the GitSkins rules, offline |
| preview [file] --user <login> | Render it with a real GitHub profile; --pro for the Pro look, --out <file> to choose the output, --author <login> for the credit line |
When it looks right, submit it at gitskins.com/community-templates with Import JSON. A person reviews every template before it goes live.
Configuration
.gitskins.json:
{
"username": "torvalds",
"theme": "satan",
"outputDir": ".gitskins",
"widgets": ["card", "languages", "streak", "stats", "projects"],
"projects": ["torvalds/linux", "git/git", "torvalds/subsurface"]
}Available widgets: card, languages, streak, stats, portrait,
wordmark, projects.
Curated projects panel
Add the projects widget and a projects array of owner/repo slugs to hand-
pick and order the repos in your projects panel (instead of relying on GitHub
pins). GitSkins fills each card with live data — stars, languages (the animated
donut), topics, and last-push freshness. Edit the list any time; the README
never changes. Up to 6 repos.
How it compares to hot-linking
| | Hot-linked image URL | Committed via this CLI | | --- | --- | --- | | README load when GitSkins is slow/down | Broken image | Loads instantly (local file) | | Render traffic | Every viewer hits the API | Once per scheduled refresh | | Freshness | Live, but rate-limited | Refreshed daily by the Action | | Works offline / in forks | No | Yes |
Requirements
Node.js 18+. No dependencies.
License
MIT
