# How Omarchy Hooks Function Across pre-refresh, post-update, and Other Event Directories

> Understand how Omarchy hooks execute across pre-refresh, post-update, and event directories. Learn its script and directory processing order for efficient event handling.

- Repository: [37signals/omarchy](https://github.com/basecamp/omarchy)
- Tags: internals
- Published: 2026-08-19

---

**Omarchy executes hooks by first running a single flat-file script at `~/.config/omarchy/hooks/<event>` if it exists, then processing every executable file inside the corresponding `<event>.d/` directory in lexical order, stopping immediately if any script returns a non-zero exit code.**

The basecamp/omarchy repository implements a lightweight, file-based automation system that attaches custom scripts to system events. All hook logic resides under the user’s configuration directory, requiring no complex registration APIs—only executable files placed in the correct location.

## Hook Directory Structure and Naming Conventions

Omarchy stores all hooks in `~/.config/omarchy/hooks/`. The system recognizes two distinct storage patterns for each event:

- **Flat-file hook:** A single executable file named exactly after the event (e.g., `post-update`). This runs first when the event fires.
- **Directory hooks:** A subdirectory named `<event>.d/` (e.g., `post-update.d/`). Every executable file inside this directory runs after the flat-file hook, sorted lexicographically.

This dual structure allows you to maintain one master script for an event while keeping supplementary modular scripts in the `.d` directory.

## How the Hook Dispatcher Executes Scripts

When Omarchy triggers an event, the internal dispatcher performs a strict three-phase execution sequence:

1. **Flat-file check:** If `~/.config/omarchy/hooks/<event>` exists and is executable, the dispatcher invokes it with the event’s arguments.
2. **Directory enumeration:** The dispatcher scans `<event>.d/` for executable files, sorts them by filename, and runs each sequentially.
3. **Exit propagation:** If any hook exits with a non-zero status, the dispatcher aborts further processing for that event. This behavior lets hooks act as guard points that can prevent subsequent actions.

Hooks inherit the full environment of the calling `omarchy` process, allowing them to invoke other Omarchy commands or access user environment variables safely.

## Common Hook Events and Use Cases

Omarchy defines several built-in event names that correspond to specific lifecycle moments. The directory names directly reflect these events.

### pre-refresh-pacman

The `pre-refresh-pacman.d/` directory (and corresponding `pre-refresh-pacman` flat file) triggers **before** `omarchy refresh pacman` begins re-syncing packages. Use this to stop services that might interfere with package database locks.

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

# ~/.config/omarchy/hooks/pre-refresh-pacman.d/01-stop-music

systemctl --user stop mpd.service

```

### post-update

The `post-update.d/` directory fires **after** `omarchy update` completes all package installations and migrations. This is the standard location for cleanup tasks or daemon restarts.

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

# ~/.config/omarchy/hooks/post-update.d/01-cleanup

sudo pacman -Sc --noconfirm

```

### post-boot

Scripts in `post-boot.d/` execute after the desktop environment has started. Typical uses include launching background services like `waybar` or setting UI state.

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

# ~/.config/omarchy/hooks/post-boot (flat-file example)

/usr/bin/waybar &

```

### theme-set

When users change themes, Omarchy runs hooks in `theme-set.d/`, passing the new theme slug as `$1`. This lets you apply tweaks that Omarchy does not handle natively.

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

# ~/.config/omarchy/hooks/theme-set.d/99-custom-alert

notify-send "Theme changed to $1"

```

### battery-low and font-set

- **battery-low:** Hooks in `battery-low.d/` receive the current battery percentage as `$1` when the system drops below a low threshold.
- **font-set:** Hooks in `font-set.d/` receive the new font name as `$1`, useful for refreshing application caches.

## Installing and Managing Hooks

Rather than manually copying files, use the `omarchy hook install` command to ensure correct placement and permissions. The entry point for this functionality resides in `bin/omarchy-hook`.

```bash

# Install a script to run after theme changes

omarchy hook install theme-set ~/scripts/my-theme-hook.sh

```

This command copies the script to `~/.config/omarchy/hooks/theme-set.d/` and marks it executable. The dispatcher requires executable permissions to run a file, so manual additions must include `chmod +x`.

## Hooks in the Source Code

The hook system architecture is documented across several repository files:

- [`default/agents/skills/omarchy/hooks.md`](https://github.com/basecamp/omarchy/blob/main/default/agents/skills/omarchy/hooks.md) — Describes the directory layout and execution semantics.
- [`default/agents/skills/omarchy/SKILL.md`](https://github.com/basecamp/omarchy/blob/main/default/agents/skills/omarchy/SKILL.md) — Lists the `omarchy hook` command interface.
- [`manual/31-dotfiles.md`](https://github.com/basecamp/omarchy/blob/main/manual/31-dotfiles.md) — Provides end-user guidance on placing scripts in hook directories.
- `bin/omarchy-hook` — The executable entry point that handles installation, listing, and removal of hooks.

These files collectively define the deterministic, lexicographic ordering and the flat-file-first precedence rules that govern hook execution.

## Summary

- **Storage location:** All hooks live under `~/.config/omarchy/hooks/`.
- **Dual structure:** Use a flat file `<event>` for single scripts or `<event>.d/` directories for modular collections.
- **Execution order:** Flat file runs first, followed by `.d/` contents sorted lexicographically.
- **Error handling:** A non-zero exit from any hook aborts the entire event chain.
- **Installation:** Use `omarchy hook install <event> <script>` to ensure proper permissions and placement according to the `bin/omarchy-hook` implementation.

## Frequently Asked Questions

### What happens if a hook script fails?

If any hook exits with a non-zero status code, Omarchy immediately stops processing that event. Subsequent hooks in the same `.d/` directory will not run, effectively letting you use hooks as circuit breakers.

### Can I use any scripting language for Omarchy hooks?

Yes. The dispatcher treats any executable file as a valid hook. Python, Ruby, or compiled binaries work as long as the file has execute permissions and a valid shebang or binary header. The system simply executes the file and passes arguments via `$1`, `$2`, etc.

### How do I ensure my hooks run in a specific order?

Name your files lexicographically. The dispatcher sorts files in `<event>.d/` by filename, so prefixing with numbers (e.g., [`10-prepare.sh`](https://github.com/basecamp/omarchy/blob/main/10-prepare.sh), [`20-process.sh`](https://github.com/basecamp/omarchy/blob/main/20-process.sh), [`99-cleanup.sh`](https://github.com/basecamp/omarchy/blob/main/99-cleanup.sh)) guarantees execution sequence.

### Where is the hook documentation located in the repository?

The canonical documentation resides in [`default/agents/skills/omarchy/hooks.md`](https://github.com/basecamp/omarchy/blob/main/default/agents/skills/omarchy/hooks.md). User-facing guides appear in [`manual/31-dotfiles.md`](https://github.com/basecamp/omarchy/blob/main/manual/31-dotfiles.md), while the command implementation lives in `bin/omarchy-hook`.