Skip to content

Releases

erssi Shellter Edition 2026.11.4

Choose a tag to compare

@y-o-o-z y-o-o-z released this 12 Nov 00:26
shellter-v2026.11.4
0fc5623

A security fix leads this release: an off-by-one in OTR message
reassembly could write one byte past a heap buffer, and a peer in an OTR
session could trigger it. With it come two smaller correctness fixes and
a dead-code cleanup, and the secure DCC (SDCC) added since 2026.11.3 -
DCC chat and file transfer over TLS 1.3 - has its certificate handling
hardened.

erssi Shellter Edition 2026.11.3

Choose a tag to compare

@y-o-o-z y-o-o-z released this 07 Nov 07:47
shellter-v2026.11.3
1966258

Fixes from a security review of the code erssi adds to irssi: /e2e
decline now holds against everything the declined peer sends afterwards,
two erssi on one keyring no longer overwrite each other's changes, and
the web frontend, the image preview, /UPGRADE, the installer and the
release tools are hardened.

erssi Shellter Edition 2026.11.2

Choose a tag to compare

@y-o-o-z y-o-o-z released this 03 Nov 14:32
shellter-v2026.11.2
13c458b

A fix for the disk space warning of 2026.11.1: under a seccomp filter
that kills on the quota calls, as systemd's
SystemCallFilter=@System-service does, erssi was killed at its first
look at the disk.

erssi Shellter Edition 2026.11.1

Choose a tag to compare

@y-o-o-z y-o-o-z released this 03 Nov 05:35
shellter-v2026.11.1
a7a1aa0

Backups can be encrypted with a passphrase (erssi --backup --encrypt),
erssi warns when the disk or the quota is nearly full, and a review of
2026.11.0 brought fixes for the mouse, E2E, the first-run setup and
backups.

erssi Shellter Edition 2026.11.0

Choose a tag to compare

@y-o-o-z y-o-o-z released this 01 Nov 14:55
shellter-v2026.11.0
9951097

An erssi installed for the whole system is updated by its administrator:
erssi never runs the installer of another user.

erssi Shellter Edition 2026.10.9

Choose a tag to compare

@y-o-o-z y-o-o-z released this 31 Oct 15:45
shellter-v2026.10.9
e9f354f

Update from inside erssi with /UPDATE INSTALL, a short summary of each
new release in the update notice, and automatic backups. Release tools,
and tests that hold under load.

erssi Shellter Edition 2026.10.8

Choose a tag to compare

@y-o-o-z y-o-o-z released this 30 Oct 08:48
shellter-v2026.10.8
28a8a5c
erssi Shellter Edition 2026.10.8

The FreeBSD packages, which 2026.10.7 does not have. erssi itself is
the same as in 2026.10.7.

+ Tests
  - the live backup case that checks /UPGRADE no longer reads the
    arguments of the new process: on FreeBSD, with the long paths of
    a package build, ps showed only the program name there, the case
    failed, and with it the FreeBSD 14 and 15 packages of 2026.10.7.
    It now looks for <home>/session, which /UPGRADE writes and the new
    erssi removes, with the same process still running
  - in the installer's lock cases the process that stands in for a
    running installer lived 30 seconds, less than a slow run of
    stale-lock takes; it now lives until the case ends

For what is new since 2026.10.6 (more ready-made binaries, packages you can build again, the update notice, clickable links, backup and restore) see 2026.10.7.

Binary packages: erssi-2026.10.8-debian12-amd64.tar.xz, erssi-2026.10.8-debian13-amd64.tar.xz, erssi-2026.10.8-ubuntu24-amd64.tar.xz, erssi-2026.10.8-freebsd14-amd64.tar.xz and erssi-2026.10.8-freebsd15-amd64.tar.xz, each built twice from the signed tag and compared (identical byte for byte; FreeBSD 14.5 and 15.1), listed in SHA256SUMS, which the release key signs (SHA256SUMS.sig, namespace erssi-release). The installer checks all of it; to check by hand see install.md. erssi --update takes it from any earlier release.

erssi Shellter Edition 2026.10.7

Choose a tag to compare

@y-o-o-z y-o-o-z released this 30 Oct 07:02
shellter-v2026.10.7
5bd5158
erssi Shellter Edition 2026.10.7

Ready-made binaries for more systems, packages that can be built
again and compared, a notice of new releases, clickable links, and
backup and restore of the whole setup. Every change went through an
independent review before the release.

+ Install and update
  - ready-made binaries also for Debian 12 and Ubuntu 24.04 (amd64),
    next to Debian 13, FreeBSD 14 and FreeBSD 15
  - a source install runs the tests of erssi only: the tests of the
    release tools (the installer, the packager, the release hook)
    are in the meson suite 'tooling', which the installer leaves out
    (meson test --no-suite tooling) and CI and the release builds
    run. Two of them stopped installs on AlmaLinux 10 and other
    boxes: the pre-push interrupt case where /bin/sh is bash, and
    the hostile-package cases where perl has no Archive::Tar (both
    fixed too)
  - when a test fails, the installer names the failed tests, where
    the full results are, where to report it, and how to install the
    build anyway (--no-test)
  - a box where only one tool keeps the ready-made package out
    (ssh-keygen, perl, sha256sum, xz, curl) is told which package
    gives it, instead of only building from source
  - the library packages to install are named right on Debian 12
    (libssl3, libchafa0, libutf8proc2) and Ubuntu 24.04
    (libperl5.38t64)
  - erssi --check-update downloads only the signed tag and its
    commit, about 6 KB instead of 3 MB
  - shellter-install.sh --update --check --porcelain prints one line
    for programs: update, current, error or unmanaged (exit codes 0,
    0, 1 and 3)
  - a GIT_DIR (and the like) in the environment no longer sends the
    installer's git into the caller's repository

+ Packages you can build again
  - utils/build-binary.sh --verify PACKAGE builds a package again
    from the signed tag its MANIFEST names, with that tag's own
    packager and the full test suite, and compares: exit 0 when it
    is the same byte for byte, 3 when it differs (with the files and
    the MANIFEST lines that differ), 1 when it cannot compare
  - the MANIFEST also records the build's tools and libraries (cc,
    meson, ninja, strip, xz, libs), so two builds that differ say why
  - every package of this release was built twice and compared

+ Update notice
  - /SET update_check ON (off by default: it contacts the erssi
    repository) checks once a day, in the background, whether a
    newer signed release is out, and says so once per release in the
    Notices window; the new "update" statusbar item shows it
    (/STATUSBAR ADDITEM -after lag update info). It runs the
    installer installed with erssi, which checks the signature as
    erssi --update does; nothing is installed. /UPDATE shows what the
    last check found, /UPDATE CHECK checks now. The first-run setup
    asks whether to turn it on. An erssi the installer did not
    install, one of another user and one in Capsicum capability mode
    do not check, and say why

+ Look and feel
  - addresses in messages (http, https, ftp, gopher, gemini, irc,
    ircs) are clickable OSC 8 links, also when they wrap over several
    lines. The link is always the text that is shown; a colour change
    ends an address. /SET term_hyperlinks auto|on|off; auto turns them
    on in kitty, WezTerm, iTerm2, Ghostty, foot, Alacritty, Contour,
    Windows Terminal, Konsole, VS Code, VTE terminals and inside tmux,
    and off under GNU Screen, on a console and in terminals it does
    not know (over ssh, set it on yourself)

+ Backup and restore
  - erssi --backup [FILE] puts the erssi home into one file of mode
    0600: config, themes, startup, scripts and their autorun links,
    the E2E keyring, OTR and fe-web keys, credentials and the
    Mentions log; the IRC logs only with --with-logs. It holds private
    keys and passwords: keep it private. An existing file is never
    overwritten, and the backup checks its own file as a restore would
  - erssi --restore FILE checks every entry before it unpacks
    anything (files and directories only, no absolute name, no ..,
    links only inside the home), moves the old home aside to
    <home>.before-restore-<time> and the backup into its place, under
    the lock of erssi.lock; --dry-run lists what it would restore.
    Refused while an erssi runs on the home. Works in any locale and
    with non-ASCII names, and on a minimal system without cmp, diff
    or ps
  - also as shellter-install.sh --backup / --restore, so a new box
    can restore before erssi is installed
  - a running erssi holds a shared lock on <home>/erssi.lock

+ Tests
  - the E2E keyring cache test no longer fails when a second ends
    between its save and its load (about 1 run in 40 under load)

Binary packages: erssi-2026.10.7-debian12-amd64.tar.xz, erssi-2026.10.7-debian13-amd64.tar.xz and erssi-2026.10.7-ubuntu24-amd64.tar.xz, each built twice from the signed tag and compared (identical byte for byte), listed in SHA256SUMS, which the release key signs (SHA256SUMS.sig, namespace erssi-release). The installer checks all of it; to check by hand see install.md.

FreeBSD: this release has no FreeBSD packages: one test of the package build failed there (the test, not erssi). 2026.10.8 is the same erssi with the FreeBSD 14 and 15 packages.

erssi Shellter Edition 2026.10.6

Choose a tag to compare

@y-o-o-z y-o-o-z released this 25 Oct 09:51
shellter-v2026.10.6
bdf44f5
erssi Shellter Edition 2026.10.6

Fixes from a full review of 2026.10.5.

+ Core
  - /UPGRADE goes ahead only when the session file can be written:
    with a full disk or quota, or a directory erssi cannot write to,
    it says why and keeps its connections (before, they were all
    lost and the new process started with no session); only when the
    final write is what fails, the TLS connections, already quit for
    the upgrade, connect again
  - a script that handles the MONITOR replies (730/731) no longer
    sees them printed a second time by erssi; the built-in keepnick
    hides only its own targets from erssi's own print of them
  - with credentials in the old external file, reading the
    networks (at start, /RELOAD) no longer leaks their settings
  - /HELP CAPSICUM says that in capability mode erssi waits while a
    server name is looked up (a slow DNS server holds it)

+ End-to-end encryption
  - docs/shellter/security.md says that the server can drop whole
    messages or parts of a long one, or reorder them, unnoticed
  - the keyring is read from disk again only when the file changed,
    and a handshake that changed nothing writes nothing: a stranger's
    handshake NOTICE costs a fraction of what it did with a large
    keyring. One sender's requests are limited to 16 in 10 seconds
    whatever context they name (its answers and new keys to 64)
  - a peer whose ident holds '|' is no longer taken for a damaged
    entry (which skipped its acceptance and rotated the key), and
    /e2e export and /e2e list show its address and channel right
  - the plaintext pieces of a long message are wiped before they are
    freed

+ Web frontend (fe-web)
  - a key fe-web makes for TLS is ECDSA P-256: a handshake, which
    anyone who reaches the port can start, costs about an 18th of
    one with the RSA key of older versions. A stored pair is kept
    until its certificate comes within 30 days of its end or its
    files are removed (see below)
  - a new certificate has a random serial (a reused serial is what
    Firefox refuses after a new pair), says it is for a TLS server
    (serverAuth, keyUsage digitalSignature, no CA) and is valid for
    825 days. A stored one is kept; to get a new one, remove
    ~/.erssi/fe-web-key.pem and ~/.erssi/fe-web-cert.pem: the next
    start makes a new pair (pin it again in the web client)
  - a stored certificate ending within 30 days is replaced when the
    server starts (also at /SET fe_web_enabled OFF, then ON), and a
    replaced pair is said with the new certificate's SHA-256
    fingerprint; while the server runs, a daily look warns in those
    30 days
  - a remote address, or another local user known by uid, may open
    at most 8 new connections in 10 seconds, and all of them together
    200 a second (a peer that logged in before is not held by the
    200); more are closed before their TLS handshake. Your own uid
    is not counted. A loopback peer whose uid is not known (the BSDs,
    or Linux without an answer from the kernel), which every local
    user then shares, is not refused: its handshakes are spaced out
    to 50 a second, oldest first. There another local user can still
    delay your connection or close it while it waits, as in
    2026.10.5; fe_web_socket avoids that. A connection its peer
    already reset or closed is closed at once
  - the web client's nicklists lose a nick that quits only in the
    channels it was in, not in every channel, and joins, parts,
    kicks, quits and nick changes reach them also when they are
    hidden (/IGNORE, netsplit hiding)
  - text the server sends in another charset (a WHOIS realname in
    ISO-8859-2) reaches web clients as valid UTF-8: WHOIS text is
    read in the charset /RECODE gives the network or nick, else in
    recode_fallback
  - the startup notices, /FE_WEB STATUS and /HELP FE_WEB no longer
    present the AES-256-GCM layer over the messages as protection:
    its key comes from the password, which travels inside the same
    TLS connection
  - /HELP FE_WEB explains the login and connection limits, what
    they mean behind a proxy, and that on the BSDs and macOS every
    local user is one peer on a loopback port, so fe_web_socket is
    what keeps users apart there; fe-web says so when it listens on
    TCP on those systems
  - the copies of a login's password that fe-web and its libraries
    keep (the read buffers, OpenSSL's record buffer, a refused
    request, the digests of the password and the guess) are wiped;
    the configured password itself stays in the settings

+ Screen
  - no control character from the network reaches the terminal any
    more, on any terminal type: the side panels drew the low byte of
    each character of a channel name or nick on a terminal that is not
    UTF-8, so a name with a Cyrillic letter could send ESC (and with it
    a clipboard write by OSC 52, a new window title, ...). C0, DEL and
    C1 are now drawn as '?' by the terminal output itself, also in
    UTF-8 mode, and an 8-bit name is shown as its bytes there, as the
    text view shows it. What now shows as '?': on an 8-bit terminal
    the bytes 0x80-0x9F (ISO-8859-x is not affected, but CP125x
    letters there are, such as CP1250 ś Ś ź Ź); on a Big5 terminal
    the lead bytes 0x81-0xA0 (HKSCS, user-defined area); on a UTF-8
    terminal bytes that are not valid UTF-8 in the text view and the
    status bar (the side panels show U+FFFD for them)
  - with term_notify on, a focus report the terminal sends in two
    pieces (over a slow ssh link) is still read as one: it used to
    become the keys ESC [ I or ESC [ O, and the focus change was
    missed

+ Image preview
  - a preview no longer outlives its line: after /CLEAR or closing a
    window, a new line could get the address of a freed one and a
    click on its link showed the picture of the old link. The
    records go with their lines, and a record is only used for the
    link it was made for
  - a picture downloaded from a direct link with a query string (or
    an extension other than jpg, jpeg, png, gif and webp) is found in
    the cache again: it was saved under another name than the one
    looked for, and downloaded again for every line with the link
  - a download is written as <name>.part and gets the cache's name
    only when complete: a download that failed or was cancelled
    after /CLEAR or closing its window left its partial file in the
    cache, shown as a broken picture on the next click
  - the picture of a page (og:image) is found when the page writes
    its address with &amp; or relative to the page ("/img.png",
    "//cdn.example.net/x.png"): it is decoded and resolved against
    the page's address before it is downloaded; it must still be an
    http or https address
  - typing and drawing no longer lag while a picture downloads: curl
    waited up to 50 ms at a time (up to half a second while data
    came in) inside erssi's main loop; it is now only called when
    one of its sockets is ready or its timer is due

+ Install and update
  - --uninstall removes only what the installer put into the prefix:
    the files its source installs recorded, the release trees of a
    binary install, its links and its settings. Libraries, headers,
    configuration and man pages that other software built into the
    same prefix (~/local) stay, and the installer names what it left;
    it used to remove the whole prefix with them. A source install by
    an older installer is uninstalled from its build directory's
    install log, or after one more install
  - a source install takes the lock of the prefix as well, so it
    cannot run at the same time as --rollback, --uninstall or another
    install into the same prefix
  - a lock left behind by an installer that was killed (kill -9, the
    OOM killer) or by a reboot is taken over once that process is
    gone; it used to stop every later erssi --update until removed by
    hand. A lock of another host or PID namespace (a container) is
    left alone, and the message says why, as is one made in or seen
    from a FreeBSD jail, or one with no pid in it (installers before
    2026.10.6 write none)
  - the prefix is checked like the source directory: it must be yours
    and only you may write to it and to the directory that holds it,
    before its erssi is run or anything in it is changed
  - a binary install stopped half-way leaves a working prefix that
    says what is in it: the settings name the new release right
    after the switch, a release of the same version moved aside goes
    back, and old releases are renamed before they are removed, so a
    half-removed one is never used again. A source install over a
    binary one puts the bin/erssi link back when it is stopped; a
    source install stopped inside its install step can still leave
    old and new files mixed (install again to repair it)
  - --keep with a number too large for the shell is refused (it used
    to become --keep 1 and remove old releases)
  - erssi --update on a box without git says that git is missing
    instead of blaming the signature check
  - a variable in the environment named like one of the installer's
    own (STAGE, say, common in CI and deploy scripts) no longer makes
    it remove that directory, or drop another installer's lock, when
    it exits early, as an erssi --update with nothing new does
  - the installer checks for the same GLib as the build (2.70, see
    below) and names the version it found: an older GLib used to
    pass its check and fail later in meson setup
  - man erssi works for an install in the home: beside
    ~/.local/bin/erssi the installer links
    ~/.local/share/man/man1/erssi.1 to the manual of the release in
    use (a file of yours there is kept), --uninstall removes the link,
    and the irssi.1 an older install left is removed

+ Build and documentation
  - erssi has a manual page of its own, erssi(1), installed into the
    prefix's sh...
Read more

erssi Shellter Edition 2026.10.5

Choose a tag to compare

@y-o-o-z y-o-o-z released this 19 Oct 19:07
shellter-v2026.10.5
3a6baa1
erssi Shellter Edition 2026.10.5

A fix from another review of 2026.10.4.

+ End-to-end encryption
  - reading the keyring or a /e2e import file reserves room for each
    string as long as that string, not for the rest of the file: a
    keyring near its limit of 64 MB used to ask for about 256 MB at
    every string, so on a box with little memory erssi could be
    stopped while loading it

Binary packages: erssi-2026.10.5-debian13-amd64.tar.xz and erssi-2026.10.5-freebsd14-amd64.tar.xz, listed in SHA256SUMS, which the release key signs (SHA256SUMS.sig, namespace erssi-release). The installer checks all of it; to check by hand see install.md. A 2026.10.4 install from a package takes it with erssi --update.