How Omarchy Handles Code Review for Third-Party Plugins: A Security-First Architecture

Omarchy forces mandatory human review by cloning all third-party plugins into a disabled state, displaying git diffs before activation, and requiring explicit enablement via omarchy plugin enable before any QML or JavaScript code executes.

Omarchy treats third-party plugins as untrusted Git checkouts that cannot execute until manually reviewed. According to the basecamp/omarchy source code, the shell's plugin architecture implements a "disabled by default" policy engineered into PluginRegistry.qml and the bin/omarchy CLI. This design ensures that third-party code remains inert—stored on disk but never loaded—until a user explicitly inspects the source and enables the plugin.

The Six-Stage Code Review Pipeline

Omarchy's workflow is hardcoded into the shell lifecycle, creating an obligatory inspection checkpoint between installation and execution.

1. Cloning to a Quarantined State

When you run omarchy plugin add <git-url>, the CLI clones the repository into ~/.config/omarchy/plugins/<plugin-id>/ and immediately flags it as disabled. The PluginRegistry adds the plugin ID to the disabledPlugins[] array in shell.json via the addDisabled function. At this stage, the shell process cannot see the plugin; the QML files exist on the filesystem but are invisible to the runtime.

2. Manifest Validation and Trust Stamping

The PluginRegistry.qml service validates every manifest.json against a strict schema. Third-party plugins are stamped with __isFirstParty: false to distinguish them from built-ins. The registry rejects manifests containing unsafe entry points—such as paths like ../Panel.qml that attempt directory traversal—or malformed metadata. This validation occurs in the registry's discovery phase, preventing invalid plugins from ever appearing in the enabled list.

3. Mandatory Diff Presentation

Before prompting for enablement, the CLI executes git diff against the newly cloned checkout and streams the output to the terminal. This step is non-negotiable: even in non-interactive mode with the --yes flag, the diff is captured in the logs for auditability. Users see exactly what code is being introduced, including any post-clone changes or potentially malicious scripts.

4. Manual Review Period

Because the plugin remains in disabledPlugins[], the omarchy-shell process never loads its QML or JavaScript files. The user can navigate to ~/.config/omarchy/plugins/<plugin-id>/, read the source code, inspect dependencies, and verify the manifest.json without any risk of execution. This quarantine state persists across shell restarts until explicitly cleared.

5. Explicit Enablement

After review, activation requires a deliberate action: omarchy plugin enable <id> or using the --enable flag during installation. The PluginRegistry.setEnabled method (lines 49-66 in PluginRegistry.qml) handles this transition, removing the ID from disabledPlugins[] and triggering a hot-reload via omarchy-shell rescanPlugins. Only then does the shell's QML engine parse and execute the plugin code.

6. Update Verification

When updating via omarchy plugin update, the CLI fast-forwards the Git checkout and displays a diff of incoming changes before applying them. Crucially, updates are applied to the disabled plugin directory without executing the new code. If the plugin was previously enabled, the update process maintains the disabled state until the user reviews the changes and re-enables the plugin.

Security Safeguards in PluginRegistry.qml

The shell/services/PluginRegistry.qml file implements multiple defense layers beyond the disabled-by-default policy. The registry validates manifest schemas against hardcoded rules, rejecting plugins with unsupported schema versions or missing required fields. Path traversal attacks are mitigated by sanitizing entry point paths—any manifest referencing parent directory traversal (e.g., ../Panel.qml) is rejected during the scanning phase. The disabledPlugins[] array manipulation functions (addDisabled and removeDisabled) ensure that plugin state transitions are atomic and logged, preventing race conditions where partially installed plugins might accidentally load.

Practical CLI Workflow Examples

Review the source of a weather plugin before enabling it:


# Clone and quarantine the plugin

omarchy plugin add https://github.com/acme/omarchy-weather.git

# Review the diff output, then manually inspect files

cat ~/.config/omarchy/plugins/acme.weather/manifest.json
cat ~/.config/omarchy/plugins/acme.weather/Panel.qml

# Enable after verification

omarchy plugin enable acme.weather

For automated deployments in CI pipelines, maintain audit trails while skipping interactive prompts:


# Non-interactive installation with logged diff

omarchy plugin add https://github.com/acme/omarchy-weather.git --enable --yes

# Update with diff review in logs

omarchy plugin update acme.weather

The --yes flag bypasses the confirmation prompt but preserves the git diff in the shell logs, allowing security teams to retroactively audit what code was approved for execution.

Summary

  • Disabled by default: All third-party plugins are added to disabledPlugins[] in shell.json and remain inert until explicitly enabled.
  • Mandatory diff review: The CLI displays git diff output for every installation and update, with logs preserved in non-interactive mode.
  • Schema validation: PluginRegistry.qml rejects unsafe manifests, path traversal attempts, and malformed entry points before they reach the runtime.
  • Explicit activation: The setEnabled method in PluginRegistry.qml (lines 49-66) controls the transition from quarantine to execution, requiring deliberate user action.
  • Atomic updates: The omarchy plugin update command applies Git fast-forwards without executing code, maintaining the disabled state until re-reviewed.

Frequently Asked Questions

What prevents a third-party plugin from executing immediately after installation?

The addDisabled function in PluginRegistry.qml immediately adds the plugin ID to the disabledPlugins[] array in shell.json during the omarchy plugin add command. The shell's QML engine only loads plugins marked as enabled, so the code remains on disk but is never parsed or executed by the omarchy-shell process, regardless of how many times the shell restarts.

How does Omarchy's manifest validation protect against unsafe code?

The registry rejects manifests containing directory traversal patterns like ../Panel.qml and validates all JSON against a strict schema that enforces safe entry points and required metadata fields. As shown in the test fixtures around lines 134-143, the registry stamps third-party plugins with __isFirstParty: false and applies additional scrutiny to their declared file paths, preventing plugins from escaping their installation directories.

Can organizations automate plugin deployment while maintaining security audits?

Yes, by using the --yes flag with omarchy plugin add or omarchy plugin update, scripts and AI agents can automate the workflow while preserving the git diff in the system logs. The --enable flag can combine installation and activation, but the diff is always generated and logged, creating an immutable audit trail that security teams can review without blocking automation pipelines.

Which source files should reviewers examine before enabling a plugin?

Reviewers should inspect the manifest.json for unsafe entry points and schema compliance, the main QML files (typically Panel.qml or index.qml) for malicious JavaScript or network calls, and any bundled shell scripts or binary dependencies. All these files reside in ~/.config/omarchy/plugins/<plugin-id>/ and are readable before the plugin enters the enabled state managed by PluginRegistry.setEnabled.

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 →