Development Guidelines for Omarchy: Contributing to the Arch-Based Desktop Environment

Development guidelines for Omarchy require following a strict repository layout with runtime binaries in bin/, system defaults in default/, user configs in config/, and migrations in migrations/, alongside Bash 5 scripting standards, idempotent migration scripts, and comprehensive testing via ./test/all.

Omarchy is a tightly-integrated Arch-based desktop environment maintained by Basecamp that combines runtime packages, user-land configuration, and a Quickshell desktop. Understanding the development guidelines for Omarchy is essential before contributing code, as the project enforces specific architectural boundaries between system-wide defaults and per-user state. This guide covers the repository structure, coding conventions, testing requirements, and contribution workflow based on the actual source code implementation.

Repository Layout and File Architecture

The architecture is documented in docs/file-layout.md. The repository organizes code into distinct layers that map to specific filesystem locations upon installation.

Source-to-Install Mapping

Layer Source Tree Install Target
Runtime binaries bin/ /usr/bin/omarchy-*
System-wide defaults default/ /usr/share/omarchy/default/ (plus /etc/skel/ seeds)
User-side config config/ ~/.config/omarchy/ (seeded from /etc/skel/)
Migrations migrations/ ~/.local/state/omarchy/migrations/
Shell plugins shell/ /usr/share/omarchy/shell/
Documentation docs/, manual/ Rendered on the website

When adding new files, adhere to this rule: system-wide resources belong in default/, while per-user configuration must live in config/ or be handled via the migrations/ system.

Coding Standards and Conventions

Bash Scripting Requirements

All shell scripts in the Omarchy repository must conform to Bash 5 standards. According to the Shell-Dev Skill Guide at agents/skills/shell-dev.md, scripts must:

  • Use set -euo pipefail to enable strict error handling
  • Use [[ … ]] for string comparisons and (( … )) for numeric operations
  • Target Bash 5 syntax exclusively

Quickshell Plugin Development

Plugins for the Quickshell desktop are written in JavaScript and stored in shell/plugins/. Each module must export its logic using module.exports = … to enable unit testing with Node. This architecture allows the test harness to load and validate plugin logic outside the graphical environment.

Example plugin structure:

// shell/plugins/example/ExamplePlugin.js
const { registerPlugin } = require('omarchy-plugin-utils');

function init() {
  // Plugin logic here
}

if (typeof module !== 'undefined') {
  module.exports = { init };
}

registerPlugin('example', init);

CLI Command Naming

All user-facing commands must follow the omarchy- prefix convention and be placed in the bin/ directory. The central dispatcher at bin/omarchy maintains a GROUP_DESCRIPTIONS array that automatically categorizes commands in the help router. Include metadata comments in new scripts:

#!/usr/bin/env bash

# omarchy:summary=Show a friendly greeting

# omarchy:group=demo

set -euo pipefail
echo "Hello from omarchy-foo-bar!"

Commit and Documentation Standards

Follow the atomic commit guidelines in AGENTS.md: one coherent change per commit. Documentation updates must accompany code changes, with user-facing guides in manual/ and developer documentation in docs/.

Testing Strategy and CLI Validation

The test suite runs via ./test/all and supports multiple test types:

  • CLI tests: Validate routing, metadata extraction, and theme pipelines
  • Shell tests: Located in test/shell.d/, one file per feature, each sourcing base-test.sh
  • Node tests: Execute JavaScript modules using run_node_test for Quickshell plugins

All shell test files must begin with this boilerplate:

#!/usr/bin/env bash
set -euo pipefail
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/base-test.sh"

require_command omarchy
pass "omarchy command is present"

Tests should create temporary bin/ directories containing mock executables to log arguments, ensuring the suite remains hermetic and CI-friendly. Full details are available in docs/testing.md.

Migration Model for User State

Changes affecting per-user state after initial installation must be implemented as idempotent migration scripts in migrations/. These scripts:

  • Execute as the user via omarchy-migrate
  • Store completion markers in ~/.local/state/omarchy/migrations/
  • Must be safe to run multiple times

Example migration structure:

#!/usr/bin/env bash

# 2025-03-01-add-example-config.sh

set -euo pipefail
SRC="$OMARCHY_PATH/config/example.conf"
DEST="${HOME}/.config/omarchy/example.conf"

[[ ! -e "$DEST" ]] && cp -a "$SRC" "$DEST"

See agents/skills/migrations.md for the complete authoring checklist.

Contribution Workflow

To contribute to Omarchy:

  1. Fork the repository: gh repo fork basecamp/omarchy --clone
  2. Create a descriptive branch name
  3. Place files according to the architecture (runtime in bin/, configs in config/ or default/)
  4. Run the full test suite: ./test/all
  5. Open a PR following AGENTS.md guidelines

For local development, use omarchy dev link to create a live symlink tree, allowing you to test changes without reinstalling the package. The Development Tools manual at manual/18-development-tools.md documents additional runtimes and helper scripts.

Summary

  • Repository Layout: Respect the boundary between bin/ (runtime), default/ (system-wide), config/ (user), and migrations/ (state updates)
  • Coding Standards: Write Bash 5 with set -euo pipefail, export JavaScript modules for testability, and prefix commands with omarchy-
  • Testing: Validate changes via ./test/all, with shell tests in test/shell.d/ and Node tests for Quickshell plugins
  • Migrations: Implement per-user changes as idempotent scripts in migrations/ that mark completion in ~/.local/state/omarchy/migrations/
  • Workflow: Fork, branch, test, and PR following AGENTS.md, using omarchy dev link for local testing

Frequently Asked Questions

What directory should I use for new configuration files?

Place system-wide defaults in default/ (installs to /usr/share/omarchy/default/ and seeds /etc/skel/), but put per-user configuration templates in config/ (installs to ~/.config/omarchy/). If you need to update existing user installations, create a migration script in migrations/ instead.

How do I test JavaScript Quickshell plugins?

Export your plugin logic using module.exports = … at the end of the JavaScript file, then use the run_node_test helper from the bash test suite. The Node bridge loads the module in a Node environment to validate logic without launching the graphical desktop.

Why must migration scripts be idempotent?

Migration scripts run every time omarchy-migrate executes and store completion markers in ~/.local/state/omarchy/migrations/. They must be idempotent because users may trigger migrations multiple times, and the script should safely skip already-applied changes without error.

Where are the authoritative style and commit guidelines documented?

The AGENTS.md file at the repository root contains the definitive rules for commit message format, atomic commit size, and pull request standards. All contributors must follow these conventions to maintain project coherence.

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 →