{"id":50813985,"url":"https://github.com/ashinno/wechat-multi","last_synced_at":"2026-06-13T07:33:51.055Z","repository":{"id":358261921,"uuid":"1240691727","full_name":"ashinno/wechat-multi","owner":"ashinno","description":"Run multiple WeChat accounts side by side on macOS — menu bar app that clones WeChat.app with unique bundle IDs to bypass the singleton check.","archived":false,"fork":false,"pushed_at":"2026-06-06T11:04:59.000Z","size":1077,"stargazers_count":23,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-06T11:20:49.681Z","etag":null,"topics":["appkit","macos","menubar","multi-instance","productivity","swift","wechat"],"latest_commit_sha":null,"homepage":null,"language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ashinno.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-16T12:56:04.000Z","updated_at":"2026-06-06T09:53:14.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ashinno/wechat-multi","commit_stats":null,"previous_names":["ashinno/wechat-multi"],"tags_count":17,"template":false,"template_full_name":null,"purl":"pkg:github/ashinno/wechat-multi","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ashinno%2Fwechat-multi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ashinno%2Fwechat-multi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ashinno%2Fwechat-multi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ashinno%2Fwechat-multi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ashinno","download_url":"https://codeload.github.com/ashinno/wechat-multi/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ashinno%2Fwechat-multi/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34276501,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-13T02:00:06.617Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["appkit","macos","menubar","multi-instance","productivity","swift","wechat"],"created_at":"2026-06-13T07:33:50.321Z","updated_at":"2026-06-13T07:33:51.047Z","avatar_url":"https://github.com/ashinno.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/icon.png\" width=\"180\" alt=\"WeChat Multi icon\" /\u003e\n\u003c/p\u003e\n\n# WeChat Multi\n\n\u003e Run multiple WeChat accounts side by side on macOS — from a single menu bar icon.\n\n**English** | [简体中文](README.zh-CN.md)\n\n![platform](https://img.shields.io/badge/platform-macOS%2013%2B-blue)\n![swift](https://img.shields.io/badge/swift-5.7%2B-orange)\n![license](https://img.shields.io/badge/license-MIT-green)\n[![build](https://github.com/ashinno/wechat-multi/actions/workflows/build.yml/badge.svg)](https://github.com/ashinno/wechat-multi/actions/workflows/build.yml)\n\nWeChat for Mac enforces a singleton: it only lets you launch one copy at a\ntime and silently kills any second process. **WeChat Multi** gets around that\nby cloning `/Applications/WeChat.app` into uniquely-identified copies under\n`~/Applications/WeChat Multi/`. Each clone has its own `CFBundleIdentifier`,\nso macOS gives it a fresh sandbox container and WeChat treats it as a separate\napp with its own login session.\n\nThe result: you can sign in to as many accounts as you want — work and\npersonal, two phone numbers, a burner — each in its own window, each\nsurviving restarts.\n\n\u003e **Windows?** A Windows port is in development under [`windows/`](windows/) —\n\u003e it uses a different technique (releasing WeChat's named-mutex single-instance\n\u003e lock, since Windows has no app-bundle cloning). See the\n\u003e [port plan](docs/windows-port-plan.md) and [`windows/README.md`](windows/README.md).\n\n## What the menu looks like\n\n```\n 💬 WC 2                                          ⏰ 9:41\n ┌──────────────────────────────────────┐\n │ 2 WeChat instances running           │\n ├──────────────────────────────────────┤\n │ ⚠️ 1 clone out of date               │\n │ Refresh Outdated Clones…             │\n ├──────────────────────────────────────┤\n │ Launch New Instance              ⌘N  │\n ├──────────────────────────────────────┤\n │ Running                              │\n │ Main account — PID 34810           › │\n │ Work (Slot 1) — PID 40853          › │\n │ Quit All Instances               ⌘K  │\n ├──────────────────────────────────────┤\n │ Choose WeChat.app Location…          │\n │   ↳ /Applications/WeChat.app         │\n │ Open Clones Folder                   │\n │ Reset All Clones (1)…                │\n ├──────────────────────────────────────┤\n │ About WeChat Multi                   │\n │ Quit WeChat Multi                ⌘Q  │\n └──────────────────────────────────────┘\n```\n\nEach running-instance row expands to a submenu with **Bring to Front**,\n**Quit This Instance**, and **Rename…** (lets you name a clone \"Work\" or\n\"Personal\" — the name shows in Cmd+Tab and the Dock).\n\nThe **⚠️ outdated clones** row only appears when WeChat has updated since\nyour clones were last built; one click rebuilds them while preserving each\nclone's signed-in session.\n\n## Download\n\nDon't want to compile? Grab the pre-built `.app` from\n[the latest release](https://github.com/ashinno/wechat-multi/releases/latest),\ndrag it into `/Applications`, and double-click. macOS may ask you to right-\nclick → Open the first time because it's ad-hoc signed.\n\n### Homebrew\n\n```bash\nbrew tap ashinno/wechat-multi https://github.com/ashinno/wechat-multi\nbrew install --cask wechat-multi\n```\n\nUpgrade with `brew upgrade --cask wechat-multi`; the cask version is bumped\nautomatically by CI whenever a new release is published. To remove it later,\n`brew uninstall --cask wechat-multi` (add `--zap` to also delete clones and\ntheir signed-in sessions).\n\n## Features\n\n- 🍎 **Native menu bar app** — no Dock clutter, no Electron, ~190 KB binary\n- ⚡ **One click to launch** a new, isolated WeChat instance\n- 🏷️ **Per-slot custom names** (\"Work\", \"Personal\") — shown in Cmd+Tab and Dock\n- 🎨 **Color-coded avatars** — each clone gets a distinct dot color so you can\n  tell instances apart at a glance\n- 📊 **Progress panel during first-time clone** so you know it isn't hung\n  during the multi-second copy + sign step\n- 🚀 **Launch at login** toggle in Preferences (uses `SMAppService` — no\n  helper app, persists across reboots)\n- 🔄 **Auto-detects WeChat updates** and offers to refresh stale clones,\n  preserving each clone's signed-in session\n- 💾 **Automatic settings snapshots** — rotating backups of your slot names,\n  order, and preferences (taken on launch and before any import); roll back\n  from **Preferences → Restore from Snapshot…** if something goes wrong\n- 📋 **Lists running instances** with their PIDs and start times\n- 🪟 **Bring any instance to the front**, quit individual instances, or quit all\n- 🔍 **Auto-detects WeChat** in `/Applications`; falls back to a file picker\n- 🖥️ **Universal binary** (arm64 + x86_64), ad-hoc signed, no third-party\n  dependencies\n\n## Requirements\n\n- macOS 13 Ventura or later (uses `SMAppService` for launch-at-login)\n- The official WeChat app installed at `/Applications/WeChat.app`\n- Xcode Command Line Tools (`xcode-select --install`) — only needed to build\n\n## Install\n\n```bash\ngit clone https://github.com/ashinno/wechat-multi.git\ncd wechat-multi\n./install.sh\n```\n\n`install.sh` runs `build.sh` if needed, copies the bundle to\n`/Applications/WeChat Multi.app`, and launches it. The first launch shows a\nbrief alert pointing at the menu bar; look for **WC** in the top-right corner\nof your screen.\n\nTo build without installing:\n\n```bash\n./build.sh\nopen \"dist/WeChat Multi.app\"\n```\n\n## Usage\n\n1. Click the **WC** icon in the menu bar\n2. Choose **Launch New Instance** (⌘N)\n   - The first time each slot is created the app spends a few seconds\n     cloning WeChat.app (APFS makes this near-instant once the file system\n     primes)\n   - A separate WeChat window appears, ready for a fresh login\n3. Repeat as many times as you need accounts. Slot numbers go up indefinitely\n4. Each running instance shows up in the menu. Hover one to:\n   - **Bring to Front** — focuses that specific WeChat window\n   - **Quit This Instance** — sends SIGTERM to just that PID\n   - **Rename…** — name a clone \"Work\", \"Personal\", etc.; Cmd+Tab and the\n     Dock pick up the new name the next time you launch it\n5. **Quit All Instances** terminates every WeChat (clones and the original)\n\nThe original `/Applications/WeChat.app` is left untouched. You can keep\nlaunching it normally from the Dock or Spotlight; it shows up in the menu as\n\"Main account\".\n\n### After a WeChat update\n\nWhen the official WeChat updates itself, your clones are still on the old\nversion. The app detects this automatically the next time you open the menu\nand shows **⚠️ N clones out of date**; click **Refresh Outdated Clones…** to\nrebuild them from the new `/Applications/WeChat.app`.\n\nPer-account sandbox containers (saved logins, chat history) are preserved\nduring refresh because they live in `~/Library/Containers/com.wechatmulti.cloneN/`,\nwhich is separate from the bundle being replaced. Custom slot names are\npreserved too. You will need to quit running instances that are being\nrefreshed; the dialog asks for confirmation first.\n\nIf you want a *full* reset including sandbox data:\n\n```bash\n# Quit everything first via the menu, then:\nrm -rf \"$HOME/Applications/WeChat Multi\"\nrm -rf \"$HOME/Library/Containers/com.wechatmulti.clone\"*\n```\n\n## How it works\n\nFor each slot *N*, the app:\n\n1. `cp -Rc /Applications/WeChat.app ~/Applications/WeChat Multi/WeChat N.app`\n   (the `-c` flag uses APFS copy-on-write, so it's instant and uses no extra\n   disk space until WeChat writes to the bundle)\n2. Rewrites `Contents/Info.plist`:\n   - `CFBundleIdentifier` → `com.wechatmulti.cloneN`\n   - `CFBundleName` / `CFBundleDisplayName` → your custom slot name, or\n     `WeChat N` as a fallback\n3. Deletes `Contents/_CodeSignature` (modifying Info.plist invalidates the\n   original Tencent signature)\n4. `codesign --force --deep --sign - \u003cclone\u003e` (ad-hoc re-sign)\n5. `xattr -dr com.apple.quarantine \u003cclone\u003e` (skip the Gatekeeper first-launch\n   prompt)\n6. `open -na \u003cclone\u003e`\n\nBecause each clone has a different bundle identifier, macOS allocates a\nseparate sandbox container and WeChat's \"another instance is running\" check\ndoesn't fire.\n\nThe trade-off of ad-hoc signing: keychain access entitlements tied to\nTencent's team ID no longer apply, so passwords aren't shared between clones.\nYou'll log in fresh per instance — which is exactly what you want for\nmulti-account use.\n\n## Uninstall\n\n```bash\n# Quit the menu bar app, then:\nrm -rf \"/Applications/WeChat Multi.app\"\nrm -rf \"$HOME/Applications/WeChat Multi\"\nrm -rf \"$HOME/Library/Containers/com.wechatmulti.clone\"*\ndefaults delete com.wechatmulti.app 2\u003e/dev/null\n```\n\n## Caveats\n\n- WeChat's auto-update only runs inside `/Applications/WeChat.app`. Clones\n  are read-only as far as Sparkle is concerned — rebuild them via **Reset\n  All Clones** after the official app updates\n- macOS treats each clone as a distinct app for permissions. The first time\n  a clone wants camera, microphone, or screen-recording access, you'll get\n  the standard prompt and need to grant it\n- Notifications are namespaced per bundle ID, so each instance gets its own\n  banner style and \"Do Not Disturb\" entry in System Settings\n- This tool is unofficial and not affiliated with Tencent. Use at your own\n  risk; if WeChat changes how it enforces single-instance behavior in a\n  future update, the clone trick may need to be revisited\n\n## Architecture\n\nThe code is split into a pure, fully-tested core and a thin AppKit/SwiftUI shell:\n\n```\n.\n├── Package.swift                       # 3 targets: Core (lib), app (exe), tests\n├── Sources/\n│   ├── WeChatMultiCore/                # Foundation-only, 100% unit-tested\n│   │   ├── KeyValueStore.swift         #   settings seam + DefaultsKey catalog\n│   │   ├── SemVer.swift                #   version parsing / comparison\n│   │   ├── ProcessTable.swift          #   ps-output parser (locale-robust)\n│   │   ├── SlotOrdering.swift          #   display-order reorder/resolve\n│   │   ├── CloneNaming.swift           #   slot ↔ bundle-id / folder mapping\n│   │   ├── SlotSettings.swift          #   thread-safe names + order store\n│   │   ├── SettingsBackup.swift        #   JSON export/import + validation\n│   │   └── Changelog.swift             #   What's-new data\n│   └── WeChatMulti/                    # the app (UI + filesystem orchestration)\n│       ├── WeChatLauncher.swift        #   clone engine (atomic), composes Core\n│       ├── AppDelegate.swift / *View   #   menu bar, popover, windows\n│       └── …\n├── Tests/WeChatMultiCoreTests/         # 61 tests across 8 suites — run in CI\n├── Resources/Info.plist                # Bundle metadata (LSUIElement = true)\n├── build.sh                            # swift build → .app bundle assembly\n└── install.sh                          # Copy to /Applications and launch\n```\n\nAll the historically bug-prone logic — the `ps` parser, slot ordering, version\ncomparison, naming conventions, and backup/restore — lives in `WeChatMultiCore`\nwith no AppKit or filesystem dependencies, so it's exercised deterministically\nby `swift test` on every push and release.\n\n```bash\nswift test          # run the full Core suite\n```\n\n## Contributing\n\nPRs welcome. A few directions if you're looking for ideas:\n\n- Sparkle auto-update (with EdDSA-signed appcast from CI)\n- Notarization (would remove the right-click-Open ceremony)\n- Global hotkey to toggle the popover from anywhere\n\n## License\n\n[MIT](LICENSE) © 2026 ashinno\n\nWeChat is a trademark of Tencent Holdings Ltd. This project is not\naffiliated with, endorsed by, or sponsored by Tencent.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fashinno%2Fwechat-multi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fashinno%2Fwechat-multi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fashinno%2Fwechat-multi/lists"}