# Arc To Zen Migration

> 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.

- **Type:** Skill
- **Install:** `agentstack add skill-shub-rajput-arc-to-zen-migration-arc-to-zen-migration`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [shub-rajput](https://agentstack.voostack.com/s/shub-rajput)
- **Installs:** 0
- **Category:** [Web & Browser](https://agentstack.voostack.com/c/web-and-browser)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [shub-rajput](https://github.com/shub-rajput)
- **Source:** https://github.com/shub-rajput/arc-to-zen-migration

## Install

```sh
agentstack add skill-shub-rajput-arc-to-zen-migration-arc-to-zen-migration
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## 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.
4. **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).
5. **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

```python
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 found** → `brew 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.

- **Author:** [shub-rajput](https://github.com/shub-rajput)
- **Source:** [shub-rajput/arc-to-zen-migration](https://github.com/shub-rajput/arc-to-zen-migration)
- **License:** MIT

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

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-shub-rajput-arc-to-zen-migration-arc-to-zen-migration
- Seller: https://agentstack.voostack.com/s/shub-rajput
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
