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-config utility in bin/omarchy-refresh-config provides 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-hyprland reuse this pattern to batch-process related configuration files.
  • Comprehensive tests in test/shell.d/refresh-config-test.sh validate 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.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →