An Arc-style sidebar for Firefox: favorites, spaces, pinned tabs and folders, a command bar for new tabs, and an address bar in the sidebar.
With a small one-time setup it replaces Firefox's tab strip and toolbar, so the sidebar and the page get the whole window.
Not affiliated with or endorsed by The Browser Company. “Arc” is their browser; this is an independent extension that brings its sidebar ideas to Firefox.
Import from Arc. Brings over spaces, pinned tabs, folders and favorites. Each Arc profile becomes a Firefox container.
Shortcuts can be changed in about:addons → ⚙ → Manage Extension Shortcuts.
Arcsidebar needs Firefox 155 or newer (desktop; Firefox for Android has no sidebar).
-
Download the latest signed
.xpifrom Releases and open it in Firefox. It updates itself from there (Firefox checks daily;about:addons→ ⚙ → Check for Updates forces it). -
Give Arc the whole window (hides Firefox's tab strip and toolbar). Run the setup for your system — it finds the Firefox profile with Arc and adds Arc's layout, keeping any customizations you already have:
macOS / Linux (Terminal)
curl -fsSL https://raw.githubusercontent.com/trajche/arc/main/extras/setup/arc-setup.txt | bashWindows (PowerShell)
irm https://raw.githubusercontent.com/trajche/arc/main/extras/setup/arc-setup.ps1 | iex
Then quit Firefox and open it again. Run it again after updating Arc. To remove Arc's layout: add
| bash -s -- --uninstallon macOS/Linux, or run& ([scriptblock]::Create((irm <url>))) -Uninstallon Windows. The scripts arearc-setup.txtandarc-setup.ps1if you'd rather read and run them yourself. -
Coming from Arc? Right-click the space name → Import from Arc…
The welcome page (opened on install, or right-click the space name → Welcome & Setup) explains the features and offers the setup script.
<profile>/chrome/userChrome.csshides the tab strip, Firefox's sidebar launcher and panel header, and turns the toolbar into a row of extension buttons in the sidebar. Firefox's own address bar appears as a centered overlay with⌘L/Ctrl+L(needed forabout:pages, which extensions can't open).<profile>/user.jsenablesuserChrome.css, horizontal tabs and session restore, keeps the window open when the last tab closes, and opens Arc's sidebar at startup.<profile>/user.jsalso turns on Firefox's Picture-in-Picture when switching tabs, so a playing video pops out when you leave its tab and goes back when you return, like Arc (media.videocontrols.picture-in-picture.enable-when-switching-tabs.enabled; set it tofalseinabout:configif you'd rather it didn't).<profile>/customKeys.jsonclears Firefox's built-in New tab and Close tab shortcuts. They're reserved keys, so Arc can only take⌘T/Ctrl+T(command bar) and⌘W/Ctrl+W(close tab, but a space keeps its last command bar instead of emptying) once they're cleared; any other shortcuts you've customized are kept. Undo it inabout:keyboard.
Firefox doesn't allow extensions to do these:
- Draw over the page. Arc's floating command bar becomes a tab here.
- Open
about:pages, create split views, or read Arc's saved logins and cookies. - Switch browser profiles. Containers stand in for Arc profiles: separate cookies and logins, but shared history, bookmarks and extensions.
Spaces, pins and favorites are stored locally; Firefox Sync's extension storage is too small for large Arc imports.
Other extensions can put small badges on tabs in the sidebar. Tab Driver uses this to tag tabs an AI agent is controlling.
await browser.runtime.sendMessage("arc@sidebar", {
type: "arcsidebar:set-badges",
badges: [{ tabId: 12, label: "AI", title: "Claude is controlling this tab", color: "#7c5cff" }],
});- Each call replaces all badges from your extension. Send an empty list to clear them.
labelis up to 12 characters, andtitle(the tooltip) up to 120.coloris optional and must be a hex color; the default is the space's color. At most 200 badges per extension.iconshows a built-in Lucide icon instead of the label:"bot"or"sparkles".position: "start"puts the badge before the title, next to the sound icon (default: after the title).pulse: truemakes it blink; on an icon, a small green dot blinks instead.- Badges last until Firefox restarts or Arcsidebar updates. Arcsidebar then sends
{ type: "arcsidebar:ready" }to every extension that set badges before; send yours again when you get it. - The call fails if Arcsidebar isn't installed. Retry now and then until it succeeds.
They can also add items to the tab menu (right-click on a tab in the sidebar):
await browser.runtime.sendMessage("arc@sidebar", {
type: "arcsidebar:set-tab-menu",
items: [{ id: "control", title: "Let AI agents control this tab", exceptTabIds: [12] }],
});
// A click arrives as { type: "arcsidebar:menu-clicked", id: "control", tabId }.- Each call replaces your items (up to 5).
tabIdsshows an item only on those tabs,exceptTabIdshides it on them. - Items last as long as badges, and the same
arcsidebar:readymessage asks you to send them again. - Arcsidebar pings extensions that set badges or items (
{ type: "arcsidebar:ping" }, no answer needed) and drops what they set once they're disabled or removed.
npm install
npm run setup-dev # once: creates the "arc-dev" Firefox Developer Edition profile
npm run dev # start Developer Edition with that profile (macOS)
npm run reload # reload Arc in place after changing code
npm run lintThe dev profile loads Arc unsigned, straight from this folder, and links extras/userChrome.css into the profile. Code changes need npm run reload; userChrome.css changes need a Developer Edition restart. Release Firefox only runs signed add-ons.
npm run build:setupregeneratesextras/setup/fromextras/userChrome.cssandextras/user.js. Run it after changing either.npm run build:gifsre-renders the feature animations (HyperFrames project invideos/arc-feature-loops) and slices them intodocs/features/.npm run signbumps the version and signs an unlisted build with addons.mozilla.org. It readsWEB_EXT_API_KEY/WEB_EXT_API_SECRETfrom.env(git-ignored).npm run releasesigns a build, publishes it as a GitHub release, and pointsupdates.jsonat it so installed copies update themselves. Needs theghCLI and a clean git tree.
| Path | What |
|---|---|
background.js |
Tab lifecycle, spaces, context menus, commands |
shared/store.js |
Data: spaces, favorites, pinned items, folders, import |
sidebar/ |
The sidebar: tabs, address bar, spaces footer |
palette/, newtab/ |
Command bar and the new-tab page that opens it |
editor/ |
Space editor window (emoji data in emoji.json) |
import/ |
Import from Arc (arc-parse.js reads Arc's StorableSidebar.json) |
welcome/ |
Welcome and setup page |
extras/ |
userChrome.css, user.js and the generated setup scripts |
scripts/ |
Dev tooling: setup-script generator, dev profile, reload |
MIT. Emoji data from unicode-emoji-json and emojilib (MIT, see editor/emoji.LICENSE.txt).








