QOpen is a personal resource launcher for Omarchy. It puts projects, files, documentation, web tools, terminal applications, commands and SSH destinations behind one searchable, keyboard-first interface.
Unlike an application launcher, QOpen is intentionally curated. A new catalog starts with a few generic examples; every resource can then be kept, edited, regrouped or removed by you.
中文简介:QOpen 是 Omarchy 上的个人统一资源启动层。它不是应用索引, 而是把项目目录、文件、常用文档、前端生态网站、TUI、命令和 SSH 目标集中到 一个支持搜索、分组、收藏与原生编辑的界面中。
Current release: 2.5.1
Documentation: 简体中文 · Development record
- Native Omarchy Shell and Quickshell interface using live theme tokens.
- Search across name, description, stable id, type, group, target and command.
- Collections with counts, recommended ordering and a dedicated favorites view.
- A small first-run catalog with useful examples across common resource types.
- Six resource types: web, project, file, TUI, command and SSH.
- Single-page add/edit form with type-aware fields and inline validation.
- Built-in file and directory browser that does not use GTK/GVFS file dialogs.
- Normal keyboard paste plus an explicit clipboard button for path fields.
- Automatic name, id, default group and icon inference where appropriate.
- Inline favorite, copy-target, edit and confirmed remove actions.
- Descriptor-anchored JSON writes with directory locking and a last-known-good backup.
- Bounded backend responses and real process deadlines before data reaches QML.
- Validated backup recovery and explicit private-permission repair commands.
- Lossless editing of command arguments containing spaces or quotes.
- Optional bar widget: left-click opens all resources; right-click opens favorites.
- Standalone CLI for launching, inspection, CRUD and diagnostics.
Omarchy already launches installed desktop applications and shell commands well. QOpen covers the layer that application indexes do not model cleanly:
- the project directory you open every day;
- a configuration file that belongs in a terminal editor;
- a carefully selected framework or library reference;
- a TUI with a memorable display name;
- a safe, explicit command invocation;
- an SSH destination grouped with the rest of an environment.
The catalog remains small, portable and understandable. QOpen never crawls your home directory. It creates starter examples only when the catalog is missing and never inserts them into an existing catalog.
QOpen complements the stock Omarchy Menu; it does not replace it. The two interfaces have deliberately different ownership:
| Concern | Omarchy Menu | QOpen |
|---|---|---|
| Primary role | System control and application management | Curated personal resource access |
| Typical content | Apps, setup, install, remove, update, style and system actions | Projects, files, selected documentation, web tools, TUI commands and SSH targets |
| Data source | Omarchy defaults, application providers and menu extensions | ~/.config/qopen/config.json |
| Organization | System-defined menus and routes | User-defined groups, descriptions and favorites |
| Best entry point | Stock shortcut or Omarchy bar button | Super+Alt+O, optional bar button or Omarchy Menu submenu |
The integration does not override stock identifiers. Omarchy Menu uses plugin
id omarchy.menu and layer namespace omarchy-menu; QOpen uses
qopen.launcher and qopen-launcher. Its menu-extension ids are namespaced as
custom-qopen.*. The recommended QOpen shortcut did not collide with the stock
menu binding on the tested Omarchy 4.0.1 setup, but local bindings should still
be checked before installation.
Keep system-wide operations such as application discovery, package installation, updates, appearance and power actions in Omarchy Menu. Keep manually selected projects, files, references and environment targets in QOpen. Mirroring all of Apps, Install, Update or System inside QOpen would create unnecessary duplication.
The QOpen submenu inside Omarchy Menu is an optional bridge, and its bar widget
is also optional. Both menus are full-screen overlay surfaces with exclusive
keyboard focus. Launching QOpen from an Omarchy Menu action is safe because the
stock menu closes before running the action. QOpen also asks Omarchy Shell to
hide omarchy.menu whenever it opens, so invoking its separate shortcut while
the stock menu is visible does not leave two exclusive-focus overlays mounted.
- Omarchy with the current Omarchy Shell plugin commands.
- Quickshell as provided by Omarchy.
- Python 3.10 or newer.
- A Nerd Font for the supplied icons.
wl-clipboard(wl-pasteandwl-copy) for clipboard actions.
QOpen uses Omarchy launch helpers when available and checks the complete local environment with:
~/.config/omarchy/plugins/qopen.launcher/bin/qopen --doctorThe 2.5.1 release was developed and verified on Omarchy 4.0.1, Quickshell 0.3.1 and Qt 6.11.2. These are tested versions, not strict pins.
Install directly from GitHub:
omarchy plugin add https://github.com/CoderLambert/qopen-omarchy-plugin.git --enableReview the repository before enabling it: Omarchy Shell plugins execute inside the long-running shell process and are not sandboxed.
For a non-interactive install after review:
omarchy plugin add https://github.com/CoderLambert/qopen-omarchy-plugin.git --enable --yesThe plugin id is qopen.launcher. If you installed without --enable, enable
the optional bar widget later:
omarchy plugin enable qopen.launcher --section leftAdd the following entries to
~/.config/omarchy/extensions/omarchy-menu.jsonc inside the root object:
The Omarchy menu extension file hot-reloads after saving.
Add this binding to ~/.config/hypr/bindings.lua:
o.bind(
"SUPER + ALT + O",
"QOpen resource search",
"omarchy-shell shell toggle qopen.launcher '{}'"
)Then validate Hyprland:
hyprctl reload
hyprctl configerrorsOpen QOpen from the shortcut, menu, bar widget or shell command:
omarchy-shell shell toggle qopen.launcher '{}'Other useful routes:
# Favorites
omarchy-shell shell toggle qopen.launcher '{"favorites":true}'
# A specific collection
omarchy-shell shell toggle qopen.launcher '{"group":"projects"}'
# Open the add form
omarchy-shell shell toggle qopen.launcher '{"action":"add"}'
# Add a project and open its browser immediately
omarchy-shell shell toggle qopen.launcher \
'{"action":"add","type":"project","browse":true}'
# Open the editor for a specific resource
omarchy-shell shell toggle qopen.launcher \
'{"action":"edit","item":"react"}'Route payloads only select the initial UI state. They do not bypass editor validation or write the catalog directly.
The example shows a react search with curated collections on the left and
keyboard-friendly resource actions on the right. The screenshot is cropped to
the QOpen panel so it does not include the surrounding desktop.
Type directly to search the selected collection. Collections are backed by the
resource group field, and QOpen displays their live item counts. Common groups
include projects, frameworks, ui, testing, tools and docs.
- Press
Ctrl+Nor use+ Add. - Choose a resource type.
- Fill in the name, id, group and type-specific target.
- For file/project resources, paste a path or use the embedded browser.
- Use Check to validate the target, then Save.
Resource type is fixed while editing so type-specific fields cannot be silently lost. When a file or project is selected from the path browser, QOpen can infer the name and id from the selected path; the values remain editable before save.
| Key | Action |
|---|---|
| Type or paste | Search the selected collection |
| Up / Down | Move the resource cursor |
| Enter | Open the selected resource |
| Escape | Clear search, close editor, then close QOpen |
| Ctrl+N | Add a resource |
| Ctrl+E | Edit the selected resource |
| Ctrl+D | Remove the selected resource after confirmation |
| Ctrl+R | Reload the catalog |
| Ctrl+Enter | Save while editing |
| Key | Action |
|---|---|
| Up / Down | Select an entry |
| Enter | Open a directory or choose a file |
| Alt+Up | Open the parent directory |
| Ctrl+L | Focus the path field |
| Ctrl+H | Toggle hidden entries |
| Escape | Return to the resource form |
Project mode lists directories only and chooses the current directory with the footer button. File mode lists directories and regular files; double-clicking a file chooses it immediately.
| Type | Required value | Launch behavior |
|---|---|---|
web |
HTTP(S) target | Omarchy web app or the default browser |
project |
Directory path | Opens a terminal in that directory |
file |
File path | Opens the configured terminal editor |
tui |
Argument array | Opens through the Omarchy TUI helper |
command |
Argument array | Runs detached or in a terminal |
ssh |
Host or user@host |
Opens ssh in a terminal |
Paths may use ~, environment variables or absolute paths. Expansion occurs in
the Python backend, not through shell interpolation.
A useful catalog groups related resources together, for example React rich-text editors, motion libraries, icon systems, TanStack tools, frameworks and testing references. QOpen ships recommended ordering for its known frontend-oriented groups while still allowing arbitrary group ids.
The default catalog is stored at:
~/.config/qopen/config.json
When the catalog does not exist, the first QOpen launch creates six ordinary, editable resources:
| Resource | Type | Purpose |
|---|---|---|
| Omarchy | web |
Open the official Omarchy website and documentation |
| GitHub | web |
Open repositories, issues, pull requests and releases |
| Home Directory | project |
Open a terminal in ~ |
| Omarchy Shell Config | file |
Edit ~/.config/omarchy/shell.json |
| btop | tui |
Monitor CPU, memory, disks and processes |
| Fastfetch | command |
Show a concise system information summary |
Existing catalogs are never seeded or modified. The starter resources behave like any other item and can be edited or removed. QOpen does not create an SSH example because no host is both useful and valid for every user.
Example:
{
"version": 1,
"defaults": {
"editor": "nvim",
"webMode": "app"
},
"items": [
{
"id": "react",
"name": "React Documentation",
"type": "web",
"group": "frameworks",
"icon": "",
"description": "Official React guides and API reference",
"target": "https://react.dev/learn",
"mode": "browser",
"favorite": true
},
{
"id": "my-app",
"name": "My App",
"type": "project",
"group": "projects",
"icon": "",
"target": "~/Code/my-app"
},
{
"id": "lazygit",
"name": "Lazygit",
"type": "tui",
"group": "tools",
"command": ["lazygit"]
}
]
}Important guarantees:
- ids contain lowercase letters, numbers,
_or-and must be unique; - each mutation validates the complete catalog;
- every state-directory component is opened without following symlinks;
- configuration and backup access rejects symlinks, hard links and non-regular files;
- writes use a lock on the trusted state-directory descriptor and same-directory atomic replacement;
- the previous catalog is retained as
config.json.bak; - new default state directories are created with
0700, and new or rewritten state files use0600; existing state is accepted only when it is not group- or world-writable, while--doctorreports looser private modes andfix-permissionsrepairs the default state directory and files to0700/0600; - catalog reads, API responses, helper output and directory scans are bounded;
- QML never opens or writes the catalog directly and backend processes have deadlines;
- personal resource data is not automatically synchronized to this GitHub repository.
Set QOPEN_CONFIG to use a different catalog with the CLI:
QOPEN_CONFIG=~/Documents/qopen-work/config.json \
~/.config/omarchy/plugins/qopen.launcher/bin/qopen --listUse a dedicated directory that is owned by your account and is not group- or world-writable. QOpen validates custom state directories but never changes their directory permissions.
The backend is installed with the plugin:
QOPEN=~/.config/omarchy/plugins/qopen.launcher/bin/qopen
$QOPEN # Interactive resource picker
$QOPEN --groups # Browse by collection
$QOPEN --favorites # Browse favorites
$QOPEN --list # Print catalog items
$QOPEN <id> # Launch one item
$QOPEN add # Guided add flow
$QOPEN edit [id] # Guided edit flow
$QOPEN remove [id] # Confirmed removal
$QOPEN favorite <id> toggle # Toggle favorite state
$QOPEN recover # Validate and restore config.json.bak
$QOPEN fix-permissions # Secure the default state directory and files
$QOPEN --doctor # Validate dependencies and every item
$QOPEN --versionNon-interactive example:
$QOPEN add project \
--id qopen \
--name "QOpen Plugin" \
--group projects \
--target ~/Code/qopen-omarchy-plugin \
--favoriteThe api subcommands are a machine interface used by QML. They emit compact
JSON and should not be treated as a long-term public integration API yet.
Omarchy menu / shortcut / bar widget
|
v
QOpen.qml
|
+---------+----------+
| |
ResourceEditor.qml PathPicker.qml
| |
+---------+----------+
| bounded argv / one-line JSON
v
BoundedProcess.qml
|
v
bin/qopen
|
descriptor-anchored validation
+ directory FD lock
|
v
~/.config/qopen/config.json
QML owns presentation, focus and interaction. Python owns directory listing, normalization, validation, persistence and process dispatch.
The embedded path browser deliberately avoids Qt FileDialog, GTK, GIO and
GVFS. QOpen runs inside the shared Omarchy Shell process; keeping native file
dialog integration out of that process prevents a picker failure from
terminating the entire desktop shell. Version 2.2 briefly used native dialogs;
2.3 removed them after reproducible Quickshell crashes. The evidence and release
validation are documented in DEVELOPMENT.md.
User-selected resource browsing intentionally follows symlinks so ordinary
project and file workflows behave like the filesystem the user selected. That
browser path is not used for QOpen persistence: catalog, backup, lock and
replacement operations stay inside the separately validated SecureStateStore
trust boundary.
Commands are passed as argument arrays. Resource values are never concatenated into a shell command by QML.
QML does not use FileView for the catalog and does not retain complete process
streams with StdioCollector. The Python producer validates and caps every API
response before writing it; QML then applies a secondary protocol-size check.
Bounded helper processes run in their own process groups and have real deadlines
with TERM-to-KILL escalation. Catalog, backup and recovery operations remain
anchored to one trusted directory descriptor for their complete lifecycle.
Direct raw editing through $QOPEN --edit is intentionally disabled because an
external editor cannot participate in QOpen's lock, validation, backup and atomic
replacement protocol. Use the native editor or $QOPEN edit [id] instead.
Update a Git-installed copy:
omarchy plugin update qopen.launcher --yesRemove the plugin:
omarchy plugin remove qopen.launcher --yesRemoval does not delete ~/.config/qopen/config.json, so the personal catalog
can be re-used after reinstalling.
omarchy plugin validate ~/.config/omarchy/plugins/qopen.launcher
omarchy-shell shell rescanPlugins
omarchy restart shellRun the doctor and inspect the failed item:
~/.config/omarchy/plugins/qopen.launcher/bin/qopen --doctorFor files and projects, confirm that the expanded path exists. For TUI and
command resources, confirm that the first executable is available on PATH.
QOpen refuses partial or malformed writes. Inspect:
~/.config/qopen/config.json
~/.config/qopen/config.json.bak
The backup is the catalog state immediately before the last successful mutation. Restore it only after validation:
~/.config/omarchy/plugins/qopen.launcher/bin/qopen recoverBefore replacing the catalog, QOpen preserves the current invalid file as a
private timestamped config.json.invalid-* snapshot. If --doctor reports
insecure default-state permissions, repair them explicitly:
~/.config/omarchy/plugins/qopen.launcher/bin/qopen fix-permissionsOmarchy normally hot-reloads files below ~/.config/omarchy/plugins. For a
multi-file change, restart the shared shell once after copying all files:
omarchy restart shellThis avoids repeatedly rebuilding the plugin graph while files are in a transitional state.
See DEVELOPMENT.md for architecture decisions, release history, the 2.3 native file-dialog incident, validation procedures and the maintainer workflow. User-facing changes are recorded in CHANGELOG.md.
Run the portable backend test suite with:
python -m unittest discover -s tests -vMIT © 2026 CoderLambert
