Files
latchd/README.md
Zane Walker f2a885d621 refactor: split the TUI and refresh project docs
Move login state, authentication, discovery, input, rendering, and tests into focused TUI modules. Add detailed CLI error reports with recovery commands, align the build and host-check documentation, and keep the legacy Go tree outside normal builds.

Checks: make check; make integration-test; go test ./... (legacy/go).
2026-10-05 21:37:15 +05:30

6.3 KiB
Raw Blame History

latchd

Want a TUI-based login manager because you are tired of GDM or Plasma Login? Latchd gives you a small keyboard-first login screen on a Linux virtual terminal, then starts a TTY shell, an X11 desktop, or a Wayland desktop for the account you choose.

Latchd is written in Rust and runs as a systemd service. It finds login accounts through NSS, reads desktop entries from the configured directories, The old Go prototype is still in legacy/go/, but it is not part of the build.

Latchd login screen

This screen comes from the Docker preview capture; the UI guide has the keyboard map and the help screen.

What latchd does

  • account discovery — reads normal login accounts through NSS; filters low UIDs, excluded names, no-login shells, and unsafe home directories
  • account status — reads shadow aging fields and the configured faillock helper; shows expiry, lock, inactivity, and failure counts in the screen
  • session discovery — reads X11 and Wayland .desktop files plus administrator scripts; keeps the program and its arguments separate instead of passing them to a shell
  • login handoff — builds the user environment, opens the configured login session, starts the selected program with the account UID and groups, and closes the session when it exits
  • X11 startup — creates a private Xauthority file, waits for the X server readiness signal, and removes the file after the desktop exits
  • Wayland startup — starts the selected desktop with the session values it needs; it does not start a compositor
  • TTY startup — attaches the selected shell to the virtual terminal and records the user process when UTMPX is available
  • user interface — provides account switching, last-session preferences, filtering, refresh, notifications, wallpapers, reduced motion, and confirmed power actions

Preview mode draws the same screen and reads the same TOML structure, but it does not authenticate or start a user program, which makes it useful for layout work and config checks.

Quick start

Install the build requirements on Debian or Ubuntu:

sudo apt-get install build-essential pkg-config libpam0g-dev libpam-modules

Build the release binary and run the checks:

make check
make build

The binary is build/latchd. Open the preview screen with:

./build/latchd --preview --no-log

The repository pins Rust 1.88 in rust-toolchain.toml.

Configuration

The service reads /etc/latchd/config.toml. Preview mode first checks $XDG_CONFIG_HOME/latchd/config.toml, then ~/.config/latchd/config.toml, and finally the system file. --config PATH selects one file directly.

Create a user file from the example with:

make install-user

That command creates ~/.config/latchd/ with mode 700, writes config.toml with mode 600, and leaves an existing file alone. The full field reference, variable substitution, command-line overrides, desktop entry rules, and permission checks are in docs/configuration.md.

Install on a test machine

Use a disposable machine and keep another login path available while you change the display manager:

sudo make install
sudo systemctl enable latchd.service
sudo systemctl start latchd.service

The install target writes the binary, /etc/latchd/config.toml, /etc/pam.d/latchd, the session-script directories, and the systemd unit. The supplied unit uses /dev/tty2, so change both tty in the TOML file and TTYPath in the unit if you use another virtual terminal. The install target does not disable the current display manager for you.

Keyboard controls

Key Action
Tab / Shift-Tab Move focus
Up / Down Move focus or move in a filtered list
Left / Right Change the selected session
/ Filter sessions or accounts
Ctrl-R Refresh accounts and sessions
Ctrl-N / Ctrl-P Select the next or previous account
Ctrl-B Toggle the background
Ctrl-M Toggle reduced motion
Enter Authenticate or submit a password change
Esc Clear the password or close a popup
? Show the key reference
Ctrl-C Restore the terminal and quit
F1–F12 Confirm a configured power action

Lowercase filters ignore case, while a filter with an uppercase character is case-sensitive. The preview screen and the capture command are documented in docs/ui.md.

Checks and releases

Use make check for formatting, unit tests, Clippy, and rustdoc; use make integration-test for the CLI paths and make docker-test for the pinned container build. make pam-fixture-test needs root because it installs temporary test policies, while make system-e2e checks the services and devices available on the current host.

Run make system-e2e-strict only in a disposable VM that has a test policy, a real virtual terminal, systemd-logind, and the X11 or Wayland stack you want to test. docs/e2e-testing.md explains what each check can and cannot cover.

Create a local release archive with:

make package

GitLab CI runs the same Rust, CLI, container, and capability checks, then creates an archive and SHA-256 file for a SemVer tag. The release process is described in docs/development.md.

Project layout

crates/latchd-core/  account discovery, configuration, sessions, and UTMPX
crates/latchd-auth/  authentication worker and session handoff
crates/latchd-tui/   terminal state, rendering, input, and effects
rust/main.rs         command-line entry point and service loop
extra/               example configuration, login policy, and systemd unit
scripts/             CLI, Docker, fixture, and host checks
legacy/go/           reference implementation from the early prototype

License

Apache-2.0. See LICENSE.