Skip to content

Repository files navigation

Project launcher — Omarchy plugin

⚠️ This plugin is entirely vibe-coded. Every line of it — the QML, the Bash, the JavaScript, the tests and this README — was written by an AI coding agent (Claude Code) from prompts, not hand-authored. It is tested and it works, but read the code before you enable it: Omarchy plugins run unsandboxed inside omarchy-shell.

A project menu for the Omarchy shell (Quickshell). A keybinding opens an overlay listing the projects in your working folders; pick one and it opens (or re-attaches) a per-project tmux session built from the layout you configure. By default:

  • window gitlazygit in the project
  • window edit → your editor (nvim by default) in the project
  • window code → an AI pane (default claude --dangerously-skip-permissions) on top taking 75% of the height, and a companion pane (cliamp) below. The separator is horizontal (stacked panes).

For each project the menu shows an ecosystem icon, git status (branch · ahead/behind · dirty files) and a when a tmux session is already live (picking it just re-attaches). Order is: favourites → live sessions → frecency (most used / most recent first). Optionally a preview pane on the right with git log + the highlighted project's README.

In-menu shortcuts

Key Action
/ , PgUp / PgDn Move the selection
Enter Open / re-attach the session
type Filter (fuzzy)
Tab / Shift+Tab Switch the AI preset (when aiPresets is set)
Ctrl+P Toggle the preview pane
Ctrl+K Kill the selected project's tmux session
Ctrl+R Kill and re-open the session
Ctrl+D Toggle favourite
Esc Clear the filter, or close

If you type a name that matches no project, a + Create «…» row appears that creates <projectRoots[0]>/<name> (mkdir + git init) and opens the session.

preview

Requirements

  • Omarchy 4 (Quattro) with the omarchy-shell plugin system.
  • tmux, lazygit on PATH.
  • Whatever AI command you configure (claude by default).
  • Optional: cliamp (or whichever companion you pick), jq (for frecency and for the script to read the config), a Nerd Font (Omarchy already ships JetBrainsMono Nerd Font).

Installation

omarchy plugin add https://github.com/Cache21/omarchy-project-launcher --enable

It is cloned to ~/.config/omarchy/plugins/io.github.cache21.project-launcher/ and enabled. Then add the keybinding (a plugin can't touch your Hyprland config). Either:

A. Automatic (adds SUPER + ALT + P to ~/.config/hypr/bindings.lua):

~/.config/omarchy/plugins/io.github.cache21.project-launcher/install.sh

B. Manual — paste this into ~/.config/hypr/bindings.lua:

o.bind("SUPER + ALT + P", "Project launcher",
  "omarchy-shell shell toggle io.github.cache21.project-launcher '{}'")

then reload with hyprctl reload.

Configuration

Read from ~/.config/omarchy-project-launcher/config.json (created on first run from config.default.json). Hot-reloaded on save. See config.example.jsonc for the commented version.

Key Default Description
projectRoots ["~/Projects"] Root folders to scan for projects. It's an array: add as many as you want, e.g. ["~/Projects", "~/eclipse-workspace", "~/work"]. Supports ~ and $VARS.
scanDepth 1 Subdirectory depth per root (2 surfaces sub-apps like mono/backend).
onlyGitRepos false List only folders that are git repos.
ignore ["node_modules", ".git", ".*"] Name globs to exclude.
aiCommand "claude --dangerously-skip-permissions" AI command. Substitutes {{ai}} in the layout.
companionCommand "cliamp" Companion command. Substitutes {{companion}}.
editorCommand "nvim" Editor. Substitutes {{editor}}. "" removes the edit window.
aiPaneHeightPercent 75 Substitutes {{companionSize}} with $(100-this)% (10–90).
startWindow "code" Window focused on attach (any layout name).
reuseExistingSession true If the session already exists, re-attach instead of creating another.
terminalAppId "dev-session" Terminal --app-id (for Hyprland window rules). See note below.
layout see below Windows/panes of the tmux session.
aiPresets {} { name: command } for the Tab selector in the menu. {} = hidden.
showPreview true Preview pane on the right (Ctrl+P toggles it; auto-hidden on narrow screens).
createGitInit true The + Create action runs git init in the new folder.
remainOnExit false If a pane's command dies, keep the pane showing its output.
favorites [] Projects pinned to the top (name or path). Also Ctrl+D in the menu.
colorIcons true Colour each project's icon by language (devicon palette).

Note on terminalAppId: it is passed as --app-id to xdg-terminal-exec. foot, ghostty and alacritty honour it (Wayland app-id). kitty ignores it and keeps its class = kitty; with kitty, match on title in the window rule, or change your default terminal in ~/.config/xdg-terminals.list.

Session layout

layout is a list of windows. Each has name and panes: the first pane creates the window; the rest split it ("v" = horizontal / stacked separator, "h" = vertical / side by side) with an optional size ("25%" or a line/column count). Placeholders: {{ai}}, {{editor}}, {{companion}}, {{companionSize}}. A pane with an empty command is dropped; a window with no panes is dropped (so editorCommand: "" removes the edit window).

"layout": [
  { "name": "git",  "panes": [ { "command": "lazygit" } ] },
  { "name": "edit", "panes": [ { "command": "{{editor}}" } ] },
  { "name": "code", "panes": [
      { "command": "{{ai}}" },
      { "command": "{{companion}}", "split": "v", "size": "{{companionSize}}" }
  ] },
  { "name": "run",  "panes": [ { "command": "npm run dev" } ] }
]

Per-project override

A .project-session.json (plain JSON) at a project's root overrides any global config key for that project (deep object merge; arrays such as layout are replaced wholesale). E.g. ~/Projects/my-app/.project-session.json:

{ "aiPaneHeightPercent": 60,
  "layout": [
    { "name": "git",  "panes": [ { "command": "lazygit" } ] },
    { "name": "code", "panes": [ { "command": "{{ai}}" }, { "command": "{{companion}}", "split": "v", "size": "{{companionSize}}" } ] },
    { "name": "web",  "panes": [ { "command": "npm run dev" } ] },
    { "name": "db",   "panes": [ { "command": "npx prisma studio" } ] } ] }

AI presets

"aiPresets": {
  "claude": "claude --dangerously-skip-permissions",
  "codex":  "codex",
  "aider":  "aider",
  "shell":  ""
}

In the menu the header shows ▸ <preset>; Tab / Shift+Tab switches, Enter launches with it, and the last choice is remembered (state.json).

Standalone use (fallback)

The script does all the tmux work and runs on its own:

project-session ~/Projects/my-project    # build/attach the session
project-session create my-app            # mkdir + git init + open
project-session kill my-project          # kill the tmux session
project-session preview ~/Projects/x     # git log + README (used by the preview pane)
project-session --pick                   # picker (omarchy-menu-select / fzf) + open
project-session list                     # TSV of projects (consumed by the QML menu)
project-session doctor                   # deps + config + resolved layout

It lives at ~/.config/omarchy/plugins/io.github.cache21.project-launcher/bin/project-session (symlink it into a PATH dir if you like).

The script is the only thing that writes state, under ~/.local/state/omarchy-project-launcher/: frecency.json, favorites.json, state.json (last AI preset).

Development

node tests/model.test.js                          # pure logic in Model.js
qmllint -I "$OMARCHY_PATH/shell" Menu.qml
omarchy plugin validate .
omarchy-shell shell rescanPlugins                 # reload after changes

How it works

  • manifest.json — plugin kind: ["menu"], entry point Menu.qml.
  • Menu.qml — layer-shell overlay (PanelWindow + WlrLayershell): list + search + preview + preset selector. Scans via bin/project-session list, queries tmux list-sessions and git status, orders with Model.sortEntries. Only reads the state files; shells out to the script's subcommands for everything else.
  • Model.js — pure, testable logic (parsing, ecosystem detection, git, frecency, fuzzy, resolveLayout, presets, the "create" row). Imported from QML and runs under node (tests/model.test.js).
  • bin/project-session — resolves the config (+ per-project override), builds the layout with jq, creates the tmux session and opens it with omarchy-launch-tui (or $TMUXswitch-client, or $TERMINAL). The only writer of state.

License

MIT — see LICENSE. Not affiliated with the Claude, cliamp, lazygit or tmux projects.

About

Omarchy (Quickshell) plugin: a project menu that opens a per-project tmux session — lazygit + a configurable layout with an AI pane and companion — bound to SUPER+ALT+P. Colored language icons, git status, preview, AI presets, favourites, multi-root.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages