A safe, interactive workstation installer for Arch Linux, Hyprland, and a CLI-first development setup.
Website · Quick start · Features · Modules · Safety
Kairo turns a fresh Arch installation into a configured development workstation without assuming your home directory is disposable.
It combines curated dotfiles, optional package installation, developer toolchains, GPU detection, and a dependency-free terminal UI. Changes are staged before activation, existing configuration can be backed up, and failed transactions roll back instead of leaving half-installed state behind.
Preview first. Install second.
./install.sh --dry-runperforms a zero-write preview of the selected changes.
- Interactive installer — full-screen Bash TUI using standard terminal sequences
- Selective deployment — install only the dotfile modules and toolchains you want
- Arch-native packages —
pacmanfirst, with optional Paru or Yay for AUR packages - Transactional changes — staged replacements, private backups, validation, and rollback
- GPU detection — reviewed package proposals for Intel, AMD, and modern NVIDIA hardware
- Developer profiles — Rust, Python, web, C/C++, containers, Wayland, and media tooling
- Per-shell prompts — separate Starship configuration for Bash, Fish, Nushell, and Zsh
- Curated rice branches — coordinated Hyprland, Waybar, Kitty, and wallpaper palettes
- Automation-friendly output — deterministic plain output outside interactive terminals
- No surprise upgrades — Kairo installs what you selected without silently upgrading the whole system
curl -fsSL https://raw.githubusercontent.com/nihitdev/kairo/main/install.sh | bashor:
wget -qO- https://raw.githubusercontent.com/nihitdev/kairo/main/install.sh | bashThe remote entry point requests sudo when required, clones Kairo to ~/kairo, and launches the interactive installer. If a clean checkout already exists, it is updated with a fast-forward pull. Modified or unrelated directories are not overwritten.
git clone https://github.com/nihitdev/kairo.git
cd kairo
./install.shWant to inspect everything before Kairo writes anything?
./install.sh --dry-runWelcome → Detect → Dependencies → Modules → Review
→ Backup → Packages → Dotfiles → Configure → Validate → Complete
Kairo detects the distribution, architecture, shell, display session, package tools, service manager, and configuration root. The review step shows the selected modules, missing packages, replacement targets, and backup behavior before privileged or destructive work begins.
| Key | Action |
|---|---|
↑ / ↓ or J / K |
Move |
Space |
Toggle item |
A |
Select all |
N |
Select none |
Enter |
Continue |
Q or Esc |
Cancel safely |
# Preview one module
./install.sh --dry-run --only starship
# Install selected modules
./install.sh --only yazi --only broot --only starship
# Select every supported dotfile module
./install.sh --only all
# Install missing packages for selected modules
./install.sh --install-packages --only nvim --only yazi
# Add development toolchains
./install.sh --install-packages \
--profile core-build \
--profile rust \
--profile web
# Use Yay instead of the default Paru helper
./install.sh --install-packages --aur-helper yay
# Review and install detected GPU drivers
./install.sh --install-packages --install-gpu-drivers
# Explicitly disable backups
./install.sh --no-backup --only starshipThe interactive installer asks which login shell to use: keep current (the default), Bash, Zsh, Fish, or Nushell. Installing shell configs does not implicitly change your login shell. For command-line installation:
./install.sh --dry-run --only zsh --default-shell zsh
./install.sh --no-backup --install-packages --only fish --default-shell fish
./install.sh --only nushell --default-shell nu--install-packages includes a missing selected shell even if its config module is
not selected. The installer checks /etc/shells and runs chsh for the current
user only, after the configuration transaction succeeds. Authentication may be
required. Log out and back in afterward; terminal-specific shell overrides can
still take precedence. --default-shell keep never calls chsh.
Run ./install.sh --help for the authoritative list of options, modules, and profiles.
| Area | Modules |
|---|---|
| Shells | Bash, Fish, Nushell, Zsh + Oh My Zsh |
| Prompt & history | Starship, Atuin, Oh My Posh |
| CLI workflow | Bat, Broot, Yazi, LazyGit, Fastfetch, Cava |
| Development | Git, Neovim, SSH |
| Desktop | WezTerm, Kitty, Hyprland, Waybar, Kairo Shell |
Hyprland is deliberately opt-in because replacing compositor configuration can disrupt an active session:
./install.sh --dry-run --only hyprThird-party snapshots and intentionally duplicated assets are documented in VENDORED.md.
The Hyprland and Waybar payloads track the live dark Rosé Pine setup: compact glass surfaces, Dwindle/Scrolling switching, event-driven notifications, and CPU-reactive skull/cat artwork. The original workspace, media, launcher, lock, and wallpaper shortcuts are preserved. These Lua configs target Hyprland 0.56 or newer.
# Preview the complete desktop (no writes or package installation)
./install.sh --dry-run --only hypr
# Install the desktop plus its runtime tools; skip persistent backups if desired
./install.sh --no-backup --install-packages --only hypr
# Update only Waybar and its bundled artwork fonts
./install.sh --dry-run --only waybar
./install.sh --no-backup --only waybarhypr includes Waybar, Hyprlock, and SwayNC. It seeds the custom Rofi setup only
when no Rofi directory exists; select --only rofi explicitly to replace one.
Kairo Shell takes precedence over Waybar when both are selected. Its startup
command lives in an installer-generated hypr/config/bar.lua, avoiding edits to
the daemon list. Installing only Waybar expects the matching Hyprland/Rofi scripts
to already be present for its click actions.
The installer deploys Waycat and Skulltype into the user's XDG font directory and
refreshes that directory's font cache. --install-packages includes Iosevka Nerd
Font, Hyprpaper/Hypridle/Hyprlock, SwayNC, and the TUI tools used by the bar. It does
not automatically install every application mentioned in personal keybinds.
Wallpaper images and machine-specific wallpaper links are not included in Git.
An install preserves the target user's existing wallpaper link or saved selection,
then falls back to the installed Hyprland wallpaper if available. Add your images
to ~/Pictures/wallpapers/catppuccin and use Super+Alt+Space to choose one.
The picker updates Hyprpaper's persistent selection. Locking falls back to a solid
background when no image is available. Desktop launchers use the standard
~/.config layout; use that location for the complete desktop installation.
Desktop source syntax and destinations are checked before package installation or configuration replacement. The installer does not restart the compositor, bar, or session services. Review the result and reload them when ready.
A remote --dry-run prints bootstrap guidance without cloning, updating, invoking
sudo, or changing ~/kairo. Use an existing checkout for the detailed install plan.
WezTerm is selected by default and is available in the interactive module picker
and through --only wezterm:
# Preview the configuration deployment
./install.sh --dry-run --only wezterm
# Install the configuration and missing Arch dependencies
./install.sh --install-packages --only weztermThe installer deploys the complete modular configuration
to ~/.config/wezterm (or $XDG_CONFIG_HOME/wezterm) using Kairo's transactional
copy, backup, and rollback workflow. Package installation includes wezterm,
zsh for the configured default shell, and ttf-jetbrains-mono-nerd for the font
and UI icons. Packages are only installed with --install-packages or when
selected during interactive review.
The configuration retains the 9.75 font size, custom tab bar, left-click new-tab
action, right-click launch menu, colours, keybindings, and status modules.
Personal backdrop images are excluded; the background colour works without
images. To use your own wallpapers, set an external directory with
set_images_dir in wezterm.lua, before
scan_images_dir. An external directory keeps images outside the managed
configuration that the installer replaces.
If ~/.wezterm.lua exists, Kairo skips WezTerm deployment and reports the
conflict. Move that file aside before installing the XDG configuration.
Upstream attribution and the retained MIT license are documented in
VENDORED.md.
The optional kairo-shell module installs Kairo Shell v2.2.0-beta.1, verified
against commit 64420cb38748b406608af95b2252f60958a8e5a9. It is unselected by
default; --only all includes it.
# Preview the shell and Hyprland startup integration
./install.sh --dry-run --only hypr --only kairo-shell
# Install the shell, Hyprland configuration, and required packages
./install.sh --install-packages --only hypr --only kairo-shellSelecting both modules writes a managed bar override with the installed
kairod start path and skips Waybar deployment. Selecting
only hypr continues to install Waybar. Selecting only kairo-shell installs
the shell without changing Hyprland; start it with ~/.local/bin/kairod start
in a Hyprland session. Installation does not start a daemon or change an active
session.
The installer manages these paths with its normal backup and rollback workflow:
- Application:
${XDG_DATA_HOME:-~/.local/share}/kairo - Launchers:
${KAIRO_BIN_DIR:-~/.local/bin}/{kairo,kairod} - Settings:
${XDG_CONFIG_HOME:-~/.config}/kairo/settings.json(created only when absent) - Version state:
${XDG_STATE_HOME:-~/.local/state}/kairo/version - Desktop entry and icon under the XDG data directory
All destinations must resolve inside your home directory. Existing unrelated
launcher files and unmanaged application directories are rejected. Put the
launcher directory first in your session's PATH; its kairo command controls
the desktop shell. Use ./install.sh from this checkout for the dotfile installer.
Runtime dependencies from the pinned release are included in Kairo's package
review, including Quickshell, Hyprland, Qt, audio/network utilities, the Iosevka
Nerd Font, and the AUR package wl-gammarelay-rs. Installation remains opt-in
through --install-packages or interactive review. Without it, missing packages
are reported and must be installed before starting the shell. The upstream
interactive installer, system upgrades, display-manager setup, service changes,
and optional wallpaper downloads are not run.
The downloaded payload retains upstream AGPL-3.0 licensing and attribution. The local shell prototype is separate from this release.
Profiles are independent from dotfile modules. Repeat --profile to combine them, or use --profile all.
| Profile | Included tools |
|---|---|
core-build |
Base development tools, Git, curl, wget, rsync, archives, jq, ShellCheck |
cpp |
GCC, Clang, CMake, Ninja, Meson, GDB, LLDB |
rust |
Rustup |
python |
Python, pip, uv |
web |
Node.js, npm, pnpm, Bun |
containers |
Docker, Docker Compose, Podman, Buildah |
wayland |
Portal, clipboard, screenshot, brightness, media, and DDC tooling |
media |
PipeWire, WirePlumber, FFmpeg, ImageMagick, yt-dlp |
Package installation is opt-in through --install-packages or the interactive review. Kairo checks what is already installed and only requests packages required by the selected modules and profiles.
- Official packages are grouped into
sudo pacman -S --needed .... - AUR packages use Paru by default or Yay with
--aur-helper yay. - AUR helpers run as the current user, never through
sudo. - A missing helper can be bootstrapped from its official AUR PKGBUILD.
- Kairo does not perform a surprise full-system upgrade.
When Fish and package installation are selected, Kairo installs Fisher when required and synchronizes the plugins declared in .config/fish/fish_plugins: fzf.fish, autopair.fish, and fish-abbreviation-tips. Fish provides autosuggestions, syntax highlighting, completions, and history search natively. Generated functions and machine-specific fish_variables stay outside version control.
For Neovim, Kairo can bootstrap lazy.nvim and perform a headless LazyVim sync using the tracked lazy-lock.json. Without package installation, LazyVim performs its normal bootstrap when Neovim first starts.
Privileged work is requested only after review and before filesystem changes begin.
Chaotic-AUR is treated as a separate trust decision:
./install.sh --dry-run --enable-chaotic-aur --profile web
./install.sh --enable-chaotic-aur --profile webKairo imports and locally signs the published key, installs the signed keyring and mirror list, backs up /etc/pacman.conf, and adds the repository idempotently. If the later transaction fails, the original Pacman configuration is restored.
With --install-gpu-drivers, Kairo inspects graphics controllers and proposes an Arch package set for review.
| Hardware | Proposed stack |
|---|---|
| AMD | Mesa and RADV Vulkan |
| Intel | Mesa, Intel Vulkan, and Intel media drivers |
| Modern NVIDIA | Open kernel modules, utilities, VA-API bridge, and matching installed-kernel headers |
Mixed Intel/AMD systems receive both applicable userspace stacks. Legacy or unclassified NVIDIA hardware produces a warning rather than a guess. Kairo does not generate an Xorg configuration or require Hyprland to be running.
Each curated desktop palette lives on a rice/* Git branch and coordinates the relevant Kitty, Waybar, Hyprland, and wallpaper configuration.
| Family | Branches |
|---|---|
| Classic terminal | rice/campbell, rice/vintage |
| One Half | rice/one-half-dark, rice/one-half-light |
| Tango | rice/tango-dark, rice/tango-light |
| Catppuccin | rice/catppuccin-latte, rice/catppuccin-frappe, rice/catppuccin-macchiato, rice/catppuccin-mocha |
| Rosé Pine | rice/rose-pine, rice/rose-pine-moon, rice/rose-pine-dawn |
Switching rice is an ordinary Git workflow:
cd ~/kairo
git fetch origin
git switch rice/catppuccin-mocha
./install.sh --dry-run --only hypr --only kitty
./install.sh --only hypr --only kittymain remains the stable development branch. Switching branches changes the configuration available to the installer; Git does not modify files already deployed under ~/.config.
Kairo backs up replaced destinations unless --no-backup is explicitly supplied.
Kairo uses one Starship binary with a separate configuration for each shell:
~/.config/starship/
├── bash.toml
├── fish.toml
├── nushell.toml
└── zsh.toml
STARSHIP_CONFIG selects the appropriate file. The installer manages the complete Starship directory rather than using a single root-level prompt configuration.
Kairo is designed to make workstation setup repeatable without turning configuration replacement into a gamble.
- Existing destinations are backed up under private, unique
~/.dotfiles-backup/YYYYMMDD-HHMMSS.xxxxxx/directories. - Replacement payloads are staged before activation.
- Failed operations restore replaced destinations and remove newly created partial targets.
/,$HOME, the configuration root, traversal paths, symlink escapes, and destinations outside the home directory are rejected.--dry-runperforms no writes, package changes, plugin installation, shell changes, or cache mutation.- Repeated installations preserve unchanged payloads and avoid duplicate Git/SSH includes.
- Git identity, signing configuration, credentials, personal SSH material,
known_hosts, andauthorized_keysare not overwritten. --no-backupdisables backup creation, not staging, destination validation, or rollback handling.
kairo/
├── .config/
│ ├── bash/
│ ├── fish/
│ ├── nushell/
│ ├── zsh/
│ ├── starship/
│ ├── wezterm/
│ ├── scripts/
│ │ ├── install-ui.sh
│ │ └── validate_repo.py
│ └── tests/
├── shell/ # Local Quickshell prototype
├── site/
├── install.sh
├── VENDORED.md
└── LICENSE
The website at get-kairo.vercel.app lives in site/ and uses Vite with Tailwind CSS v4.
cd site
bun install
bun run dev
bun run buildpnpm is also supported:
pnpm install
pnpm dev
pnpm buildbash -n install.sh
bash -n .config/scripts/install-ui.sh
./install.sh --dry-run
./install.sh --dry-run --only starship
./install.sh --dry-run --only yazi --only broot --only starship
./install.sh --dry-run --only hypr --only kairo-shell
python3 .config/scripts/validate_repo.py
./.config/tests/test-install.shThe Linux test suite covers normal and repeated installation, dry-run immutability, component selection, backup and no-backup modes, Git and SSH include deduplication, shell-specific Starship paths, rollback, remote bootstrap, non-interactive execution, terminal input handling, and Kairo Shell deployment, preservation, release verification, and rollback.
See Contributing for development and pull request guidance, Support for help and bug reports, Security for vulnerability reporting, and the Code of Conduct for community expectations.
Released under the terms of LICENSE.