Files
latchd/README.md

6.7 KiB

latchd

a display manager that runs in your terminal. lets you pick a desktop environment and log in — supports tty, x11, and wayland.

what problem does this solve

Most display managers are graphical. that means you need x11 or wayland running before you can even log in. latchd runs in a plain linux terminal (like tty2), so you can log in first, then start your desktop. it's lightweight, looks decent, and doesn't drag in a full graphics stack just to show a login screen.

how it works

latchd takes over a virtual terminal (tty2 by default) and draws a login screen using ansi escape codes, powered by bubbletea. you type your username and password, pick a session from the switcher, and hit enter.

The actual authentication happens through pam (pluggable authentication modules). Once you're authenticated, latchd forks a child process that opens the pam session, sets up your environment, spawns your desktop or window manager, and does utmp accounting so tools like who and loginctl can see you're logged in.

For x11 sessions it handles the whole setup — xauthority cookies, sigusr1 handshake with the x server, timing out if xorg fails to start. for wayland it just runs your compositor script. for tty it drops you into your shell.

While the login screen is up, it renders a conway's game of life simulation as the background at 30fps, using unicode half-block characters for a pixelated look.

what you get

  • Session switcher with left/right arrows and dot indicators
  • username and password fields
  • Status line for errors and info
  • power controls (f1 shutdown, f2 reboot by default — configurable)
  • caps lock indicator
  • shake animation on wrong password
  • spring animation on switcher transitions
  • faillock integration — shows remaining attempts, detects lockouts
  • Admin override (ctrl+u) to unlock a locked-out account
  • configurable color theming via toml
  • variable substitution in config ($varname)
  • Preview mode for testing inside an existing session

Known Issues

This project is a work in progress. here's what you should know:

  • no tests. at all. no unit tests, no integration tests. if you hit a bug, you'll find it the hard way.
  • Session spawning is a bit rough. it uses ForkExec to re-launch itself as a child process, which means the pam session lifecycle isn't as clean as the original fork-then-exec model. this can cause pam modules that track session leaders to get confused.
  • a handful of open bugs — edge cases in the switcher, occasional terminal state corruption on abrupt exits, and the automata background can flicker when the terminal resizes rapidly.
  • not all config options are fully wired. things like SwitcherConfig.ShowNeighbours, various color options, and input field styling fields exist in the config struct but may not all be hooked up to the rendering yet.

installing

from source

you need go 1.22 or later, libpam0g-dev (debian/ubuntu) or pam-devel (rhel/fedora) or pam (arch), and a c compiler (build-essential).

make deps              # install system dependencies
sudo make install      # build, install binary + configs + systemd unit
sudo systemctl enable latchd

to test without rebooting:

make run-preview

arch

pacman -S latchd
systemctl enable latchd

command line

latchd [options]

  -c, --config <file>     config path (default: /etc/latchd/config.toml)
  -v, --variables <file>  variables path
  --tty <n>               override the tty number to run on
  --preview               run inside an existing session for testing
  --no-log                disable all logging
  --show-config           print the parsed config and exit
  -V, --version           print version and exit
  --xsessions <dir>       override xsessions path
  --wlsessions <dir>      override wayland-sessions path
  --initial-path <path>   override initial PATH value

adding sessions

drop executable scripts into the right folder and they show up in the switcher.

x11 — put your xinitrc scripts in /etc/latchd/wms/:

# /etc/latchd/wms/bspwm
#!/bin/sh
sxhkd &
exec bspwm
chmod +x /etc/latchd/wms/bspwm

wayland — same thing in /etc/latchd/wayland/:

# /etc/latchd/wayland/sway
#!/bin/sh
exec sway

latchd also reads freedesktop .desktop files from /usr/share/xsessions and /usr/share/wayland-sessions automatically.

tty sessions are added automatically if no other environments are found, or you can force one with include_tty_shell = true in the config.

configuring

the config lives at /etc/latchd/config.toml. all options are documented inline in the file. you can also use a variables.toml file with $VAR syntax:

# /etc/latchd/variables.toml
accent = "orange"
# /etc/latchd/config.toml
[password_field.style]
title_color_focused = "$accent"
border_color_focused = "$accent"

debugging

three log files:

  • /var/log/latchd.log — main latchd events
  • /var/log/latchd.client.log — stdout/stderr of your session
  • /var/log/latchd.xorg.log — x server output (64mb cap)

run latchd --show-config to verify your configuration. run latchd --preview to test the login screen without leaving your current session.

keybindings

standard shell-style bindings in text fields:

key what it does
ctrl+a start of line
ctrl+e end of line
ctrl+l or ctrl+u clear field
ctrl+d delete forward
ctrl+h backspace
ctrl+b/f left/right
ctrl+p/n up/down (previous/next field)
tab, shift+tab next/prev field
left/right switch session (in switcher mode)
f1, f2 power controls
ctrl+u admin unlock (when account is locked)

source layout

src/
├── main.go           entry point, cli, vt switching, session forking
├── auth/
│   ├── pam.go        cgo pam bindings (locks goroutine to os thread)
│   ├── faillock.go   faillock tally detection and reset
│   └── utmpx.go      user accounting records
├── config/
│   └── config.go     toml parsing, variable substitution, defaults
├── session/
│   ├── env.go        xdg and environment variable setup
│   ├── exec.go       process spawning, privilege dropping, log limits
│   ├── scan.go       session discovery and .desktop parsing
│   ├── x11.go        xorg setup, xauth, sigusr1 handshake
│   └── wayland.go    wayland placeholder
├── login/
│   └── login.go      login form ui, state machine, animations, rendering
└── tui/
    └── bg/
        └── automata.go   conway's game of life background

license

MIT or Apache-2.0