Release notes

Changelog

New features, fixes, and platform improvements from GitHub Releases, newest first.

v1.11.1

Fixed

  • Checking for updates from an installed Windows copy downloads the setup again. The HTTP body limit matched the asset size exactly, and ureq then failed the end-of-stream read, so About showed "Could not download the update."
View release on GitHub →

v1.11.0

Fixed

  • The composer top rule matches the identity footer divider. The center column no longer keeps an always-on 2px drag border that inset the strip.
  • An empty CHANNELS heading stays hidden in the sidebar, matching DIRECT MESSAGES: the group label appears only when that network has channels.
View release on GitHub →

v1.11.0rc2prerelease

Changed

  • Nick and network icon colors keep the classic palette by default and can select the brighter vivid set from Preferences → Color palette, with /pref palette vivid, or colorPalette=vivid under [preferences] in omairc.conf. Desktop classic uses the live theme accent for slot 0; the TUI classic nick hues stay on the fixed dark fallback accent so they do not move with Omarchy theme changes. Vivid uses fixed hues on both clients.
  • Per-nick colors hash nicks with FNV-1a, fold the high bits, then take modulo the eight-color palette, instead of summing character codes, so anagrams and similar short names spread across hues more evenly. A nick's color may change once on upgrade.
  • Dev builds use an omairc-dev config/state tree and OMAIRC_DEV_HOME (was omairc-poc / OMAIRC_POC_HOME). Desktop proof scripts and the CI recipe job use verify-omairc-desktop / control-omairc-desktop and test-artifacts/verify-desktop/ (was *-poc).
  • The desktop release build uses a size-focused Cargo profile (opt-level = "s", thin LTO, strip = "debuginfo"). On Windows MSVC the product omairc.exe is about 16 MiB (was about 23 MiB with Cargo's default release settings).
View release on GitHub →

v1.11.0rc1prerelease

Added

  • /pref colors and a Show mIRC colors switch on the Preferences tab strip mIRC foreground and background colors (formatting stays). Desktop client.
  • A channel line delivered only to you is marked "only visible to you" in the desktop and terminal clients. The mark is used when you have joined that channel and the sender is in it. A normal channel line stays unmarked.
  • The terminal client wheel-scrolls and clicks rows when started with --mouse or OMAIRC_TUI_MOUSE=1. The pointer path stays off by default, so the terminal keeps its own text selection.
  • Direct-message avatars in the terminal client use the Kitty graphics protocol when the terminal answers the probe, with a half-block raster fallback. WezTerm stays on half-blocks because it answers the probe but does not draw Unicode placeholders.

Known regressions

  • Screen readers: GPUI has no AccessKit tree yet, so Accessible names and roles from the retired Qt shell are gone until upstream GPUI gains AccessKit. Surfaces to restore are listed in client/NOTES.md.
  • KWallet / Secret Service password items created by QtKeychain stay readable through the dual-attribute Linux lookup, but a fresh Rust-only install does not write QtKeychain-shaped attributes; older third-party readers may not see new secrets.
  • Wayland minimize / hide: _NET_WM_STATE_HIDDEN suspension matches X11; some compositors still disagree on when a Wayland surface counts as minimized, so background suspension can lag the Qt shell on those setups.

Fixed

  • The terminal client's /autoaway settings survive a restart, matching the desktop PreferenceStore keys and leaving the one-shot reason unpersisted.
  • Transcripts label the first day when it is not today, in the desktop and terminal clients. The mark matches a day change, and loading older history moves it so a date is not shown twice. On that first message the unread mark sits under the leading date rule. That placement is intended, and the terminal client draws it the same way.
  • A channel already at the history cap, whose oldest day is not today, keeps that date rule when a new line arrives. Only the trimmed lines are removed, so a reader who has scrolled up stays put. The transcript still rebuilds when the oldest day itself changes.
  • Loading an older page keeps the line you were reading in place. A date rule that appears or disappears above that line no longer shifts the desktop transcript, or the terminal transcript when that rule moves onto the older lines.
  • The terminal client's Alt+U keeps ↓ new while the next unseen row is not fully visible. Another press steps to that row, and the view follows the end once that landing reaches it. Scrolling back into history already read hides the marker until Alt+U returns to the unseen run.

Changed

  • Short transcripts and Status grow up from the composer. Page Up still anchors history from the first rendered row.
  • Terminal member panel, jump cards, and shortcuts sheet draw titles and position counters into the rounded border so the content keeps those rows.
  • The desktop client is the Rust GPUI binary in client/ (default product feature). Arch PKGBUILD, bin/test, bin/test-install, and bin/test-desktop build and drive that binary. The Qt/qmake tree is gone; shared contracts compare the Rust client with the TUI.
  • The Arch package depends on hicolor-icon-theme, matching the official Omarchy package.
  • Omarchy edge installs with omarchy pkg add omairc. The GitHub releases repository remains the install path for Omarchy stable, Omarchy rc, and other Arch-based systems.
  • /pref feedback prints one row per line.
  • Nick-targeted non-service NOTICEs are also filed into the DM.
  • TLS errors no longer append (CN=…); DNS failures read lookup HOST: no such host.
  • MONITOR while disconnected reports after resolving server features.
  • Short dates use a locale-style approximation instead of Qt's.
  • Windows and macOS builds no longer ship Qt libraries; the Windows installer removes them on upgrade.
View release on GitHub →

v1.10.3

Fixed

  • Linux pacman packages are built against Omarchy's Qt stack (currently 6.11.x) from Arch Linux Archive, not rolling Arch's newest Qt. The 1.10.2 package linked against Qt 6.12 and failed to start on Omarchy until Qt caught up. Release CI now pins Qt during makepkg and rejects binaries that need newer Qt_6.* symbol versions than Omarchy ships.
View release on GitHub →

v1.10.2

Added

  • The terminal transcript header shows the channel name, and the topic when the channel has one, so the buffer stays identifiable when the server list is hidden.
  • The terminal client shows a calm notice instead of a broken layout when the terminal is below the minimum size.

Fixed

  • On Unix, Shift+3 types # again. The terminal client no longer asks those terminals to report every key as an escape code, which turned # into 3 and dropped AltGr, dead keys, and composed input. Windows still requests that mode, plus alternate keys, so shift chords stay distinct.
  • The terminal client drops escape and other unused control characters from incoming text and from saved history, so a remote message cannot restyle the transcript or plant a link whose label hides its target.
  • The terminal client gives the transcript a minimum width and shrinks or hides the member column on a medium terminal.
  • The terminal footer keeps the Ctrl+/ shortcuts hint whole on narrow widths, drops the version label first, shortens status before hints, and pads the row to the window width instead of truncating it.
  • The terminal shortcuts sheet lays groups in columns and scrolls on a short terminal so the bottom border stays visible.
  • The terminal client shows … when a label does not fit, instead of cutting the word.

Changed

  • The terminal client keeps the terminal's own background and foreground, so a translucent terminal stays translucent instead of painting a solid theme color behind the UI.
View release on GitHub →

v1.10.1

Changed

  • The desktop Status header no longer has a channel field or a Join button. Joining still uses /join (including from Status), /list, an invite, or the channel header's Join after a part.
View release on GitHub →

v1.10.0

Fixed

  • The Windows build keeps Qt Quick Dialogs, so choosing a file can load. The terminal client accepts a pasted file:// path on Windows, including a drive letter.
  • A refused nick, including 432, 433 after the nick_ and nick2 fallback, and the other registration refusals, or a registration ERROR, shows the server's reason on that network and in the open pane. The desktop client and the terminal client both stop instead of retrying. A sentence the existing transcript or preview redactors reject is left off the connection error and off the Status line. A refusal with no usable sentence shows the numeric on Status.

Added

  • A direct message shows who you are talking to. The header paints a presence dot when the server offers away-notify, the real name under the nick, and short labels for an account, an unauthenticated nick, a server operator, and a bot. The member tooltip lists the same facts, one per line. A channel header keeps the topic.
  • Ctrl+K jump matches a channel topic and a person's real name, in both clients. Name matches stay above those, sidebar order holds inside each group, the list stays at most 20 rows, and a shared name still shows its network.
  • While the window is unfocused, the title shows a mention or direct message with IRC formatting stripped. A muted conversation stays quiet. Focusing the window, or opening that conversation, clears it. The terminal client puts the same text in the title it already sets.
  • A channel name in a message or a topic opens inside the client. A buffer that is already open switches to it. A channel that is not already a row asks first, and only then joins. The name is recognized from the network's advertised CHANTYPES.
  • The desktop client inserts a web link when you paste, drop, or pick a file on a server that offers a file host.
  • The terminal client inserts a web link when you paste a file path or pick a file (Ctrl+Shift+U) on a server that offers a file host. It has no drop target.
  • Join, part, quit, and nick lines fold together. A leave followed at once by the same nick rejoining is omitted, and a nick chain keeps the final name. /pref joins shows every line or hides these lines, including history playback.
  • The terminal client catches up on lines that arrived while it was away when the server offers chathistory. Open conversations resume with CHATHISTORY AFTER, and a direct message that was never opened is discovered and filled. A closed conversation stays closed. A server without chathistory keeps the playback it already had.
  • The desktop client catches up on lines that arrived while it was away when the server offers chathistory. Open conversations resume with CHATHISTORY AFTER, and a direct message that was never opened is discovered and filled. A closed conversation stays closed. A server without chathistory keeps the playback it already had.
  • Leaving a channel keeps its row. Join brings that channel back, and Close drops a channel you have left. A closed channel stays closed until you join it again. A direct message someone else writes after it was closed stays open across a restart. A join you did not ask for does not bring a closed channel back. The desktop header offers Leave, Join, and Close. Middle-click closes a sidebar row. The server buffer can join a channel that is not already open.
  • The terminal client keeps the same row: /part leaves without dropping it, /join brings it back, and /close drops a channel you have left. A direct message someone else writes after it was closed stays open across a restart. A join you did not ask for does not bring a closed channel back.
  • The terminal client marks every conversation read with Alt+Shift+A. Sidebar badges clear, and that background title clears with them. Alt+A still prefers a mention, then ordinary unread. When nothing is unread, it opens Status for the selected conversation's network. When Status is already open, it opens that Status network.
  • Tab completes channel names as well as nicks, and Shift+Tab cycles those matches backward, in both clients. The first token of a message still gets a colon. The composer stops at the focused network's LINELEN, including a paste. That length is client-to-server octets with CRLF included and tags excluded. An absent token means a classic 512-byte frame (510 bytes on Status, and the PRIVMSG body that fits for the open conversation). A larger token raises the cap. A smaller token lowers it. /me counts the CTCP ACTION wrapper, so a filled action still fits in one frame.
  • The desktop client remembers each conversation's scroll position. Switching away and back, and restarting, lands on the same line. The end stays pinned only when the reader was already there.
  • The terminal client remembers each conversation's scroll position. Switching away and back, and restarting, lands on the same line. The end stays pinned only when the reader was already there.
  • The terminal client supports IRC read markers (draft/read-marker, and soju.im/read when that is the only token offered): a server marker clears unread another client already read, and Omairc publishes a marker when this window is caught up on the selected conversation.
  • The terminal client loads an older page when paging to the top of a conversation whose server offers chathistory.
  • The desktop client marks every conversation read with Alt+Shift+A. Sidebar badges clear, and that background title clears with them. Alt+A still prefers a mention, then ordinary unread. When nothing is unread, it opens Status for the selected conversation's network. When Status is already open, it opens that Status network.
  • The desktop client supports IRC read markers (draft/read-marker, and soju.im/read when that is the only token offered): a server marker clears unread another client already read, and Omairc publishes a marker when this window is caught up on the selected conversation.
  • The desktop client loads an older page when paging to the top of a conversation whose server offers chathistory.

Changed

  • The terminal client's CTCP VERSION reply names the client: omairc-tui https://omairc.app. The desktop client answers https://omairc.app. Neither reply includes the build number.
View release on GitHub →

v1.0.7

Added

  • install-tui.sh installs the omairc-tui terminal client on Linux or macOS without a package manager. It resolves the latest release, downloads the static binary for the host OS and architecture, checks its --version, and installs it under ~/.local/bin. install.sh still installs the Qt client only, and now publishes install-tui.sh as a release asset too.

Fixed

  • The TUI member column scrolls. A roster taller than the panel always rendered from the top, so Page Up / Page Down, Home / End, and the arrow keys moved the member cursor off-screen with no way to see it. The column now slides to keep the focused row visible, matching the desktop client.
  • The TUI sidebar scrolls. A roster taller than the left column always rendered from the top, so Alt+Down / Alt+Up walked to a conversation below the fold and Alt+Left / Alt+Right focused a network header below it, both off-screen and unreachable without a mouse. The column now slides to keep the selected conversation, or the focused network header, visible, matching the desktop client's revealSidebarRow.
View release on GitHub →

v1.0.6

Fixed

  • The TUI sends after a sidebar walk. Alt+Down / Alt+Up moved to a conversation but left a previously focused network header armed, so the next Enter opened that network's Status instead of sending, and the typed line stayed in the composer as a draft until a second attempt. A selection change now clears the header focus, matching the desktop client.
  • The TUI hides the channel member column on the Status console. Connecting a second network opens Status while the previous channel stays selected, so the old channel's member panel lingered beside the console transcript. Status now hides the panel and the console transcript takes the freed width, matching the desktop client.
View release on GitHub →

v1.0.5

Added

  • The terminal client ships as a static omairc-tui binary on the same GitHub release as the Qt app. Arch installs it with pacman -S omairc-tui after the existing repository is configured. go install, a Homebrew formula, and a Scoop manifest point at that same tag. install.sh still installs the Qt client.
  • Native Windows toast notifications for mentions and direct messages. A click opens the conversation that raised it, even when the window was closed.
  • The TUI writes a crash log to <state>/omairc/omairc-tui.log, beside the Qt client's omairc.log. A recovered Bubble Tea panic and an unrecovered runtime fatal both land there with the full stack, so a crash is diagnosable after the terminal that printed it is gone. The file stays empty until something crashes.

Changed

  • Per-nick colors grew from five hue families to eight in both clients: green, cyan, and gold join blue, violet, teal, orange, and rose. A nick's exact color can change once on upgrade, because the palette index is the nick hash modulo the palette length.
  • The TUI composer is a window-level bar spanning the window, independent of the sidebar and the member panel, so toggling a column never moves it. The slash-completion menu floats over the transcript column without resizing any column.
  • The TUI sidebar draws a divider rule above every network section after the first, so a multi-network roster reads as distinct blocks.
  • The TUI transcript keeps the topic header pinned above the scrolling rows, which stay packed edge to edge. The sidebar separates its CHANNELS and DIRECT MESSAGES groups and its networks with blank lines.
  • The TUI composer carries a row of surface fill above and below its input, so it reads as a panel instead of a one-row band.
  • TUI overlay cards are anchored to a fixed top row, so a shorter jump filter or a Connect tab switch no longer moves the card while you work in it.
  • The TUI Connect sheet windows its fields on a short terminal, pinning the title and the validation and action rows, so the focused field and Apply stay reachable.
  • TUI member-list nicks carry the transcript's per-nick palette color, so one nick reads as the same person in both places.
  • The TUI build version moved from the sidebar identity footer to the bottom right of the shell footer, trailing the shortcut list.
  • The TUI sidebar identity footer is two rows: the initials chip and nick on their own row, with the presence word and inbox pill indented below. A divider rule above the nick mirrors the desktop identity footer.
  • The TUI typing indicator animates in all three surfaces — the member panel, the direct-message transcript footer, and the sidebar direct row — with the Bubbles Points spinner instead of a static ellipsis.

Fixed

  • The TUI composer publishes typing again: editing a channel or direct message on a network that granted message-tags sends +typing=active TAGMSG and clearing or sending the line withdraws it, matching the desktop client. The session already built the frames, but nothing in the shell ever reported composer text to the controller, so no hint reached the wire.
  • The TUI direct-message typing dots keep their own line under the peer's message instead of being appended to the end of it. A wrapped body left them glued to the last word, as if the text were part of the message. Grouping still drops the repeated nickname and avatar, matching the desktop client.
  • TUI transcript clocks are shown in the reader's timezone, matching the desktop client. A parsed server-time tag is stored in UTC, so a message carried the wrong hour on any non-UTC machine. The row's clock is localized once, which also restores the same-minute grouping the transcript rows and the direct-message typing footer share.
  • The TUI direct-message typing footer groups under the peer's last message again, matching Qt, instead of repeating the peer's nickname and avatar. The footer compares the row's clock cell against the current minute, but the two were read in different zones, so outside UTC they never matched.
  • TUI Tab nick completion now matches Qt: an ambiguous prefix completes to the first matching nick, and repeated Tabs cycle through the candidates. It used to require exactly one match, so Tab did nothing in a channel where two nicks shared a prefix (for example s in #ricing matching sam and sol).
  • The TUI transcript follows the first conversation to arrive instead of staying on Status. Connecting opens Status with nothing selected, so a server's auto-join was the first event to claim the selection, and the sidebar and member panel switched to the joined channel while the transcript did not. Claiming a conversation now closes the console model, and the Status surface is derived the way the desktop client derives consoleVisible, so clearing the selection also returns to Status.
View release on GitHub →

v1.0.4

Added

  • Ctrl+Shift+O opens a link sheet for the current transcript. It lists http/https URLs newest first, filters as you type, and Enter opens the URL or joins an INVITE channel on Status.
  • Ctrl+Shift+/ opens About. The chord is blocked while Connect, find, jump, nick, link, or inbox sheets are open.
  • The session inbox sheet dismisses a row with Delete or its delete control without navigating.

Changed

  • The session inbox no longer appends rows for plain direct messages. Mentions and highlight hits in a direct message still do.

Fixed

  • A failed profile save or remove is reported on the Connect sheet, and Apply no longer closes the sheet when the settings file could not be written.
  • SASL PLAIN credentials longer than one AUTHENTICATE chunk are sent through the existing chunk framer, including the empty continuation when the base64 encoding lands on a 400-byte boundary.
  • httpUrlAt keeps balanced parentheses and brackets in URL paths. Trailing ) or ] is stripped only when the close count exceeds the open count inside the match.
  • Transcript and CLI cursor filenames are Windows-safe and respect server casemapping. Existing logs migrate on read.
View release on GitHub →

v1.0.3

Fixed

  • The About update checks click the status line after it can accept a click, and the half-page transcript scroll test no longer times out the package check.
View release on GitHub →

v1.0.2

Added

  • Page Up / Page Down (and Shift variants) page the member nick list when it has keyboard focus. Home / End jump to the first or last nick. Transcript paging is unchanged while the composer is focused.

Changed

  • Connect tabs cycle with Ctrl+Tab. Ctrl+Shift+Tab no longer switches them.
View release on GitHub →

v1.0.1

Fixed

  • An in-source build no longer hides the generated version header. A later shadow build still reports OMAIRC_BUILD_VERSION from omairc --version, so the Arch package check can see the override.
View release on GitHub →

v1.0.0

Added

  • Omairc requests znc.in/playback when a bouncer offers it together with batch. After registration it sends ZNC *playback PLAY, starting from each target's stored server-time, or 0 on the first attach. A channel PLAY is sent again on self-JOIN until a playback batch for that channel is kept. Replayed lines stay muted backlog and are not duplicated. A bouncer that replays without the cap is unchanged.
  • SASL uses SCRAM-SHA-256 when the server advertises it, and PLAIN otherwise.
  • IRCv3 account-tag, account-notify, and extended-join. Omairc keeps each nick's services account and shows it in the member list, on message headers, beside your nick, and on the join line only when it differs from the nick.
  • --demo-server seeds IRCv3 service accounts so the member list, message header, and identity footer can show an account that differs from the nick.
  • --demo-server keeps profiles, preferences, open directs, transcripts, and window geometry in memory instead of writing them to your config. On Windows it also redirects QSettings into that temporary tree so ignores, highlights, mutes, and monitors never touch the registry.
  • /pref reads and sets the Preferences toggles from the composer. Bare /pref prints all three. A name (directs, avatars, unread) prints one, and on or off changes it. Completion offers the names, then on and off. Asking about avatars also prints the IP note.
  • On a Windows Inno Setup install, Check for Updates downloads the new setup in the background. The About line and the footer version then read Restart to update and open the installer wizard. Closing the window after the download has finished opens that same wizard. Portable copies still open the GitHub release page.
  • A network remembers the /avatar URL and sends it again after connect when the server offers metadata.
  • Connect preference toggles show help on hover and keyboard focus, the same way the connection fields do.
  • /autoaway writes a Status line when the idle timer trips and when activity clears it. Turning /autoaway off still clears AWAY without that return line.

Fixed

  • Ctrl+C copies selected text in a message, whois line, or Status line. The composer keeps focus. A selection in the composer still copies that draft.
  • Demo PRIVMSG seed lines combine account and time in one IRCv3 tag section so tagged history replays parse.
  • Repeated account tags with the same value no longer repaint the open transcript; logout and real account changes still refresh member rows and headers.
  • Message headers clamp long account labels like the member list and identity footer.
  • Windows builds ship qsvg.dll so the About logo loads. qmake no longer uses a leftover Linux QtKeychain tree.
  • The Homebrew cask follows Homebrew 7, so brew install no longer warns about deprecated url verified and preflight.

Changed

  • The scroll-down chip keeps an accent dot while it is visible. The arrow bounces five times when a new line arrives below a scrolled-up transcript, including when there is no New messages mark. It does not bounce merely because the chip is on screen.
  • Open conversations at unread is on by default.
  • The shortcut sheet no longer lists /disconnect.
  • The public description now says simple.
View release on GitHub →

v0.9.1

Added

  • Chat that arrives in the open channel or DM while the window is unfocused is now treated as unread: the New messages mark plants on the first live line and, when focus returns, the transcript lands on that mark instead of being pinned to the bottom. Replay while that conversation is open and the window is unfocused still does not plant the mark. Status keeps following the end.
  • When a New messages mark is visible and the transcript can still scroll down, a scroll-down chip stays armed until the viewport reaches the bottom, with a subtle bounce to draw attention.

Changed

  • Transcript rows for nick mentions and /highlight hits use a softer wash so mentions stay noticeable without dominating the transcript.

Fixed

  • Connecting through ZNC now plants the New messages mark on the first auto-selected channel. znc.in/playback was landing while that buffer was already focused, so the mark never appeared there even though other channels got it. Unread and mention badges stay at zero.
  • ./bin/install (makepkg) no longer warns about an unused composer surface on /status /avatar watches, or a missing CredentialKey::purpose initializer.
View release on GitHub →

v0.9.0

Added

  • IRCv3 labeled-response. When a network advertises it (and message-tags), Omairc tags outbound WHOIS and CTCP /ping /time /version with a unique label and routes the matching reply — including labeled-response batches — to the asking transcript. Unlabeled servers keep the existing nick-keyed watches. Composer PRIVMSG/NOTICE sends stay unlabeled.
  • Shift+Page Up / Shift+Page Down scroll the conversation transcript and Status by about half a page. Unmodified Page Up / Page Down stay the full hop. The composer stays focused; both chords are disabled while Connect or the shortcuts overlay is open.
  • Ctrl+Home / Ctrl+End jump the conversation transcript and Status to the top / bottom. Ctrl+End resumes follow-the-end. The composer stays focused; both chords are disabled while Connect or the shortcuts overlay is open.
  • Transcript rows for nick mentions and /highlight hits get a calm wash so they are easy to scan.
  • Global /autoaway idle timer (off by default). /autoaway 15 or /autoaway 15m enables a timeout in minutes; /autoaway reason stores a default AWAY text; extra text on a duration is one-shot. It is not /status and does not replace manual /away.
  • Session inbox waiting list for background mentions, highlight words, direct messages, channel invites, monitored-nick online edges, and self-kicks. The identity footer shows an inbox mark with a count badge; Ctrl+Shift+A opens a sheet to walk and activate rows. Selecting the matching conversation from the sidebar consumes related rows.
  • Sidebar network order and per-network collapse persist. Alt+Shift+Left / Alt+Shift+Right collapse or expand the focused network; a header chevron toggles the same state. Ctrl+Alt+Shift+Left / Ctrl+Alt+Shift+Right collapse or expand every network. Alt+Shift+Up / Alt+Shift+Down reorder the focused header. Custom order and collapsed ids live in preferences.
  • /list [mask] opens a searchable overlay of channels on the focused network (name, users, topic; Enter joins). Each network keeps that LIST in memory until disconnect, so opening /list again with the same mask is instant; /list while the overlay is open refreshes. 322/323 stay out of Status. --demo-server answers LIST, including unjoined #linux / #random (omarchy) and #debian (oftc).
  • A centered New messages unread mark in conversation transcripts, planted on the first chat that arrives while the buffer is unselected. Find skips it. History splices plant the mark on the arriving sequence rather than the join line.
  • Preferences → Open conversations at unread (default off). When on, switching or jumping to a different conversation lands on the New messages marker instead of the bottom. An already-focused buffer is left alone; Status still pins to the end.
  • IRCv3 MONITOR watch lists. /monitor <nick>, /unmonitor <nick>, and /monitored persist per network, re-subscribe after ISUPPORT, and write a Status line on real online/offline edges. Unfocused desktop notify follows mentions, including mute, without toast spam on reconnect hydration.

Changed

  • The Ctrl+/ shortcuts sheet groups chords under MOVE, JUMP, WRITE, WINDOW, and CONNECT headings and pairs opposite network collapse/expand/move rows. Ctrl+Shift+S sits in WINDOW alongside the members-panel chords. Connect-sheet chords live under CONNECT so Ctrl+N / Ctrl+Enter are not read as global.
  • Connect sheet keyboard: Tab still walks the whole sheet and arrows stay in-region. Sheet-wide Ctrl+Tab / Ctrl+Shift+Tab switch tabs, Alt+Left / Alt+Right walk networks (focus stays in the field unless already in the rail), Ctrl+N adds a network and focuses Name, and Ctrl+Shift+Delete arms then removes the selected network. Ctrl+Enter applies the selected network from Preferences as well.
  • Pull-request and main CI no longer package or upload Windows/macOS installers, zips, or the Arch snapshot. Use a manual workflow run when you need those artifacts; version tags still package and publish. Intel macOS pull requests skip the portable test rebuild (Linux and Apple Silicon still run it).

Fixed

  • /list overlay topics strip mIRC colors and keep bold, italic, and underline the same way chat transcripts do.
  • Desktop notifications and portal theme reads no-op immediately when DBUS_SESSION_BUS_ADDRESS is autolaunch: or a unix:path that does not exist, instead of blocking on QDBusConnection::sessionBus(). An unset address still uses the normal session bus.
  • /list recovers when the server answers 263/416 or goes silent: the overlay leaves "Loading channels…", Status gets the reason, and a later /list sends LIST again. A 323 from a timed-out LIST that arrives after that retry — including after the retry's 321/322 — does not complete the new load. /list while another network's LIST is in flight shows that network's own rows instead of the previous overlay.
  • macOS relocatable builds load Quick Controls when Contents/MacOS/omairc is started through a symlink. Qt otherwise skips the bundle qt.conf and fails with qtquickcontrols2plugin not found. The Homebrew PATH helper already execs the binary inside omairc.app.
  • Sidebar network chords (Alt+Left / Alt+Right, collapse/expand, and collapse-all) work from the composer on macOS instead of moving the caret. Collapse-all matches Command as MetaModifier in Keys.onPressed. The shortcuts sheet and Connect hint show Cmd and Option in place of Ctrl and Alt.
  • --demo-server answers client PING, so the idle-socket watchdog no longer drops the loopback session after a silent minute.
View release on GitHub →

v0.8.3

Added

  • A Homebrew cask (Casks/omairc.rb) for the notarized macOS GitHub zips. brew tap fredimachado/omairc https://github.com/fredimachado/omairc then brew install --cask fredimachado/omairc/omairc installs omairc.app into /Applications and puts omairc on PATH. Uninstall leaves profiles and logs; --zap removes ~/Library/Preferences/omairc and ~/Library/Preferences/State/omairc. Version tags rewrite the cask version and sha256s.
View release on GitHub →

v0.8.2

Fixed

  • macOS GitHub zips were notarized and stapled but Gatekeeper still blocked a quarantined download. The app disabled library validation while shipping a QtKeychain LC_RPATH into the CI Qt prefix and unused SQL plugins that load Postgres.app / Homebrew libraries. Relocatable builds now keep library validation on, strip those dangling load commands, and syspolicy_check the bundle the way a downloaded copy is assessed.
  • macOS GitHub zips were about 45 MB because aqt's clang_64 Qt kit is universal and macdeployqt copied unused Quick Controls styles, Widgets, and SQL plugins. Relocatable builds now thin to the host architecture and prune those extras, matching the Windows deploy.
View release on GitHub →

v0.8.1

Added

  • /znc <text> sends PRIVMSG *status <text> on the focused network, the same way /ns talks to NickServ and /cs talks to ChanServ. Empty /znc is refused. Replies from *status stay on the Status console and do not open a DM. This is not /status.

Changed

  • macOS CI selects Xcode 16.4 with maxim-lobanov/setup-xcode on macos-15 and macos-15-intel (Qt 6.8.3; macos-latest is macOS 26 and no longer ships Xcode 16). After notarization and stapling, tag releases run spctl --assess --type execute --verbose=4 so Gatekeeper rejection fails the job. Official GitHub Actions in that workflow use their current Node 24 majors.

Fixed

  • Sidebar navigation (Alt+Up/Down, Alt+Left/Right, Alt+A, Ctrl+K, reveal) reads irc.conversations and connection.networks through the list models instead of scanning QML children, so released delegates no longer trigger QQmlVMEMetaObject warnings on startup.
View release on GitHub →

v0.8.0

Added

  • Status formats the connect-time server report instead of raw numerics: CAP LS/ACK/NAK/NEW/DEL read as Server supports/Acknowledged/Rejected/Server added/Server removed with pipe-separated tokens, outgoing CAP REQ as Requesting, 004 fields as labeled Host, IRCd, User modes, Channel modes, and Parametric channel modes, and LUSERS numerics (250–255, 265, 266, 396, among others) as their text. --demo-server seeds that burst.
  • Clicking the sidebar version opens an About sheet with the Omairc logo, an open-source GitHub link, and Check for Updates against the latest GitHub release. A 50% dimmer covers the window; a left-click on that dimmer dismisses the sheet, matching Connect.
  • A Name field on the Connect sheet, above Host. That name is what the network list, sidebar, and omairc connections / status rows show. Older configs without a name keep using the host. Name and Host stay independent: editing Host does not rewrite a loaded name.
  • A vertical scrollbar on the member list when a nick list overflows, appearing on scroll or hover like the sidebar, so long channel rosters are discoverable without permanent chrome.
  • /avatar [url|email] sets the local user's standing avatar metadata. HTTPS URLs pass the same safety checks as peer avatars; email addresses store a Gravatar SHA-256 HTTPS URL with {size} and d=404. Empty /avatar echoes the stored URL (clickable when HTTPS). Sole /avatar clear unsets the key.
  • Ctrl+Shift+S collapses and restores the left server list column. Collapsing changes its width rather than hiding the column, so Alt+Down / Alt+Up still walk conversations while it is out of view, and Alt+Left / Alt+Right brings it back. Collapsing drops the focused network header so Enter in the composer sends again. The chord is in the shortcuts sheet.

Changed

  • Connect is a window-level modal. The sidebar and member list cannot be used while it is open. Escape and a click outside the card still dismiss it after a profile exists; first-run still cannot be dismissed. The dimmer is 50% transparent so those columns stay visible behind the sheet.
  • /status and /avatar replies (inspect, set/clear confirmation, and errors) copy into the selected conversation transcript when one is open, including from the Status composer. /status [text] sets standing status; empty /status echoes the current value; sole /status clear unsets it.

Fixed

  • Channel-targeted service PRIVMSG, including Ergo's HistServ join/quit history replay, no longer floods the Status console.
View release on GitHub →

v0.7.0

Added

  • IRCv3 draft/ICON shows the server icon in the sidebar network square when the URL is safe and loads; otherwise the initial letter and palette color stay. --demo-server ships a bundled qrc icon for the omarchy seed network.
  • IRCv3 draft/metadata-2 now covers peer avatar, status, and bot, plus WHOIS extras (display-name, pronouns, homepage, color). Member, nick picker, transcript, and DM circles load an HTTPS avatar when it is safe; a bad URL keeps the initial. Bots get a small mark next to the nick. Standing status stays separate from AWAY. --demo-server ships bundled qrc avatars for mira, anna, and kai so glyphs reach Image.Ready without outbound HTTPS.
  • /status [text|clear] sets or clears the local user's standing metadata without reconnecting. Empty /status echoes the current value. Networks that do not grant metadata say so on Status or the asking transcript. Success waits for the server's 761 / 766 reply; legacy numerics and FAIL METADATA codes (KEY_NO_PERMISSION, VALUE_INVALID, RATE_LIMITED, and kin) surface the failed set/clear on Status or the asking transcript instead of an optimistic echo. Capability values honor max-subs (status-first subscriptions) and max-value-bytes (including an explicit 0, which refuses non-empty text locally) with a 512-byte client ceiling.
  • Preferences → Show peer avatars (default on) gates automatic avatar fetches. Turn it off to keep avatar hosts from seeing your IP on busy channels; the HTTPS URL policy still fails closed either way.
  • Native macOS build and CI artifacts (omairc-*-macos-arm64.zip and omairc-*-macos-x64.zip). bin/build-macos Developer ID signs when CODESIGN_IDENTITY is set. GitHub Actions notarizes and staples on version tags; pull-request zips stay signed but not notarized because Apple can hold a new Developer ID In Progress for hours. Tag releases refuse to ship an ad-hoc bundle. Local Homebrew-Qt builds stay ad-hoc.
  • omairc conversations includes topic on channel rows.
  • The Windows build embeds the app icon in omairc.exe. Explorer, the title bar, and the taskbar use it instead of the default executable mark.
  • A per-user Inno Setup installer (omairc-*-windows-x64-setup.exe) on each version tag, next to the portable zip. bin\package-windows.bat compiles it from the windeployqt tree. Start Menu and user PATH are created; config is left alone on uninstall.

Changed

  • /part drops the local channel conversation. PART is written only when the buffer was joined, so a failed /join window can be dismissed without a 403. /leave is the same command. Named channels that were never opened still send PART. A delayed self JOIN after that dismiss sends PART and drops the buffer instead of resurrecting a channel the user already left.
  • omairc send returns exit 2 with "uncertain": true after a successful local-socket write of the send request when the CLI does not get a readable reply, so agents do not double-send on a lost ack.
  • CLI JSON rows omit empty strings and false flags so agent payloads stay small. Missing means that default. Numbers such as unread stay. Top-level "ok": false on errors is unchanged.
  • The Windows portable tree ships msvcp140 and vcruntime140 next to omairc.exe so a user-mode install does not need vc_redist. bin\build.bat copies those DLLs from VCToolsRedistDir. It does not pass windeployqt --compiler-runtime: on MSVC that switch only adds an unused vc_redist.x64.exe.

Fixed

  • Join failure 448 (illegal channel name) copies into the selected channel transcript as well as Status, like the other join errors.
  • Intel macOS builds skip the Apple Silicon -include arm_acle.h workaround, so Qt 6.8 compiles on macos-15-intel instead of failing with "ACLE intrinsics support not enabled."
  • Hostname image fetches keep the hostname on the HTTP request while still pinning TCP to one pre-validated address, and parse response headers case-insensitively, so Cloudflare (Unreal draft/ICON favicon) is not 403'd.
  • Avatar fetches refuse decompression bombs whose declared or decoded dimensions exceed a fixed budget, and hostname HTTPS GETs pin to one pre-validated address so QNAM cannot re-resolve (DNS rebinding).
  • Closing the last direct message refreshes connectionStatus when focus falls back to another network, so the identity footer and Status header no longer keep a stale Connected mark next to the new nick.
  • The identity footer shows offline with a muted mark when the focused network is not Connected, matching the sidebar network status. It still shows away or available only while Connected.
  • Opening the Windows window from Explorer or the Start Menu no longer flashes a console. --help and the local CLI still print in cmd or PowerShell by attaching to the parent terminal.
  • Windows uninstall removes the install directory from PATH before the files, so a silent uninstall cannot leave the entry behind.
  • bin\build.bat finds vswhere.exe when cl is not already on PATH. Delayed expansion cannot read %ProgramFiles(x86)%.
  • The Windows installer and LICENSE copyright name Fredi Machado.
  • The Windows installer treats expanded and unexpanded PATH entries as the same directory, so a %LOCALAPPDATA%\Programs\Omairc entry is not duplicated on install and is removed on uninstall.
View release on GitHub →

v0.6.0

Added

  • A native Windows build. bin\build.bat and bin\build.ps1 produce a portable tree next to omairc.exe. CI uploads that tree as an artifact; each version tag also publishes omairc-*-windows-x64.zip on the GitHub release. Portal text scale, desktop notifications, and the Omarchy theme watch stay Linux-only.
  • install.sh adds the omairc pacman repository from the latest GitHub release and installs the package. Safe to re-run. Served from main and as a release asset for a version-pinned URL.

Changed

  • /join opens the last named channel as soon as the JOIN is sent, including /j and a Status submit. Multiple names land on the last one.
  • Our CTCP VERSION reply no longer reveals the build number. It answers https://omairc.app instead.
  • The scalable app icon puts the Omarchy mark behind the hash.

Fixed

  • /query clears the composer and focuses the new direct message. The command no longer stays as a draft on the source buffer or the new query. A refused /query stays in the composer, including on Status.
  • A successful /join is consumed from the composer before the window switches, so it cannot remain as a draft on the previous conversation.
  • A failed /join copies the server's reason into the selected channel transcript as well as Status.
  • /away and /back mark our own nick away or online on every channel member row when 306 / 305 land, even when the server does not echo our own away-notify. The identity footer already had that fact; the panel and the nick picker now match it.
  • A direct-message sidebar row's presence dot follows shared-channel membership and away facts (online, away, or unknown) instead of a hard-coded green mark. A peer who quits no longer looks available. The dot stays hidden when away-notify is off, like member rows.
  • Windows CLI output works: the Windows build uses the console subsystem so --help, --version, and control commands print in a terminal or into a redirect, then FreeConsole() drops that console when opening the window. The local server uses a named pipe (omairc) instead of a drive-letter path that QLocalServer cannot listen on.
View release on GitHub →

v0.5.0

Added

  • The sidebar identity footer shows the running app version on the right, next to the nick.
  • /ping [nick], /time [nick], and /version [nick] send those CTCP queries. Empty form uses the open direct message. Replies copy into the asking conversation, like /whois. Status stays the log. Channel targets are refused. --demo-server answers those queries so the transcript row shows up without a live peer.
  • Direct messages the user opened or replied to come back on the next connect. A query the user never touched stays session-local. Preferences has a global Reopen direct messages on startup toggle, on by default. Turning it off stops restore but still records engaged targets under [openDirects] in omairc.conf, so turning it back on can reopen them. Ctrl+W drops a query from that set. NickServ and other service queries are not restored. Replayed history stays muted, with no unread badge or notification. Restore waits until after ISUPPORT (376 / 422).
  • Jump to a channel nick with Ctrl+Shift+K. Type filters the current channel's members, Up/Down highlight, Enter opens or creates that DM, Escape dismisses. The ONLINE heading opens the same sheet. Disabled on direct messages and Status.

Changed

  • Connect is tabbed. Connection holds the per-network profile. Preferences holds global settings such as reopening direct messages. Enter walks to the next field. Ctrl+Enter applies. The network rail owns Up/Down/Home/End and shows a Ctrl+/ shortcut hint. Server password (PASS) and NickServ password are labeled apart, with the SASL fallback in the NickServ help. Closing the sheet returns focus to the composer.
  • Direct-message typing sits in the transcript, in the slot the peer's next line will occupy. It groups with that peer's last message in the same minute; otherwise it shows their avatar. Channel typing stays on the member row.
  • The member panel and omairc names list nicks by the server's PREFIX rank, highest first, then nick. Tab nick completion stays alphabetical.
View release on GitHub →

v0.4.0

Added

  • omairc read, omairc names, and omairc conversations snapshot the running window as JSON. An agent can fetch recent chat, a joined-channel member list, and the channel and DM list without changing the UI selection. read --unread is a CLI cursor under $XDG_STATE_HOME/omairc/cli-cursors/ and does not clear GUI unread or mention badges. --since and --unread keep the newest 100 lines and set "truncated": true when they drop older ones. The unread cursor tie-breaks same-millisecond lines with a per-conversation sequence so empty msgid tags do not drop later arrivals.
  • Conversation transcripts persist under $XDG_STATE_HOME/omairc/logs/{networkId}/{target}. Join and opening a DM reload the tail as muted backlog. Lines that IrcSecretPolicy redacts are not written.
  • Live transcripts insert a centered date mark when the local calendar day changes. The label is Today, Yesterday, or the locale short date. Status stays a raw console.
  • Chat bodies render bold, italic, and underline. Topics, Status, find, and notifications stay stripped plain text.
  • Click a chat or action author or avatar to open or create a DM, same as the member panel. Self, events, WHOIS, and grouped follow-up rows stay inert.
  • Activating a desktop notification raises the window and opens that conversation. A missing DM is created the same way a member click is.
  • /highlight <word>, /unhighlight <word>, and /highlights. Each network keeps its own list, persisted next to ignore. A whole-word hit increments mentions and notifies like a nick mention. Clearing the network drops the list.
  • /mute [target], /unmute [target], and /muted. Each network keeps its own list by conversation key. Chat still arrives. Mentions do not notify, increment, or badge. Alt+A skips muted mentions. Opening the buffer does not unmute. /close and clearing the network drop the flag. Status /mute without a target is refused.
  • /disconnect [reason] stops the focused network. /quit is the same command. Connect shows Disconnect next to Apply while that network is live or reconnecting. The profile, sidebar, and other networks stay.
  • Empty /join joins the latest inbound invite for that network. Clicking the channel token on the Status INVITE line does the same. A new invite replaces the stored one. Ignore still drops invites from ignored nicks.
  • A successful keyed self JOIN stores the key beside the Autojoin names. Welcome sends JOIN #chan key. Part and kick drop both. The Connect field stays names only.

Changed

  • New networks mint an 11-character base64url id instead of a UUID.

Fixed

  • The Ctrl+K jump field no longer overlaps its hint with the focused border. The hint stays inside the field as "Jump to conversation…" until you type.
View release on GitHub →

v0.3.0

Added

  • IRCv3 server-time. Omairc requests the capability whenever the server advertises it, so a server that gates the time message tag behind it now sends real timestamps instead of folding them into the message body.
  • Bouncer buffer replay on attach. A znc.in/playback batch now lands as backlog in muted text instead of as live traffic, so reattaching after a day away no longer raises unread counts or announces yesterday's mentions as new desktop notifications. A channel buffer splices above the join line. A query buffer opens its direct message only when the backlog holds a line somebody else wrote, so an outbound /msg that the bouncer kept in a buffer still opens nothing. Replay needs only the batch capability, which is what a bouncer offers.

Changed

  • --demo-server seeds the real IrcController in-process. --mock and the QML prototype sidebar are gone. OmaircWindow requires irc; a null binding no longer loads mock conversations.
  • A sender Omairc could not reply to no longer opens a conversation or notifies. A bouncer's *status and its *** playback markers stay on the Status console, where every inbound line is already logged. A nick starting with a digit is still a person and still opens a direct message.

Fixed

  • The Connect form scrollbar no longer covers the fields, and the card width stays the same.
  • Ctrl+F find works on live conversation and Status transcripts. Empty first press enters find and waits. The composer shows Find. Matches include author and body, or Status label and text. The current row uses the selection color.
View release on GitHub →

v0.2.0

Omairc 0.2.0 can stay on more than one network at once. It also keeps one window, talks to that window from the CLI, and makes the session quieter and more resilient.

Install

From a checkout:

./bin/install

Or add the release repository and pacman -Sy omairc / omarchy pkg add omairc. See the README for the [omairc] snippet.

While a window is running, the same binary can talk to it without starting another nick:

omairc --help
omairc connections
omairc status
omairc send --network <id> '#channel' hello
omairc raise

Warnings and errors go to $XDG_STATE_HOME/omairc/omairc.log.

Highlights

  • Several networks. Add them from the Connect sheet. Each keeps its own channels, DMs, nick, and Status.
  • Connect on startup is optional per network (off by default).
  • One window. A second launch raises the existing client.
  • Drafts stay with the conversation. Status has its own draft too.
  • Consecutive chat from the same nick in the same minute groups together.
  • Joins, parts, quits, and nick changes collapse onto one line.
  • Ctrl+F finds in the current buffer from the composer.
  • http/https links open from chat; javascript: and file: stay closed.
  • Mentions notify when the window is unfocused.
  • Typing shows on an existing DM row when that peer is typing in the background.
  • Reconnect starts when the network is reachable again; a silent socket after welcome is probed and then failed.
  • Nick in use during register tries nick_ then nick2 before giving up.
  • CTCP VERSION / PING / TIME replies go to Status and are rate-limited.

What's Changed

Desktop and install

  • feat(packaging): add source install script (#43)
  • feat(desktop): raise the existing window on a second launch (#44)
  • feat(cli): control the running client over the local socket (#45)
  • feat(connection): add startup connect preference (#47)
  • feat(cli): print --help without a window (#79)
  • feat(logging): write warnings and errors to an XDG state file (#84)

Networks and chat

  • feat(irc): add concurrent network connections (#78)
  • feat(composer): keep unsent drafts per conversation (#64)
  • feat(ui): open allowlisted http links from PlainText (#67)
  • feat(irc): collapse consecutive join, part, quit, and nick events (#69)
  • feat(irc): cap conversation transcripts at 2000 (#63)
  • feat(ui): find in the current buffer from the composer (#71)
  • feat(ui): notify unfocused mentions (#74)
  • feat(transcript): group consecutive messages (#86)
  • feat(sidebar): show typing on direct messages (#87)

IRC session

  • fix(irc): route CTCP requests to status (#46)
  • feat(irc): decode invalid UTF-8 wire text as Latin-1 (#59)
  • feat(irc): print standard replies on Status (#60)
  • feat(irc): use the IRCv3 time tag on chat events (#62)
  • feat(irc): probe a silent socket after welcome (#66)
  • feat(irc): request the quiet IRCv3 capabilities (#68)
  • feat(irc): join multiple channels with optional keys (#70)
  • feat(irc): retry nick_ then nick2 on 433 before welcome (#72)
  • feat(irc): start reconnect when the network is reachable again (#73)
  • feat(irc): rate-limit CTCP VERSION and PING replies (#75)
  • feat(irc): open and close IRCv3 BATCH refs (#76)

Fixes

  • fix(irc): validate privmsg targets (#49)
  • fix(cli): bound command response handling (#50)
  • fix(irc): scope away and errors by network (#51)
  • fix(cli): bound local IPC lifecycle (#52)
  • fix(irc): preserve command error network scope (#54)
  • fix(irc): keep /msg from opening a new DM (#85)

Full Changelog: https://github.com/fredimachado/omairc/compare/v0.1.0...v0.2.0

View release on GitHub →

v0.1.0

First public release: a simple IRC client for Omarchy.

  • Connect sheet with a persisted network profile, TLS by default, and no saved password.
  • Live session through IrcController, plus --mock for the bundled prototype window.
  • Status console, member list with PREFIX ranks, away on the identity footer, and IRCv3 typing.
  • Keyboard map, slash-command complete, selectable transcript, and follow-unseen.
  • qmake Unix install tree and a GitHub Releases pacman repository.
View release on GitHub →