8000 GitHub - vishnukg/initd: one stop shop for all my configs · GitHub
[go: up one dir, main page]

Skip to content
vishnukgPublic

About

one stop shop for all my configs

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

830 Commits

Folders and files

Repository files navigation

initd

initd bootstraps a fresh development machine from one repo and one shell script. It supports macOS, Fedora Workstation Linux, and headless Ubuntu VMs (a remote dev box with the toolchain and no desktop) from the same codebase.

It owns both:

  • machine setup: Homebrew (mac) / dnf (linux), apps, runtimes, OS defaults, Hyprland desktop
  • user config: Neovim, Ghostty, Fish, tmux, Git, Hyprland/Quickshell/rofi/dunst, and other dotfiles via managed symlinks

Layout

Runtime code lives in four directories: shared/, macos/, linux/, and vm/. Behavior tests live in tests/; documentation lives in docs/. The platform directories are decoupled — rm -rf macos/, linux/ or vm/ and the others keep working.

initd/
├── bootstrap.sh                 # dispatcher: bootstrap.sh [macos|linux|vm]; detects the OS when none is named
├── tests/                       # behavior tests and isolated integration tests
├── docs/                        # configuration guides and testing conventions
├── shared/                      # cross-platform
│   ├── lib/                     # logging, fs, link, cleanup, git-profile, fonts
│   ├── managed-links.sh         # MANAGED_LINKS for shared configs + git helpers
│   └── configs/                 # colima, fish, git, ghostty, kitty, mise, nvim, starship, tmux
├── macos/                       # self-contained macOS bootstrap
│   ├── bootstrap.sh
│   ├── Brewfile
│   ├── brewinstall              # add a formula/cask to the Brewfile and install it
│   ├── defaults.sh              # macOS defaults write …
│   ├── managed-links.sh
│   └── update.sh
├── linux/                       # self-contained Linux bootstrap
│   ├── bootstrap.sh              # targets Fedora Workstation 44+ (dnf5)
│   ├── packages.txt             # dnf package list (some via COPR — see below)
│   ├── setup.sh                 # fonts/theme/Firefox profile glue, system fixes
│   ├── managed-links.sh
│   ├── update.sh
│   ├── scripts/                 # session scripts invoked by hyprland.lua/Quickshell
│   └── configs/                 # hypr, hyprmoncfg, quickshell, rofi, dunst, fontconfig,
│                                #   systemd, gtk-3.0, gtk-4.0, ghostty, firefox
└── vm/                          # self-contained headless VM bootstrap (Ubuntu 24.04+, apt)
    ├── bootstrap.sh             # bash bootstrap.sh vm
    ├── packages.txt             # apt package list: CLI tools + build deps, no desktop
    ├── managed-links.sh         # drops the desktop-side shared links (terminals, Colima)
    └── update.sh

Usage

git clone https://github.com/vishnukg/initd ~/.config/initd
bash ~/.config/initd/bootstrap.sh macos    # or: linux, vm

The dispatcher runs <platform>/bootstrap.sh for the platform you name, and refuses a platform that doesn't match the OS (macos on Linux, say) before installing anything. With no platform it picks macos on macOS and linux on Linux, so a headless VM must always be named. The macOS and Linux desktop bootstraps both:

  • install required packages (Homebrew or dnf, enabling COPRs on Linux where Fedora's own repos don't carry a package)
  • install mise and gh (dnf repo on Linux, brew on macOS)
  • link managed configs into $HOME, backing up unmanaged files to ~/.config/initd-backups/<timestamp>/
  • set fish as the login shell (dscl on macOS, chsh on Linux), then sync fisher plugins
  • run mise install for shared runtimes and LSP tooling
  • prompt for personal/work Git identity on first run (both write this machine's email into local.gitconfig)

Re-running is safe and idempotent.

The macOS bootstrap targets Apple Silicon, with Homebrew at /opt/homebrew. On a headless Ubuntu VM (e.g. an exe.dev box), name vm — with no platform, every Linux host gets the Fedora desktop bootstrap:

git clone https://github.com/vishnukg/initd ~/.config/initd
bash ~/.config/initd/bootstrap.sh vm

On macOS, run it from a native arm64 shell. If Command Line Tools are missing, it launches their installer and asks you to rerun after installation completes.

Common tasks

Action Command
Full bootstrap bash bootstrap.sh <macos|linux|vm>
Re-apply links only shared/lib/link.sh <macos|linux|vm>
Set Git identity node shared/lib/git-profile.mjs personal / work
Remove managed symlinks node shared/lib/cleanup.mjs <macos|linux|vm> --dry-run
Add a brew formula/cask macos/brewinstall <name>
Update tools macos/update.sh, linux/update.sh or vm/update.sh
Run install behavior tests node --test tests/shared/install.test.mjs
Run macOS + shared tests ./macos/test.sh
Run Linux + shared tests ./linux/test.sh
Run the full regression suite INITD_TEST_TMUX=1 node --test 'tests/**/*.test.mjs'

See Testing for test organization and conventions.

Managed config mapping

Runtime paths in $HOME are symlinks back into this repo. Editing happens inside initd, not at the live paths.

Cross-platform (both OSes; the VM keeps all but colima, ghostty, kitty)

Runtime path Source
~/.colima/_templates/default.yaml shared/configs/colima/.colima/_templates/default.yaml
~/.config/fish shared/configs/fish/.config/fish
~/.config/ghostty shared/configs/ghostty/.config/ghostty
~/.config/kitty shared/configs/kitty/.config/kitty
~/.config/mise shared/configs/mise/.config/mise
~/.config/nvim shared/configs/nvim/.config/nvim
~/.config/starship.toml shared/configs/starship/.config/starship.toml
~/.config/tmux shared/configs/tmux/.config/tmux
~/.ssh/config shared/configs/ssh/.ssh/config (exe.dev dev box; personal profile only, never on the VM)
~/.config/ghostty-dev-box.conf shared/configs/ghostty/dev-box.conf (every Ghostty window runs ssh dev; personal profile only)
~/.gitconfig shared/configs/git/gitconfig (per-machine email via local.gitconfig)

Linux-only

Runtime path Source
~/.config/hypr linux/configs/hypr
~/.config/hyprmoncfg linux/configs/hyprmoncfg
~/.config/quickshell linux/configs/quickshell
~/.config/rofi linux/configs/rofi
~/.config/dunst linux/configs/dunst
~/.config/fontconfig linux/configs/fontconfig
~/.config/gtk-3.0 linux/configs/gtk-3.0
~/.config/gtk-4.0 linux/configs/gtk-4.0
~/.config/systemd/user/initd-hyprland-session.service linux/configs/systemd/user/initd-hyprland-session.service
~/.config/systemd/user/hyprmoncfgd.service.d linux/configs/systemd/user/hyprmoncfgd.service.d (Hyprland-only condition for the packaged daemon)
~/.config/systemd/user/night-light.service, night-light-schedule.service, night-light-schedule.timer linux/configs/systemd/user/ (gammastep as a unit; warm 19:00–07:00)
~/.gtkrc-2.0, ~/.icons/default/index.theme, Firefox profile glue linked individually by linux/setup.sh (paths are dynamic or outside ~/.config/)

Machine-local secrets

Gitignored paths — used if present, silently skipped if absent.

Path Purpose
shared/configs/git/local.gitconfig This machine's Git email (personal or work) — git refuses to commit without it
shared/configs/fish/.config/fish/local.env.fish Machine-specific environment variables, loaded by every Fish shell; set INITD_TMUX_AUTO_ATTACH=0 here to opt out of tmux
shared/configs/fish/.config/fish/local.fish Interactive-only aliases and preferences
shared/fonts/ Clone of the PRIVATE vishnukg/fonts repo (Berkeley Mono — paid, per-user licensed, so a public repo can't carry the OTFs). Synced by shared/lib/fonts.sh, which warns and skips without gh auth

Backups

If a managed runtime path already exists and isn't an initd symlink, it is moved to:

~/.config/initd-backups/<timestamp>/<original-path>

before initd takes ownership. Nothing is deleted.

Line endings

.gitattributes enforces LF for *.sh, *.fish, *.conf, *.ini, etc. so commits from any host (including Windows) land as LF — the only line-ending bash and /etc/-style configs accept on macOS/Linux.

macOS — Homebrew specifics

Bootstrap and update leave manually installed apps in /Applications or ~/Applications under their existing owner's control. They exclude those apps from a temporary Brewfile while retaining Homebrew-owned apps and all missing apps. This covers 1Password, BetterDisplay, Chrome, Ghostty, kitty, and iTerm; the repository's Brewfile stays unchanged. Such manually installed apps continue to use their own update mechanism.

After linking configs, bootstrap trusts and installs the mise toolchain before configuring hooks and syncing Fish plugins. Existing font symlinks are replaced with real copies. Optional private fonts still require access through gh; rerun bootstrap after authenticating to install them.

macos/brewinstall <name> detects whether the package is a formula or cask, appends it to macos/Brewfile, and runs brew bundle. This JavaScript command requires Node from the completed mise setup. Use --formula or --cask for ambiguous names. Existing entries, including lines with inline comments or options, are preserved; a failed install leaves the entry available for retry. brew bundle dump --force --file macos/Brewfile exports the current machine's state if you want a starting point — review carefully before committing.

Docker comes via Colima (no Docker Desktop): the colima, docker, docker-compose, and docker-credential-helper formulas in the Brewfile, a managed VM template at shared/configs/colima/, and an ensure_docker_config bootstrap step that points docker login at the macOS Keychain and wires the brew-installed compose plugin into the docker CLI. See docs/colima.md.

Linux — dnf specifics

linux/packages.txt is one package per line, comments allowed. Add to it and re-run linux/bootstrap.sh. The packages list intentionally tracks the brew formulas where equivalents exist (fish, tmux, tig, git) plus Fedora -devel build deps for mise-managed Python/Node. Neovim is deliberately not among them — it is installed and pinned by mise, so the distro package would only shadow it. Fedora's own repos don't carry the Hyprland ecosystem, hyprmoncfg, or ghostty — queue_listed_packages() enables the sdegler/hyprland, paolino/hyprmoncfg, and scottames/ghostty COPRs first. Docker Engine is installed separately from Docker's official dnf repository, together with Buildx and the Compose v2 plugin; bootstrap adds the login user to the privileged docker group, so log out and back in once after its first installation. gh CLI and 1Password also come from their own official dnf repos.

Intel video decoding is configured by ensure_video_codecs() in linux/bootstrap.sh. It enables RPM Fusion free/nonfree repositories, replaces Fedora's restricted Intel VA-API driver with intel-media-driver, and installs ffmpeg-free, libavcodec-freeworld, and libva-utils for H.264/HEVC support. To apply just this step to an existing Fedora install, run bash -c 'source linux/bootstrap.sh; ensure_fedora; ensure_video_codecs; install_queued_packages' from the repo (bootstrap's package steps only queue what is missing, so the install needs that last call). Restart Firefox afterward, then check vainfo and the codec table in about:support; package installation alone does not prove that a playing video uses hardware decoding.

linux/setup.sh handles things that don't fit the symlink flow:

  • system fixes requiring sudo (video group membership for backlight keys; disabling idle daemons this machine doesn't use: ModemManager, Fedora's abrt crash reporter, rsyslog)
  • GTK theme + font/cursor gsettings (Fedora has no fonts-ubuntu or DMZ-cursor package, so this uses Inter from rsms-inter-fonts and the Adwaita cursor theme instead), plus matching keyboard gsettings so GNOME gets the same ctrl:nocaps and repeat rate as Hyprland
  • session scripts symlinked to absolute ~/.config/ paths that hyprland.lua/Quickshell invoke directly
  • the hyprmoncfgd user service for automatic monitor profile switching
  • special-case paths outside ~/.config/: ~/.gtkrc-2.0, ~/.icons/default/, Firefox profile files (profile path is dynamic; Firefox itself is unmanaged by bootstrap.sh — install it however you like, this glue configures whatever it finds)

Adding a managed config

  1. Cross-platform: drop the source under shared/configs/<name>/, add an entry to MANAGED_LINKS in shared/managed-links.sh.
  2. macOS-only: drop under macos/configs/<name>/, append to MANAGED_LINKS in macos/managed-links.sh.
  3. Linux-only: drop under linux/configs/<name>/, append in linux/managed-links.sh.

Then re-run node --test tests/shared/install.test.mjs.

Reference docs

  • docs/bash-primer.md — repo-specific Bash patterns
  • docs/javascript.md — JavaScript helpers, tmux update flow, and efficiency boundaries
  • docs/config-review.md — dated validation results and remaining platform checks
  • < 4F66 li>docs/fish.md — fish/bash/zsh syntax comparison
  • docs/nvim.md — Neovim setup with Lazy.nvim
  • docs/mise.md — mise tool management
  • docs/colima.md — Colima (Docker without Docker Desktop) setup and daily use
  • docs/linux-monitors.md — monitor hotplug/lid switching, per-monitor scale and overrides
  • docs/git-branching-conflicts.md — Git branching and conflict resolution
  • docs/tmux-nvim.md — tmux and Neovim workspace concepts
  • docs/tmux-sessions.md — tmux session/window/pane workflow and keybindings
  • docs/remote-dev-box.md — the exe.dev dev box (ssh dev): setup on a new personal machine, rebuilding the VM

About

one stop shop for all my configs

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

0