diff --git a/README.md b/README.md
new file mode 100644
index 0000000..292a407
--- /dev/null
+++ b/README.md
@@ -0,0 +1,219 @@
+
+
+ ⚡ Archduino
+
+ A full TUI-based Arduino development environment — one script, zero friction.
+
+
+
+
+
+
+
+---
+
+Archduino bootstraps a **complete terminal-based Arduino IDE** on Arch Linux or Ubuntu (including WSL2). It installs, configures, and wires together a curated set of modern CLI tools — with a **unified colorscheme of your choice** — so you can go from a bare system to compiling and uploading sketches in minutes.
+
+The Idea was a Development Environment runnable by almost everything. No GUI needed! This is tested on a minimal Arch install without a Desktop Environment!
+
+```
+ ╔═══════════════════════════════════════╗
+ ║ ⚡ Archduino Bootstrap ⚡ ║
+ ║ TUI Arduino Dev Environment Setup ║
+ ╚═══════════════════════════════════════╝
+```
+
+## ✨ What You Get
+
+| Layer | Tool | Purpose |
+|---|---|---|
+| **Editor** | [Neovim](https://neovim.io) + [NvChad](https://nvchad.com) | Fully configured IDE with LSP, Treesitter, and fuzzy finding |
+| **Arduino** | [arduino-cli](https://arduino.github.io/arduino-cli) + [vim-arduino](https://github.com/stevearc/vim-arduino) | Compile, upload, and monitor directly from Neovim |
+| **Multiplexer** | [Zellij](https://zellij.dev) | Tiled workspace with a custom Arduino layout |
+| **Shell** | [Zsh](https://www.zsh.org) + [Oh My Zsh](https://ohmyz.sh) | Autosuggestions, syntax highlighting, smart completions |
+| **Prompt** | [Starship](https://starship.rs) | Fast, minimal, git-aware prompt |
+| **Git** | [Lazygit](https://github.com/jesseduffield/lazygit) | Beautiful terminal UI for git |
+| **Serial** | [tio](https://github.com/tio/tio) | Simple serial device I/O |
+| **Theme** | 5 colorschemes | Consistent look across every tool (see below) |
+
+### Colorschemes
+
+The installer lets you pick a theme that is applied **consistently** across Neovim, Starship, Zellij, and Lazygit:
+
+| # | Theme | Style |
+|---|---|---|
+| 1 | **Gruvbox Dark** | Warm retro browns and yellows |
+| 2 | **Catppuccin Mocha** | Soft pastel on dark base |
+| 3 | **Tokyo Night** | Cool blues and purples |
+| 4 | **Nord** | Arctic, muted blue-grey |
+| 5 | **Dracula** | High-contrast purple and green |
+
+### Supported Boards (out of the box)
+
+| Board | FQBN |
+|---|---|
+| Arduino Uno | `arduino:avr:uno` |
+| Arduino Mega | `arduino:avr:mega` |
+| Arduino Nano | `arduino:avr:nano` |
+| ESP32 | `esp32:esp32:esp32` |
+| ESP32-S3 | `esp32:esp32:esp32s3` |
+| ESP8266 (NodeMCU) | `esp8266:esp8266:nodemcuv2` |
+
+---
+
+## 🚀 Quickstart
+
+```bash
+git clone --depth=1 https://github.com//ArduinoArch.git
+cd ArduinoArch
+chmod +x install.sh
+./install.sh
+```
+
+The installer will:
+
+1. Show a banner with detected OS and package manager
+2. Let you pick your **colorscheme** (applied to all tools)
+3. Let you choose between **progress bar** or **verbose** output
+4. Ask for your sudo password **once** (cached for the entire install)
+5. Run through all 9 setup steps automatically
+
+After it finishes, start a new shell or run `source ~/.zshrc`.
+
+---
+
+## 📁 Project Structure
+
+```
+ArduinoArch/
+├── install.sh # Main entry point
+└── lib/
+ ├── common.sh # Colors, helpers, environment detection, progress bar
+ ├── themes.sh # Colorscheme selection menu
+ ├── themes/
+ │ ├── gruvbox.sh # Gruvbox Dark configs
+ │ ├── catppuccin.sh # Catppuccin Mocha configs
+ │ ├── tokyonight.sh # Tokyo Night configs
+ │ ├── nord.sh # Nord configs
+ │ └── dracula.sh # Dracula configs
+ ├── packages.sh # Base packages (build tools, ripgrep, fd, bat, etc.)
+ ├── zsh.sh # Oh My Zsh + plugins
+ ├── starship.sh # Starship prompt config
+ ├── zellij.sh # Zellij + config + Arduino workspace layout
+ ├── neovim.sh # Neovim + NvChad + plugin configs (Arduino, LSP)
+ ├── arduino.sh # Arduino CLI + AVR/ESP32/ESP8266 cores + common libraries
+ ├── git.sh # Lazygit config
+ ├── scaffold.sh # `arduino-new` scaffolding tool + board templates
+ └── shell-config.sh # .zshrc aliases/config + WSL2 extras
+```
+
+---
+
+## 🔧 Usage
+
+### Creating a New Project
+
+```bash
+arduino-new my-project uno
+cd my-project
+nvim my-project.ino
+```
+
+This scaffolds a ready-to-go project with:
+- Board-specific `.ino` template (WiFi-enabled for ESP boards)
+- `sketch.yaml` with your board's FQBN
+- `.clangd` config for C++17 intellisense
+- `.gitignore` for build artifacts
+- Initialized git repo
+
+### Launching the Arduino Workspace
+
+```bash
+adev
+```
+
+Opens Zellij with the custom Arduino layout:
+
+```
+┌──────────────────────┬─────────────────┐
+│ │ │
+│ Neovim (65%) │ Terminal │
+│ │ │
+│ ├─────────────────┤
+│ │ Serial Mon │
+│ │ │
+├──────────────────────┴─────────────────┤
+│ Tab: code (focused) │ Tab: git │
+└────────────────────────────────────────┘
+```
+
+### Neovim Keybindings (Arduino)
+
+All keybindings are under `a`:
+
+| Key | Action |
+|---|---|
+| `ac` | Choose board |
+| `ap` | Choose port |
+| `av` | Verify (compile) |
+| `au` | Upload |
+| `as` | Serial monitor |
+| `ai` | Board info |
+
+### Zellij Keybindings
+
+| Key | Action |
+|---|---|
+| `Alt h/l` | Move focus left/right (or switch tabs) |
+| `Alt j/k` | Move focus down/up |
+| `Alt n` | New pane below |
+| `Alt v` | New pane to the right |
+| `Alt f` | Toggle floating panes |
+| `Alt t` | New tab |
+
+### Shell Aliases
+
+| Alias | Command |
+|---|---|
+| `adev` | `zellij --layout arduino` |
+| `ac` | `arduino-cli` |
+| `acc` | `arduino-cli compile` |
+| `acu` | `arduino-cli upload` |
+| `acm` | `arduino-cli monitor` |
+| `acb` | `arduino-cli board list` |
+| `lg` | `lazygit` |
+| `v` | `nvim` |
+
+---
+
+## 🖥️ WSL2 Notes
+
+Archduino fully supports WSL2 (both Arch and Ubuntu). The installer automatically:
+
+- Detects the WSL2 environment
+- Adds your user to the `dialout` and `uucp` groups for serial access
+
+To connect your Arduino over USB you need [usbipd-win](https://github.com/dorssel/usbipd-win) on the Windows side:
+
+```powershell
+# On Windows (PowerShell as Admin)
+winget install usbipd
+
+# List USB devices
+usbipd list
+
+# Attach your Arduino to WSL
+usbipd attach --wsl --busid
+```
+
+---
+
+## 🤝 Contributing
+
+Contributions are welcome! Each installer step lives in its own file under `lib/`, making it straightforward to modify or extend individual components without touching the rest.
+
+---
+
+## 📄 License
+
+This project is open source. Feel free to use, modify, and distribute.
diff --git a/bootstrap.sh b/bootstrap.sh
deleted file mode 100644
index 6e02771..0000000
--- a/bootstrap.sh
+++ /dev/null
@@ -1,583 +0,0 @@
-#!/bin/bash
-#
-# Archduino Bootstrap — TUI Arduino Development Environment
-# Works on both native Arch Linux and Arch/Ubuntu WSL2
-#
-# Usage: curl -kL | bash
-# or: chmod +x bootstrap.sh && ./bootstrap.sh
-#
-set -euo pipefail
-
-GREEN='\033[0;32m'
-YELLOW='\033[1;33m'
-RED='\033[0;31m'
-NC='\033[0m'
-
-info() { echo -e "${GREEN}[✓]${NC} $1"; }
-warn() { echo -e "${YELLOW}[!]${NC} $1"; }
-error() {
- echo -e "${RED}[✗]${NC} $1"
- exit 1
-}
-step() { echo -e "\n${GREEN}━━━ $1 ━━━${NC}"; }
-
-# ── Detect environment ──────────────────────────────────────────
-IS_WSL=false
-[[ -f /proc/version ]] && grep -qi microsoft /proc/version && IS_WSL=true
-
-IS_ARCH=false
-IS_UBUNTU=false
-if command -v pacman &>/dev/null; then
- IS_ARCH=true
- PKG_INSTALL="sudo pacman -S --needed --noconfirm"
-elif command -v apt &>/dev/null; then
- IS_UBUNTU=true
- PKG_INSTALL="sudo apt install -y"
-else
- error "Unsupported distro. Need Arch (pacman) or Ubuntu (apt)."
-fi
-
-echo ""
-echo " ╔═══════════════════════════════════════╗"
-echo " ║ ⚡ Archduino Bootstrap ⚡ ║"
-echo " ║ TUI Arduino Dev Environment Setup ║"
-echo " ╚═══════════════════════════════════════╝"
-echo ""
-$IS_WSL && info "Detected WSL2" || info "Detected native Linux"
-$IS_ARCH && info "Package manager: pacman (Arch)" || info "Package manager: apt (Ubuntu)"
-echo ""
-
-# ── 1. Base packages ────────────────────────────────────────────
-step "1/9 — Installing base packages"
-
-if $IS_ARCH; then
- sudo pacman -Syu --noconfirm
- $PKG_INSTALL base-devel git curl unzip wget ripgrep fd bat eza tree jq zsh clang
- # tio is in AUR — install yay if needed, then tio
- if ! command -v yay &>/dev/null; then
- info "Installing yay (AUR helper)..."
- git clone https://aur.archlinux.org/yay.git /tmp/yay
- (cd /tmp/yay && makepkg -si --noconfirm)
- rm -rf /tmp/yay
- fi
- yay -S --needed --noconfirm tio
-else
- sudo apt update && sudo apt upgrade -y
- $PKG_INSTALL build-essential git curl unzip wget ripgrep bat eza tree jq zsh clang-format tio
- # fd is named differently on Ubuntu
- sudo apt install -y fd-find 2>/dev/null || true
-fi
-info "Base packages installed"
-
-# ── 2. Zsh + Oh My Zsh + plugins ───────────────────────────────
-step "2/9 — Setting up Zsh"
-
-if [[ ! -d "$HOME/.oh-my-zsh" ]]; then
- RUNZSH=no KEEP_ZSHRC=yes sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" ||
- RUNZSH=no KEEP_ZSHRC=yes sh -c "$(curl -kfsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
- info "Oh My Zsh installed"
-else
- info "Oh My Zsh already present"
-fi
-
-ZSH_CUSTOM="${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}"
-
-[[ ! -d "$ZSH_CUSTOM/plugins/zsh-autosuggestions" ]] &&
- git clone https://github.com/zsh-users/zsh-autosuggestions "$ZSH_CUSTOM/plugins/zsh-autosuggestions"
-
-[[ ! -d "$ZSH_CUSTOM/plugins/zsh-syntax-highlighting" ]] &&
- git clone https://github.com/zsh-users/zsh-syntax-highlighting "$ZSH_CUSTOM/plugins/zsh-syntax-highlighting"
-
-info "Zsh plugins installed"
-
-# ── 3. Starship prompt ──────────────────────────────────────────
-step "3/9 — Installing Starship"
-
-if ! command -v starship &>/dev/null; then
- if $IS_ARCH; then
- $PKG_INSTALL starship
- else
- curl -ksS https://starship.rs/install.sh | sh -s -- -y
- fi
-fi
-info "Starship installed"
-
-mkdir -p ~/.config
-cat >~/.config/starship.toml <<'STARSHIP'
-palette = "gruvbox_dark"
-format = """$directory$git_branch$git_status$character"""
-
-[directory]
-style = "bold fg:bright-yellow"
-truncation_length = 3
-
-[git_branch]
-style = "bold fg:bright-green"
-format = " [$branch]($style) "
-
-[git_status]
-style = "bold fg:bright-red"
-
-[character]
-success_symbol = "[❯](bold fg:bright-green)"
-error_symbol = "[❯](bold fg:bright-red)"
-
-[palettes.gruvbox_dark]
-bright-yellow = "#fabd2f"
-bright-green = "#b8bb26"
-bright-red = "#fb4934"
-bright-blue = "#83a598"
-bright-purple = "#d3869b"
-bright-aqua = "#8ec07c"
-bright-orange = "#fe8019"
-STARSHIP
-info "Starship configured with Gruvbox"
-
-# ── 4. Zellij ───────────────────────────────────────────────────
-step "4/9 — Installing Zellij"
-
-if ! command -v zellij &>/dev/null; then
- if $IS_ARCH; then
- $PKG_INSTALL zellij
- else
- curl -kL https://github.com/zellij-org/zellij/releases/latest/download/zellij-x86_64-unknown-linux-musl.tar.gz | tar xz -C /tmp
- sudo mv /tmp/zellij /usr/local/bin/
- fi
-fi
-info "Zellij installed"
-
-mkdir -p ~/.config/zellij/layouts
-
-cat >~/.config/zellij/config.kdl <<'ZELLIJ_CFG'
-theme "gruvbox-dark"
-default_layout "default"
-default_mode "normal"
-pane_frames false
-simplified_ui true
-mouse_mode false
-
-keybinds {
- shared {
- bind "Alt h" { MoveFocusOrTab "Left"; }
- bind "Alt l" { MoveFocusOrTab "Right"; }
- bind "Alt j" { MoveFocus "Down"; }
- bind "Alt k" { MoveFocus "Up"; }
- bind "Alt n" { NewPane "Down"; }
- bind "Alt v" { NewPane "Right"; }
- bind "Alt f" { ToggleFloatingPanes; }
- bind "Alt t" { NewTab; }
- }
-}
-
-themes {
- gruvbox-dark {
- fg "#ebdbb2"
- bg "#282828"
- black "#1d2021"
- red "#cc241d"
- green "#98971a"
- yellow "#d79921"
- blue "#458588"
- magenta "#b16286"
- cyan "#689d6a"
- white "#a89984"
- orange "#d65d0e"
- }
-}
-ZELLIJ_CFG
-
-cat >~/.config/zellij/layouts/arduino.kdl <<'LAYOUT'
-layout {
- tab name="code" focus=true {
- pane split_direction="vertical" {
- pane size="65%" {
- command "nvim"
- args "."
- }
- pane split_direction="horizontal" {
- pane size="60%" name="terminal"
- pane size="40%" name="serial" {
- command "bash"
- args "-c" "echo '⚡ Serial — run: tio /dev/ttyUSB0 -b 115200'"
- }
- }
- }
- }
- tab name="git" {
- pane {
- command "lazygit"
- }
- }
-}
-LAYOUT
-info "Zellij configured with Gruvbox + Arduino layout"
-
-# ── 5. Neovim ───────────────────────────────────────────────────
-step "5/9 — Installing Neovim (latest)"
-
-NVIM_NEEDED=true
-if command -v nvim &>/dev/null; then
- NVIM_VER=$(nvim --version | head -1 | grep -oP '\d+\.\d+\.\d+')
- if [[ "$(printf '%s\n' "0.11.2" "$NVIM_VER" | sort -V | head -1)" == "0.11.2" ]]; then
- NVIM_NEEDED=false
- info "Neovim $NVIM_VER already meets requirements"
- fi
-fi
-
-if $NVIM_NEEDED; then
- curl -kLO https://github.com/neovim/neovim/releases/latest/download/nvim-linux-x86_64.tar.gz
- sudo rm -rf /opt/nvim-linux-x86_64
- sudo tar -xzf nvim-linux-x86_64.tar.gz -C /opt
- sudo ln -sf /opt/nvim-linux-x86_64/bin/nvim /usr/local/bin/nvim
- rm nvim-linux-x86_64.tar.gz
- info "Neovim installed: $(nvim --version | head -1)"
-fi
-
-# ── 6. LazyVim + plugins ────────────────────────────────────────
-step "6/9 — Setting up LazyVim"
-
-if [[ ! -d "$HOME/.config/nvim/lua" ]]; then
- for d in ~/.config/nvim ~/.local/share/nvim ~/.local/state/nvim ~/.cache/nvim; do
- [[ -d "$d" ]] && mv "$d" "${d}.bak.$(date +%s)"
- done
- git clone https://github.com/LazyVim/starter ~/.config/nvim
- rm -rf ~/.config/nvim/.git
- info "LazyVim starter cloned"
-else
- info "Neovim config already exists, skipping LazyVim clone"
-fi
-
-mkdir -p ~/.config/nvim/lua/plugins
-
-cat >~/.config/nvim/lua/plugins/gruvbox.lua <<'LUA'
-return {
- {
- "ellisonleao/gruvbox.nvim",
- priority = 1000,
- config = function()
- require("gruvbox").setup({ contrast = "hard" })
- end,
- },
- {
- "LazyVim/LazyVim",
- opts = { colorscheme = "gruvbox" },
- },
-}
-LUA
-
-cat >~/.config/nvim/lua/plugins/arduino.lua <<'LUA'
-return {
- {
- "stevearc/vim-arduino",
- ft = { "arduino", "cpp", "c" },
- config = function()
- vim.g.arduino_use_cli = 1
- vim.g.arduino_cli_path = "arduino-cli"
- end,
- keys = {
- { "ac", "ArduinoChooseBoard", desc = "Choose Board" },
- { "ap", "ArduinoChoosePort", desc = "Choose Port" },
- { "av", "ArduinoVerify", desc = "Verify (compile)" },
- { "au", "ArduinoUpload", desc = "Upload" },
- { "as", "ArduinoSerial", desc = "Serial Monitor" },
- { "ai", "ArduinoInfo", desc = "Board Info" },
- },
- },
- {
- "nvim-treesitter/nvim-treesitter",
- opts = function(_, opts)
- vim.list_extend(opts.ensure_installed, { "c", "cpp" })
- end,
- },
-}
-LUA
-
-cat >~/.config/nvim/lua/plugins/lsp.lua <<'LUA'
-return {
- {
- "neovim/nvim-lspconfig",
- opts = {
- servers = {
- clangd = {
- cmd = {
- "clangd",
- "--background-index",
- "--clang-tidy",
- "--header-insertion=iwyu",
- "--completion-style=detailed",
- },
- },
- },
- },
- },
-}
-LUA
-info "LazyVim plugins configured (Gruvbox + Arduino + LSP)"
-
-# ── 7. Arduino CLI ──────────────────────────────────────────────
-step "7/9 — Installing Arduino CLI + board cores"
-
-if ! command -v arduino-cli &>/dev/null; then
- if $IS_ARCH; then
- $PKG_INSTALL arduino-cli
- else
- curl -kfsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | BINDIR=/usr/local/bin sudo sh
- fi
-fi
-info "Arduino CLI installed: $(arduino-cli version 2>/dev/null | head -1)"
-
-arduino-cli config init 2>/dev/null || true
-
-# Add ESP board manager URLs
-arduino-cli config add board_manager.additional_urls \
- https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json 2>/dev/null || true
-arduino-cli config add board_manager.additional_urls \
- https://arduino.esp8266.com/stable/package_esp8266com_index.json 2>/dev/null || true
-
-arduino-cli core update-index
-
-info "Installing AVR core..."
-arduino-cli core install arduino:avr
-
-info "Installing ESP32 core..."
-arduino-cli core install esp32:esp32
-
-info "Installing ESP8266 core..."
-arduino-cli core install esp8266:esp8266
-
-# Common libs
-arduino-cli lib install "Servo" "ArduinoJson" "Adafruit Unified Sensor" "DHT sensor library" 2>/dev/null || true
-info "Board cores & libraries installed"
-
-# ── 8. Git + Lazygit ────────────────────────────────────────────
-step "8/9 — Setting up Git + Lazygit"
-
-if ! command -v lazygit &>/dev/null; then
- if $IS_ARCH; then
- $PKG_INSTALL lazygit
- else
- LAZYGIT_VERSION=$(curl -ks "https://api.github.com/repos/jesseduffield/lazygit/releases/latest" | jq -r '.tag_name' | sed 's/v//')
- curl -kLo /tmp/lazygit.tar.gz "https://github.com/jesseduffield/lazygit/releases/latest/download/lazygit_${LAZYGIT_VERSION}_Linux_x86_64.tar.gz"
- tar xf /tmp/lazygit.tar.gz -C /tmp lazygit
- sudo mv /tmp/lazygit /usr/local/bin/
- fi
-fi
-info "Lazygit installed"
-
-mkdir -p ~/.config/lazygit
-cat >~/.config/lazygit/config.yml <<'LAZYGIT'
-gui:
- theme:
- activeBorderColor:
- - "#fabd2f"
- - bold
- inactiveBorderColor:
- - "#665c54"
- selectedLineBgColor:
- - "#3c3836"
- cherryPickedCommitFgColor:
- - "#b8bb26"
- defaultFgColor:
- - "#ebdbb2"
-LAZYGIT
-info "Lazygit configured with Gruvbox"
-
-# ── 9. Scaffolding tool + templates ─────────────────────────────
-step "9/9 — Creating project scaffolding tool"
-
-mkdir -p ~/.local/bin ~/.config/archduino/templates
-
-cat >~/.local/bin/arduino-new <<'SCAFFOLD'
-#!/bin/bash
-set -e
-
-TEMPLATE_DIR="$HOME/.config/archduino/templates"
-
-declare -A FQBN_MAP=(
- ["uno"]="arduino:avr:uno"
- ["mega"]="arduino:avr:mega"
- ["nano"]="arduino:avr:nano"
- ["esp32"]="esp32:esp32:esp32"
- ["esp32s3"]="esp32:esp32:esp32s3"
- ["esp8266"]="esp8266:esp8266:nodemcuv2"
-)
-
-usage() {
- echo "Usage: arduino-new "
- echo ""
- echo "Available boards:"
- for board in "${!FQBN_MAP[@]}"; do
- printf " %-12s %s\n" "$board" "${FQBN_MAP[$board]}"
- done
- exit 1
-}
-
-[[ $# -lt 2 ]] && usage
-
-PROJECT="$1"
-BOARD="$2"
-FQBN="${FQBN_MAP[$BOARD]}"
-
-[[ -z "$FQBN" ]] && echo "Unknown board: $BOARD" && usage
-
-mkdir -p "$PROJECT"
-cd "$PROJECT"
-
-if [[ -f "$TEMPLATE_DIR/$BOARD.ino" ]]; then
- cp "$TEMPLATE_DIR/$BOARD.ino" "$PROJECT.ino"
-else
- cp "$TEMPLATE_DIR/default.ino" "$PROJECT.ino"
-fi
-
-cat > sketch.yaml < .clangd < .gitignore <~/.config/archduino/templates/default.ino <<'INO'
-void setup() {
- Serial.begin(115200);
- while (!Serial) { ; }
- Serial.println("Hello from Arduino!");
-}
-
-void loop() {
- // Your code here
-}
-INO
-
-cat >~/.config/archduino/templates/esp32.ino <<'INO'
-#include
-
-const char* ssid = "YOUR_SSID";
-const char* password = "YOUR_PASS";
-
-void setup() {
- Serial.begin(115200);
- delay(1000);
- WiFi.begin(ssid, password);
- Serial.print("Connecting to WiFi");
- while (WiFi.status() != WL_CONNECTED) {
- delay(500);
- Serial.print(".");
- }
- Serial.println();
- Serial.print("Connected! IP: ");
- Serial.println(WiFi.localIP());
-}
-
-void loop() {
- delay(1000);
-}
-INO
-
-cat >~/.config/archduino/templates/esp8266.ino <<'INO'
-#include
-
-const char* ssid = "YOUR_SSID";
-const char* password = "YOUR_PASS";
-
-void setup() {
- Serial.begin(115200);
- delay(1000);
- WiFi.begin(ssid, password);
- Serial.print("Connecting to WiFi");
- while (WiFi.status() != WL_CONNECTED) {
- delay(500);
- Serial.print(".");
- }
- Serial.println();
- Serial.print("Connected! IP: ");
- Serial.println(WiFi.localIP());
-}
-
-void loop() {
- delay(1000);
-}
-INO
-info "Scaffolding tool + templates created"
-
-# ── Write .zshrc ────────────────────────────────────────────────
-step "Finalizing shell config"
-
-# Append archduino block to .zshrc if not already present
-if ! grep -q "ARCHDUINO" ~/.zshrc 2>/dev/null; then
- cat >>~/.zshrc <<'ZSHRC'
-
-# ── ARCHDUINO CONFIG ────────────────────────────────────────────
-plugins=(git zsh-autosuggestions zsh-syntax-highlighting)
-
-export PATH="$HOME/.local/bin:$PATH"
-export EDITOR="nvim"
-export VISUAL="nvim"
-
-eval "$(starship init zsh)"
-
-# Auto-start Zellij
-if [[ -z "$ZELLIJ" ]]; then
- zellij attach --create archduino
-fi
-
-# Arduino aliases
-alias adev="zellij --layout arduino"
-alias ac="arduino-cli"
-alias acc="arduino-cli compile"
-alias acu="arduino-cli upload"
-alias acm="arduino-cli monitor"
-alias acb="arduino-cli board list"
-alias lg="lazygit"
-alias v="nvim"
-# ── END ARCHDUINO ───────────────────────────────────────────────
-ZSHRC
- info "Shell config updated"
-else
- info "Shell config already contains Archduino block"
-fi
-
-# ── WSL2 extras ─────────────────────────────────────────────────
-if $IS_WSL; then
- step "WSL2 extras"
- warn "USB passthrough requires usbipd-win on Windows."
- warn "Install it with: winget install usbipd"
- warn "Then attach your Arduino: usbipd attach --wsl --busid "
-
- # Add user to dialout for serial access
- sudo usermod -aG dialout "$USER" 2>/dev/null || true
- sudo usermod -aG uucp "$USER" 2>/dev/null || true
-fi
-
-# ── Done ────────────────────────────────────────────────────────
-echo ""
-echo " ╔═══════════════════════════════════════╗"
-echo " ║ ⚡ Archduino Setup Complete ⚡ ║"
-echo " ╚═══════════════════════════════════════╝"
-echo ""
-info "Start a new shell or run: source ~/.zshrc"
-info "Quick start:"
-echo " arduino-new my-project uno # scaffold a project"
-echo " adev # launch Arduino workspace"
-echo " av # compile in Neovim"
-echo " au # upload in Neovim"
-echo ""
diff --git a/install.sh b/install.sh
new file mode 100644
index 0000000..7dd6b33
--- /dev/null
+++ b/install.sh
@@ -0,0 +1,94 @@
+#!/bin/bash
+#
+# Archduino Install — TUI Arduino Development Environment
+# Works on both native Arch Linux and Arch/Ubuntu WSL2
+#
+# Usage: curl -kL | bash
+# or: chmod +x install.sh && ./install.sh
+#
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+
+# ── Load helpers and detect environment ─────────────────────────
+source "$SCRIPT_DIR/lib/common.sh"
+
+echo ""
+echo " ╔═══════════════════════════════════════╗"
+echo " ║ ⚡ Archduino Bootstrap ⚡ ║"
+echo " ║ TUI Arduino Dev Environment Setup ║"
+echo " ╚═══════════════════════════════════════╝"
+echo ""
+$IS_WSL && info "Detected WSL2" || info "Detected native Linux"
+$IS_ARCH && info "Package manager: pacman (Arch)" || info "Package manager: apt (Ubuntu)"
+echo ""
+
+# ── Select colorscheme ────────────────────────────────────────────
+source "$SCRIPT_DIR/lib/themes.sh"
+select_theme
+echo ""
+
+# ── Select output mode ──────────────────────────────────────────
+echo " Select installation output:"
+echo ""
+echo " 1) Progress bar (clean)"
+echo " 2) Full details (verbose)"
+echo ""
+read -rp " Choice [1/2]: " output_choice
+case "$output_choice" in
+ 1) VERBOSE=false ;;
+ *) VERBOSE=true ;;
+esac
+echo ""
+
+# ── Acquire sudo upfront and keep it alive ──────────────────────
+info "Requesting sudo access (you will only be asked once)..."
+sudo -v || error "Failed to obtain sudo. Aborting."
+
+# Refresh sudo timestamp in the background until this script exits
+( while kill -0 $$ 2>/dev/null; do sudo -n true; sleep 50; done ) &
+SUDO_KEEPALIVE_PID=$!
+
+cleanup() {
+ kill $SUDO_KEEPALIVE_PID 2>/dev/null
+ if ! $VERBOSE && [[ -e /proc/self/fd/3 ]]; then
+ exec 1>&3 2>&4 3>&- 4>&-
+ echo ""
+ echo -e " ${RED}[✗]${NC} Installation failed. See log: $LOG_FILE"
+ fi
+}
+trap cleanup EXIT
+
+# ── Enter quiet mode if selected ────────────────────────────────
+if ! $VERBOSE; then
+ begin_quiet_mode
+fi
+
+# ── Run install steps ───────────────────────────────────────────
+source "$SCRIPT_DIR/lib/packages.sh"
+source "$SCRIPT_DIR/lib/zsh.sh"
+source "$SCRIPT_DIR/lib/starship.sh"
+source "$SCRIPT_DIR/lib/zellij.sh"
+source "$SCRIPT_DIR/lib/neovim.sh"
+source "$SCRIPT_DIR/lib/arduino.sh"
+source "$SCRIPT_DIR/lib/git.sh"
+source "$SCRIPT_DIR/lib/scaffold.sh"
+source "$SCRIPT_DIR/lib/shell-config.sh"
+
+# ── Restore output if in quiet mode ────────────────────────────
+if ! $VERBOSE; then
+ end_quiet_mode
+fi
+
+# ── Done ────────────────────────────────────────────────────────
+echo ""
+echo " ╔═══════════════════════════════════════╗"
+echo " ║ ⚡ Archduino Setup Complete ⚡ ║"
+echo " ╚═══════════════════════════════════════╝"
+echo ""
+info "Start a new shell or run: source ~/.zshrc"
+info "Quick start:"
+echo " arduino-new my-project uno # scaffold a project"
+echo " adev # launch Arduino workspace"
+echo " av # compile in Neovim"
+echo " au # upload in Neovim"
+echo ""
diff --git a/lib/arduino.sh b/lib/arduino.sh
new file mode 100644
index 0000000..e34702f
--- /dev/null
+++ b/lib/arduino.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+# Step 7: Arduino CLI + board cores
+
+step "7/9 — Installing Arduino CLI + board cores"
+
+if ! command -v arduino-cli &>/dev/null; then
+ if $IS_ARCH; then
+ $PKG_INSTALL arduino-cli
+ else
+ curl -kfsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | BINDIR=/usr/local/bin sudo sh
+ fi
+fi
+info "Arduino CLI installed: $(arduino-cli version 2>/dev/null | head -1)"
+
+arduino-cli config init 2>/dev/null || true
+
+# Add ESP board manager URLs
+arduino-cli config add board_manager.additional_urls \
+ https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json 2>/dev/null || true
+arduino-cli config add board_manager.additional_urls \
+ https://arduino.esp8266.com/stable/package_esp8266com_index.json 2>/dev/null || true
+
+arduino-cli core update-index
+
+info "Installing AVR core..."
+arduino-cli core install arduino:avr
+
+info "Installing ESP32 core..."
+arduino-cli core install esp32:esp32
+
+info "Installing ESP8266 core..."
+arduino-cli core install esp8266:esp8266
+
+# Common libs
+arduino-cli lib install "Servo" "ArduinoJson" "Adafruit Unified Sensor" "DHT sensor library" 2>/dev/null || true
+info "Board cores & libraries installed"
diff --git a/lib/common.sh b/lib/common.sh
new file mode 100644
index 0000000..4005181
--- /dev/null
+++ b/lib/common.sh
@@ -0,0 +1,84 @@
+#!/bin/bash
+# Common helpers and environment detection
+
+set -euo pipefail
+
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+RED='\033[0;31m'
+CYAN='\033[0;36m'
+BOLD='\033[1m'
+NC='\033[0m'
+
+VERBOSE=true
+LOG_FILE="/tmp/archduino-install.log"
+CURRENT_STEP=0
+TOTAL_STEPS=10
+
+info() { echo -e "${GREEN}[✓]${NC} $1"; }
+warn() { echo -e "${YELLOW}[!]${NC} $1"; }
+error() {
+ echo -e "${RED}[✗]${NC} $1"
+ exit 1
+}
+step() { echo -e "\n${GREEN}━━━ $1 ━━━${NC}"; }
+
+# ── Quiet-mode progress bar ────────────────────────────────────
+draw_progress() {
+ local current=$1
+ local total=$2
+ local label=$3
+ local pct=$((current * 100 / total))
+ local bar_width=40
+ local filled=$((pct * bar_width / 100))
+ local empty=$((bar_width - filled))
+ local bar="" space=""
+ for ((i = 0; i < filled; i++)); do bar+="█"; done
+ for ((i = 0; i < empty; i++)); do space+="░"; done
+ printf "\033[2K\r ${GREEN}${bar}${NC}${space} %3d%% ${BOLD}%s${NC}" "$pct" "$label" >&3
+}
+
+begin_quiet_mode() {
+ $IS_WSL && TOTAL_STEPS=11
+ : >"$LOG_FILE"
+
+ # Save real terminal to fd 3/4, redirect everything else to log
+ exec 3>&1 4>&2
+ exec 1>>"$LOG_FILE" 2>&1
+
+ # Override output helpers to talk to the terminal via fd 3
+ step() {
+ CURRENT_STEP=$((CURRENT_STEP + 1))
+ draw_progress "$CURRENT_STEP" "$TOTAL_STEPS" "$1"
+ }
+ info() { :; }
+ warn() { printf "\033[2K\r ${YELLOW}[!]${NC} %s\n" "$1" >&3; }
+ error() {
+ printf "\033[2K\r ${RED}[✗]${NC} %s\n" "$1" >&3
+ echo " See log: $LOG_FILE" >&3
+ exit 1
+ }
+}
+
+end_quiet_mode() {
+ # Restore stdout/stderr
+ exec 1>&3 2>&4
+ exec 3>&- 4>&-
+ echo ""
+}
+
+# ── Detect environment ──────────────────────────────────────────
+IS_WSL=false
+[[ -f /proc/version ]] && grep -qi microsoft /proc/version && IS_WSL=true
+
+IS_ARCH=false
+IS_UBUNTU=false
+if command -v pacman &>/dev/null; then
+ IS_ARCH=true
+ PKG_INSTALL="sudo pacman -S --needed --noconfirm"
+elif command -v apt &>/dev/null; then
+ IS_UBUNTU=true
+ PKG_INSTALL="sudo apt install -y"
+else
+ error "Unsupported distro. Need Arch (pacman) or Ubuntu (apt)."
+fi
diff --git a/lib/git.sh b/lib/git.sh
new file mode 100644
index 0000000..cbba992
--- /dev/null
+++ b/lib/git.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+# Step 8: Git + Lazygit
+
+step "8/9 — Setting up Git + Lazygit"
+
+if ! command -v lazygit &>/dev/null; then
+ if $IS_ARCH; then
+ $PKG_INSTALL lazygit
+ else
+ LAZYGIT_VERSION=$(curl -ks "https://api.github.com/repos/jesseduffield/lazygit/releases/latest" | jq -r '.tag_name' | sed 's/v//')
+ curl -kLo /tmp/lazygit.tar.gz "https://github.com/jesseduffield/lazygit/releases/latest/download/lazygit_${LAZYGIT_VERSION}_Linux_x86_64.tar.gz"
+ tar xf /tmp/lazygit.tar.gz -C /tmp lazygit
+ sudo mv /tmp/lazygit /usr/local/bin/
+ fi
+fi
+info "Lazygit installed"
+
+mkdir -p ~/.config/lazygit
+write_lazygit_config ~/.config/lazygit/config.yml
+info "Lazygit configured with $THEME_DISPLAY_NAME"
diff --git a/lib/neovim.sh b/lib/neovim.sh
new file mode 100644
index 0000000..101dbeb
--- /dev/null
+++ b/lib/neovim.sh
@@ -0,0 +1,107 @@
+#!/bin/bash
+# Steps 5+6: Neovim + NvChad
+
+step "5/9 — Installing Neovim (latest)"
+
+NVIM_NEEDED=true
+if command -v nvim &>/dev/null; then
+ NVIM_VER=$(nvim --version | head -1 | grep -oP '\d+\.\d+\.\d+')
+ if [[ "$(printf '%s\n' "0.11.2" "$NVIM_VER" | sort -V | head -1)" == "0.11.2" ]]; then
+ NVIM_NEEDED=false
+ info "Neovim $NVIM_VER already meets requirements"
+ fi
+fi
+
+if $NVIM_NEEDED; then
+ curl -kLO https://github.com/neovim/neovim/releases/latest/download/nvim-linux-x86_64.tar.gz
+ sudo rm -rf /opt/nvim-linux-x86_64
+ sudo tar -xzf nvim-linux-x86_64.tar.gz -C /opt
+ sudo ln -sf /opt/nvim-linux-x86_64/bin/nvim /usr/local/bin/nvim
+ rm nvim-linux-x86_64.tar.gz
+ info "Neovim installed: $(nvim --version | head -1)"
+fi
+
+step "6/9 — Setting up NvChad"
+
+if [[ ! -d "$HOME/.config/nvim/lua" ]]; then
+ for d in ~/.config/nvim ~/.local/share/nvim ~/.local/state/nvim ~/.cache/nvim; do
+ [[ -d "$d" ]] && mv "$d" "${d}.bak.$(date +%s)"
+ done
+ git clone https://github.com/NvChad/starter ~/.config/nvim
+ rm -rf ~/.config/nvim/.git
+ info "NvChad starter cloned"
+else
+ info "Neovim config already exists, skipping NvChad clone"
+fi
+
+# ── Theme ───────────────────────────────────────────────────────
+mkdir -p ~/.config/nvim/lua
+
+cat >~/.config/nvim/lua/chadrc.lua <~/.config/nvim/lua/plugins/arduino.lua <<'LUA'
+return {
+ {
+ "stevearc/vim-arduino",
+ ft = { "arduino", "cpp", "c" },
+ config = function()
+ vim.g.arduino_use_cli = 1
+ vim.g.arduino_cli_path = "arduino-cli"
+ end,
+ },
+}
+LUA
+
+# ── LSP (clangd) ───────────────────────────────────────────────
+mkdir -p ~/.config/nvim/lua/configs
+
+cat >~/.config/nvim/lua/configs/lspconfig.lua <<'LUA'
+local configs = require "nvchad.configs.lspconfig"
+
+local on_attach = configs.on_attach
+local on_init = configs.on_init
+local capabilities = configs.capabilities
+
+local lspconfig = require "lspconfig"
+
+lspconfig.clangd.setup {
+ on_init = on_init,
+ on_attach = on_attach,
+ capabilities = capabilities,
+ cmd = {
+ "clangd",
+ "--background-index",
+ "--clang-tidy",
+ "--header-insertion=iwyu",
+ "--completion-style=detailed",
+ },
+}
+LUA
+
+# ── Keymaps ─────────────────────────────────────────────────────
+cat >~/.config/nvim/lua/mappings.lua <<'LUA'
+require "nvchad.mappings"
+
+local map = vim.keymap.set
+
+map("n", "ac", "ArduinoChooseBoard", { desc = "Arduino Choose Board" })
+map("n", "ap", "ArduinoChoosePort", { desc = "Arduino Choose Port" })
+map("n", "av", "ArduinoVerify", { desc = "Arduino Verify (compile)" })
+map("n", "au", "ArduinoUpload", { desc = "Arduino Upload" })
+map("n", "as", "ArduinoSerial", { desc = "Arduino Serial Monitor" })
+map("n", "ai", "ArduinoInfo", { desc = "Arduino Board Info" })
+LUA
+
+info "NvChad configured ($THEME_DISPLAY_NAME + Arduino + LSP)"
diff --git a/lib/packages.sh b/lib/packages.sh
new file mode 100644
index 0000000..25a3f3b
--- /dev/null
+++ b/lib/packages.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+# Step 1: Base packages
+
+step "1/9 — Installing base packages"
+
+if $IS_ARCH; then
+ sudo pacman -Syu --noconfirm
+ $PKG_INSTALL base-devel git curl unzip wget ripgrep fd bat eza tree jq zsh clang
+ # tio is in AUR — install yay if needed, then tio
+ if ! command -v yay &>/dev/null; then
+ info "Installing yay (AUR helper)..."
+ git clone https://aur.archlinux.org/yay.git /tmp/yay
+ (cd /tmp/yay && makepkg -si --noconfirm)
+ rm -rf /tmp/yay
+ fi
+ yay -S --needed --noconfirm tio
+else
+ sudo apt update && sudo apt upgrade -y
+ $PKG_INSTALL build-essential git curl unzip wget ripgrep bat eza tree jq zsh clang-format tio
+ # fd is named differently on Ubuntu
+ sudo apt install -y fd-find 2>/dev/null || true
+fi
+info "Base packages installed"
diff --git a/lib/scaffold.sh b/lib/scaffold.sh
new file mode 100644
index 0000000..ffce67d
--- /dev/null
+++ b/lib/scaffold.sh
@@ -0,0 +1,138 @@
+#!/bin/bash
+# Step 9: Project scaffolding tool + templates
+
+step "9/9 — Creating project scaffolding tool"
+
+mkdir -p ~/.local/bin ~/.config/archduino/templates
+
+cat >~/.local/bin/arduino-new <<'SCAFFOLD'
+#!/bin/bash
+set -e
+
+TEMPLATE_DIR="$HOME/.config/archduino/templates"
+
+declare -A FQBN_MAP=(
+ ["uno"]="arduino:avr:uno"
+ ["mega"]="arduino:avr:mega"
+ ["nano"]="arduino:avr:nano"
+ ["esp32"]="esp32:esp32:esp32"
+ ["esp32s3"]="esp32:esp32:esp32s3"
+ ["esp8266"]="esp8266:esp8266:nodemcuv2"
+)
+
+usage() {
+ echo "Usage: arduino-new "
+ echo ""
+ echo "Available boards:"
+ for board in "${!FQBN_MAP[@]}"; do
+ printf " %-12s %s\n" "$board" "${FQBN_MAP[$board]}"
+ done
+ exit 1
+}
+
+[[ $# -lt 2 ]] && usage
+
+PROJECT="$1"
+BOARD="$2"
+FQBN="${FQBN_MAP[$BOARD]}"
+
+[[ -z "$FQBN" ]] && echo "Unknown board: $BOARD" && usage
+
+mkdir -p "$PROJECT"
+cd "$PROJECT"
+
+if [[ -f "$TEMPLATE_DIR/$BOARD.ino" ]]; then
+ cp "$TEMPLATE_DIR/$BOARD.ino" "$PROJECT.ino"
+else
+ cp "$TEMPLATE_DIR/default.ino" "$PROJECT.ino"
+fi
+
+cat > sketch.yaml < .clangd < .gitignore <~/.config/archduino/templates/default.ino <<'INO'
+void setup() {
+ Serial.begin(115200);
+ while (!Serial) { ; }
+ Serial.println("Hello from Arduino!");
+}
+
+void loop() {
+ // Your code here
+}
+INO
+
+cat >~/.config/archduino/templates/esp32.ino <<'INO'
+#include
+
+const char* ssid = "YOUR_SSID";
+const char* password = "YOUR_PASS";
+
+void setup() {
+ Serial.begin(115200);
+ delay(1000);
+ WiFi.begin(ssid, password);
+ Serial.print("Connecting to WiFi");
+ while (WiFi.status() != WL_CONNECTED) {
+ delay(500);
+ Serial.print(".");
+ }
+ Serial.println();
+ Serial.print("Connected! IP: ");
+ Serial.println(WiFi.localIP());
+}
+
+void loop() {
+ delay(1000);
+}
+INO
+
+cat >~/.config/archduino/templates/esp8266.ino <<'INO'
+#include
+
+const char* ssid = "YOUR_SSID";
+const char* password = "YOUR_PASS";
+
+void setup() {
+ Serial.begin(115200);
+ delay(1000);
+ WiFi.begin(ssid, password);
+ Serial.print("Connecting to WiFi");
+ while (WiFi.status() != WL_CONNECTED) {
+ delay(500);
+ Serial.print(".");
+ }
+ Serial.println();
+ Serial.print("Connected! IP: ");
+ Serial.println(WiFi.localIP());
+}
+
+void loop() {
+ delay(1000);
+}
+INO
+info "Scaffolding tool + templates created"
diff --git a/lib/shell-config.sh b/lib/shell-config.sh
new file mode 100644
index 0000000..e99e1cb
--- /dev/null
+++ b/lib/shell-config.sh
@@ -0,0 +1,50 @@
+#!/bin/bash
+# Shell config (.zshrc) and WSL2 extras
+
+step "Finalizing shell config"
+
+# Append archduino block to .zshrc if not already present
+if ! grep -q "ARCHDUINO" ~/.zshrc 2>/dev/null; then
+ cat >>~/.zshrc <<'ZSHRC'
+
+# ── ARCHDUINO CONFIG ────────────────────────────────────────────
+plugins=(git zsh-autosuggestions zsh-syntax-highlighting)
+
+export PATH="$HOME/.local/bin:$PATH"
+export EDITOR="nvim"
+export VISUAL="nvim"
+
+eval "$(starship init zsh)"
+
+# Auto-start Zellij
+if [[ -z "$ZELLIJ" ]]; then
+ zellij attach --create archduino
+fi
+
+# Arduino aliases
+alias adev="zellij --layout arduino"
+alias ac="arduino-cli"
+alias acc="arduino-cli compile"
+alias acu="arduino-cli upload"
+alias acm="arduino-cli monitor"
+alias acb="arduino-cli board list"
+alias lg="lazygit"
+alias v="nvim"
+# ── END ARCHDUINO ───────────────────────────────────────────────
+ZSHRC
+ info "Shell config updated"
+else
+ info "Shell config already contains Archduino block"
+fi
+
+# ── WSL2 extras ─────────────────────────────────────────────────
+if $IS_WSL; then
+ step "WSL2 extras"
+ warn "USB passthrough requires usbipd-win on Windows."
+ warn "Install it with: winget install usbipd"
+ warn "Then attach your Arduino: usbipd attach --wsl --busid "
+
+ # Add user to dialout for serial access
+ sudo usermod -aG dialout "$USER" 2>/dev/null || true
+ sudo usermod -aG uucp "$USER" 2>/dev/null || true
+fi
diff --git a/lib/starship.sh b/lib/starship.sh
new file mode 100644
index 0000000..e6774bc
--- /dev/null
+++ b/lib/starship.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+# Step 3: Starship prompt
+
+step "3/9 — Installing Starship"
+
+if ! command -v starship &>/dev/null; then
+ if $IS_ARCH; then
+ $PKG_INSTALL starship
+ else
+ curl -ksS https://starship.rs/install.sh | sh -s -- -y
+ fi
+fi
+info "Starship installed"
+
+mkdir -p ~/.config
+write_starship_config ~/.config/starship.toml
+info "Starship configured with $THEME_DISPLAY_NAME"
diff --git a/lib/zellij.sh b/lib/zellij.sh
new file mode 100644
index 0000000..6b81b17
--- /dev/null
+++ b/lib/zellij.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+# Step 4: Zellij terminal multiplexer
+
+step "4/9 — Installing Zellij"
+
+if ! command -v zellij &>/dev/null; then
+ if $IS_ARCH; then
+ $PKG_INSTALL zellij
+ else
+ curl -kL https://github.com/zellij-org/zellij/releases/latest/download/zellij-x86_64-unknown-linux-musl.tar.gz | tar xz -C /tmp
+ sudo mv /tmp/zellij /usr/local/bin/
+ fi
+fi
+info "Zellij installed"
+
+mkdir -p ~/.config/zellij/layouts
+write_zellij_config ~/.config/zellij/config.kdl
+
+cat >~/.config/zellij/layouts/arduino.kdl <<'LAYOUT'
+layout {
+ tab name="code" focus=true {
+ pane split_direction="vertical" {
+ pane size="65%" {
+ command "nvim"
+ args "."
+ }
+ pane split_direction="horizontal" {
+ pane size="60%" name="terminal"
+ pane size="40%" name="serial" {
+ command "bash"
+ args "-c" "echo '⚡ Serial — run: tio /dev/ttyUSB0 -b 115200'"
+ }
+ }
+ }
+ }
+ tab name="git" {
+ pane {
+ command "lazygit"
+ }
+ }
+}
+LAYOUT
+info "Zellij configured with $THEME_DISPLAY_NAME + Arduino layout"
diff --git a/lib/zsh.sh b/lib/zsh.sh
new file mode 100644
index 0000000..c4cba05
--- /dev/null
+++ b/lib/zsh.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+# Step 2: Zsh + Oh My Zsh + plugins
+
+step "2/9 — Setting up Zsh"
+
+if [[ ! -d "$HOME/.oh-my-zsh" ]]; then
+ RUNZSH=no KEEP_ZSHRC=yes sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" ||
+ RUNZSH=no KEEP_ZSHRC=yes sh -c "$(curl -kfsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
+ info "Oh My Zsh installed"
+else
+ info "Oh My Zsh already present"
+fi
+
+ZSH_CUSTOM="${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}"
+
+[[ ! -d "$ZSH_CUSTOM/plugins/zsh-autosuggestions" ]] &&
+ git clone https://github.com/zsh-users/zsh-autosuggestions "$ZSH_CUSTOM/plugins/zsh-autosuggestions"
+
+[[ ! -d "$ZSH_CUSTOM/plugins/zsh-syntax-highlighting" ]] &&
+ git clone https://github.com/zsh-users/zsh-syntax-highlighting "$ZSH_CUSTOM/plugins/zsh-syntax-highlighting"
+
+info "Zsh plugins installed"