Quick WeChat forward can now include an HTML preview. Tick it and the ZIP gains an index.html: unpack the whole ZIP, open it, and read the chat as bubbles — search by sender or text, jump by date, zoom images, play audio and video inline.
Your own messages are placed on the right automatically, and there is a picker in the top corner when they cannot be detected.
A sponsored post no longer ends the whole export. An ad has no author the way an ordinary post does, so reading one raised the author error — the deliberate refusal to guess, which is right for a post whose author failed to load and wrong for one that never had an author. A single ad anywhere in the requested range meant nothing was exported. Ads are now skipped and the run continues. The ad badge is absent from the accessibility tree, so the evidence is the ad's own popover: both the 赞助商提供的广告信息 notice and the 关闭该广告 button must be present, in those roles, before anything is treated as an ad — a post that merely mentions ads is not dropped from your export. The probe happens before the avatar is touched, since an ad's avatar navigates to the advertiser's site, and the popover is always dismissed with Esc, never by pressing 关闭该广告, which would remove the ad from your own feed.
Quick Moments forward (experimental). Choose how many recent posts to export, with photos and videos as separate options. Authors, the times WeChat displays and the full text go into a chronological TXT, with the media in a media/ folder inside one ZIP, pasted into an app or saved to a folder. A post whose author cannot be read stops the run rather than being guessed at — a wrong attribution is worse than a missing post — and anything that could not be loaded is written into the text instead of quietly dropped. Photos and videos have to be opened and downloaded one at a time, which is slow, so leave the computer alone while it runs; ESC stops it. The clipboard is borrowed during collection and is not restored over anything you copied in the meantime.
Either quick forward can now land in a folder. Pasting into an app was the only ending, which ruled out the case where the export itself is the point — an archive you keep, hand to someone, or feed to something that reads a directory. A destination is now an app or a folder, picked the same way; folders open after saving, and a name collision is worked around rather than overwritten.
No cap on the message count, and batches can be merged. Batches of 100 export back to back and the pane estimates five seconds per hundred. A run can extract those batches and repack them as a single ZIP, which is offered past 500 messages — the point where handing an app many files starts failing on its own. The original ZIPs stay in history if merging or delivery stops.
One naming scheme. Chat and Moments exports are both named by source, the span the content covers and the count. Only a range with both endpoints describes content; anything else is dated by export time, which is all a Moments post with a relative timestamp can honestly claim.
A shorter README. The build commands and source tree are gone, and what remains is written for people who do not read Swift.
A right-click that does not take no longer ends the run. Just after a scroll settles, WeChat sometimes shows the context menu without the click having actually landed on the message; and because Qt's menu items expose no AXPress, the press has to be a synthetic click, which misses while the popup's coordinates are still moving. The whole right-click → 多选 → 合并转发 transition now retries — up to four times, alternating between the two click points on the bubble and re-locating the anchor row from the current geometry each time — and a menu item is only clicked once two consecutive scans agree on where it is.
A message arriving mid-run no longer stops the forward. The tracker assumed the list only moves when it is scrolled: an arrival adds or pushes out visible rows and can reverse the direction things moved in, and any of that used to end the run — in an active group that is the normal case, not an edge one. It now re-locates itself by the longest stretch of messages the two snapshots still share, falling back to whichever position is nearest the previous one when repeated rows make that ambiguous.
An unrecognised message kind no longer aborts a forward. Each exported record used to be compared against the message it was supposed to be, and that comparison had to know the kind first — red packets, Channels cards, merged chat-record cards, labeled stickers, video calls each needed their own rule, every one of them written after a run had already failed on it. Any kind not yet accounted for stopped the forward, for messages WeChat had exported perfectly well. The native ZIP is now delivered as-is.
The archive is still checked for integrity: every entry goes through the same CRC check, and an empty or unreadable one is refused with the file kept.
The count is now shown as "about N": it comes from parsing the transcript, so it is an estimate and no longer presented as exact.
History loads faster: each page of history used to be confirmed by travelling back to the newest message. The pass now reads how much arrived from where the keyboard focus moved, and returns to the bottom only once at the end.
Fixed: a run could stall when the last row was a timestamp or a 拍了拍 notice. Neither is a message, and the list was judged not to have reached the bottom when it already had.
Fixed: these message kinds stopped a forward — merged chat-record cards, labeled animated stickers, video calls, red packets and videos. WeChat's exported text describes them differently from the interface, and the mismatch used to abort the run.
Quick WeChat forward is much faster: about 20 seconds for 500 messages (the previous release took about 30 seconds for 300). It used to scroll the wheel a screen at a time and stop after each one to work out where it had landed. It now uses the message list's own keyboard navigation — Home crosses the entire loaded history in one step, and an arrow key moves exactly one message. The keys go to WeChat directly rather than through the global event stream.
Messages taller than the window are handled correctly: an image or a long text bubble taller than a screen could not be stepped over by the wheel. One arrow key crosses it.
Channels cards pass verification: accessibility exposes such a card's author but not its video URL, so these messages used to be read as a mismatch and stop the run.
Forwarding several hundred WeChat messages no longer gives up halfway: WeChat reads a conversation off disk as you scroll into it — measured at about 64 rows per second over history it already holds and about 8 over history it does not. Every batch of 100 used to hit that boundary again, and the third or fourth would simply time out. A request past 100 now loads the whole stretch once before selecting anything, and it reads WeChat's own count first: if the history is already in memory, the pass costs nothing.
A long-standing bug fixed: returning to the newest message used one enormous scroll gesture, which WeChat clamps to about 50 points. It only ever appeared to work because the list is normally already at the newest message — scroll up first and it could not get back.
Forward to Other Apps is found on every Mac: WeChat stacks a promotion above that row for each companion app installed (企业微信, WorkBuddy), so it sits in one of three places. Clicking a fixed position happened to match a machine with exactly one promotion; on macOS 26 with none, the click landed in the recipient list. It is now located by structure — promotions and the tab row have no name, every contact does — and verified on both macOS 15 and macOS 26, with no screen-recording permission involved.
Escape stops a forward immediately: the automation owns the pointer while it runs, so Cancel has to be aimed at. Escape does not.
The message count takes only digits: the field was free text until it lost focus, so an input method could leave "②00" sitting in it. Non-digits are now refused as typed, and digits in any form (②00, 200) fold to 200.
Quick WeChat forward reaches apps that are not in front: it used to fail whenever the destination was behind another window or minimised. Dukou now brings the app forward, restoring a minimised window, before it pastes.
A status capsule while it runs: it floats in the corner, names the step it is on, asks you to keep your hands off the mouse and keyboard, and cancels on one click. A failure is said there too, with a button back to Settings — by then Settings is usually buried behind WeChat.
A third less waiting: the scroll now steps by the height of the visible list instead of crawling, and paces itself to what WeChat can keep up with. 120 messages went from 17.3 s to 11.2 s; 300 take about 30 s.
The Send to Custom picker opens next to the pointer: it used to sit in the shelf's corner, which on a multi-display Mac was often the wrong screen. It now appears beside the click that raised it, on that screen.
A redrawn DMG background: six Dukou bubble stickers ring the drag lane in the middle, every pointer aimed at the Applications folder.
Five forward-menu entries: Stash in Dukou / Send to Codex / Send to Claude / Copy to Clipboard / Send to Custom appear in WeChat's "forward to other apps" menu, each switchable in Settings.
A share extension with no interface: nothing appears on screen; the files land before the system reclaims its temporary copy, committed as one atomic batch.
A Dropover-style shelf: docked to the corner you chose, consumed when dragged out, gone when empty; files stay in History and age out on schedule.
Send to any app: your own list of targets — one goes straight through, several get a picker; terminal-like apps can receive quoted paths instead of files.
Attached prompt: a prompt of your own is pasted ahead of the files; keep up to three and switch between them.
Quick WeChat forward (experimental): name a group and a message count; Dukou drives WeChat through Accessibility, verifies the exported ZIP and pastes it into the target app.
Secure distribution: the Universal 2 app and DMG are Developer ID-signed, Apple-notarized and stapled, with an EdDSA-signed Sparkle update feed.