AgentStack
SKILL verified MIT Self-run

Arc To Zen Migration

skill-shub-rajput-arc-to-zen-migration-arc-to-zen-migration · by shub-rajput

Use when migrating Arc browser spaces/workspaces into Zen Browser, or bulk-creating Zen workspaces, folders, essentials, or pinned tabs by editing the session store. Covers reading/writing Zen's mozlz4 session file and its folder/group/space schema.

No reviews yet
0 installs
0 views
view→install

Install

$ agentstack add skill-shub-rajput-arc-to-zen-migration-arc-to-zen-migration

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Arc To Zen Migration? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Arc → Zen Migration

Overview

Zen has no Arc importer. But Zen (Firefox-based) keeps its whole tab/folder/workspace state in one compressed file you can script against, so Arc spaces can be rebuilt in bulk — folders become folders, not flat pins.

Read side (Arc): ~/Library/Application Support/Arc/StorableSidebar.json — plain JSON holding every space, folder, and pinned tab. No manual pasting needed. Write side (Zen): /zen-sessions.jsonlz4 — Mozilla-lz4 (mozLz40\0) compressed JSON.

Tools:

  • scripts/arc_extract.py — reads Arc's sidebar, returns each space as a nested tree.
  • scripts/zen_session.py — read/write Zen's mozlz4 session + folder/tab/essential builders.
  • scripts/migrate.py — end-to-end: Arc space → Zen workspace (preserves nested folders).
  • scripts/migrate_example.py — manual fill-in template (when there's no Arc file, e.g. user pastes URLs).

When to Use

  • "Migrate my Arc workspaces/spaces to Zen"
  • "Bulk add folders / pinned tabs / essentials to Zen"
  • Recreating Arc's folder structure inside a Zen workspace

Not for: bookmarks (use Arc export HTML → Zen bookmark import) or passwords (use a password manager / keychain export).

The Iron Rule

Zen MUST be fully quit (Cmd+Q) before writing. It rewrites the session on exit and will clobber your changes otherwise. Always backup() first — a wrong schema corrupts the session; the .bak restores instantly.

Workflow (automatic — Arc installed)

  1. Quit Zen (Cmd+Q) — non-negotiable (see Iron Rule).
  2. Preview: python3 scripts/migrate.py --list prints Arc spaces ↔ Zen workspaces.
  3. Migrate everything from zero: python3 scripts/migrate.py --all --favorites

— creates a Zen workspace per Arc space (with Arc's emoji icon), imports folders + pins, and adds Arc's global Favorites as global essentials.

  1. Or one space: python3 scripts/migrate.py "Home" --favorites (creates the workspace if missing; --zen "Name" maps to a differently-named one; --essentials N promotes the first N top-level pins to essentials).
  2. Reopen Zen, verify. Re-runnable — clear_workspace wipes the target first. Restore the .bak if wrong.

Mapping Arc → Zen: space list → folder (nesting preserved) · space top-level tab → regular pin · global Favorites (topApps) → global essentials.

Workflow (manual — no Arc file, user pastes URLs)

Use migrate_example.py: fill ESSENTIALS/PINS/FOLDERS, quit Zen, run. Screenshots of the Arc sidebar are enough to fill it.

If Zen's schema drifted (script misbehaves): make ONE folder with 2 tabs by hand in Zen, quit, zen_session.py --dump, compare the live folders[]/groups[]/tabs[] shapes, update the builders.

Schema (Zen 1.20.x / Firefox 151)

A folder = two synced records sharing one id, plus member tabs:

| Where | Key fields | |---|---| | folders[] | id, name, workspaceId, collapsed, parentId:null, emptyTabIds:[], userIcon | | groups[] | id (same), name, color:"zen-workspace-color", collapsed | | tabs[] (member) | groupId:, zenWorkspace:, pinned:true, zenEssential:false |

  • Essential: zenEssential:true. Scoped by CONTAINER (userContextId), not zenWorkspace — this is the #1 gotcha. With zen.workspaces.separate-essentials=true (Zen default), an essential shows only in workspaces whose containerTabId matches its userContextId; userContextId:0 = the default container = the first/Home workspace. To make essentials global (Arc-style, same in every space), set zen.workspaces.separate-essentials=false (via user.js) and use userContextId:0 / zenWorkspace:null. For a per-workspace essential, set userContextId to that workspace's containerTabId.
  • Plain pin: zenEssential:false, zenWorkspace:, no groupId. Scoped by zenWorkspace (works with userContextId:0).
  • Workspace lives in spaces[]: {uuid, name, icon(emoji), containerTabId, position, theme}. ensure_workspace() creates one if absent.
  • Ordering = tab array order. tab.index is the active history-entry pointer (set to 1), NOT position.
  • IDs are -. Tabs need only a minimal entries:[{url,title,triggeringPrincipal_base64:"{\"3\":{}}"}]; Firefox fills the rest on load.
  • Skip arc://* URLs — they don't resolve in Zen.

Library Quickref

from zen_session import ZenSession, find_profiles
s = ZenSession(find_profiles()[0])
s.backup()
home = s.workspace_by_name("Home")
s.clear_folders(workspace=home)                 # idempotent re-runs
s.add_essential("https://discord.com/")         # global top icon
s.add_tab("https://news.com/", workspace=home)  # plain pin
fid = s.add_folder("Finance", home)
s.add_tab("https://sheet/", workspace=home, folder_id=fid)
s.save()                                         # Zen must be quit

Common Mistakes

  • Writing while Zen runs → changes vanish on quit. Quit first.
  • Folder in only one array → ghost/empty folder. Always write BOTH folders[] and groups[] (the library does).
  • Tab missing zenWorkspace → tab lands in the wrong/no space. Set it (essentials use null).
  • liblz4 not foundbrew install lz4 (mac) / apt install liblz4-1 (linux); fix the path list in zen_session.py if needed.
  • No backup → re-run with backup(); keep the .bak until verified.

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.