Hark is a Wayland/Hyprland AI command palette built around a Quickshell UI and a Go daemon.
A conversation with an LLM response
A screenshot attached to the prompt
Tokyo Night |
Catppuccin Latte |
Solitude |
Nord |
- streaming through OpenAI, OpenRouter, or xAI, selectable per model
- automatic web search with clickable citations and source lists
- Markdown-formatted response rendering
- copy latest answer
- initial paste latest answer
- active Hyprland window capture for paste-back focus restore
- region screenshot attachments for image+text prompts
- conversation-level SQLite history for completed AI responses
- recent conversation restore and delete in the overlay
- optional history saving, configurable retention, and screenshot cleanup
- model selector with persisted selected model
Paste-back requires wtype:
omarchy pkg add wtypeCheck local Wayland helper dependencies:
go run ./cmd/harkctl doctor
go run ./cmd/harkctl doctor --jsonHark is an Omarchy 4 plugin with service, overlay, and bar-widget entry
points. Enabling it adds a Hark button to the center section of the Omarchy
bar; click it to toggle the command palette. Install it from the generated
plugin repository, which carries the QML sources together with static harkd
and harkctl binaries, so installation needs no Go toolchain or first-run
download:
omarchy plugin add https://github.com/konradk/hark-plugin.git --enable
omarchy-shell shell summon harkkonradk/hark-plugin is published
from this repository on every release and is not edited by hand. omarchy plugin add clones its default branch and omarchy plugin update
fast-forwards it, so each commit there is one complete, self-consistent
release. Report issues and read the sources here instead.
Use the source checkout for local plugin development:
./scripts/build-plugin-runtime.sh
ln -sfn "$PWD" ~/.config/omarchy/plugins/hark
omarchy restart shell
omarchy plugin enable harkThe plugin starts its bundled daemon when necessary. If a compatible harkd
is already running through systemd, the plugin attaches to it and does not
stop it when the shell exits. Disable or remove the plugin with the normal
omarchy plugin commands; history and configuration remain in their XDG data
directories.
Build and install Hark for the current user:
./scripts/install.shThe installer writes:
~/.local/bin/harkd
~/.local/bin/harkctl
~/.config/quickshell/hark/shell.qml
~/.config/quickshell/hark/HarkShell.qml
~/.config/quickshell/hark/components/
~/.config/quickshell/hark/dev/
~/.config/quickshell/hark/js/
~/.config/systemd/user/harkd.service
~/.config/hark/hyprland.conf (managed Hark shortcut blocks)
~/.config/hypr/hyprland.conf (one Hark source line)
~/.config/hark/env
A source checkout requires Go 1.25.13 and runs the test suite before building.
A release archive contains static binaries and installs without Go. Files are
replaced atomically. The installer restarts an already-running daemon and
Quickshell instance; it does not enable a service that was previously
disabled. Set HARK_SKIP_TESTS=1 or HARK_NO_RESTART=1 only for controlled
automation.
Quickshell is required. Clipboard, screenshot, and paste-back features also
use wl-clipboard, grim, slurp, and wtype; hyprctl is supplied by
Hyprland. Run harkctl doctor --json to inspect the current system.
Store your OpenAI, OpenRouter, and/or xAI API key in the desktop Secret Service keyring:
harkctl secret set openai
harkctl secret status openai
harkctl secret set openrouter
harkctl secret status openrouter
harkctl secret set xai
harkctl secret status xaiYou can also read from stdin for scripts:
printf '%s' "$OPENAI_API_KEY" | harkctl secret set --stdin openai
printf '%s' "$OPENROUTER_API_KEY" | harkctl secret set --stdin openrouter
printf '%s' "$XAI_API_KEY" | harkctl secret set --stdin xaiThe keyring always wins. Only when it holds no key — or when no Secret Service
daemon is running at all, which is common on a minimal Wayland session — does
Hark falls back to OPENAI_API_KEY, OPENROUTER_API_KEY, or XAI_API_KEY. Put them in
~/.config/hark/env (mode 0600, read by the systemd unit); exporting them from
your shell profile does not reach the daemon, because systemd starts it outside
your interactive shell. Keys sourced this way are shown as
Set by environment variable in settings and cannot be deleted from the UI.
The native xAI provider uses the Responses API with streaming, image input,
automatic web search, and clickable citations. The default catalog includes
grok-4.6 and grok-4.5; Grok 4.6 additionally supports xhigh reasoning.
Then start the daemon:
systemctl --user enable --now harkd.service
harkctl statusThe installer adds Super+A to open Hark and Super+Alt+A to capture the
focused window and attach it to Hark when both combinations are available.
Change or disable either shortcut from Hark Settings (Ctrl+,), or manage
them from the CLI:
harkctl shortcut get
harkctl shortcut set "SUPER + CTRL + A"
harkctl shortcut get --action screenshot
harkctl shortcut set --action screenshot "SUPER + ALT + A"
harkctl shortcut removeThese commands use standard Hyprland configuration by default. To manage an
Omarchy plugin shortcut explicitly, pass --integration omarchy; the generated
command summons the plugin through omarchy-shell rather than starting a
second Quickshell process.
Go 1.25.13 or newer is required to build the daemon and CLI. The version is
pinned in mise.toml; the Go toolchain directive provides the same version
when automatic toolchain downloads are enabled.
go mod tidy
go test ./...
go build ./cmd/harkd
go build ./cmd/harkctlBuild the static runtime used by the plugin and run its isolated lifecycle test:
./scripts/build-plugin-runtime.sh
./scripts/test-plugin.sh
python3 scripts/test-plugin-manifest.py
omarchy plugin validate .Both binaries expose embedded build metadata:
harkctl version
harkd -versionStart the daemon:
go run ./cmd/harkdCheck daemon status:
go run ./cmd/harkctl statusAsk a text-only question:
printf '%s' '{"prompt":"Say hello in one sentence"}' | go run ./cmd/harkctl ask --stdinContinue with prior context from the CLI. Prompts and prior turns are read from
stdin so they never appear in ps output:
printf '%s' '{
"prompt": "What is my codeword?",
"messages": [
{"role": "user", "content": "My codeword is amber."},
{"role": "assistant", "content": "Noted."}
]
}' | go run ./cmd/harkctl ask --stdin --conversation-id example-chatReuse the same --conversation-id for later turns that should share one entry
in Recent.
Ask with an image attachment:
printf '%s' '{"prompt":"What is shown here?"}' | go run ./cmd/harkctl ask --stdin --image "${XDG_CACHE_HOME:-$HOME/.cache}/hark/screenshots/window-....png"Use a PNG path returned by screenshot-region --json or
screenshot-active-window --json. Attachments are limited to four
Hark-managed screenshots, 20 MiB per file and 40 MiB in total. The daemon
validates file signatures and does not follow symlinks.
For UI integrations, stream newline-delimited JSON events:
printf '%s' '{"prompt":"Say hello in one sentence"}' | go run ./cmd/harkctl ask --stdin --jsonCopy the latest daemon-tracked answer:
go run ./cmd/harkctl copy-latest --conversation-id example-chatCopy explicit text through the daemon:
printf '%s' 'text to copy' | go run ./cmd/harkctl copy-text --stdinPaste the latest daemon-tracked answer into the focused app:
go run ./cmd/harkctl paste-latest --conversation-id example-chat
printf '%s' 'explicit text' | go run ./cmd/harkctl paste-text --state-id example-ui --stdinInspect or remember the current Hyprland active window:
go run ./cmd/harkctl active-window
go run ./cmd/harkctl remember-active-window --state-id example-uiUse the same state ID with remember-active-window and paste-text when
focus should be restored to the remembered window. Conversation-scoped
copy-latest and paste-latest require the ID used by ask.
Capture a screenshot region:
go run ./cmd/harkctl screenshot-region
go run ./cmd/harkctl screenshot-region --jsonIn the Quickshell overlay, use the Screenshot button or Ctrl+Shift+C while
the prompt is focused.
Inspect history:
go run ./cmd/harkctl history list --limit 20
go run ./cmd/harkctl history list --limit 20 --json
go run ./cmd/harkctl history get 1
go run ./cmd/harkctl history get --json 1
go run ./cmd/harkctl history delete 1
go run ./cmd/harkctl history clear --yesThe Quickshell overlay shows the ten most recent conversations. Click one to restore its prompt and answer into the panel.
Persisted settings:
go run ./cmd/harkctl setting get selected_model
go run ./cmd/harkctl setting set selected_model gpt-5.6-sol
go run ./cmd/harkctl setting set show_recent_chats false
go run ./cmd/harkctl setting set save_history false
go run ./cmd/harkctl setting set history_retention_days 30
go run ./cmd/harkctl reasoning-modes --model gpt-5.6-sol --jsonshow_recent_chats only controls visibility. save_history independently
controls whether completed answers are persisted. A retention value of 0
keeps history until it is deleted manually; positive values remove complete
inactive conversations after that many days. These privacy controls and a
confirmed “Clear all” action are also available in Hark Settings.
Global shortcut:
go run ./cmd/harkctl shortcut get
go run ./cmd/harkctl shortcut set --shell "$PWD/quickshell/shell.qml" "SUPER + A"
go run ./cmd/harkctl shortcut get --action screenshot
go run ./cmd/harkctl shortcut set --action screenshot --shell "$PWD/quickshell/shell.qml" "SUPER + ALT + A"
go run ./cmd/harkctl shortcut removeThe shortcut command updates only Hark's marked block in
~/.config/hark/hyprland.conf, refuses occupied bindings, and validates the
configuration after reloading Hyprland. The standalone installer adds the
corresponding source line to ~/.config/hypr/hyprland.conf. For a plugin
shortcut, use --integration omarchy; that mode manages Hark's marked block in
~/.config/hypr/bindings.lua and invokes omarchy-shell.
Secrets:
go run ./cmd/harkctl secret status openai
go run ./cmd/harkctl secret set openai
go run ./cmd/harkctl secret delete openai
go run ./cmd/harkctl secret status openrouter
go run ./cmd/harkctl secret set openrouter
go run ./cmd/harkctl secret delete openrouter
go run ./cmd/harkctl secret status xai
go run ./cmd/harkctl secret set xai
go run ./cmd/harkctl secret delete xaiSecrets are stored through the Linux Secret Service keyring when available.
OPENAI_API_KEY, OPENROUTER_API_KEY, and XAI_API_KEY remain supported as environment
fallbacks.
History is stored at:
~/.local/share/hark/history.db
Useful overlay keys:
Enter ask
Ctrl+Enter paste latest answer
Ctrl+Shift+C capture screenshot region
Ctrl+L focus prompt and select text
Ctrl+J/K move through recent history suggestions
Ctrl+M open model picker
Ctrl+, toggle settings
Ctrl+N back to recent conversations (Ctrl+Backspace also works)
Ctrl+R refresh recent history
Escape close, or stop an active request
The default config path is:
~/.config/hark/config.lua
Example:
return {
ui = {
theme = "system",
colors = {
panel = "#17191f",
panel_border = "#3a3f4b",
surface = "#101218",
surface_elevated = "#10141c",
surface_hover = "#202632",
surface_active = "#263142",
input = "#171d27",
button = "#171d27",
button_disabled = "#141821",
button_hover = "#222a36",
button_down = "#2a3240",
primary = "#a7c7ff",
primary_hover = "#9fd1ff",
primary_down = "#7fb8e8",
primary_text = "#071116",
text = "#d7dce5",
text_strong = "#f3f4f6",
text_muted = "#7f8794",
text_disabled = "#596170",
assistant = "#8fbce8",
error = "#d66a6a",
error_text = "#ffb3b3",
error_surface = "#24171b",
error_border = "#6f3035",
selection_text = "#111318",
},
},
provider = {
default_model = "gpt-5.6-sol",
default_reasoning_effort = "low",
models = {
{ id = "gpt-5.6-sol", label = "GPT-5.6 Sol", provider = "openai", reasoning_efforts = { "auto", "none", "low", "medium", "high", "xhigh", "max" } },
{ id = "gpt-5.6-terra", label = "GPT-5.6 Terra", provider = "openai", reasoning_efforts = { "auto", "none", "low", "medium", "high", "xhigh", "max" } },
{ id = "gpt-5.6-luna", label = "GPT-5.6 Luna", provider = "openai", reasoning_efforts = { "auto", "none", "low", "medium", "high", "xhigh", "max" } },
{ id = "gpt-5.5", label = "GPT-5.5", provider = "openai", reasoning_efforts = { "auto", "none", "low", "medium", "high", "xhigh" } },
{ id = "gpt-5.4", label = "GPT-5.4", provider = "openai", reasoning_efforts = { "auto", "none", "low", "medium", "high", "xhigh" } },
{ id = "gpt-5.4-mini", label = "GPT-5.4 Mini", provider = "openai", reasoning_efforts = { "auto", "none", "low", "medium", "high", "xhigh" } },
{ id = "gpt-5.4-nano", label = "GPT-5.4 Nano", provider = "openai", reasoning_efforts = { "auto", "none", "low", "medium", "high", "xhigh" } },
{ id = "anthropic/claude-opus-5", label = "Claude Opus 5 (OpenRouter)", provider = "openrouter", reasoning_efforts = { "auto", "none", "low", "medium", "high", "xhigh", "max" } },
{ id = "google/gemini-3.6-flash", label = "Gemini 3.6 Flash (OpenRouter)", provider = "openrouter", reasoning_efforts = { "auto", "minimal", "low", "medium", "high" } },
{ id = "x-ai/grok-4.6", label = "Grok 4.6 (OpenRouter)", provider = "openrouter", reasoning_efforts = { "auto", "low", "medium", "high", "xhigh" } },
{ id = "x-ai/grok-4.5", label = "Grok 4.5 (OpenRouter)", provider = "openrouter", reasoning_efforts = { "auto", "low", "medium", "high" } },
{ id = "grok-4.6", label = "Grok 4.6 (xAI)", provider = "xai", reasoning_efforts = { "auto", "low", "medium", "high", "xhigh" } },
{ id = "grok-4.5", label = "Grok 4.5 (xAI)", provider = "xai", reasoning_efforts = { "auto", "low", "medium", "high" } },
},
},
paste = {
restore_focus = true,
delay_ms = 80,
shortcut = "ctrl_shift_v",
},
}Each model owns its reasoning_efforts capability list. auto is Hark's
provider-default option; the remaining values are sent to the provider API.
When adding a custom model, set this list to the efforts that model accepts.
See CHANGELOG.md for user-visible changes in each release.
Releases are built from annotated or lightweight SemVer tags:
git tag v0.1.0
git push origin v0.1.0MIT.




