TUISTREAM/cmd/tuistream/main.go
28allday 959e507a83 Initial commit: TUISTREAM — headless Jellyfin TUI for Omarchy/Arch
Three-tab Bubble Tea TUI (Setup / Manage / Monitor) for setting up and
running a headless Jellyfin server over SSH:

- Setup: install/uninstall Jellyfin, add media drives (single or btrfs
  RAID pool), import an existing detached btrfs pool non-destructively,
  firewall, move Jellyfin storage onto a media drive
- Boot-drive-safe drive classifier (walks LUKS/LVM/RAID to the physical
  disk; never offers a disk hosting /, /boot or swap)
- Keep-existing-filesystem path previews on-disk content, skips starter
  folders when content exists, and grants Jellyfin recursive read access
- Manage: copy from external drives, mount/eject, rename/delete
- Monitor: per-core CPU, load/mem/uptime, btrfs error counters, SMART

Single static binary; installs to /usr/local/bin so sudo can find it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 16:47:18 +01:00

59 lines
1.9 KiB
Go

// Command tuistream is a TUI for setting up and managing a headless Jellyfin
// Media Server on Omarchy / Arch Linux.
//
// Two tabs:
//
// Setup — install Jellyfin, attach media drives, firewall, uninstall.
// Manage — copy files from an external drive to a media drive,
// delete files, rename files.
//
// The picker hides any partition that lives on a disk hosting the OS or
// active swap, so the boot drive can never be selected as a media drive.
package main
import (
"flag"
"fmt"
"os"
tea "github.com/charmbracelet/bubbletea"
"tuistream/internal/system"
"tuistream/internal/theme"
"tuistream/internal/tui"
)
func main() {
readOnly := flag.Bool("read-only", false,
"open the TUI without checking for root; only the inventory views work")
flag.Parse()
if !*readOnly && os.Geteuid() != 0 {
fmt.Fprintln(os.Stderr,
"tuistream needs administrator rights to install Jellyfin, edit /etc/fstab, etc.")
fmt.Fprintln(os.Stderr, " Run: sudo tuistream")
fmt.Fprintln(os.Stderr, " Or: tuistream --read-only (inventory only, no actions)")
os.Exit(1)
}
// Pre-flight: install any userspace tools the flows assume are present.
// Only attempted when running as root — read-only just skips the check.
if !*readOnly {
if err := system.EnsureInstalled(); err != nil {
fmt.Fprintln(os.Stderr, "tuistream: pacman failed:", err)
fmt.Fprintln(os.Stderr,
" Some actions may not work until the missing packages are installed.")
}
}
m := tui.NewModel(theme.Load())
// No mouse capture: TUISTREAM is keyboard-driven, and grabbing the mouse
// would stop the user's terminal/tmux from selecting-to-copy text (e.g.
// the Jellyfin web URL) or click-opening links. Leaving it off keeps
// native selection and hyperlink handling working over SSH + tmux.
p := tea.NewProgram(m, tea.WithAltScreen())
if _, err := p.Run(); err != nil {
fmt.Fprintln(os.Stderr, "tuistream:", err)
os.Exit(1)
}
}