Skip to content
magicelk235 edited this page Jul 22, 2026 · 2 revisions

Viaduct

Viaduct is a macOS command-line tool that converts a Google Chrome extension into a Safari Web Extension ready for local development, ad-hoc testing, or an Xcode/TestFlight build. It extracts the extension, rewrites the manifest for Safari, injects a runtime compatibility shim for unsupported chrome.* APIs, and drives Apple's safari-web-extension-packager + xcodebuild to produce a signed app.

npm install -g @magicelk235/viaduct
viaduct <input> [options]

This wiki is contributor-grade documentation, verified against the source under src/ and grounded in the git history. Every non-obvious behavior cites the commit that introduced it; the Release History maps each version tag to what shipped.


Quick start

Convert straight from a Chrome Web Store link (the CRX is downloaded for you):

viaduct "https://chromewebstore.google.com/detail/<name>/<id>"

Analyze without converting, reports incompatibilities and previews the manifest rewrites:

viaduct ./my-extension.zip --analyze

Stage for Safari 18's "Add Temporary Extension" (no Xcode, fastest iteration):

viaduct ./my-extension.zip --temp-load

Full build + team-signed install that persists across Safari restarts:

viaduct ./my-extension.zip --install --team auto

Full flag reference: CLI Reference.


How it works (the short version)

A single orchestrator (src/convert.ts) runs a deterministic pipeline: extract → analyze → stage → inject shim → rewrite manifest → wire OAuth/actions → convert the service worker → package with Xcode → build/sign → install. Blocking errors abort unless --force.

Chrome ext ─▶ extract ─▶ analyze ─▶ stage ─▶ shim ─▶ manifest rewrite
   ─▶ OAuth bridge ─▶ SW→bg page ─▶ (temp-load stop | package → xcodebuild → install)

The two hardest problems are handled by dedicated subsystems: the Runtime Shim (a ~5,900-line hand-written .js that backfills or emulates the chrome.* APIs Safari lacks, without ever throwing at top level) and the Manifest Transform (which strips what Safari rejects and reshapes what it needs). The Safari Quirks page catalogs the specific WebKit behaviors these work around.


Documentation map

Understand it

  • Architecture: tech stack, source layout, invariants, the build model.
  • Conversion Pipeline: every stage in convert.ts, in execution order, with the flow diagram.

Use it

  • CLI Reference: every flag, default, standalone mode, exit code, and recipe.
  • Build and Install: Xcode packaging, ad-hoc vs team signing, install/uninstall/verify, temp-load.
  • Limitations and FAQ: what conversion can't fix (platform limits, not bugs) + troubleshooting.

Subsystems (deep dives)

  • Input Handling: download, extract (magic-byte detection, CRX parsing), clean staging, icon synthesis.
  • Manifest Transform: the manifest rewrite, the DNR sanitizer, the compat-data tables.
  • Analyzer: the compatibility scanner, the issue/severity model, the --analyze JSON output.
  • Runtime Shim: the flagship compatibility layer: messaging/port routing, storage, native proxy, SW conversion.
  • OAuth Bridge: the Chrome↔Safari identity/externally_connectable handshake (and what it can't fix).
  • Safari Quirks: the cross-cutting catalog of WebKit behaviors viaduct defends against.

Contribute


What it can't do (read before filing a bug)

Some things are Safari/platform constraints no converter can fix. Full uBlock Origin's blocking webRequest can't block, chrome.identity OAuth logins can't complete, and storage.sync doesn't sync across devices. See Limitations and FAQ for the full honest list and the real remediation for each.

Clone this wiki locally