# How to Configure Hyprland Autostart Applications: A Complete Guide

> Learn how to configure Hyprland autostart applications using the exec-once directive in hyprland.conf. This guide explains the process for seamless startup.

- Repository: [Hypr Development/Hyprland](https://github.com/hyprwm/Hyprland)
- Tags: how-to-guide
- Published: 2026-07-29

---

**Hyprland launches autostart applications through the `exec-once` directive in `~/.config/hypr/hyprland.conf`, which the `CExecutor` class processes exactly once during compositor initialization via [`src/config/supplementary/executor/Executor.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/config/supplementary/executor/Executor.cpp).**

When the hyprwm/Hyprland compositor starts, it reads your configuration file and executes designated commands automatically. This mechanism allows you to configure Hyprland autostart applications such as status bars, wallpaper daemons, and background services without manual intervention each session.

## Understanding the exec-once Mechanism

The autostart system centers on the **Executor** subsystem located in [`src/config/supplementary/executor/Executor.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/config/supplementary/executor/Executor.cpp). The `CExecutor` class maintains two private vectors—`m_execOnce` and `m_execShutdown`—that store commands parsed from your configuration file.

During Hyprland's initialization sequence, the method `CExecutor::applyExecOnce()` iterates over the `m_execOnce` vector and spawns each command using `spawn()` (which ultimately performs a `fork/exec` system call). Because the executor clears this vector immediately after the first execution, these commands **never run again** until you restart the compositor entirely.

According to the Hyprland source code, the execution flow follows this path:

1. Config parser encounters `exec-once = command`
2. Command string pushes to `CExecutor::m_execOnce`
3. Startup triggers `applyExecOnce()` 
4. Each entry spawns via `spawn()` or `spawnWithRules()`
5. Vector clears, preventing re-execution

## Basic Configuration Syntax

Add `exec-once` entries to your `~/.config/hypr/hyprland.conf` file. Each line defines one autostart command:

```conf

# ~/.config/hypr/hyprland.conf

# Autostart a status bar

exec-once = waybar

# Start a compositor-friendly clipboard manager

exec-once = cliphist daemon

# Launch wallpaper daemon

exec-once = hyprpaper

# Execute a custom setup script

exec-once = $HOME/.config/hypr/autostart.sh

```

Place these directives at the top level of your configuration file, outside of any category blocks. The parser identifies lines beginning with `exec-once` and immediately routes them to the executor subsystem.

## Advanced Usage and Environment Variables

You can chain multiple commands using logical operators or subshells when you need complex startup sequences:

```conf

# Chain commands with && (subsequent only runs if previous succeeds)

exec-once = sh -c 'nm-applet & volumeicon && picom --experimental-backends'

# Group related services in a single subshell

exec-once = sh -c 'nm-applet & 
                volumeicon &
                xrandr --output eDP-1 --primary --auto'

```

Environment variable expansion occurs before execution. The helper functions in [`src/helpers/MiscFunctions.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/helpers/MiscFunctions.cpp) handle the expansion of `$HOME`, `$DISPLAY`, `$USER`, and other variables defined in your environment. This ensures that paths and settings resolve correctly regardless of where you launch Hyprland from.

## exec-once vs exec: Key Differences

Hyprland offers two distinct execution directives with different persistence behaviors:

- **`exec-once`**: Runs **only during the initial compositor startup**. According to the implementation in [`Executor.cpp`](https://github.com/hyprwm/Hyprland/blob/main/Executor.cpp), the executor runs `applyExecOnce()` exactly once and clears the `m_execOnce` vector afterward. Reloading your configuration with `hyprctl reload` does not re-trigger these commands.

- **`exec`**: Executes commands immediately when parsed, typically used within keybind definitions. These run every time the binding triggers or the configuration reloads.

If you need applications to restart when you reload your configuration, use `exec` within a keybind or script rather than `exec-once`.

## Summary

- **Location**: Define autostart applications in `~/.config/hypr/hyprland.conf` using the `exec-once` directive.
- **Implementation**: The `CExecutor` class in [`src/config/supplementary/executor/Executor.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/config/supplementary/executor/Executor.cpp) stores commands in the `m_execOnce` vector and executes them via `applyExecOnce()` during startup.
- **Behavior**: Commands run exactly once per compositor session; configuration reloads do not re-execute them.
- **Variables**: Environment variables expand automatically through helpers in [`src/helpers/MiscFunctions.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/helpers/MiscFunctions.cpp).
- **Complex sequences**: Use `sh -c` with `&` or `&&` operators to chain multiple applications.

## Frequently Asked Questions

### Why don't my autostart applications restart when I reload Hyprland's config?

**The `exec-once` directive intentionally prevents re-execution during configuration reloads.** As implemented in [`src/config/supplementary/executor/Executor.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/config/supplementary/executor/Executor.cpp), the `CExecutor::applyExecOnce()` method clears the `m_execOnce` vector immediately after spawning commands during the initial startup. This design ensures that long-running background services do not spawn duplicate processes when you tweak keybindings or window rules.

### Can I use environment variables like $HOME in exec-once commands?

**Yes.** Hyprland expands environment variables before execution through helper functions located in [`src/helpers/MiscFunctions.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/helpers/MiscFunctions.cpp). You can safely use `$HOME`, `$USER`, `$DISPLAY`, and custom variables defined in your shell profile. For example: `exec-once = $HOME/.local/bin/custom-script.sh` resolves correctly at startup.

### How do I run multiple commands on startup without creating a separate script?

**Use a subshell with `sh -c` and background operators.** Wrap your command sequence in single quotes and separate individual programs with `&` (background) or `&&` (conditional). For instance: `exec-once = sh -c 'waybar & cliphist daemon & hyprpaper'` starts all three services simultaneously. This approach keeps your [`hyprland.conf`](https://github.com/hyprwm/Hyprland/blob/main/hyprland.conf) self-contained while launching complex application groups.

### What is the difference between exec and exec-once in Hyprland?

**`exec-once` runs exclusively during the compositor's initial startup sequence**, stored in `CExecutor::m_execOnce` and triggered once via `applyExecOnce()`. **`exec` executes immediately when parsed**, typically within keybind handlers or during configuration reloads. Use `exec-once` for one-time initialization tasks like starting panels or daemons, and reserve `exec` for commands you want to trigger via hotkeys or run on every config reload.