tui-tools

tui-users

Accounts, groups, keys and sudo, with every change previewed before it runs

A terminal UI (TUI) for useradd and ssh-keygen on Linux: the machine's local accounts.

v0.2.2betausersMIT
The accounts table, findings first: uid 0 twice, an empty password, a service account with a shell
The accounts table, findings first: uid 0 twice, an empty password, a service account with a shell

A terminal UI for the machine's local accounts. It lists every account with the facts that decide what it can do — uid, primary group, groups, shell, last login, whether the password is usable, locked or missing — and puts the ones worth a second look at the top, with the reason: a second account with uid 0, an empty password, a service account with a login shell.

Open an account and you get the whole picture: its aging policy in words rather than in days-since-1970, the authorized keys in its ~/.ssh with their fingerprints, what sudo says it may run, and its open sessions. A second screen lists the groups with their real membership, primary members included; a third quotes every rule in /etc/sudoers and /etc/sudoers.d, marking the ones that run without a password.

Changes are previewed: creating and deleting accounts and groups, locking an account, setting a password, granting or revoking sudo, editing group membership, the login shell, the expiry, and authorized keys. A password never reaches a command line — it goes to chpasswd on standard input.

Run tui-users --demo to drive a sample machine: every key works and nothing touches your system.

Keys

KeyAction
enterOpen the selected account or group
tabMove between accounts, groups and sudo rules
n / DCreate an account or a group / delete one; a group has to be empty first
lLock or unlock the account's password
pSet a password, never echoed and never in a command line
a / xAdd the account to a group / remove it from one
SGrant or revoke sudo through the group that grants it on this machine
sChange the login shell
eSet the account expiry and the password lifetime
KAdd an authorized key, or remove one, with a diff to confirm
/Filter the screen across every column
?Help
qQuit

Press ? inside the tool for the full help screen, which is generated from the same action table as the key map.

Compatibility

This tool is a face on the program below, so its version matters. Tested is not a claim: a version lands there only after the tool's own suite passed against it on a real machine in the lab, and the run is kept as evidence in the repository. At startup the tool probes the backend once and says what it found in its header — a version nobody has run against is shown as (untested) in the warning colour, one older than the minimum as (below minimum) in the error colour. Neither stops it: the backend still refuses what it cannot do, in its own words.

shadow-utils

useradd ≥ 4.8
Binary
useradd
Minimum
4.8
Tested
No recorded run yet. The tool still runs and reports the version it found as untested.

What changes on older versions

  • shadow-utils >=4.8

    shadow-utils prints no version from any of its programs: useradd --version, chage --version and every sibling answer "unrecognized option" on Arch, Debian and Fedora alike. This backend therefore declares no version command, and the header shows none for it

  • shadow-utils >=4.8

    the minimum above is informative, not enforced: it is the release whose flags this tool uses (useradd -r -m -G, usermod -L -U -s, userdel -r, gpasswd -a -d, groupadd -g, groupdel, chage -E -M -l), all far older than any supported distribution

  • shadow-utils >=4.8

    reading the lock state and the expiry of an account needs getent shadow, which needs root; an unprivileged run lists every account and says the password state is unknown rather than implying it is fine

openssh

ssh-keygen ≥ 8.2
Binary
ssh-keygen
Minimum
8.2
Probed with
ssh -V
Tested
9.610.210.5

Needs a version this new

  • security-keyssince 8.2

What changes on older versions

  • openssh <8.2

    ssh-keygen -l does not know the sk- key types, so a FIDO security key in an authorized_keys file cannot be fingerprinted and adding one is warned about: sshd would ignore the line it wrote

  • openssh <6.8

    ssh-keygen -l prints MD5 fingerprints rather than SHA256, so the fingerprint column will not match what a modern ssh-keygen -lf shows elsewhere

Maintain shadow-utils or openssh? You are welcome to help shape this tool. About → maintainers

Guides

Written after the work, from a machine the commands were actually run on. Every guide that mentions tui-users is listed here.

  • What a bug report sends, and what it never does

    The --report flag prints the block a maintainer needs to reproduce a bug, and leaves out your hostname, your user name and your home path by construction, not by asking you to trust it.

Install

Once per machine, then every tool in the family is one pacman away.

Add the repository
$ curl -fsSL https://pkgs.tui.tools/install.sh | sh
Or run the same thing yourself, one command at a time

A family whose whole promise is preview before you run is not going to insist you pipe a script into a shell. These are the commands that script runs.

The one-time setup, by hand
$ curl -fsSL -o /tmp/tui-tools.asc https://pkgs.tui.tools/pubkey.asc
  sudo pacman-key --add /tmp/tui-tools.asc
  sudo pacman-key --lsign-key \
    "$(gpg --show-keys --with-colons /tmp/tui-tools.asc | awk -F: '/^fpr:/{print $10; exit}')"
  printf '[tui-tools]\nServer = https://pkgs.tui.tools/arch/$arch\n' \
    | sudo tee -a /etc/pacman.conf
  sudo pacman -Sy
Arch Linux · tui-users
$ sudo pacman -S tui-users

Upgrades then arrive with the rest of your system updates.

What it can do to your machine

  • Preview, then confirm

    Every change is shown as an exact command line and confirmed before it runs. The dialog and the runner receive the same value, so the preview cannot drift from what executes.

  • Escalates for actions

    Most reads are unprivileged: getent passwd, getent group, lastlog and loginctl answer to any user. sudo -n, which never prompts, covers three reads — /etc/shadow, the sudoers files and another account's chage -l — and every change.

  • No daemon, no state of its own

    Nothing keeps running after you quit, and nothing is installed to run later. The system is the source of truth; the tool re-reads it after every change.

  • No network access

    The tool opens no network connection of its own. No telemetry, no update check, no phone home.

  • Static binary

    Released statically linked, with no runtime dependencies to install.

  • Signed release, with provenance

    checksums.txt carries a keyless cosign signature from this repository's release workflow, every archive has a CycloneDX SBOM, and every archive, package and the checksum file carry SLSA build provenance. The security page shows the three commands that check it.

Reporting

Report a security issue privately, through GitHub's private vulnerability reporting on the repository's Security tab. The family-wide policy, and what counts as in scope, is on the security page.

Downloads

v0.2.2 · 2026-09-25
FileSizeSHA-256
checksums.txt1016 B—
checksums.txt.sigstore.json10 KB—
provenance.intoto.jsonl12 KB—
tui-users-0.2.2-1-aarch64.pkg.tar.zst1.8 MB3cc0a17c0db3b8ac5dbe0a409cd2bb7ccc9944e14ebb0678884e6f84b25c3e41
tui-users-0.2.2-1-x86_64.pkg.tar.zst1.9 MB9b4fc2a2fd664e99de0c4d0f0fa7d79d1b209a6debe953f2770490138ddfed10
tui-users-0.2.2-1.aarch64.rpm1.8 MB411e3a773b4f629d14a7cd7a6e424298c4c46514af66578dd7950e068434e9d2
tui-users-0.2.2-1.x86_64.rpm1.9 MBeb5047453cdf0cb90b1ae4561c38c4b0a765e0f70f7f73e35a40aef28ce8bfdc
tui-users_0.2.2_amd64.deb1.9 MBf8c36803ddd4b37c38f5b7f4cda127fb08cf45d874735ab5f0d9d8915da67a1a
tui-users_0.2.2_arm64.deb1.8 MB683038e7495dd006bbe65237f8a9e771805c1ce2cfd9974a72314a6877d4fb02
tui-users_0.2.2_linux_amd64.tar.gz1.9 MB83508e4028eb8152319130872c1af7a1d1c49f4c529a5b81305cdbb752abef8d
tui-users_0.2.2_linux_amd64.tar.gz.cyclonedx.json23 KB3f4509929a7579e3a04c8893f6ce07e2d121233b3e0419d6f17565276e15e4ae
tui-users_0.2.2_linux_arm64.tar.gz1.8 MB8370ef4fcbb83b791e07aa3f1d91e8616b7838df083bbae88cdaf932c6ecebae
tui-users_0.2.2_linux_arm64.tar.gz.cyclonedx.json23 KB369332377c1d0470a769ca9303aa677b5cf957022756e906781f4a3160a0e0db

Every release ships a checksums.txt. Download it next to the archive and run sha256sum -c checksums.txt --ignore-missing. See verifying a download.

Releases

v0.2.2

2026-09-25
## tui-users v0.2.2

tui-users 0.2.2: tui-kit v0.4.4

tui-users 0.2.2 moves to tui-kit v0.4.4: every useradd, usermod, chpasswd and gpasswd step now runs in its own session without a controlling terminal, so a step that would prompt fails at once instead of hanging behind the UI (passwords keep arriving on standard input through chpasswd), and a failed step reports its meaningful line, cleaned of escape codes. Command previews are POSIX shell-quoted (a full name now reads as `-c 'Alice Moreira'`), the README screenshots are re-rendered with continuous box borders, and the README banner now carries the kit's stability markers.

Built by this repository's CI on the tag itself. Each archive ships a
CycloneDX SBOM, `checksums.txt` carries a keyless cosign signature, and
every file has SLSA build provenance — see the README's "Verify a
download" for the two commands that check them.

The commits in this release:

## Changelog
* 00cea62f28106cf78018c606307617199066dc8c 0.2.2: tui-kit v0.4.4 (#20)
* de89345a6e83863305e85114e4adc96edef6ee86 Bump anchore/sbom-action/download-syft in the github-actions group (#18)
* ea359a620e164f0e1485f977a70a2ccd18c23636 Bump the github-actions group with 4 updates (#19)
* 5879feef29ae5e16a48a3c819ef1b4232febc925 README: link the tool's page on tui.tools (#17)
* 2cbc63f96434590bf7cea79137c077a69d8a5313 README: point the install snippet at the current release (#16)

v0.2.1

2026-09-02
## tui-users v0.2.1

Read a missing authorized_keys as "no keys", not as a failed command.

Also: tui-kit v0.3.0 — dialogs wrap and scroll instead of clipping the
command preview, and the picker filters as you type.

Built by this repository's CI on the tag itself. Each archive ships a
CycloneDX SBOM, `checksums.txt` carries a keyless cosign signature, and
every file has SLSA build provenance — see the README's "Verify a
download" for the two commands that check them.

The commits in this release:

## Changelog
* 6e6ccef0b570a28bdc1e1db063209e9f402f4c75 Bump tui-kit to v0.3.0 (#15)
* b1780f92888597c502ae94659c5638e495d64d2f Read a missing authorized_keys as "no keys", not as a failed command (#14)

v0.2.0

2026-09-01
## tui-users v0.2.0

Manage, not view (wave 3): create what does not exist, edit what does; lab-validated.

Built by this repository's CI on the tag itself. Each archive ships a
CycloneDX SBOM, `checksums.txt` carries a keyless cosign signature, and
every file has SLSA build provenance — see the README's "Verify a
download" for the two commands that check them.

The commits in this release:

## Changelog
* 3575a919e9823ba72e590a398e058189a3e19632 A code of conduct that fits on one screen (#10)
* 690156f9468eba2be32b43317b2fde45bf394d0f Add --report, and a bug form that asks for it (#11)
* 2185e0a91fdc41cee3d8abc5a7d3688e197aa738 Bump anchore/sbom-action/download-syft (#4)
* 39b407f080bca4a493e86c364c44cb39ecae8314 Carry the OpenSSF Best Practices badge (#8)
* 85ae5e4d2eb64738b389659498de773eab1ca2af Carry the family's gitleaks configuration unchanged (#2)
* 4d42d895418375fbb3a7cd9c87e4dad793f0888f Create groups and grant sudo from the TUI (#13)
* 65868717e96f6c7cba9d7a9bc233870b2206f6be Do not let a host named after its distribution fail the leak check (#12)
* 80f14553ae40ed81afcd5674c77bd79fc9b7530b Fetch the tag annotation before releasing (#6)
* a678af49e7c6ffee7a134aae1d7f86d8afee51f9 Pin what CI runs, fuzz the parsers, and say the releases are signed (#3)
* f88d74b6fa0e992393c5d1b4b42fbd7ff3bee107 Print the whole tag message, not only its body (#7)
* a776b3b2e8dea5703729b3e0cb46e228d3ef11d7 Say beta once (#5)
* 097e81c05e325f9c55faf44aab921124a1d52a61 Take tui-kit v0.2.8: hashed pip install, provenance bundle on the release (#9)

v0.1.2

2026-08-30
## Changelog
* 343bf943de00185c557758197985ac4bd9634d39 Drop cross-repo dispatch; the package repo and the site poll releases
* 6e621f603c509620b62d820db66a1178a12b9d75 Gate the release on a security job, and sign what it publishes (#1)
* 5c39baa483f3b8f67771d93ca09f8a1b2d80a77e Stop telling readers the packages are unpublished

v0.1.1

2026-08-30
## Changelog
* 7baf740f811d5b13861f0393ee764df84e4882dd Make the per-account read testable, and fix a smoke test that never could pass
* 5641c827d25e1e6887ee341ebf55d17181a9af9e Packages are available from pkgs.tui.tools
* f9a78957ad0fd46d89226ecd7c6b689a9645b10a Re-pin the kit at v0.2.3
* 2e3df14ec117e69ca89164a8c260dad11f867e7e Ship the tool as a .deb, an .rpm and a pacman package

v0.1.0

2026-08-30
## Changelog
* 359c5841ab5c9523c15bbbaacaa1eb9a723e5b43 Initial commit
* 941e5197cdcb0638d7dd161f1d63738bf48b07c9 Point the install command at the v0.1.0 release
* 8749568f04d8294e3282137ec168b0446da00818 tui-users v0.1: the machine's accounts, previewed before they change