Omarchy Config Refresh Pattern: Defaults, Backups, and Idempotent Updates
Omarchy uses the omarchy-refresh-config shell utility to safely synchronize user configuration files with repository defaults, automatically creating timestamped backups and cleaning up unchanged copies while displaying diffs for modified files.
The Omarchy configuration management system employs a deterministic config refresh pattern to propagate upstream defaults into user environments without destroying customizations. This utility-centric approach, implemented in bin/omarchy-refresh-config, ensures that dotfiles remain synchronized with the basecamp/omarchy repository while providing robust safety mechanisms for local modifications. Understanding how the script resolves paths, validates defaults, and manages backups is essential for anyone maintaining an Omarchy installation.
How the Refresh Pattern Works
The core utility follows an eight-step sequence that guarantees idempotent updates—running the command repeatedly will not create unnecessary backups or duplicate files. The pattern operates on a relative configuration path (e.g., hypr/hyprland.lua) and manipulates three absolute locations: the user file in ~/.config, the default file in $OMARCHY_PATH/config, and a timestamped backup file.
Path Resolution and Environment Variables
When invoked with a relative path, the script immediately constructs three critical file paths using environment variables:
- User file:
${HOME}/.config/$config_file - Default file:
$OMARCHY_PATH/config/$config_file - Backup file:
$user_config_file.bak.$(date +%s)
This resolution happens at the start of bin/omarchy-refresh-config, ensuring all subsequent operations work with absolute paths. The backup filename appends a Unix timestamp (seconds since epoch) to guarantee uniqueness and chronological ordering.
Validation and Safety Checks
Before modifying any files, the script validates that the requested default actually exists in the repository:
if [[ ! -e $default_config_file ]]; then
echo "Error: Not a shipped user config"
exit 1
fi
This check prevents typos or attempts to refresh non-shipped files from corrupting the user configuration. If the default is missing, the command aborts immediately without touching existing user files.
Directory Preparation and Backup Creation
Once validated, the script ensures the target directory structure exists:
mkdir -p "$(dirname "$user_config_file")"
If the user already has a configuration file at the target location, the utility creates a timestamped backup before any overwriting occurs:
cp -f "$user_config_file" "$backup_config_file"
This preservation step guarantees that user customizations remain recoverable even after the refresh overwrites the original file.
Copy Logic and Post-Copy Cleanup
The default configuration is then copied to the user location using force-copy to ensure overwrites:
cp -f "$default_config_file" "$user_config_file"
After copying, the script compares the new file with the backup using cmp -s. If the files are identical—meaning the user had not customized the file or the default hasn't changed—the backup is automatically deleted to prevent filesystem clutter:
if cmp -s "$user_config_file" "$backup_config_file"; then
rm "$backup_config_file"
If the files differ, the script displays a colored diff between the backup and the new file, allowing users to see exactly what changed. The backup persists in this case for later reference or manual recovery.
Handling Missing User Configurations
When the user has no existing configuration file, the script performs a simple copy without creating a backup:
else
cp -f "$default_config_file" "$user_config_file"
This optimization avoids storing redundant backups of files the user never customized.
Practical Usage Examples
Refresh a single configuration file to synchronize it with the repository default:
omarchy-refresh-config hypr/hyprland.lua
This command copies $OMARCHY_PATH/config/hypr/hyprland.lua to ~/.config/hypr/hyprland.lua. If a user version existed, it creates a backup like ~/.config/hypr/hyprland.lua.bak.1692748123 and displays a diff if the content changed.
For batch operations, Omarchy provides convenience wrappers that invoke the core utility multiple times. To refresh all Hyprland configurations:
omarchy-refresh-hyprland
Internally, this wrapper executes sequential calls:
omarchy-refresh-config hypr/.luarc.json
omarchy-refresh-config hypr/autostart.lua
omarchy-refresh-config hypr/bindings.lua
# ... additional Hyprland files
Integration with Higher-Level Commands
The config refresh pattern is designed for reuse across the Omarchy ecosystem. Specific refresh commands—such as omarchy-refresh-tmux and omarchy-refresh-hyprland—act as thin wrappers that call omarchy-refresh-config for each file in their respective domains. This architecture centralizes backup logic, diff generation, and error handling in a single well-tested utility while allowing domain-specific scripts to manage file lists.
According to the source code in plans/dots.md, this pattern guarantees that shipped defaults can safely propagate to user environments without requiring manual merge operations or risking configuration loss.
Testing and Validation
The behavior of the refresh system is covered by automated tests in test/shell.d/refresh-config-test.sh. These tests verify:
- Correct copying of default files to user directories
- Backup creation with valid timestamp formats
- Automatic cleanup of identical backups
- Proper error handling when default files are missing
- Diff generation for modified configurations
This test coverage ensures that changes to the shell script maintain backward compatibility and safety guarantees across different Linux environments.
Summary
- The
omarchy-refresh-configutility inbin/omarchy-refresh-configprovides the core implementation for synchronizing user configurations with repository defaults. - Every refresh creates a timestamped backup (
.bak.<timestamp>) before overwriting existing user files, ensuring recoverability. - The script automatically deletes backup files when the new content matches the old, preventing unnecessary filesystem clutter.
- Colored diffs display changes when defaults differ from user customizations, providing immediate visibility into updates.
- Higher-level commands like
omarchy-refresh-hyprlandreuse this pattern to batch-process related configuration files. - Comprehensive tests in
test/shell.d/refresh-config-test.shvalidate copy operations, backup handling, and error conditions.
Frequently Asked Questions
How does Omarchy protect my existing configurations during a refresh?
Omarchy creates a timestamped backup file (using the pattern .bak.$(date +%s)) before overwriting any existing user configuration. If the new default differs from your previous version, the backup persists and a colored diff is displayed. If the files are identical, the backup is automatically removed to keep your ~/.config directory clean.
What happens if I try to refresh a configuration file that doesn't exist in the repository?
The omarchy-refresh-config script validates that the default file exists at $OMARCHY_PATH/config/<config_file> before performing any operations. If the specified file is not shipped with Omarchy, the command exits with status 1 and prints "Not a shipped user config", protecting against typos and unauthorized file refreshes.
Can I see exactly what changed when Omarchy updates my config files?
Yes. When the refresh process detects that the new default differs from the user's previous configuration (by comparing the backup with the new file using cmp -s), it automatically displays a colored diff between the backup and the current file. This output shows line-by-line changes, additions, and deletions.
Are there convenience commands for refreshing multiple related configs at once?
Yes. Omarchy provides wrapper scripts such as omarchy-refresh-hyprland and omarchy-refresh-tmux that batch-execute the core omarchy-refresh-config utility for all files in a specific application domain. These wrappers ensure consistent application of the refresh pattern across related configuration files without requiring multiple manual commands.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →