A cozy terminal clubhouse for computer people. Lofi, games, chat, artboard, and tech news, all via SSH.
翻譯準備中
正在載入完整 README。
檢視完整 README ↗A cozy command-line clubhouse for computer people. Chat, music, games, art, coding, and tech news. Connect with any SSH client!
ssh late.sh
late.sh is a terminal-first social app: real-time chat, music, games, news, profiles, and a shared always-on space you can enter from any SSH client.
This repository is the main codebase for late.sh.
late.sh service remains the canonical deployment.Read the details in LICENSE, the plain-English policy in LICENSING.md, and contribution rules in CONTRIBUTING.md.
7: anyone posts an event, everyone sees it, i says I'm in; your own events sit beside it, private/listen page/listen pageIRC uses #name for public rooms and ##name for private rooms. /LIST
shows both when you belong to the private room; /join ##name opens that
private room using your existing late.sh membership. Create private rooms
and invite members from the TUI. IRC JOIN only opens existing rooms.
IRC clients with draft/chathistory can retrieve joined-channel and existing
DM history, including missed conversations through CHATHISTORY TARGETS.
Requests support message IDs and timestamps, up to 300 stored messages per
page. Clients with batch and server-time that do not request
draft/chathistory receive the latest 25 messages after joining a channel.
Private membership and room bans apply to history as well as live chat.
The Rust workspace contains the main apps and standalone door hosts:
| Crate | Role |
|---|---|
late-cli | Companion CLI for local audio playback, paired controls, and visualizer sync |
late-core | Shared domain code, database layer, migrations, and infrastructure helpers |
late-ssh | SSH server and terminal UI application |
late-web | Web server, landing page, profiles/gallery, stream proxy, and the public /listen page |
late-webview | Helper process hosting the official YouTube IFrame Player for the CLI |
late-zork | Private SSH/PTY host for the separately executed Frotz interpreter and Zork trilogy |
The other standalone door hosts are late-bashquest, late-brogue,
late-codekeep, late-dcss, late-dopewars, late-nethack, and late-usurper.
The stack is backed by PostgreSQL, Icecast, and Liquidsoap.
Try the live service:
ssh late.sh
The SSH login name is discarded rather than used as a public handle. On the first connection, a new account receives a random modifier-and-noun username; the username can still be changed later in Settings.
Run it yourself (requires Docker):
git clone https://github.com/mpiorowski/late-sh
cd late-sh
make start
Then connect to your local instance:
ssh localhost -p 2222
That's it. Postgres, Icecast, and Liquidsoap all come up automatically.
Install the companion CLI for local audio playback and synced visualizer:
macOS / Linux / Termux:
curl -fsSL https://cli.late.sh/install.sh | bash
On Termux, the installer fetches the Android CLI build instead of the GNU/Linux one.
Windows PowerShell (x64):
irm https://cli.late.sh/install.ps1 | iex
mise (from the GitHub Release archives):
mise use -g github:mpiorowski/late-sh
Nix / NixOS:
nix run github:mpiorowski/late-sh#late
Or build it from source:
mise install # optional — sets up the expected Rust toolchain
cargo build --release --bin late
Everything runs in Docker Compose: the development profiles point at the
compose service names (postgres, icecast), so late-ssh and late-web
do not run outside it.
mise install # rust, mold (Linux only) and cargo-nextest, as pinned in .mise.toml
make start # copies .env.dev to .env and starts the stack
ssh localhost -p 2222
Personal keys (an AI key, a YouTube key) go in the gitignored .env.local,
which wins over .env. make start-instance2 runs a second instance from
.env.dev2.
late-ssh runs the way production runs it, as a pod behind a copy of the
production SSH edge. A saved change that rebuilds the binary rolls out like a
deploy: a new pod starts, and once it is ready the old one drains. Your open
session stays on the old code behind the update banner until you reconnect
(the native CLI, scripts/run_local_cli_native.sh, moves it on its own after
30 s without input), and a change that does not compile leaves the old pod
serving.
make fleet-rollout rolls out by hand, make fleet-ps lists the pods, and
make fleet-logs follows them.
The Zork door is enabled in the development profile. Build its vendored asset image once before building the Compose services (the door base images target amd64):
docker build --platform linux/amd64 -f docker/doors/zork.Dockerfile \
-t ghcr.io/mpiorowski/late-sh/door-zork:2.56pre-r1 .
make start
Fixtures for manual testing, each described in its domain's CONTEXT.md:
make seed-artboard (gallery pieces, applause and staff accounts),
make seed-calendar (the events board), make seed-paper (a long edition of
The Late Edition), make seed-irc-history USERNAME=<you> (IRC history for
Halloy and other clients), and make seed-leaderboard. The development
profile grants admin to every session; set force_admin to false in
late-ssh/src/config.rs to test role-based permissions.
Run the local gate before opening a PR:
make check
This runs cargo fmt --check, then cargo clippy and cargo nextest across the
whole workspace with --features otel. It is the full pre-merge sweep and the
only place the otel (telemetry) build is exercised, since CI skips otel to stay
fast; otel breakage is caught here or at the release build, never in prod.
The local check starts a dedicated Compose Postgres project (late-check) on
port 55433 and points DB-backed tests at it via TEST_DATABASE_URL.
Override CHECK_INSTANCE or CHECK_PG_HOST_PORT if you need a parallel check
database.
Contributions are welcome, but read the project policy first:
This repository uses DCO sign-off for commits:
git commit -s
If you distribute a fork, do not present it as the official late.sh service or use the project branding as your own.
CONTEXT.md lives. Written for humans and LLMs alike; point your AI editor at it first.