fxcss install
fxcss install owner/theme # into your default profile
fxcss install owner/theme --with compact-tabs # optional sheets, permanently
fxcss install ~/src/my-theme # a local checkout works too
fxcss install --list-profiles # see what it found firstPut a theme into the Firefox profile you actually use — the cross-platform
replacement for each theme's own install.sh (and the answer for themes whose
install script never covered Windows). Resolution is the same as try:
a GitHub owner/name or URL with --ref/--commit, or a local directory.
As with try, the theme's own install script is never executed.
It finds your real profiles by parsing profiles.ini in the platform's
Firefox directory (macOS ~/Library/Application Support/Firefox, Windows
%APPDATA%\Mozilla\Firefox, Linux ~/.mozilla/firefox plus the snap and
flatpak locations) and installs into the profile Firefox itself would open.
--profile <name-or-path> overrides; with several profiles and no clear
default, interactive runs get a picker and scripts get an error — CI is never
prompted. Profiles kept somewhere unusual can be added to the search with
FXCSS_PROFILE_ROOTS=/path/to/dir, mirroring FXCSS_FIREFOX_ROOTS.
Firefox's default profile decides only for install, which is choosing where
to put a theme. Every command that acts on one already installed —
uninstall, upgrade, rollback — looks for the profile that has it,
so a theme installed deliberately into your Developer Edition profile is
still found by a bare fxcss uninstall. adopt looks for the opposite: a
chrome/ folder fxcss did not install. Firefox's default breaks the tie only
when more than one profile qualifies, and --profile always wins.
The picker and --list-profiles say which Firefox each profile belongs to,
because default-release and dev-edition-default are one word apart in a
list of hashed directory names — and installing into the wrong one looks
exactly like the theme not working:
Several Firefox profiles exist:
1. default-release [Release] …/Profiles/8f2b1a.default-release (Enter)
2. dev-edition-default [Developer Edition] …/Profiles/c41d9e.dev-edition-default
3. work [unrecognised] …/Profiles/7ab3.workThe label comes from the directory suffix Firefox itself assigns, so a profile
you named yourself reads [unrecognised] rather than being guessed at.
Run it without --with and it offers the theme's optional stylesheets rather
than leaving you to find them in the repository:
This theme ships optional stylesheets:
1. compact-tabs
2. theme-dracula
…
Numbers separated by commas, `all`, or Enter for none.
Include:Options that cancel each other out
Some of a theme's optional sheets are alternatives rather than additions.
Installing two colour themes is two @imports, and nothing about that warns
you — the later one silently wins outright, leaving a browser that looks like
neither the one you picked nor the one before it. install measures for this
and stops:
$ fxcss install AdamXweb/WhiteSurFirefoxThemeMacOS --with theme-nord,theme-dracula
theme-dracula and theme-nord are alternatives, not additions: both set the
same 122 declaration(s), so whichever loads last replaces the other entirely
:root { --gnome-browser-before-load-background: #282a36 } vs { …: #2e3440 }
Refusing to install stylesheets that cancel each other out — only one
of them would have any effect, and which one is decided by import
order rather than by you. Pick one, or pass --force.It is a measurement, not a guess about names. Two sheets are alternatives when
they set the same properties on the same selectors — provable from their
text, and true whatever they are called. Matching on a theme- prefix would
be a convention rather than a fact: it would tell a theme shipping theme-blue
and theme-compact that those clash when they compose perfectly well, and
miss a pair named dark.css and nord.css. Sheets that agree exactly are not
in conflict, because two options setting the same border radius the same way
compete for nothing.
try reports the same thing and continues — a throwaway profile is a fine
place to watch two colour themes cancel out — and tweaks says so before
screenshotting a --combo that cannot take effect.
What this does not see. It compares declarations, so it catches sheets fighting over the same property. Two sheets that rearrange the same area through different selectors — WhiteSur's
tabs-swapcloseandwindows-swapcloseboth move a close button and share no declarations at all — are invisible to it.fxcss tweaks --combo a+bproves those from the rendered pixels — and says so itself: a combo that renders identically to one of its parts alone is called out in TWEAKS.md as not a real combination on that Firefox. Silence from the static check is "nothing measurable", never "verified compatible"; the pixels are the judge.
When the theme's default branch has moved on since its newest release, that choice is put to you as well — a tag can be a year behind a fix you are looking for, and equally the branch can be mid-rewrite, so neither is right to assume:
The default branch has moved on since the latest release:
1. release v2.0 2025-01-03 what the author last published (Enter)
2. latest commit on master 2026-08-14 newer than the release — fix tab colours
Install [1-2]:Scripts and CI never see any of these prompts: without a terminal the release
wins, as before, with a one-line note that --commit exists.
The install is what a theme's install script does, done carefully:
- the complete replacement is prepared before your existing
chrome/moves to a timestampedchrome.backup-*sibling; a failed swap restores it; - any
--withoptional sheets go where the theme's own@imports expect them, or load after the base theme through an import-only wrapper; toolkit.legacyUserProfileCustomizations.stylesheetsis enabled inuser.js— inside a clearly marked block, so it can be removed cleanly — together with anyconfiguration/user.jsthe theme ships;- a manifest (
chrome/fxcss-install.json) records every file written, its sha256, and where the theme came from — which repo, which ref, and whether that ref was a release or a branch.
Restart Firefox after installation; it reads userChrome.css at startup.
See uninstall to remove a theme later.