# How User Hooks Automation Works in Omarchy: A Complete Guide to Custom Script Execution

> Discover how Omarchy user hooks automation executes custom scripts during user lifecycle events. Learn to automate post-update, theme changes, and package refreshes with this powerful guide.

- Repository: [37signals/omarchy](https://github.com/basecamp/omarchy)
- Tags: how-to-guide
- Published: 2026-08-18

---

**Omarchy's user hooks automation provides a lightweight, event-driven system that executes custom user scripts at specific lifecycle moments like post-update, theme changes, and package refreshes.**

This hook architecture lets you extend Omarchy's behavior without modifying core source code. Whether you want notifications after updates, automatic service restarts, or custom configuration tweaks, the hook system in `basecamp/omarchy` provides clean integration points.

## Overview of the Hook System Architecture

The automation layer centers on two command-line tools and a standardized directory structure under `~/.config/omarchy/hooks/`.

| Component | Purpose | Source Location |
|-----------|---------|---------------|
| `omarchy-hook` | Executes hooks by name, running single scripts and all executables in matching `.d` directories | [`bin/omarchy-hook`](https://github.com/basecamp/omarchy/blob/quattro/bin/omarchy-hook) |
| `omarchy-hook-install` | Installs user scripts into the correct hook directory with proper permissions | [`bin/omarchy-hook-install`](https://github.com/basecamp/omarchy/blob/quattro/bin/omarchy-hook-install) |
| Hook directories | Organize scripts by event type (e.g., `post-update.d/`, `theme-set.d/`) | `~/.config/omarchy/hooks/` |
| Sample hooks | Reference implementations shipped with `.sample` suffix for easy activation | `config/omarchy/hooks/…/*.sample` |

Core Omarchy commands invoke `omarchy-hook <type>` at strategic points, creating an **extensible automation pipeline** that remains robust even when user scripts fail.

## How Hooks Are Executed: Step-by-Step Flow

Understanding the execution order helps you write reliable automation scripts.

### Step 1: Install Your Hook Script

Use `omarchy-hook-install` to place scripts in the correct location:

```bash

# Create a cleanup script that runs after every update

cat > ~/cleanup-temp.hook <<'EOF'
#!/usr/bin/env bash
echo "Cleaning temporary files after Omarchy update..."
rm -rf ~/.cache/omarchy/tmp/*
EOF

# Install it as a post-update hook

omarchy-hook-install post-update ~/cleanup-temp.hook

```

This command copies the file to `~/.config/omarchy/hooks/post-update.d/` and sets executable permissions automatically.

### Step 2: Trigger Event Occurs

Built-in Omarchy commands fire hooks at predetermined moments:

- `omarchy-update` → runs `omarchy-hook post-update` after completion
- `omarchy-theme-set` → runs `omarchy-hook theme-set "$THEME_NAME"` with the theme name as argument
- `omarchy-refresh-pacman` → runs `omarchy-hook pre-refresh-pacman` before package synchronization

You can also trigger hooks manually for testing:

```bash
omarchy-hook post-update

```

### Step 3: Hook Dispatcher Runs Scripts

The `omarchy-hook` dispatcher in `bin/omarchy-hook` follows this execution order:

1. **Single-file hook first** — If `~/.config/omarchy/hooks/<name>` exists as an executable file, run it
2. **Directory scripts next** — Run every regular file in `~/.config/omarchy/hooks/<name>.d/` in lexical (alphabetical) order
3. **Skip samples** — Ignore any file ending in `.sample`
4. **Forward arguments** — Pass all original arguments to each script

### Step 4: Error Handling Preserves System Stability

If a hook exits with a non-zero status, the dispatcher prints a failure message but **does not abort the calling command**. This design prevents user automation errors from breaking core Omarchy operations.

## Available Hook Types and Invocation Points

The following hooks are integrated into standard Omarchy workflows:

| Hook Name | Triggered By | Typical Use Case |
|-----------|-----------|----------------|
| `post-update` | `omarchy-update` after system update completion | Notifications, cleanup, service restarts |
| `theme-set` | `omarchy-theme-set` when switching themes | Theme-specific configurations, per-theme automation |
| `pre-refresh-pacman` | `omarchy-refresh-pacman` before package sync | Pre-sync backups, mirror selection |
| `first-run` hooks | `omarchy-provision-first-run` after initial setup | Onboarding tasks (voxtype, fingerprint, agent setup) |

Source references for hook invocations:
- [`bin/omarchy-update`](https://github.com/basecamp/omarchy/blob/quattro/bin/omarchy-update): `omarchy-hook post-update`
- [`bin/omarchy-theme-set`](https://github.com/basecamp/omarchy/blob/quattro/bin/omarchy-theme-set): `omarchy-hook theme-set "$THEME_NAME"`
- [`bin/omarchy-refresh-pacman`](https://github.com/basecamp/omarchy/blob/quattro/bin/omarchy-refresh-pacman): `omarchy-hook pre-refresh-pacman`

## Practical Hook Examples

### Post-Update Desktop Notification

Enable the provided sample or create your own at `~/.config/omarchy/hooks/post-update.d/show-update-notification`:

```bash
#!/usr/bin/env bash

# Notify user that system update completed successfully

omarchy-notification-send -u low "Update Complete" "Omarchy system is now up to date"

```

To activate a sample hook, remove the `.sample` suffix:

```bash
mv ~/.config/omarchy/hooks/post-update.d/show-update-notification.sample \
   ~/.config/omarchy/hooks/post-update.d/show-update-notification

```

### Theme-Aware Configuration Script

Access the theme name passed as an argument:

```bash
#!/usr/bin/env bash

# ~/.config/omarchy/hooks/theme-set.d/apply-wallpaper

THEME="$1"

case "$THEME" in
  dark)
    feh --bg-scale ~/wallpapers/night.jpg
    ;;
  light)
    feh --bg-scale ~/wallpapers/day.jpg
    ;;
esac

```

### Pre-Refresh Backup Hook

Run before package synchronization to preserve critical state:

```bash
#!/usr/bin/env bash

# ~/.config/omarchy/hooks/pre-refresh-pacman.d/backup-pacman-db

mkdir -p ~/backups/pacman
cp /var/lib/pacman/local ~/backups/pacman/local-"$(date +%Y%m%d)"

```

## First-Run Hooks: Special Automation Pattern

Omarchy uses the same hook system for **first-run provisioning**. The `omarchy-provision-first-run` command installs three invitation hooks:

- `install-voxtype.hook` — Prompts to install voice typing tools
- `setup-fingerprint.hook` — Guides fingerprint reader configuration  
- `setup-agent.hook` — Configures SSH/GPG agent preferences

These live in `install/user/first-run/*.hook` in the repository and are copied to `~/.config/omarchy/hooks/post-update.d/` during initial setup. They demonstrate that **hooks can be distributed as part of packages**, not just user-created scripts.

## File Locations and Source Reference

Key files for understanding and extending the hook system:

| Path | Description |
|------|-------------|
| [`bin/omarchy-hook`](https://github.com/basecamp/omarchy/blob/quattro/bin/omarchy-hook) | Core dispatcher implementation |
| [`bin/omarchy-hook-install`](https://github.com/basecamp/omarchy/blob/quattro/bin/omarchy-hook-install) | Installation helper |
| `config/omarchy/hooks/.../*.sample` | Template hooks (post-update, theme-set, pre-refresh-pacman) |
| `install/user/first-run/*.hook` | First-run invitation implementations |
| [`docs/file-layout.md`](https://github.com/basecamp/omarchy/blob/main/docs/file-layout.md) | Repository layout including hook paths |
| [`docs/update-process.md`](https://github.com/basecamp/omarchy/blob/main/docs/update-process.md) | Update flow documentation |

## Summary

- **Two-command interface**: `omarchy-hook` runs hooks, `omarchy-hook-install` adds your scripts
- **Dual execution path**: Single file `hooks/<name>` first, then all files in `hooks/<name>.d/` alphabetically
- **Fail-safe design**: Hook errors warn but don't stop core operations
- **Argument forwarding**: Scripts receive all parameters passed to `omarchy-hook`
- **Sample-based onboarding**: Enable templates by removing `.sample` suffix
- **First-run integration**: The same system handles post-installation setup tasks

## Frequently Asked Questions

### What happens if a hook script fails?

The `omarchy-hook` dispatcher prints "Hook failed: [script-name]" to stderr, logs the exit code, and continues executing remaining hooks. The calling Omarchy command proceeds normally—hook failures never block core functionality. Check your terminal output or system logs to diagnose script errors.

### Can I run hooks manually for testing?

Yes. Execute `omarchy-hook <type>` directly with any arguments your scripts expect. For example: `omarchy-hook theme-set custom-theme` passes "custom-theme" to all theme-set hooks. This is useful for debugging before the triggering event occurs naturally.

### How do I discover what hooks are available?

List the contents of `~/.config/omarchy/hooks/` to see installed hooks, and check `config/omarchy/hooks/` in the Omarchy repository for available samples. Currently integrated hooks include `post-update`, `theme-set`, and `pre-refresh-pacman`—examine the `bin/omarchy-*` scripts to find invocation points and expected arguments.

### Can packages distribute hooks automatically?

Yes. The `omarchy-hook-install` command supports programmatic installation. Packages can ship hook files and install them to `~/.config/omarchy/hooks/<type>.d/` during setup. The first-run system uses this pattern—`omarchy-provision-first-run` copies invitation hooks from `install/user/first-run/` into the user's hook directory.