CLI tool
mpiorowski/late-sh avatar
mpiorowski/late-sh

late.sh: A Terminal Clubhouse over SSH

A cozy terminal clubhouse for computer people. Lofi, games, chat, artboard, and tech news, all via SSH.

1,514 stars97 forksRustNOASSERTION

At a glance

What is it?
late.sh packages chat, music, terminal games, events, profiles, news, and shared activity behind an SSH connection. It suits terminal users who want a hosted social space or a self-hosted Rust deployment with Docker-backed infrastructure.
Who is it for?
late.sh is a good fit for terminal-oriented users who want one SSH endpoint for chat, music, games, events, and profiles. It is a poor fit for users who need an OSI-approved license without reviewing the FSL terms, or operators who do not want to manage PostgreSQL, Icecast, Liquidsoap, and multiple Rust services.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What late.sh puts behind one SSH connection

late.sh is aimed at computer users who prefer working inside a terminal and want a shared social space rather than a collection of separate web applications. The public service can be reached with an ordinary SSH client, and the repository presents the hosted late.sh deployment as the canonical service. The same repository also contains the code needed to run a local instance.

The feature set is broader than chat. The TUI includes a dashboard, chat, profiles, news, arcade screens, an events board, and terminal games. The events board on screen 7 allows users to post events, mark attendance with i, and keep their own events private. Timed events appear in the Home now strip and Live panel, while all-day events take the lounge topic row for their day. Music is streamed through Icecast and Liquidsoap and can be played by the companion CLI or the public /listen page. This makes late.sh closer to a small terminal-hosted clubhouse than a standalone IRC client.

The intended audience includes programmers and other technically inclined users, but the application does not require the reader to be a Rust developer for the hosted service. A local deployment does require Docker and an understanding of a multi-service application. The README also says the SSH login name is discarded rather than becoming a public handle. New accounts receive a random modifier-and-noun username, which can be changed later in Settings. That account model is easy to understand, but it also means that the SSH account name should not be treated as a stable identity.

The Rust workspace and service boundaries

The repository is organized as a Cargo workspace with separate crates for the user-facing components. late-ssh contains the SSH server and terminal UI application. late-core holds shared domain code, the database layer, migrations, and infrastructure helpers. late-web provides the web server, landing page, profiles and gallery, stream proxy, and token-less /listen page. late-cli is the companion command-line application for local audio playback, paired controls, and visualizer synchronization.

Some games and doors are isolated as standalone hosts rather than built directly into the main SSH application. The workspace includes late-zork for the separately executed Frotz interpreter, plus late-bashquest, late-brogue, late-codekeep, late-dcss, late-dopewars, late-nethack, and late-usurper. A helper process, late-webview, hosts the official YouTube IFrame Player for the CLI. This separation gives each interactive or media-heavy component a distinct deployment boundary.

The runtime stack uses PostgreSQL for persistent application data, Icecast for audio distribution, and Liquidsoap for stream processing. Docker Compose wires these services together with the SSH and web services. The Compose file exposes SSH, API, IRC, and IRC TLS ports, while the service health check targets /api/health over the API port. The architecture therefore spans terminal interaction, an HTTP-facing web component, chat protocols, database-backed state, and streaming infrastructure. The README does not give a single lightweight command for running only chat or only the web frontend.

IRC is also part of the application rather than an unrelated integration. Public rooms use #name, while private rooms use ##name. /LIST includes private rooms when the user belongs to them, and /join ##name opens an existing private room using the user's existing late.sh membership. JOIN cannot create a room. Clients that support draft/chathistory can request message IDs or timestamps and receive up to 300 stored messages per page. Clients using batch and server-time without draft/chathistory receive the latest 25 messages after joining. Room bans and private membership apply to history as well as live messages.

Using the hosted service with an SSH client

The shortest documented first use is to connect to the public service. The command below is taken directly from the README. An SSH client with normal terminal and interactive keyboard support is the only client command documented for this entry point.

bash
ssh late.sh

After connecting, the user is placed in the terminal application rather than at an ordinary operating-system shell. The SSH login name is not used as the public handle. A first-time account receives a generated modifier-and-noun username, and the username can be changed in Settings. The available screens are reached through the TUI, including dashboard, chat, profiles, news, and arcade areas. The README identifies screen 5 as Profiles, screen 7 as the events board, and screen 3 as the route to Games.

The hosted service also exposes the public /listen page for browser-based audio access, while local audio can be handled by the companion CLI. IRC access is described in the project documentation as using port 6667 without TLS for the local Halloy test setup, with an IRC token from the local application's Settings. That IRC connection is a development and integration path, not a replacement for the documented `ssh late.sh` entry point.

For a first real session, connect, inspect the dashboard and chat, open Profiles, and try the events board on screen 7. These are the documented interaction surfaces. The README does not specify a command-line flag for selecting a screen, so screen navigation should be performed through the TUI rather than an invented SSH option.

Running a local Docker instance

The documented local deployment clones the repository and starts the Docker stack. The Makefile refreshes the .env file from .env.dev on each run, and Compose also loads .env.local when that optional file exists. This matters because configuration is not kept in the Makefile: the README and Makefile point contributors to the environment templates and application configuration in late-ssh/src/config.rs.

bash
git clone https://github.com/mpiorowski/late-sh
cd late-sh
make start

The local SSH service is then reached on port 2222. The README says PostgreSQL, Icecast, and Liquidsoap come up automatically.

bash
ssh localhost -p 2222

The Compose configuration shows that the stack is not just a single container. It includes service-ssh and service-web, with dependencies on PostgreSQL and the standalone game hosts. A health check calls /api/health through the API port, and the SSH service has a long start period because several dependencies must start first. Operators should expect a containerized deployment rather than a single-process trial.

For native Rust development, the README documents starting only infrastructure in Docker and running the applications through Cargo.

bash
docker compose up -d postgres icecast liquidsoap
cargo run -p late-ssh
cargo run -p late-web

The Zork door requires an additional vendored asset image build before Compose services are built. The documented command uses linux/amd64, so this step is not portable to every host architecture without separate verification.

bash
docker build --platform linux/amd64 -f docker/doors/zork.Dockerfile \
  -t ghcr.io/mpiorowski/late-sh/door-zork:2.56pre-r1 .
make start

Companion CLI installation and local media use

The late-cli crate is useful when the user wants audio playback and visualizer data on the local machine rather than using only the public /listen page. The README provides separate installation routes for macOS, Linux, Termux, Windows PowerShell, mise, Nix, and source builds. These are installation methods, not six different applications.

On macOS, Linux, or Termux, the documented installer is:

bash
curl -fsSL https://cli.late.sh/install.sh | bash

On Termux, the installer selects the Android CLI build instead of the GNU/Linux build. Windows PowerShell uses:

powershell
irm https://cli.late.sh/install.ps1 | iex

The README also documents installation from GitHub Release archives through mise:

bash
mise use -g github:mpiorowski/late-sh

For Nix or NixOS, the command selects the late executable from the repository:

bash
nix run github:mpiorowski/late-sh#late

A source build requires the expected Rust toolchain. The README presents mise install as the way to set up that toolchain, mold, and cargo-nextest, then builds the release binary with Cargo.

bash
mise install
cargo build --release --bin late

The companion CLI is paired with the application for playback and visualizer synchronization. The README does not document authentication setup for the CLI in the excerpt, nor does it specify a standalone playback command. That means the documented value is the pairing architecture, while exact CLI usage beyond installation would require the crate documentation or source-level help output.

Operational limits, alternatives, and maintenance

The largest operational limitation is the number of moving parts. A self-hosted instance requires Docker Compose, PostgreSQL, Icecast, Liquidsoap, the SSH service, the web service, and several standalone game hosts. A deployment can therefore fail for infrastructure reasons before an application feature is involved. The Compose health check uses an HTTP health endpoint, but the README does not document a complete backup, restore, migration rollback, or production sizing procedure in the excerpt.

Zork also has a documented platform constraint. The current door base images target amd64, and the documented build command forces that platform. On an arm64 workstation, this may require emulation or a separately prepared image. The game host also has a distinct save contract: automatic progress, one deliberate SAVE per edition, six account-owned slots, RESTORE confirmation, and a 20-minute Continue timeout. Those are product-specific details that make the game more than a static TUI menu.

A real alternative is a conventional IRC client connected to a separate chat server, with music, calendars, and games handled by independent applications. IRC clients can provide chat history and room access, but they do not give the same integrated TUI, paired local audio player, shared events board, profile surface, or hosted SSH entry point. The trade-off is breadth versus specialization: late.sh concentrates several community features, while a chat-first platform concentrates communication and typically leaves media and games to separate clients.

Maintenance is current according to the repository facts. It is not archived, and the last push was on 2026-10-16. Recent releases include v0.49.4-full on 2026-10-15, v0.49.3-zork on 2026-10-14, and v0.49.2-infra on 2026-10-14. The project is source-available rather than OSI open source during the FSL protection period. The LICENSE, LICENSING.md, and CONTRIBUTING.md therefore need review before redistribution, modification, or commercial deployment. This is a licensing status, not legal advice. Upgrade planning should also account for infrastructure changes, standalone door image pins, database migrations, and the additional assets required by specific games.

Editorial conclusion

late.sh is a good fit for terminal-oriented users who want one SSH endpoint for chat, music, games, events, and profiles. It is a poor fit for users who need an OSI-approved license without reviewing the FSL terms, or operators who do not want to manage PostgreSQL, Icecast, Liquidsoap, and multiple Rust services. Evaluate the hosted service and the LICENSE, LICENSING.md, CONTRIBUTING.md, and deployment configuration first. The first concrete check is whether the SSH experience and current licensing terms match the intended community or internal use.

Frequently asked questions

How do I connect to late.sh?

Use any SSH client with the command `ssh late.sh`. The first connection creates an account with a generated username that can later be changed in Settings.

Can I run late.sh locally?

Yes. The README documents cloning the repository and running `make start` with Docker. The local SSH service is then available through `ssh localhost -p 2222`.

What license does late.sh use?

The repository describes the project as source-available and not OSI open source during the FSL protection period. Review LICENSE, LICENSING.md, and CONTRIBUTING.md for the applicable terms and contribution rules.

Official sources

  1. Issues
  2. mpiorowski/late-sh on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/mpiorowski-late-sh.svg)](https://hysenlabs.com/projects/mpiorowski-late-sh)

Was this useful?