Browser extension · GitHub ⇄ GitLab · any forge · any skin
Use any forge, keep your muscle memory.
GitAlike makes every major forge speak one UI. Point it at GitHub, GitLab, Codeberg/Gitea, Bitbucket, Gerrit or any instance you add, and it re-skins the page as the product you know best — colour, words, navigation, reference markers and keyboard shortcuts included. Nothing else makes GitHub read like GitLab — and back. It changes nothing about what the site does, and every change is reverted the moment you switch it off.
No account No network requests No data collected GPL-3.0 Chromium, Firefox & their forks


How it works
Three steps, no account, and it is invisible the moment you turn it off.
Pick a skin
Open the popup and choose GitHub UI, GitLab UI or Bitbucket UI — for the whole web, or for the one host you are on.
The site repaints
GitAlike re-points the site's own design tokens and matches the other product's words, navigation and shortcuts — with no reload.
Switch it off
Every change is recorded and undone exactly. With the skin off, the extension is completely inert — nothing to clean up.
See it
Live captures of the real sites at 1280×900. Pick a source forge and a page kind, and the capture shows that page wearing every skin it can — drag a divider to reveal one, or focus it and use the arrow keys. All five sources are here: GitHub, GitLab and Codeberg in full, and Bitbucket and Gerrit from their app shells (their pages render client-side).
GitHub project page
A horizontal tab bar, shown as GitLab — a vertical sidebar-style column — and as Bitbucket — a Source / Pull requests / Pipelines sidebar in Atlassian blue.



GitLab project page
GitLab's scattered sidebar rebuilt as GitHub's flat tab row under the repository header, and as Bitbucket's Source / Pull requests / Pipelines sidebar.



Codeberg (Gitea) project page
GitHub-flavoured, so it can wear all three: GitLab's grouped Plan / Code / Build / Deploy sidebar, GitHub's underlined tab row, or Bitbucket's Source / Pull requests / Pipelines sidebar.




Bitbucket project page
Bitbucket's own left source sidebar. A
Bitbucket source has its Atlassian --ds-* tokens
mapped onto the applied palette, so the other UIs change the
colours and the words — "Pull requests"
becomes "Merge requests", "pull request #207" becomes "merge
request #207" — and reorient the bar: a column
alongside a sidebar layout, a row under the
GitHub layout, and grouped under the applied skin's
headings when that skin groups its menu.



Gerrit change list
PolyGerrit is a client-rendered app. Its palette is re-pointed through the root custom properties it reads (--primary-text-color, --link-color, …), which inherit across its shadow boundary, so the skins recolour it without reaching inside — and its header navigation is reoriented to the layout, a column or a row, since PolyGerrit's roots are open and the pass can reach the nav.




Gerrit owner changes
Gerrit has no public profile; its closest page is an owner query, here scoped to one account. As on its project pages, the skins recolour it through the root properties PolyGerrit reads and reorient its header navigation to the layout — and they reshape PolyGerrit's user header (avatar, name, email, join date) into the applied product's profile identity block, with a tab row built from Gerrit's own owner views. The content below stays Gerrit's change list.




GitHub profile page
A horizontal profile tab row, shown as GitLab's full-height super-sidebar and as Bitbucket's sidebar, with the identity moved into the content.



GitLab profile page
A vertical super-sidebar, shown as GitHub's flat row of tabs and as Bitbucket's sidebar, with the counts brought down into the profile card.



Bitbucket profile page
Bitbucket's workspace repositories page
— the closest account page it serves, since it has no public user
profile. Its Atlassian --ds-* tokens are mapped onto
the applied palette, and "Pull requests" becomes
"Merge requests" in the sidebar, while the
layout stays Bitbucket's.



Codeberg (Gitea) profile page
GitHub-flavoured, so it can wear all three: GitLab's sidebar, GitHub's flat tab row, or Bitbucket's sidebar.




Not just a theme
A theme changes the colours and stops there. GitAlike also matches the other product's words, navigation, reference markers and shortcuts — then undoes every change when you switch it off.
Colour
Each site's own design tokens (GitHub's Primer, GitLab's Pajamas) are re-pointed at the other product's palette — light and dark.
Words
"Pull request" ⇄ "Merge request", "Insights" ⇄ "Analytics", "Actions" ⇄ "CI/CD". Ordinary page copy only — never inside code, inputs or editable regions.
Navigation
Repo tabs are relabelled, reordered and re-oriented — GitHub's bar becomes GitLab's grouped sidebar, and GitLab's sidebar becomes GitHub's flat tab row.
References
A pull/merge-request link shows the other product's marker:
#42 ⇄ !42.
Shortcuts
The other product's g-combos work, so the muscle
memory you built on one forge carries over to the other.
Reversible
Every change is recorded and reverted exactly when the skin is switched off. With it off, the extension is completely inert.
The same page, in each product's words
Same repository, same commits, same history. Only the words on the screen change.
GitAlike does not gloss the page with a dictionary. It swaps the navigation for the applied product's own menu — that product's vocabulary, that product's order, that product's words for the things the two forges name differently. What you are reading is that product's UI, not a translation of yours, and the page keeps every commit, branch, file and review it always had.
So one open code review is a
merge request under the GitLab UI, a
pull request under the GitHub UI, and a
pull request under Bitbucket's — and its
reference marker changes with it, !42 ⇄
#42. A feature the applied product simply has no page
for is never renamed into nothing: it stays where it is, marked
≠ GitLab, so the page says so instead of pretending.
The mapping lives in each skin's own plugin file under
src/plugins/skins/, so a label cannot drift from the
skin it belongs to — and adding a skin is adding one folder.
| Concept | GitHub | GitLab | Bitbucket | Gitea / Forgejo | Gerrit |
|---|---|---|---|---|---|
| Source tab | Code | Repository | Source | Code | Browse |
| Issue tracking | Issues | Work items | Jira issues | Issues | — |
| Code review | Pull requests | Merge requests | Pull requests | Pull requests | Changes |
| Continuous integration | Actions | CI/CD | Pipelines | Actions | — |
| Insights | Insights | Analytics | — | Insights | — |
| File finder | Go to file | Find file | — | — | — |
| Snippets | Gists | Snippets | Snippets | Snippets | — |
| Project boards | Projects | Issue boards | — | Projects | — |
| Reference marker | #42 | !42 | #42 | #42 | change no. |
A dash is one of two very different things, and the table does not
pretend otherwise. Bitbucket has no insights page at all —
issues live in Jira, and it keeps no snippets on a repository.
Bitbucket, Gitea and Gerrit have no modelled file-finder
label: the extension only translates a word it has an entry
for, so a blank there means "not mapped", not "does not exist".
Every cell above is read from a plugin's own
nav / phrases table, so the page cannot
claim a word the extension does not actually swap.
The design systems behind the UIs
Layout, palette, type and interaction are what make a forge feel like itself — and what your hands learn. These are the pieces a skin has to reproduce.
The words table above shows what each product calls a thing. This one shows how each product builds it: the shape its navigation takes, the colour it owns, the type it sets and the muscle memory it teaches. A skin that only recolours gets one row of this table and drops the rest — which is why GitAlike re-points the palette, re-orients the navigation and re-labels the controls, then reverts all of it.
| Factor | GitHub | GitLab | Bitbucket | Gitea / Forgejo | Gerrit |
|---|---|---|---|---|---|
| Layout & structure | |||||
| Design system | Primer | Pajamas | Atlassian Design System (ADS) | Gitea's own, Bootstrap-derived | PolyGerrit, Material Design |
| Navigation shape | Horizontal repo tab row | Vertical, grouped super-sidebar | Vertical, flat sidebar | Horizontal tab row (overflow-menu) |
Header views and query tabs; no repo tabs |
| Page frame | Dark app bar → tab row → content beside an About rail | Light super-topbar → left rail → one wide content column | Dark blue app bar → left sidebar → card content | Top bar → tab row → bordered cards | Header → change list → info panel per change |
| Landing page | File table, README, About rail | README-first, then Project information | Card overview with its own navigation | File table, then README | Change list / query results |
| Metadata lives | In a right-hand About rail | Full-width Project information block | Sidebar and header badges | Repo header, then sidebar | Change info panel |
| Colour | |||||
| Accent | Blue #0969da |
Blue #1f75cb, purple #7759c2 |
Atlassian blue #0052cc |
Green #609926 |
Material blue links on grey; no brand hue at rest |
| Header surface | Near-black #000000 app bar |
Light grey #ececef — the rail's own grey |
Dark blue #0049b0 bar |
Its own bar (--color-nav-bg) |
Header drawn from the applied skin |
| Primary action | Green Code / Merge | Blue Code / Merge | Blue Clone / Merge | Green primary button | Material blue button |
| Dark theme | Canvas #0d1117 |
Canvas #1f1e24 |
Canvas #1d2125 |
Its own [data-theme] dark mode |
PolyGerrit's root properties, dark |
| Typography | |||||
| Sans stack | System UI — -apple-system, Segoe UI, Noto Sans |
GitLab Sans (Inter-based) | Atlassian Sans (Inter-derived); Charlie for brand | System UI stack | Roboto |
| Mono stack | ui-monospace — SF Mono, Menlo, Consolas |
GitLab Mono (JetBrains Mono-based) | Atlassian Mono | System mono stack | Roboto Mono |
| Type character | Dense and tabular, ~14px base | Airier and documentation-like, ~14px base | Medium density, ~14px base | Compact and utilitarian, ~14px base | Material, dense list, ~14px base |
| Interaction & muscle memory | |||||
| Corner radius | 4 / 6 / 8px, three steps | 4 / 8px, two steps | 3 / 8px, two steps | 3–4px controls | Small, Material radius |
| Elevation | Hairline borders, faint shadow | Flat, hairline borders | Flat with borders, occasional shadow | Bordered cards, minimal shadow | Material elevation — shadowed cards |
| Icons | Octicons | Pajamas / GitLab SVGs | Atlassian icons | Gitea's own SVGs | Material icons |
| Keyboard | g p pull requests, g b projects, g n notifications; t file finder, / search |
g m merge requests, g p projects, g t todos; / search |
No g-combos; its own shortcut set is small |
Ships no g-combos of its own |
No g-combos; a change view is navigated with single keys |
Every cell is the product's own choice, not GitAlike's: the palette
values are the ones the colour gate scores in
tests/fixtures/target-chrome.json, the radius and type
stacks are the skins' --gs-* declarations, and the
layout, landing page and navigation rows are the anatomy in
FORGE-UX.md. The keyboard row is the
muscle memory itself — and the one a skin can hand across forges:
GitAlike replays the applied product's g-combos on a
site that honours synthetic keys and delivers them as trusted
clicks where it does not, so the combos you know keep working after
the UI changes. Bitbucket reuses GitLab's layout pass, so a
Bitbucket skin is GitHub's or GitLab's shape in Atlassian's palette.
Gitea ships none of these combos of its own, so the applied
product's are delivered as clicks on its own navigation links, and
the Bitbucket skin maps none at all.
How it compares
Most tools here answer make this site nicer or make this site work better. Only one answers make one forge read like another.
Most browser tools for GitHub and GitLab answer one question: make this site look nicer. A smaller set answers a second: make this site work better. Neither is what GitAlike does. GitAlike answers a third — make one forge read like another, and back — which is the one no other tool is built for.
Two axes separate them: how deep a tool reaches (colour → words and navigation → behaviour), and which way it points (one product, or two of them reciprocally).
| One-way one product, on its own terms | Reciprocal two products read as each other | |
|---|---|---|
| Colour the palette | GitSkin · userstyles | GitAlike |
| Words & navigation labels, menu order, markers, keys | — | GitAlike |
| Behaviour workflow, API | Refined GitHub · Octotree | — |
Every other tool here lives in the left-hand column. GitAlike is the only one of them that works reciprocally — it is the only one that can show a GitHub page as GitLab and a GitLab page as GitHub, from the same install. That is the cell it occupies, and it is not the same cell as any of the others.
Shaded rows are ones GitAlike does not win. It is a skin: it changes how a page reads, not what the site does, and it ships three built-in skins rather than a marketplace.
| Capability | GitAlike | GitSkin | Userstyles | Refined GitHub |
|---|---|---|---|---|
| Repaints the palette | ● | ● | ● | ◐ |
| Renames the product's words | ● | ○ | ○ | ○ |
| Rebuilds navigation | ● | ○ | ○ | ◐ |
Swaps reference markers (#42 ⇄ !42) | ● | ○ | ○ | ○ |
Delivers the other product's g-shortcuts | ● | ○ | ○ | ◐ |
| Works in both directions | ● | ○ | ○ | ○ |
| Covers GitLab as well as GitHub | ● | ○ | ◐ | ○ |
| Community themes / a marketplace | ○ | ● | ● | ○ |
| Improves a forge's own UX rather than translating it | ○ | ○ | ○ | ● |
| Unifies the API or CLI across forges | ○ | ○ | ○ | ○ |
| Survives upstream DOM churn | ◐ pinned selectors + daily canary | ◐ network adapters | ○ often breaks | ◐ active team |
| No network requests, no remote code | ● | ○ CDN adapters | ● | ● |
| Works on self-hosted / enterprise instances | ● | ○ GitHub-only | ● | ● |
● does it · ◐ partial or adjacent · ○ does not. "Survives upstream DOM churn" is partial for everybody that touches the DOM: no skin is immune to a site rebuilding its markup, and each tool answers it differently — GitAlike pins every selector and runs a daily canary against the live sites, which catches a change instead of silently shipping a broken page. It does not prevent the change. Where no tool does something, the row says so rather than being left out.
GitSkin
The closest neighbour — one-way
The most sophisticated approach to the same hard problem: themes target abstract components, resolved to GitHub's DOM by adapters, with a marketplace and a five-level scale from Primer tokens up to global CSS. It is GitHub-only, and its adapters are delivered from a CDN, so a theme needs network requests. It answers make GitHub look like anything.
Userstyles (Stylus, GitHub-Dark, …)
The DIY substitute — one-way
A large free ecosystem that recolours a site and stops. CSS cannot rename what a button says, reorder a menu, or swap a reference marker, and a style that reaches into a page's structure tends to break when the site changes. That is not a knock — for a dark theme it is the better tool, and the community that moved off Stylish onto Stylus for its privacy is exactly this audience.
Refined GitHub
The benchmark — one-way
The strongest answer to make GitHub itself better: a large, org-backed, MIT extension that has shipped so many good ideas GitHub absorbed dozens of them. It is not a reskin and it does not translate GitHub into anything — it improves GitHub on GitHub's own terms, which is a different job from the one here.
GitAlike
The other cell — reciprocal
Not a theme and not an enhancer: a translation between two products. Same repository, same commits, same history — read in the UI you already know, in either direction, and reverted the moment you switch it off. If the question is make GitHub nicer, use Refined GitHub. If it is a dark theme, use Stylus. If it is I work on both and keep hitting the wrong muscle memory, that is the one here.
Works with your forges
Three skins over five source products, and no rebuild to add your own. GitHub, GitLab, Codeberg/Gitea, Bitbucket and Gerrit all work — out of the box, or after one prompt — and any site you set up can wear any skin.
Add any instance by visiting it or typing its address — no rebuild.
Paste a link and GitAlike highlights the product it looks like
(/-/merge_requests is GitLab, /pull/
GitHub, /pulls/ Gitea/Forgejo,
/pull-requests/ Bitbucket, /c/…/+/…
Gerrit), so you usually only confirm it. Bitbucket is both a skin and
a source; Gerrit is a source with no bundled host, so you add your
instance. Adding a self-hosted host asks the browser to grant that
one origin. Sourcehut is the next candidate.
Plugins
GitAlike is assembled from two kinds of plugin, and the registry
is open — anyone can add one. A skin is a target UI
a page is made to look like; a source is a forge's markup.
They are independent — any source can wear any skin — so one new
forge or one new UI extends every page the extension already
touches. Each is a self-contained folder under
src/plugins/: its definition, its tests, and a
stylesheet for a skin.
Skins
One folder in src/plugins/skins/: the product's
vocabulary, navigation order, profile menu and shortcuts — not
just its palette, which lives beside it. Its own tests run with
npm test.
Sources
One folder in src/plugins/sources/: the DOM hooks a
skin reads, the live page the daily canary watches, and its own
tests, so a rename upstream fails a check instead of a user.
Bitbucket Cloud and Gerrit are client-rendered sources:
their app shells are canaried, and their palettes are re-pointed
through the design tokens each reads (Atlassian --ds-*
on Bitbucket, PolyGerrit's root properties on Gerrit), so they
recolour without reaching into the app. Gerrit's chrome lives in
open shadow roots, so its copy, navigation and query pages are
reached from the content scripts too.
The registry is open — contributions are welcome. Adding one
is meant to be small: a plugin is one folder — its definition and its
tests, plus a stylesheet for a skin and, for a forge people host, a
host entry. node tools/new-plugin.mjs skin <name>
(or source <name>) writes that skeleton for you,
and this list is generated from the plugins — so it cannot drift
from the code. A new source brings another forge (Sourcehut is
the next candidate); a new skin brings another target UI. The
rules are the same for everyone — GPL-3.0-or-later, no monetisation,
and your own original mark rather than a vendor's.
Propose a plugin →
Contributing guide →
Nothing leaves your browser
GitAlike collects no data and makes no network requests. Both stylesheets are bundled and the mark is an inline data URI.
It stores only your on/off choices and the instances you add, in the browser's own synced extension storage. Nothing read from a page is stored or sent anywhere.
Which sites it can reach
Only five hosts are granted at install — github.com, gitlab.com, codeberg.org, gitea.com and bitbucket.org. A self-hosted instance is granted when you add it: the popup asks for that one origin, a prompt you only see if you asked for that host. There is no all-sites grant, and its scripts load only on hosts you have set up and granted.
Questions
Does it send my data anywhere?
No. GitAlike makes no network requests at all — no CDN, no remote configuration, no telemetry. The stylesheets ship in the bundle and the mark is an inline data URI. It stores only your on/off choices and the instances you add, in the browser's own synced storage.
Which sites can it access?
The five bundled hosts — github.com, gitlab.com, codeberg.org, gitea.com and bitbucket.org — are granted at install. Everything else is asked for one origin at a time, when you add it, so a self-hosted GitHub Enterprise, GitLab, Bitbucket Data Center or Gerrit instance triggers a single prompt for its host, and nothing is granted before that.
Does it work on my self-hosted instance?
Yes. Add the host by visiting it or typing its address — no rebuild. Adding it asks the browser to grant that one origin. GitHub Enterprise Server, self-hosted GitLab, Bitbucket Data Center and Gerrit all work, and Codeberg (Forgejo) and gitea.com are already covered.
How does it know which forge a link is?
When a host is not set up yet, the popup reads the address and
highlights the product it looks like, so a pasted deep link
needs only a confirmation: /-/merge_requests/42 is
GitLab, /pull/42 GitHub, /pulls/42
Gitea/Forgejo, /pull-requests/42 Bitbucket and
/c/project/+/42 Gerrit — even on a host it has
never seen. It reads the URL only, never the page, and makes no
network request; a bare host it cannot place is left for you to
choose.
Does it change what the site does?
No. It changes how the page looks and reads, not what it does: no requests are intercepted and no data is touched. It never rewrites text inside code, inputs or editable regions, and every change is reverted when you switch the skin off.
Which browsers does it run in?
The two extension platforms, so it covers their forks too. The Chromium build runs in Chrome, Edge, Brave, Opera, Vivaldi and the rest; the Firefox build needs Firefox 142 or newer and runs in the forks that track it, such as LibreWolf, Floorp and Zen.
Is it free?
Yes — GPL-3.0-or-later, no account and no paid tier. The source
is on GitHub, and you can build it yourself with
npm run build.
Install
Two clicks, or build it yourself.
Chromium
Chrome, Edge, Brave, Opera, Vivaldi and the other Chromium-based browsers share the API — one build.
- Download the ZIP and unzip it.
- Go to chrome://extensions and turn on Developer mode.
- Load unpacked → choose the unzipped folder.
Load unpacked takes the folder, not the ZIP. Most Chromium browsers install from the Chrome Web Store, where GitAlike is live.
Firefox
Needs Firefox 142 or newer, and works in the forks that track it (LibreWolf, Floorp, Zen, …). The ZIP is unsigned, so Firefox loads it temporarily — it is gone when the browser restarts. A permanent install comes from addons.mozilla.org.
- Download the ZIP.
- Go to about:debugging#/runtime/this-firefox.
- Load Temporary Add-on… → choose the ZIP itself; it does not need unzipping.
Every major store
GitAlike targets the two extension platforms, so it runs in the Chromium browsers (Chrome, Edge, Brave, Opera, Vivaldi, …) and in Firefox and the forks that track it (LibreWolf, Floorp, Zen, …). It is live on the Chrome Web Store and on addons.mozilla.org, with Microsoft Edge Add-ons and Opera to follow. Until those are listed, the ZIPs above install it today.
Chromium
Chrome
Edge
Brave
Opera
Vivaldi
Firefox
LibreWolf
Floorp
Zen
From source
No runtime or build dependencies — the build only generates the two per-browser manifests.
npm run build # -> dist/chromium and dist/firefox npm test # unit tests, no browser needed node tools/compare/e2e.mjs # Playwright end-to-end test against the live sites