diff --git a/bin/omarchy-export b/bin/omarchy-export new file mode 100755 index 0000000000..a7e905f144 --- /dev/null +++ b/bin/omarchy-export @@ -0,0 +1,166 @@ +#!/bin/bash + +# Omarchy export script +# This exports personal customizations which can be imported/restored to a new machine + +EXPORT_DIR="$HOME/omarchy_export_$(date +%Y%m%d_%H%M%S)" + + +echo "Creating export directory: $EXPORT_DIR" +mkdir -p "$EXPORT_DIR" + + +# 1. Back up personal files and customizations +echo "Backing up personal files and Omarchy customizations..." +mkdir -p "$EXPORT_DIR/home" + + +# Personal dotfiles (not managed by Omarchy) +for file in .bashrc .bash_profile .zshrc .profile; do + if [ -f "$HOME/$file" ]; then + cp "$HOME/$file" "$EXPORT_DIR/home/" + echo " Backed up $file" + fi +done + +# Back up .config customizations (excluding caches, browser profiles, and large app data) +echo "Backing up configuration files..." +if [ -d "$HOME/.config" ]; then + mkdir -p "$EXPORT_DIR/config" + + # Copy config files + cd "$HOME/.config" || exit 1 + find . -type f -o -type l | while read -r file; do + # Skip cache, temporary files, browser profiles, and large application data + case "$file" in + */Cache/*|*/cache/*|*/CachedData/*|*/logs/*|*/GPUCache/*|*/Code\ Cache/*|\ + */GrShaderCache/*|*/ShaderCache/*|*/DawnCache/*|*/Crash\ Reports/*|\ + */crashes/*|*/Crashpad/*|\ + ./BraveSoftware/*|./chromium/*|./google-chrome*/*|./vivaldi*/*|./microsoft-edge*/*|\ + ./Microsoft/*|./Cursor/*|./1Password/*|./obsidian/*|./Insync/*|./spotify/*) + continue + ;; + esac + + # Create directory structure and copy file + mkdir -p "$EXPORT_DIR/config/$(dirname "$file")" + cp -P "$file" "$EXPORT_DIR/config/$file" 2>/dev/null + done + cd - > /dev/null + + echo " Backed up .config files" +fi + + +# 2. Back up user-added web apps +echo "Backing up user-added web apps..." +if [ -d "$HOME/.local/share/applications" ]; then + mkdir -p "$EXPORT_DIR/home/.local/share/applications" + + # List of default Omarchy web apps to exclude (dynamically read from source) + OMARCHY_WEBAPPS_SOURCE="$HOME/.local/share/omarchy/install/packaging/webapps.sh" + OMARCHY_WEBAPPS=() + + if [ -f "$OMARCHY_WEBAPPS_SOURCE" ]; then + # Extract web app names from the installation script + while IFS= read -r line; do + if [[ $line =~ omarchy-webapp-install[[:space:]]+\"([^\"]+)\" ]]; then + OMARCHY_WEBAPPS+=("${BASH_REMATCH[1]}.desktop") + fi + done < "$OMARCHY_WEBAPPS_SOURCE" + fi + + # Copy only user-created web apps + USER_APP_COUNT=0 + for app in "$HOME/.local/share/applications"/*.desktop; do + if [ -f "$app" ]; then + APP_NAME=$(basename "$app") + + # Skip if it's a default Omarchy web app + SKIP=false + for omarchy_app in "${OMARCHY_WEBAPPS[@]}"; do + if [[ "$APP_NAME" == "$omarchy_app" ]]; then + SKIP=true + break + fi + done + + if [[ $SKIP == false ]]; then + cp "$app" "$EXPORT_DIR/home/.local/share/applications/" + ((USER_APP_COUNT++)) + fi + fi + done + + # Back up custom icons for user web apps + if [ -d "$HOME/.local/share/applications/icons" ] && [ $USER_APP_COUNT -gt 0 ]; then + mkdir -p "$EXPORT_DIR/home/.local/share/applications/icons" + + # Only copy icons for user-created apps + for app in "$EXPORT_DIR/home/.local/share/applications"/*.desktop; do + if [ -f "$app" ]; then + APP_NAME=$(basename "$app" .desktop) + if [ -f "$HOME/.local/share/applications/icons/$APP_NAME.png" ]; then + cp "$HOME/.local/share/applications/icons/$APP_NAME.png" \ + "$EXPORT_DIR/home/.local/share/applications/icons/" + fi + fi + done + echo " Backed up user-created web apps with icons" + elif [ $USER_APP_COUNT -gt 0 ]; then + echo " Backed up user-created web apps" + else + echo " No user-created web apps found (all are Omarchy defaults)" + fi +else + echo " No applications directory found" +fi + + +# 3. Save package lists (includes packages beyond Omarchy defaults) +echo "Saving package lists..." +pacman -Qqe > "$EXPORT_DIR/pkglist.txt" +echo " Saved explicitly installed packages (includes Omarchy packages + your additions)" + + +pacman -Qqm > "$EXPORT_DIR/aurlist.txt" 2>/dev/null +echo " Saved AUR packages" + + +# Create a referencelist of packages you installed yourself (beyond Omarchy) +echo " Creating reference list of all installed packages..." +pacman -Qq > "$EXPORT_DIR/all_packages.txt" + + +# 4. Create a README with export/import instructions +cat > "$EXPORT_DIR/README.txt" << 'EOF' +OMARCHY CUSTOM SETTINGS IMPORT GUIDE + +To import settings from export tar.gz archive: +1. Copy the exported tar.gz archive to the home directory on the new machine +2. Open the Omarchy menu (Super + ALT Space) > Setup > Config > Export/Import +3. Follow the prompts to restore your settings +4. Reboot after import to ensure all changes take effect +EOF + + +# Create a tarball for easy transport (preserves symlinks, works on any USB filesystem) +echo "" +echo "Creating tarball archive..." +cd "$HOME" || exit 1 +TARBALL_NAME="$(basename "$EXPORT_DIR").tar.gz" +tar -czf "$TARBALL_NAME" "$(basename "$EXPORT_DIR")" + +echo "" +echo "Export complete!" +echo "Archive created: $HOME/$TARBALL_NAME" +echo "" +echo "IMPORTANT NOTES:" +echo "- Omarchy will install with all its default packages and configs" +echo "- You will need to restore the following items separately: SSH/GPG keys, fingerprint settings, fido2 settings, personal files, and non-included customizations" +echo "- Review the README.txt in the backup folder for restoration steps" +echo "" +echo "To import:" +echo "1. Copy this tar.gz archive to the home directory on the machine you are importing to." +echo "2. Open the Omarchy menu (Super + ALT + Space) > Setup > Config > Export/Import" +echo "3. Follow the prompts to restore your settings" diff --git a/bin/omarchy-import b/bin/omarchy-import new file mode 100644 index 0000000000..bb59813604 --- /dev/null +++ b/bin/omarchy-import @@ -0,0 +1,199 @@ +#!/bin/bash + +# Omarchy import script +# This restores personal customizations from an export directory created by omarchy-export + +# Ensure scripts have execute permissions (needed after copying from export) +SCRIPT_DIR="$HOME/.local/share/omarchy/bin" +if [ -f "$SCRIPT_DIR/omarchy-import" ] && [ ! -x "$SCRIPT_DIR/omarchy-import" ]; then + chmod +x "$SCRIPT_DIR/omarchy-import" 2>/dev/null && \ + echo " Fixed permissions for omarchy-import" +fi +if [ -f "$SCRIPT_DIR/omarchy-export" ] && [ ! -x "$SCRIPT_DIR/omarchy-export" ]; then + chmod +x "$SCRIPT_DIR/omarchy-export" 2>/dev/null && \ + echo " Fixed permissions for omarchy-export" +fi + +echo -e "\e[32mOmarchy Customization Import\e[0m" +echo "" +echo -e "\e[33m⚠️ WARNING: This will overwrite your current configurations for the imported settings.\e[0m" +echo "Before starting, make sure you've:" +echo " 1. Copied your export tar archive to your home folder" +echo " 2. Backed up any current configurations you don't want to overwrite" +echo "" + +# Look for export tar archives in home folder +EXPORT_ARCHIVES=($(find "$HOME" -maxdepth 1 -type f -name "omarchy_export_*.tar.gz" 2>/dev/null | sort -r)) + +if [ "$#" -lt 1 ]; then + INTERACTIVE_MODE=true + + if [ ${#EXPORT_ARCHIVES[@]} -eq 0 ]; then + # No export archives found + echo "No export archives found in home folder." + echo "Looking for archives named: omarchy_export_YYYYMMDD_HHMMSS.tar.gz" + echo "" + TARBALL_PATH=$(gum input --prompt "Enter export archive path> " --placeholder "$HOME/omarchy_export_20251006_150000.tar.gz") + elif [ ${#EXPORT_ARCHIVES[@]} -eq 1 ]; then + # Only one export found + echo "Found export archive: $(basename "${EXPORT_ARCHIVES[0]}")" + if gum confirm "Use this archive?"; then + TARBALL_PATH="${EXPORT_ARCHIVES[0]}" + else + TARBALL_PATH=$(gum input --prompt "Enter export archive path> " --placeholder "$HOME/omarchy_export_20251006_150000.tar.gz") + fi + else + # Multiple exports found + echo "Found multiple export archives:" + echo "" + + # Create array of just the archive names for display + DISPLAY_OPTIONS=() + for archive in "${EXPORT_ARCHIVES[@]}"; do + DISPLAY_OPTIONS+=("$(basename "$archive")") + done + + SELECTED=$(printf '%s\n' "${DISPLAY_OPTIONS[@]}" | gum choose --header "Select an archive to import:") + + if [[ -n "$SELECTED" ]]; then + TARBALL_PATH="$HOME/$SELECTED" + else + echo "" + TARBALL_PATH=$(gum input --prompt "Or enter a custom path> " --placeholder "$HOME/omarchy_export_20251006_150000.tar.gz") + fi + fi +else + TARBALL_PATH="$1" + INTERACTIVE_MODE=false +fi + +# Validate and extract the tarball +if [[ -z "$TARBALL_PATH" ]]; then + echo "Error: You must provide an export archive path!" + exit 1 +fi + +if [[ ! -f "$TARBALL_PATH" ]]; then + echo "Error: Export archive not found: $TARBALL_PATH" + exit 1 +fi + +# Extract the tarball +echo "" +echo "Extracting archive: $(basename "$TARBALL_PATH")" +EXTRACT_DIR="$HOME" +tar -xzf "$TARBALL_PATH" -C "$EXTRACT_DIR" + +# Find the extracted directory +EXPORT_DIR=$(find "$EXTRACT_DIR" -maxdepth 1 -type d -name "omarchy_export_*" 2>/dev/null | sort -r | head -n 1) + +if [[ -z "$EXPORT_DIR" ]]; then + echo "Error: Could not find extracted export directory" + exit 1 +fi + +echo "Extracted to: $EXPORT_DIR" +echo "" + +if [[ $INTERACTIVE_MODE == true ]]; then + if ! gum confirm "Continue with import?"; then + echo "Import cancelled." + exit 0 + fi + echo "" +fi + +# 1. Restore personal dotfiles +echo "Restoring personal dotfiles..." +if [[ -d "$EXPORT_DIR/home" ]]; then + for file in .bashrc .bash_profile .zshrc .profile .gitconfig; do + if [[ -f "$EXPORT_DIR/home/$file" ]]; then + cp "$EXPORT_DIR/home/$file" "$HOME/$file" + echo " Restored $file" + fi + done +else + echo " No dotfiles found in export" +fi + +# 2. Restore all .config files +echo "" +echo "Restoring all configuration files..." +if [[ -d "$EXPORT_DIR/config" ]]; then + mkdir -p "$HOME/.config" + cp -r "$EXPORT_DIR/config"/* "$HOME/.config/" 2>/dev/null + echo " Restored all .config files" +else + echo " No configuration files found in export" +fi + +# 3. Restore user-created web apps +echo "" +echo "Restoring user-created web apps..." +if [[ -d "$EXPORT_DIR/home/.local/share/applications" ]]; then + mkdir -p "$HOME/.local/share/applications" + + # Copy user-created web apps + if ls "$EXPORT_DIR/home/.local/share/applications"/*.desktop &> /dev/null; then + cp "$EXPORT_DIR/home/.local/share/applications"/*.desktop "$HOME/.local/share/applications/" + chmod +x "$HOME/.local/share/applications"/*.desktop 2>/dev/null + fi + + # Copy custom icons + if [[ -d "$EXPORT_DIR/home/.local/share/applications/icons" ]]; then + mkdir -p "$HOME/.local/share/applications/icons" + cp "$EXPORT_DIR/home/.local/share/applications/icons"/*.png "$HOME/.local/share/applications/icons/" 2>/dev/null + fi + + echo " Restored user-created web apps and icons" +else + echo " No user-created web apps found in export" +fi + +# 4. Optionally restore packages +echo "" +echo "Package restoration..." +if [[ -f "$EXPORT_DIR/pkglist.txt" ]]; then + PACKAGE_COUNT=$(wc -l < "$EXPORT_DIR/pkglist.txt") + echo " Found $PACKAGE_COUNT packages in export" + + if [[ $INTERACTIVE_MODE == true ]]; then + if gum confirm "Install packages from export? (This may take a while)"; then + echo " Installing packages..." + sudo pacman -S --needed - < "$EXPORT_DIR/pkglist.txt" + echo " Packages installed" + else + echo " Skipped package installation" + echo " To install later: sudo pacman -S --needed - < $EXPORT_DIR/pkglist.txt" + fi + else + echo " To install packages: sudo pacman -S --needed - < $EXPORT_DIR/pkglist.txt" + fi +else + echo " No package list found in export" +fi + +if [[ -f "$EXPORT_DIR/aurlist.txt" ]]; then + AUR_COUNT=$(wc -l < "$EXPORT_DIR/aurlist.txt") + if [[ $AUR_COUNT -gt 0 ]]; then + echo " Found $AUR_COUNT AUR packages in export" + + if [[ $INTERACTIVE_MODE == true ]]; then + echo " Installing AUR packages..." + yay -S --needed - < "$EXPORT_DIR/aurlist.txt" + echo " AUR packages installed" + else + echo " To install AUR packages: yay -S --needed - < $EXPORT_DIR/aurlist.txt" + fi + fi +fi + +echo "" +echo -e "\e[32mImport complete!\e[0m" +echo "" +echo "NEXT STEPS:" +echo "1. Review restored configurations in ~/.config/" +echo "2. Re-enroll fingerprint/FIDO2 if needed (Omarchy menu > Setup > Security)" +echo "3. Restore SSH/GPG keys separately if needed" +echo "4. Reboot to ensure all changes take effect" +echo "" diff --git a/bin/omarchy-menu b/bin/omarchy-menu index 0dd68ec10d..b8b9d12554 100755 --- a/bin/omarchy-menu +++ b/bin/omarchy-menu @@ -210,7 +210,7 @@ show_setup_power_menu() { } show_setup_config_menu() { - case $(menu "Setup" " Hyprland\n Hypridle\n Hyprlock\n Hyprsunset\n Swayosd\n󰌧 Walker\n󰍜 Waybar\n󰞅 XCompose") in + case $(menu "Setup" " Hyprland\n Hypridle\n Hyprlock\n Hyprsunset\n Swayosd\n󰌧 Walker\n󰍜 Waybar\n󰞅 XCompose\n Export/Import") in *Hyprland*) open_in_editor ~/.config/hypr/hyprland.conf ;; *Hypridle*) open_in_editor ~/.config/hypr/hypridle.conf && omarchy-restart-hypridle ;; *Hyprlock*) open_in_editor ~/.config/hypr/hyprlock.conf ;; @@ -219,10 +219,19 @@ show_setup_config_menu() { *Walker*) open_in_editor ~/.config/walker/config.toml && omarchy-restart-walker ;; *Waybar*) open_in_editor ~/.config/waybar/config.jsonc && omarchy-restart-waybar ;; *XCompose*) open_in_editor ~/.XCompose && omarchy-restart-xcompose ;; + *Export/Import*) show_export_import_menu ;; *) show_main_menu ;; esac } +show_export_import_menu() { + case $(menu "Export/Import" " Export Settings\n Import Settings") in + *"Export Settings"*) present_terminal omarchy-export ;; + *"Import Settings"*) present_terminal omarchy-import ;; + *) show_setup_config_menu ;; + esac +} + show_setup_security_menu() { case $(menu "Setup" "󰈷 Fingerprint\n Fido2") in *Fingerprint*) present_terminal omarchy-setup-fingerprint ;; @@ -487,4 +496,4 @@ if [[ -n "$1" ]]; then go_to_menu "$1" else show_main_menu -fi +fi \ No newline at end of file diff --git a/config/walker/config.toml b/config/walker/config.toml index cfd79aab95..0869cba35c 100644 --- a/config/walker/config.toml +++ b/config/walker/config.toml @@ -64,7 +64,7 @@ hidden = true hidden = true [builtins.custom_commands] -hidden = true +hidden = false [builtins.emojis] name = "Emojis" @@ -98,3 +98,8 @@ hidden = true [builtins.translation] hidden = true + +[[builtins.custom_commands.entries]] +label = "Export/Import" +cmd = "omarchy-menu export_import" +terminal = false \ No newline at end of file