Be careful with old versions! These versions are displayed for testing and reference purposes.You should always use the latest version of an add-on.
Latest version
Version 1.7.134
Released Nov 14, 2026 - 2.02 MBWorks with firefox 128.0 and later- release: 1.7.134
- fix(multichat): a tab whose twitch channel the page dropped rejoins within 15s instead of freezing until a refresh; a config change no longer parts a name another tab or the page still shows; the join-failed toast says it once
Source code released under MIT License
Older versions
Version 1.7.133
Released Nov 14, 2026 - 2.02 MBWorks with firefox 128.0 and later- release: 1.7.133
- fix(multichat): a mod removing any copy of a simulcast send greys its one row; a ban greys only the platform it was made on
- fix(multichat): a removal on a leg folded into another platform's row clears that row
Source code released under MIT License
Version 1.7.132
Released Nov 12, 2026 - 2.02 MBWorks with firefox 128.0 and later- release: 1.7.132
- feat(relay): one extension posts a relayed send: claim before posting, decline with the reason when it cannot (background.js budget +2000B for the claim step)
- fix(send): one submit posts once per platform: retry resends only legs that never confirmed under the same send id, kick never re-posts an unconfirmed send, one reconnect drain at a time, ime enter is not a send
- fix(marks): one send is one [h] row in every arrival order — origins fold legs already on screen, the own-send notice keeps the twitch identity, dropped kick/youtube echoes are still recorded, a stranger's same words are not your echo
Source code released under MIT License
Version 1.7.131
Released Nov 11, 2026 - 2.02 MBWorks with firefox 128.0 and later- release: 1.7.131
- fix(marks): the background forwards chat:origin_tag, a page-sent frame type off its allowlist was dropped without a word
- feat(marks): a send from the extension is recorded server-side — one send id per send, twitch origin_tag after the socket write, kick and youtube own echoes witnessed by message id
Source code released under MIT License
Version 1.7.130
Released Nov 11, 2026 - 2.02 MBWorks with firefox 128.0 and later- release: 1.7.130
- fix(marks): youtube tabs join their origins room and seed under the handle key; every seeded channel re-seeds after a ws reconnect
- feat(marks): [h] is live for everyone — origin ids seed per channel and arrive as chat:origin; rows are born [h] or flip in place; legs fold by send id
- fix(marks): platformMarkHtml escapes its fields; stale source-pin tests follow the helper
- test(marks): discover chip guard
- fix(marks): a stranger's line with your words is not re-marked as your send; discover chips use platformMark
- fix(marks): one platformMark helper for every [T]/[K]/[Y]/[H]; unknown platform is [?], whisper dm is [H] not [HS]
- test(merged): the simulcast fold runs from the real module, so its lines count — coverage fell under the floor and ci went red; pre-push now gates the floor like ci
Source code released under MIT License
Version 1.7.129
Released Nov 11, 2026 - 2.01 MBWorks with firefox 128.0 and later- release: 1.7.129
- test(e2e): firefox freshness — the twitch panel against an independent irc socket, through a background tab, a network drop, an update and a channel switch
- fix(send): a twitch send that never echoes replaces the send socket, so the next send goes out on a fresh one instead of needing a refresh
- fix(merged): one line sent to twitch and kick shows once — legs fold by sender and words like the site, so history and a pane opened after the send no longer show [T] and [K]
- fix(twitch): a line twitch shows reaches the panel even when the reader never got it — the tap waits for the reader's copy instead of dropping its own, and a reader that keeps missing lines reconnects (background.js budget +384B for that handler)
- fix(multichat): timers that outlive a channel switch stay armed — native tap, auto-claim, native-chat watchdog, persist debounces, send timeouts
- fix(send): the twitch send socket keeps its keepalive, reconnect and handshake timers across a channel switch — a drained keepalive left a dead socket reading as alive and every send vanished until a refresh
- feat: open profile card joins its author room so profile:updated reaches it
- refactor(card): drop the dead hs-follow/block-btn/report-btn overrides, mirrored from the site
- feat(card): the underlined letters are real keys, one keymap from the shared model
- ci: headless firefox smoke beside the chromium one
- test(ws): the send scan no longer reads broadcasterId as a send, six excuses it invented go
Source code released under MIT License
Version 1.7.128
Released Nov 10, 2026 - 2.01 MBWorks with firefox 128.0 and later- release: 1.7.128
- build: regenerate chrome/ locales and manifest (centrifugo csp, new notice keys)
- feat(notif): user-warned shows the moderator's reason as a notice that outlasts a toast
- feat(card): profile:updated re-reads the open profile card
- feat(logs): user-log:removed drops the removed archive lines from an open chat-logs view live
- fix(ws): message:hidden is read flat, as the server sends it — a hidden post was never removed
- feat(card): an open profile card re-asks on profile:color and on follow changes
- feat(live): a single twitch sub (stream:sub) shows as an event line; worker-level tests for the new live frames
- feat(feed): a post's media scan settling (message:approved / message:flagged) updates the cached copies — flagged media is held behind the viewer's toggles
- feat(dm): threaded dms arrive live in the whispers tab — dm:message, dm:thread-update, dm:typing
- refactor(ws): drop the dead settings:patch and settings:delete cases — the server never sends either
- fix(kick): move the realtime tap from pusher to centrifugo — fresh discovery per connect, a backoff that ends, exact event names so an unpin no longer deletes a line
- fix(zebra): stripes stay in phase when a merged tab drops rows mid-list and when rows rebuild in place — restripe upward from the gap so the newest rows never change
- fix(ws): a silent channel no longer reconnects the whole socket — the background only obeys a watchdog's force-reconnect when its own socket has gone quiet
- fix(live): a follow-history replay no longer marks its texts seen, so a go-live with the same text as yesterday's still shows its line
- style(tests): biome format health-checkin-wire
- test(render): the youtube delete check re-places its rows if the overlay re-renders them away; the picker End check waits for the cursor's tile to settle
- fix(picker): the keyboard cursor keeps its tile in view while images and chunks reflow the grid; composer check waits for the list's last redraw
- test(render): tab-complete seeds the background's channel copy, waits for the set to draw before the first Tab
- style(tests): biome format health-checkin-wire, it held the pre-push lint red
- feat(tour): a big yellow arrow points at the thing each card talks about
- ci: pin gitleaks 8.30.1; the action's default 8.24.3 ignores [[allowlists]]
- build: ratchet bundle budgets again after the duplicate and dead-code cuts
- refactor: one platform-row, cell-loader and badge-hires def each; drop write-only yt maps, dead helpers, unused props
- build: ratchet bundle budgets to the post-shake sizes (locale keys, dead code and lib tree-shake)
- refactor(css): drop the old colour picker, mode grid and cheer preview rules nothing renders
- perf(build): minified bundles tree-shake the lib in one esbuild pass; drop four never-read window exports
- refactor: drop dead functions, the native notes cache and the unused autocomplete preload map
- …see the full changelog in the repo
Source code released under MIT License
Version 1.7.127
Released Nov 9, 2026 - 2.04 MBWorks with firefox 128.0 and later- release: 1.7.127
- feat(rows): mod anniversary wears the green fill; twitch's msg-id modiversary is recognised
- fix(callouts): mod anniversary share sends SendUserModiversaryNotice
- Revert "fix(callouts): mod anniversary token picked by count, mod kind or only non-resub; a miss records the queue's key shapes"
- fix(callouts): mod anniversary token picked by count, mod kind or only non-resub; a miss records the queue's key shapes
- build: locale refresh for the mod anniversary share prompt
- fix(callouts): mod anniversary share uses its own token in heatsync's share mode
Source code released under MIT License
Version 1.7.126
Released Nov 9, 2026 - 2.04 MBWorks with firefox 128.0 and later- release: 1.7.126
- test(render): the youtube deletion goes to every twitch tab, not whichever one find() lists first
- ci: whole-suite line and function coverage has a floor that only rises
- ci: the emote collision rigs run on every push
- fix(upload): the accept list is one literal, so both pickers' html is provably safe
- feat(native): upload your own emote from the native picker; native rows pick your emote's size rung by dpr
- test(release): every tagged version and the current one have a changelog entry
- docs(changelog): entries for the 34 tagged versions that had none
- docs(readme): localized claim says what is true, links the architecture page
- docs: architecture — what runs where, src to dist, the site mirrors
- build: locale refresh for the relay, announce and close strings
- test(emotes): the hostile-input suite gets the rung helpers as globals, as the bundle does — it failed run alone
- style(tests): biome import order
- test(parity): all three platforms feed the open chat-logs view live
- fix(thread): loading/error/empty lines in a thread are 13px; type ratchet cap for sub-13px goes to 0
- fix(i18n): off-twitch mod relay errors localized; announce-twitch-only and close keys added to all 34 locales
- fix(tour): a youtube-only mod sees the mod switch on the last card
- fix(badges): feed quotes and reply headers draw the picked badge beside the plus mark
- build(budget): content.js +0.9KB — the native-page close × is the shared glyph module
- fix(ui): native-page text 13px+, weights 400/700, no uppercase; ratchet at the social.js 3
- fix(ui): native-page close × is the shared glyph
- build: locale refresh for the mod-anniversary string
- build(budget): content.js +7.3KB — native chat carries the filter-rules engine
- fix(callouts): a mod anniversary is not a resub
- fix(keys): a key heatsync consumes owns its keyup too
- fix(youtube): mod actions show the gray notice and land in the mod log
- fix(youtube): replayed lines render but fire no alerts
- fix(content): highlight rules on native chat + fold old filters with the overlay off
- build: locale refresh
- fix(i18n): the new-messages pill and the card's unmute label speak the viewer's language
- fix(ui): text is 13px and up, weights are 400 or 700, no uppercase; a ratchet holds the last 21 to shrinking
- feat(ui): every icon is a unicode glyph — the twitch menu, settings tabs, undo/redo/rotate and search; a guard keeps svg to the close ×
- feat(feed): embeds load on click — a button names the host, no third party sees the viewer before it
Source code released under MIT License
Version 1.7.125
Released Nov 8, 2026 - 2.03 MBWorks with firefox 128.0 and later- release: 1.7.125
- build: locale refresh for the mod-notice and tab-mode strings
- test(bg): unknown types are answered; non-objects and bg_* still left alone
- fix(i18n): tab-mode hint and mod-toolbar chat lines come from the locale files, all 34 locales
- fix: twitch gql bridge runs only an allowlist of query shapes, else op_not_allowed
- fix(bg): unknown message types get an unknown_type reply, bg_* left to their own listeners
- fix(bg): reconnect timer catches connect failure; queue stamp stays off the wire
- fix(bg): a badge refresh that got nothing no longer holds the ttl stamp
- feat(doctrine): js-built style held to square + flat, twitch brand is the tokens value
- test(lint): the merged suites meet ci's zero-warning bar — templates, literal keys, no comma op, no useless ternary
- refactor: hand-written page scripts move from chrome/ to src/content
- build(budget): remeasure — +110KB raw is the new strings in all 34 locales (row mode, screen reader, mod log, tour, sending checklist; locale json already minified) and +40KB code for those features; background grows by the yt/twitch status checks and relay guards
- style(tests): format bridge-pages-stay-silent
- build: locale refresh
- fix(send-status): the twitch row asks the background yes/no, never holds the token; site ids escaped
- test(render): tour check follows the six cards — focus asserted before any click, row re-sent after the reload, checklist reads the open settings pane
- build: locale refresh
- fix(keys): alt+1-9, alt+[ ] and alt+r work from the composer
- test: notifyMention's two new callers meet — the rule-alert test stubs the screen-reader hook, the sr test finds notifyMention with its viaRule argument
- fix(relay): relayed sends no longer need a local keypress
- test(html): a ratchet over every html sink in src and chrome
- fix(html): paint css, ids, counters and tab labels are escaped before they reach innerHTML
- fix(relay): kick/youtube sends the server relays need a real keypress and stay under caps
- fix(twitch): the twitch login cookie stays in the worker unless the chat socket needs it
- test(render): row mode, the row menu, the tab move items and screen reader modes in a real browser
- test(emotes): the render suites that import emotes.js get the rung helpers as globals, as the bundle does
- test(kick): the send tests carve the fatal-error set as a statement, not a line
- ci(bench): the merged-tab bench takes --budget; the nightly runs it for the row-equivalence check until a baseline is measured
- refactor(kick): drop the dead typeof guard on initKickNativeTap — the module ships in the one core bundle for every host, so it was always true
- test(render): condition waits replace the fixed sleeps — stable box, retry-until-landed, observed suspend; the ones that wait out nothing or a product timer are named windows
- …see the full changelog in the repo
Source code released under MIT License
Version 1.7.123
Released Nov 7, 2026 - 1.9 MBWorks with firefox 128.0 and later- docs: reviewer notes disclose link previews and open-channel signal
- docs: internal planning docs leave the public repo; privacy policy is one page on the site
- docs: drop false preset/store-assets/host claims, trim store listing to the copy + rules
- fix: pre-push gate green — format, brand mirror exempt from biome, guards follow the shared rows
- feat(multichat): mention and reply-to-me rows are filled rows — no striping; zebra parity covers them
- build: rebased on main — shared hs-zebra, mention-row name cutout
- feat(multichat): shared stripe marker hs-zebra; mention rows put the name on the cutout
- build: shared text-role classes (hs-link, hs-mention, hs-reply-ctx) on every ext emitter
- build: shared mention row + session-first edge; style-parity covers rule, cheer, mention, seen
- build: shared contrast rule + style-parity fixtures for untriggerable row types
- feat(multichat): style-parity script — site renderer vs the built extension, per row type
- test: dim gray lives in the shared brand tokens
- refactor(multichat): rows render from the shared brand layer — tokens, filled-row css and classes are site byte copies
- feat(multichat): every notification row takes its family fill (olive, purple, navy, teal, red); mod actions go dim
- feat(multichat): one fill family — tokens, filled-row marker, name cutout for every filled row
- fix(multichat): notice rows take a chat row's type and height
- feat(multichat): filled rows never take part in striping; the name cutout is plain black
- feat(multichat): a first message ever gets a solid fill and a name cutout
- fix(multichat): a notice row does not count for zebra parity, as on the site
- test: zebra repaint harness loads the notice stripe helper
- feat(multichat): the notice-row name cutout follows the row stripe
- feat(multichat): the notice-row name sits on a black cutout
- Revert "feat(multichat): a notice-row name too dim for the olive reads white"
- feat(multichat): a notice-row name too dim for the olive reads white
- fix(multichat): notice rows take the site's padding and no bottom rule
- feat(multichat): switched-to and went-live rows get an olive fill, yellow / red text
- feat(multichat): switched-to and went-live rows get a 1px yellow box
- build: bundle refresh — trimmed tier ranking
- chore(budget): youtube-content 178300, background 305950 — exact-emote blocks and provider order
- fix(types): rank emote pool with typed sort keys
- style: format health-checkin-wire test (failed on main)
- build: bundle refresh — site emote-refs mirror (probe, pin helpers)
- build: bundle refresh — case-twin ranking
- fix(search): case twins both stay in tab/search; the one spelled like the typed word leads
- fix(search): case twins both stay in tab/search; the one spelled like the typed word leads
- build: bundle refresh — add key, probe-injected refs
- test: native kick browser collision check
- …see the full changelog in the repo
Source code released under MIT License
Version 1.7.122
Released Nov 7, 2026 - 1.89 MBWorks with firefox 128.0 and later- docs: changelog for 1.7.122
- build: bundle refresh — feed first paint, no mod lookup for built-in tabs
- perf(feed): a pane with no height waits to open before its first fetch
- fix(feed): a pane with no height builds no extra rows; one that grows taller than the rows built asks for more
- perf(feed): the first paint builds one screenful; scrolling builds the buffered rows before asking the server
- fix(multichat): rendering a built-in tab no longer asks twitch if you mod 'feed' or 'live'
- test: format
- test(ws-contract): site-settings:patch is the site's frame, the ext takes ui-state:update
- build: bundle refresh for hover reply
- feat(chat): opt-in hover reply button (hoverReply, default off), one row-reply source for menu and button
- build: bundle refresh for the highlight-word split
- fix(settings): highlight words fold per comma too, as the site split them
- build: bundle refresh for the settings pass
- chore(budget): background 305600, shared-utils 7200 — the per-site switch now reaches the server and retired keys are refused at the worker; no dependency
- refactor(settings): the site switch handler leaves the gate check to its merge
- fix(settings): typecheck the host filter and the subsystem gate reader
- style: format the settings pass
- refactor(settings): cut developer and tuning knobs — debug, crash log, render cap, provider order, partial links, per-site volume, cross-follow notify, feed shelves, native tab, feature pills
- refactor(settings): drop the highlight-word applier the filter fold left behind
- refactor(settings): one text filter — automod patterns, all-caps, muted words and highlight words fold into chat filter rules once
- refactor(settings): one third-party badges switch for bttv, ffz and chatterino
- refactor(settings): one density knob — lineHeight folds into messageDensity
- refactor(settings): cut the emote picker's second settings panel — emoteWysiwyg maps onto wysiwygEnabled, the rest were native-chat tweaks now fixed at their defaults
- refactor(settings): cut presets — one reset to defaults; retired keys are ignored from the server and dropped from the stored blob
- fix(settings): the per-site switches reach the server, so the boot merge stops switching them back
- fix(settings): a row shows only on the sites it affects — youtube layout on youtube, anonymous presence on twitch
- fix(settings): a name-paint mode from the site never inverts — 'off' is off
- fix(settings): display reset leaves the hidden-paint list alone
Source code released under MIT License
Version 1.7.121
Released Nov 6, 2026 - 1.97 MBWorks with firefox 128.0 and later- chore: release 1.7.121
- test: format
- fix(zoom): the hover card hides on touch alone, in the shared card css, so a zoomed mouse keeps it on site and ext
- chore: rebuild chrome bundle for the zoom fixes
- chore(budget): multichat-core 1587000 — the zoom fixes (twitch width refit, glyph-mask dpr watch) put the build 717B over; no dependency
- fix(zoom): painted-name glyph masks are redrawn when page zoom changes the pixel ratio
- fix(zoom): hover cards stay visible at 200%+ page zoom, the phone rule that hid them no longer matches a mouse
- fix(zoom): twitch chat no longer collapses to a 10px strip when page zoom narrows the viewport, and a squeezed width comes back on zoom-out
- fix(live): one went-live per streamer: a simulcast's other platform, or its primary changing hands as audiences cross, no longer fires a second line and desktop notification
Source code released under MIT License
Version 1.7.120
Released Nov 6, 2026 - 1.97 MBWorks with firefox 128.0 and later- chore: release 1.7.120
- feat(ws): blocks, settings deletes, whispers, plus, notifications read, bookmarks, mention rules and flair/card refresh apply live
Source code released under MIT License
Version 1.7.119
Released Nov 6, 2026 - 1.97 MBWorks with firefox 128.0 and later- test(ws-contract): drop the user:blocked/unblocked excuses, the server no longer sends them
- chore: release 1.7.119
- build: bundle refresh — stream lines
- feat(multichat): stream lines use the streamer's own platform id and colour
- test(cosmetics): put the real storage stub back after the throwing one
- build: bundle refresh — flame on your own lines
- feat(marks): your own lines wear the flame too
- fix(multichat): a hidden saved tab doesn't cover the page channel, so the temp tab shows instead of nothing
- fix(multichat): popout windows boot straight onto the temp tab or its covering saved tab
- build: bundle refresh — flair change repaints your rows
- fix(marks): a flair set or cleared on heatsync.org repaints your rows when the answer lands, not after the 10-minute ttl
- fix(multichat): a channel-less page no longer saves its fallback tab over 'live', so the next channel page opens that channel's chat; the panel follows the page to its tab
- feat(multichat): the watching tab is a temp tab, like the site's
- feat(composer): a merged tab's input shows where a send goes, [TKY] with each letter in its platform colour, like the desktop app
- test(confirm): pass t to the carved panel, and find the site's happy-dom from a worktree so the suite stops skipping
Source code released under MIT License
Version 1.7.118
Released Nov 5, 2026 - 1.96 MBWorks with firefox 128.0 and later- build: bundle refresh — sub emotes complete with inventory suggestions off
- fix(tab): twitch sub emotes complete with inventory suggestions off — they are not inventory
- build: bundle refresh — tab offers your own copy of a channel-shared name
- fix(tab-complete): a name you own under a different picture than the channel's completes to yours — the box showed the room's YESIDOTHINKSO, the sent row drew the one in your set
- revert: settings:delete handler — no server sends that frame, and its keys are site names, not the ext's
- build: bundle refresh, minified
- chore: rebuild
- chore: rebuild
- fix(settings): name-mark rows written out so the schema keeps its literal types
- chore(budget): multichat-core 1578200 — name marks, reply rows, composer lock, follows list, emoji tab, feed frames land together (+18KB measured)
- feat(chat): /nuke runs on the site too
- fix(style): no italics anywhere — stream events, system rows, /me, edited, card notes; markdown emphasis underlines
- chore(budget): multichat-core +13KB for the parity set (chat lock, follows list, emoji tab, feed frames, counter); no dependency
- feat(i18n): translate the new lock, follows, emoji and youtube status strings across 32 locales
- feat(chat): youtube chat-off and relay-full say so in a row, in plain words
- test: pin the mentions-survive-a-restart contract (owner, bound, a day, cleared on logout)
- feat(chat): an n/limit counter shows when the line is within 10% of the cap, red once over
- feat(ws): a mod-hidden post leaves the feed, post heat updates live, a dm deleted elsewhere leaves the whispers timeline
- feat(picker): an emoji tab: search by name or category, enter takes the first
- feat(chat): a keyboard list of who you follow is live (space f / alt+l): enter opens a chat tab, w watches
- feat(chat): the composer says when you're banned, timed out or locked by a room rule, and holds the send
- feat(chat): twitch rows wear sub flair, flame and heat bar before the name, like the rust app
- fix: a setting deleted on another device is deleted here too
- feat(multichat): heatsync reply, mention and fixed-report notifications are rows in the mentions tab, reading them clears the badge
- fix: a went-live row looks up a streamer chat hasn't heard: their twitch color, and their badges once the id lands
Source code released under MIT License
Version 1.7.117
Released Nov 5, 2026 - 1.94 MBWorks with firefox 128.0 and later- test(e2e-live): the known youtube opaque-frame refusal is screened on the console path too, not only pageerror
- chore(budget): manifest + totals to measured — 34-locale i18n (ce1059d1, 078309ca, bc429c21) took _locales to 5.3MB raw, kick sign-in exclusions (591a0842) grew the manifest; per-script budgets unchanged
- chore(ci): bun 1.3.14 → 1.4.4, the version heatpc and the site run; bundle rebuilds byte-identical
- feat: stream rows show the streamer's third-party badges before the name
- build: rebuild chrome bundle (minified)
- feat(i18n): translate english-identical strings across 33 locales; watch-streak notif is one message with $COUNT$
- build: rebuild chrome bundle (minified)
- feat(chat): reply + copy link live in the row right-click menu, drop hover reply button
- build: rebuild chrome bundle (minified)
- feat(i18n): route remaining ui literals through t(), slash descriptions resolve slash_desc_<cmd>
- feat(i18n): add keys + translations for multichat, popup and slash command descriptions in all locales
- fix: translate layout/tab-menu/edit-form strings in all locales, retranslate swap_upload
- refactor(multichat): channel tab menu is edit + remove; platforms, send to, sub links move into edit form
- feat(multichat): /sharelayout + /layout heatsync.org/m share links, tab menu copy
- feat(slash): announce, vip, mod, poll, prediction and color run on the site composer too
- build: bundle refresh, css minified again
- feat(multichat): twitch duplicate-message bypass via invisible suffix toggle
- build: bundle refresh for atomic swap
- fix(emotes): same-name swap is one add with replace, no remove-then-readd; your own upload keeps its name
- style: quote style in the rev test
- fix(multichat): drop a synced tab list older than the one already applied
- build: bundle refresh for sender emote until + send waits for emote add
- chore(emotes): sync emote-refs.js from the site (room emote of the same name wins over a non-inventory map hit)
- fix(emotes): a line with a just-picked emote goes out after its add lands, so it isn't stamped with your old emote of that name
- fix(emotes): a sender's past emote stops at its until, so a word they typed after removing it stays text
- fix(account): linking or unlinking a platform on heatsync.org reaches the ext without a restart: it re-reads the account on the server's account:changed and on every ws reconnect, so a linked user no longer sees "your emotes won't render for others"
- build: bundle refresh after rebase on main
- build: bundle refresh for preview order
- fix(emotes): the composer preview shows your own emote over the channel's of the same name, like the sent line; kick still sends the channel's kick-native one
- build: bundle refresh for sender-set-first line lookup
- fix(emotes): a line with no server ref draws the sender's own emote over the channel's of the same name, so the first line after an add or swap shows the one they picked
- …see the full changelog in the repo
Source code released under MIT License
Version 1.7.116
Released Nov 2, 2026 - 1.49 MBWorks with firefox 128.0 and later- chore: release 1.7.116
- docs: paint-spec comment names the field by what it is
- fix(twitch): a tab still watching revives a parked reader, and chat text saying RECONNECT no longer tears it down
Source code released under MIT License
Version 1.7.115
Released Nov 2, 2026 - 1.49 MBWorks with firefox 128.0 and later- chore: release 1.7.115
- fix(youtube): mod actions take the same road as a send, so a watch tab with no chat frame reaches the bridge tab
- fix(youtube): a send into a watch tab with no chat frame goes through the bridge tab, one routine for overlay and relayed sends
- fix: a rejected token is a logout only when the browser's cookie agrees
- chore(build): the gate is green again — budgets follow the unlinked-emote notice, one ternary, one format diff
Source code released under MIT License
Version 1.7.114
Released Nov 1, 2026 - 1.49 MBWorks with firefox 128.0 and later- build: bundle refresh (unlinked own-emote notice)
- fix: unlinked-account notice covers emotes you already own, once per emote per session
- build: bundle refresh (unlinked emote add notice)
- fix: emote auto-add on send says when the chat account isn't linked to the signed-in heatsync account
- build: bundle refresh (history reply graft)
- fix: history replay grafts reply context onto a bare live copy instead of dropping it
- build: bundle refresh (reply-parent login fallback)
- fix: twitch reply keeps its reply bar when parent display-name tag is absent (fall back to parent login)
- build: bundle refresh for yt not-live dot
- fix(youtube): a not-live answer clears a youtube-only tab's live dot
- refactor(paints): drop the unused drift backstop from the mirrored phase lib
- build: bundle refresh for paint start anchor
- fix(paints): a painted name is anchored and gated when its animations start, not when the pane scrolls
- build: bundle refresh for frame-start phase clock
- perf(paints): phase clock reads the frame's start, so the 4s drift sweep goes (idle hitch ~500ms at 4x cpu)
- build: bundle refresh for paint hover echo
- feat(paints): hovering a painted name chips every copy of it with one css rule
- build: bundle refresh for paint hover chip
- perf(paints): hover draws the name chip with overrides only; no pausing, plate removal or unhover resync (1s stall with scene paints)
- build: bundle refresh for sender emote versions
- fix(emotes): a cdn-stale sender set older than a seen version no longer wipes a just-added emote; non-ok batch replies count as errors
- build: bundle refresh for name hover
- fix: name hover on a notice row inverts only the name — the flag listener sat on the tab bar and never fired
- build: bundle refresh for tab counter
- fix: unread counts only on channel tabs, never on watching or the other built-ins
- build: bundle refresh for tab repair join
- test: ws contract excuses the site's kick-moderation frame
- fix: the twitch-only tab repair joins the new yt/kick leg at once, not on the next load
- build: bundle refresh for kick raid-in
- fix: a kick host event is an incoming raid row (raider raided in), not this channel raiding them
- build: bundle refresh for kick events
- feat: kick raids/hosts and polls from the pusher tap render as stream rows
- build: bundle refresh for card + paint spec sync
- test: ws contract excuses yt's emoji part, back to the original send scan
- test: ws contract reads broadcast only as a call, not inside 'broadcaster'
- fix: card + paint spec re-mirrored from the site (yt @handle once, chatter avatar, channel labels, paintIdFor)
- build: bundle refresh for channel parity
- test: sturdier owner-match extraction
- style: biome format
- fix: native yt chat only merges its own channel's emotes
- feat: fill my cockpit also imports kick follows
- fix: filter rules match yt @handles and list badges
- …see the full changelog in the repo
Source code released under MIT License
Version 1.7.113
Released Oct 30, 2026 - 1.47 MBWorks with firefox 128.0 and later- docs(changelog): 1.7.113
- build: bundle refresh for youtube resize release
- chore(bench): drag bench takes a kick or youtube url
- perf(resize): a youtube resize release skips the load-time player nudges, and chat position flips only the classes that changed — a release relayouted youtube five times and restyled the page on every apply
- build: bundle refresh for resize release perf
- chore(bench): real-input chat resize drag bench against a live channel
- perf(layout): a layout pass reads every size before it writes page-wide css vars, and skips vars that did not change — interleaved, each read restyled the whole twitch page
- perf(resize): letting go of the chat resize bar no longer rebuilds the panel — our own width write tripped the column watcher, which re-ran the whole ui setup and re-rendered every row
- build: bundle refresh for resize bar after soft nav
- fix(twitch): a channel reached from a non-channel page gets its chat resize bar — the panel first mounted where there was no right column, and soft nav never re-ran the handle setup
- fix(kick): the css fix checks for a page address before reading it — a test that left a document behind made it read a missing location at load, which failed the suite whenever that test ran first
- fix(7tv): a live add or removal is announced even when the channel's emote list is missing, and never becomes the whole list — every channel sharing the set hears it
Source code released under MIT License
Version 1.7.112
Released Oct 29, 2026 - 1.47 MBWorks with firefox 128.0 and later- docs: changelog for 1.7.112
- build: bundle refresh
- fix(multichat): the list re-pins after badge, paint, colour and tenure updates and after each older-row chunk on a restored tab, so the chat stops drifting up a tick and wobbling on tab switch
- build: bundle refresh
- fix(multichat): a failed emote image retries on a cache-busted url instead of dropping its src first, so the row stops collapsing to alt text and jumping back
- build: bundle refresh
- fix(multichat): twitch badge art is saved across a refresh, so sub and mod badges are pictures in the first paint instead of text chips that swap seconds later
- build: bundle refresh
- fix(multichat): emote box widths are saved across a refresh so images stop pushing text sideways as they load, and a late emote catalog swaps the on-screen rows first, in one step, holding the reader's place
- build: bundle refresh
- perf(multichat): names, badges and paints are saved across a refresh and in the first paint, the first lookup batch leaves after 60ms instead of 2s, and a backlog drains at 200ms; the ext bench reports layout shift
- build: bundle refresh
- perf(multichat): held rows mount in first-paint-sized bites again (smaller bites did more total work and no less stall); the ext bench reports felt latency, profile trees and invalidations
- build: bundle refresh
- perf(multichat): hovering an emote lights only the copies on screen, leaving a hover repaints only if a row arrived, tooltips stop re-parenting on every hover; add the interaction bench
Source code released under MIT License
Version 1.7.111
Released Oct 29, 2026 - 1.47 MBWorks with firefox 128.0 and later- build: bundle refresh
- fix(chat): the stack preview tooltip re-places itself when its images load, so a first hover is not mis-anchored
- build: bundle refresh
- fix(chat): a hovered emote stack previews at full size, and the hover hold never raises the 'N new' button
- Revert "fix(events): game-switch and go-live lines and pings only for your tabs and the live channel, not every joined room"
- Revert "build: bundle refresh"
- build: bundle refresh
- fix(events): game-switch and go-live lines and pings only for your tabs and the live channel, not every joined room
Source code released under MIT License
Version 1.7.110
Released Oct 29, 2026 - 1.47 MBWorks with firefox 128.0 and later- build: bundle refresh
- fix(picker): the sticky section header sits above the emotes scrolling under it
- build: bundle refresh
- fix(multichat): tab menu platform buttons take their platform's colour, grey when off
- build: bundle refresh
- fix(multichat): every channel tab gets platforms and send to, not only multi-platform ones
- build: bundle refresh for the tab platform filter
- feat(multichat): right-click a channel tab to show or hide a platform, matching heatsync.org
- build: bundle refresh for the tab send-to menu
- feat(multichat): right-click a channel tab for send-to, as green/red buttons
- build: bundle refresh for the card hover
- feat(card): hovering a clickable card whitens its banner too
- fix(emotes): hovering a censored emote previews its category box instead of a broken image
- build: bundle refresh for own pad 15s
- fix(emotes): own-set clock pad is 15s — a first use that auto-adds the emote is stamped by the server a moment after the line, and that stamp is all a refresh has
- build: bundle refresh for own-add pad
- fix(emotes): a line sent just before you add an emote stays text — your own adds use a 5s clock pad, not 2min
- build: bundle refresh for own emote history
- fix(emotes): your own lines keep an inventory emote that was yours when you sent them, through remove, block, unblock and re-add
- build: bundle refresh for full-size close
- fix(feed): the full-size picture closes on click or Escape
- build: bundle refresh for server-withheld media
- feat(feed): a post the server withheld shows the censored box in the feed and inline rows; show fetches the media for verified adults
- fix(tabs): op/re rows and receipts copied into every channel buffer no longer make a tab unread on reload
- feat(feed): in chat op/re rows only the >>id, links, tags and names are clickable; the [img] tag is hover-only and its peek is held for flagged posts
- feat(safety): a revealed held post gets a hide button; op/re chat rows and the [img] tag wear the pointer cursor
- fix(safety): a flagged post's own media is held behind the viewer's toggles in the feed and thread, show reveals it in place
- fix(emotes): the tooltip's source chip keeps its provider colours after a right-click removal — heatsync reads black, not white
- fix(filters): the page default button now turns the mature-content switches back off — they were exempt from reset
- build: bundle refresh — embed media gate
- fix(tests): player-volume's retry timers are cleared with the test, so a stray one can't fail whichever test runs next
- feat(embeds): giphy, tenor and imgur resolve through the server so the image is scanned first; flagged embed media is held behind the viewer's own toggles as a dashed-cyan line with a show button
- release: 1.7.109
- build: bundle refresh — typed emote caret
- fix(composer): a typed emote name + space leaves the caret after the space, like Tab, so the next word isn't flush against the emote
- …see the full changelog in the repo
Source code released under MIT License
Version 1.7.109
Released Oct 27, 2026 - 1.43 MBWorks with firefox 128.0 and later- build: bundle refresh — typed emote caret
- fix(composer): a typed emote name + space leaves the caret after the space, like Tab, so the next word isn't flush against the emote
- perf(hover): a hovered name highlights only its on-screen copies — a chatter with a hundred rows of history cost ~100ms each way on hover and unhover
- perf(hover): username and emote tooltips register right after the config gate instead of after settings hydration; the cold card lookup waits 50ms, not 120
- feat(slash): /re replies to the last [OP] in chat (was /opr, kept as an alias); /r is whispers only
- build: bundle refresh — parallel boot reads
- perf(boot): restored mentions/yt buffers load under settings hydration, and blocked users ride the one local-storage prefetch — two storage waits off the path to first rows
- build: bundle refresh — boot timing
- chore(diag): boot records which phase it waited on, closed at the first painted rows
- build: bundle refresh — switch tail timing
- chore(diag): the slow-switch line times the tail of a switch too — sub row, placeholder, layout
- test(tabs): pin the held-rows restore and its flush points
- build: bundle refresh — chunked tab restore
- perf(tabs): a tab restored from cache mounts its newest 100 rows first and puts the older ones back in chunks — the 500-row layout bill no longer blocks the switch
- build: bundle refresh — basic settings set
- feat(settings): basic shows every everyday toggle — 16 of 85 became 45; tuning, lists, debug and saved state stay in all
- test(colors): the focus-row size chip no longer uses dim gray
- build: bundle refresh — settings button fills
- feat(settings): resting settings buttons are a dim gray fill with black text — the outline-only look read black on black; selected and hover stay white
- build: bundle refresh — settings slider track
- fix(settings): slider tracks were black on the black panel — dim gray track, white thumb
- build: bundle refresh — restore timing in the slow-switch diag
- chore(diag): a slow tab switch after a cache restore says which step took the time
- build: bundle refresh — went-live inline line
- fix(live): a followed channel going live gets its inline line — the poll (the only source for kick/youtube) now announces it, and a vetted twitch push is no longer dropped as snapshot noise by the snapshot broadcast that precedes it
- build: bundle refresh — settings buttons dim gray
- feat(settings): settings buttons rest dim gray, selected and hovered go white — matches the scrollbar
- build: bundle refresh — settings scrollbar track, sound volume labels
- feat(settings): settings scrollbars are a white thumb on a dim gray track so a row's length reads; the volume labels say sound volume
- build: bundle refresh — settings scrollbar, volume switch labels
- feat(settings): the settings scrollbar is dim gray, and the twitch/kick/youtube volume switches say what they do
- build: bundle refresh — per-platform volume switches
- …see the full changelog in the repo
Source code released under MIT License