Omahub
← All plugins
G

Discord

by GM

Discord in the Omarchy bar: attention badge, call state, volume, window focus, and memory footprint.

Security review

No obvious issues detected

Deterministic scan — not a security guarantee

None
Risk level
None
Analyzed commit
08e0bf8
Scanned
1 month ago

No potentially dangerous behavior detected in the analyzed commit.

Automated analysis only — not a security guarantee.

AI advisory review

Review recommended

Language-model assessment · ~deepseek/deepseek-v4-flash-latest — advisory only

Low
AI risk level
Low
Recommendation
review
Model
~deepseek/deepseek-v4-flash-latest
Analyzed commit
08e0bf8
Reviewed
1 month ago

The deterministic scan found nothing, and most of this plugin is a transparent, user-initiated bar widget that only acts on clicks and keybindings. The reason I am not rating it 'none' is rpc.py: it silently falls back to reading ~/.claude/secrets/.env for Discord credentials without the README mentioning it, which is surprising and should be reviewed even though no exfiltration or other malicious behavior is visible.

  • rpc.py reads ~/.claude/secrets/.env (or $OMARCHY_DISCORD_SECRETS) as a credential fallback and parses KEY=value lines from it; this is undocumented in the README and touches an unrelated secrets file.
  • The optional voice bridge stores the Discord client secret and token locally in plaintext JSON with 0600 permissions; this is opt-in and appears carefully handled, but users should be aware the files exist.
How this check works

This review combines the deterministic scan (the rule-based results above) with an independent look at the plugin's code by a language model. The model reads a trimmed sample of the repository's files, the manifest, and the README, then gives a plain-language risk level and a recommendation: install (no notable danger), review (look closer first), or avoid (clearly dangerous).

It runs on the same analyzed commit as the deterministic scan and is strictly advisory — it is not a security guarantee and never blocks a plugin by itself. A human moderator still reviews plugins before they are listed.

AI advisory only — automated analysis, not a security guarantee.

Install
$ omarchy plugin add https://github.com/thisisgm/omarchy-discord --enable
Widgets #bar #quickshell #media

Discord for the Omarchy bar

A bar widget for the Discord desktop app, built the way the first-party Dropbox and Tailscale plugins are built: vector icon, keyboard-navigable panel, and no configuration.

On omarchyplugins.com Latest tag

The panel during a voice call

The mark is drawn as vector geometry, so it takes the theme's foreground at any size and sits at the same ink weight as its neighbours:

The widget in the bar, between the tray and the network icons

While you are in a call the icon grows a dot, and that dot turns the theme's urgent color whenever the call cannot hear you, which is the state above.

What it tells you

Question Answered by How
Is a supported client installed? DesktopEntries the shell's own desktop entry index, matched on StartupWMClass=discord or StartupWMClass=vesktop
Does it want you? Hyprland the window's urgency flag, which Discord raises on a mention or a DM
Where is the window? Hyprland toplevels, with title and workspace
Are you in a call? PipeWire Discord's WebRTC voice streams exist only while connected
How good is the call? Discord RPC VOICE_CONNECTION_STATUS ping, drawn as signal strength (optional tier)
Can the call hear you? PipeWire the capture stream, and whether it is muted
What does it cost? ps resident memory and process count

Nothing polls Discord's servers, and no account, token, or developer application is involved.

Requirements

  • Omarchy Quattro. This is built against its shell plugin contract.
  • Discord from the Arch discord package, or vesktop. Every signal keys off the client's shape: window class discord, desktop entry discord.desktop and a process called Discord, or the same three slots reading vesktop. A Flatpak build, another fork, or Discord run as a web app publishes different values and is not supported. Making those work is a real change with a real test rather than a configuration knob, so the plugin does not pretend otherwise.
  • python3, and only for the optional voice bridge at the bottom of this page. Omarchy already ships it.

Install

omarchy plugin add https://github.com/thisisgm/omarchy-discord.git --enable

Or, from a local checkout:

cp -r omarchy-discord ~/.config/omarchy/plugins/io.github.thisisgm.discord
omarchy-shell shell rescanPlugins
omarchy plugin enable io.github.thisisgm.discord

Replace Discord's own tray icon

Discord registers a tray item of its own, so out of the box you get two Discord icons in the bar. Omarchy already solves this for its bundled plugins, since the tray hides Dropbox's item when the Dropbox widget is loaded, but that list lives in the shell and takes no plugin hook. So hide Discord's item once by hand:

right-click the tray > Manage > untick Discord.

That writes discord_status_icon_1 into the tray's hidden list in ~/.config/omarchy/shell.json, and it stays hidden across restarts. Untick it again if you ever remove this widget.

Using it

The bar icon dims when Discord is not running, turns the theme's urgent color when Discord wants your attention, and grows a dot while you are in a voice call. The dot is urgent-colored whenever the call cannot hear you.

Input Does
Left click open the panel
Middle click raise Discord, or start it
Right click mute the call mic, or refresh when not in a call
Scroll Discord's volume
o / m / d / r raise / mute mic / deafen / refresh
j k, Enter move and activate; h l set volume on the volume row

Keybindings

The panel is not the only way in. Bind these anywhere:

omarchy-shell discord raise    # focus the window, or start Discord
omarchy-shell discord mute     # toggle the call microphone
omarchy-shell discord deafen   # toggle deafen (needs the bridge, below)
omarchy-shell discord hangup   # leave the call (needs the bridge, below)
omarchy-shell discord toggle   # the panel

mute is the interesting one: it works from any workspace without focusing Discord. Without the optional bridge it mutes Discord's microphone at the PipeWire level; with it, it presses Discord's own mute button.

Each verb answers ok, or says why it did nothing: no voice bridge, no microphone to mute, Discord is not installed.

Settings

One, in Setup > Plugins: hide the icon when Discord is not running.

Limits worth knowing

  • Attention needs a window. Hyprland can only flag a window that exists, so an instance closed to the tray reports nothing. The widget shows "Running in the background" and can raise it.
  • Mic control needs an open capture stream. Discord releases the stream when it closes the microphone, and there is nothing to mute at the PipeWire level until it comes back. The row appears when the stream does.
  • Vesktop's call dot rides its capture stream. Vesktop publishes no voice-engine name for its streams, so the capture stream is the call signal. Unlike Discord it keeps that stream under its own mute, so the dot survives muting.
  • Muting here is not Discord's mute button. Discord's own UI will still show you as unmuted while PipeWire feeds it silence.

Both limits go away with the optional bridge below, which drives Discord's own mute instead.

Optional: Discord's own voice controls

Everything above needs no account, token, or setup. Four things cannot be had that way, because nothing outside Discord knows them: which channel you are in, Discord's own mute and deafen, and hanging up.

Those come from Discord's local RPC socket, and Discord gates it. The socket refuses any client id that is not a registered application:

{"code":4000,"message":"Invalid Client ID"}

Client ids are public, so the plugin could ship one, but the rpc scope it needs is approval-gated, and until an app is approved only accounts on its App Testers list may authorize. A shipped client id would therefore work for the author and for nobody else. There is no anonymous route.

So the bridge is opt-in, and the plugin is complete without it. With no credentials rpc.py exits immediately, the panel still knows you are in a call because PipeWire says so, and the voice section quietly offers to set itself up:

The panel with no credentials, offering to set up voice controls

To turn it on, open the panel and use Set up voice controls, which takes the two values inline, no terminal. The same thing from a shell, if you prefer:

python3 ~/.config/omarchy/plugins/io.github.thisisgm.discord/rpc.py --setup

That opens the developer portal, prints the two things to create there, and takes the Client ID and Client Secret, both on the application's OAuth2 page with the secret behind Reset Secret. It then authorizes against your running Discord, so you find out it worked before you leave the terminal. It stores the pair in ~/.config/omarchy-discord/credentials.json and the token in ~/.local/state/omarchy-discord/token.json, both 0600. The panel writes those values over stdin, so a secret never appears in a command line or in ps.

The Public Key on General Information is a different value: it verifies interaction webhook signatures and cannot buy a token. It is 64 hex characters, and --setup rejects it by name if you paste it.

Open the panel afterwards, no restart needed, and it gains the call's name, deafen, mic gain, and a leave-call row, and the mic row starts driving Discord's own mute. --probe re-checks it any time.

If you are not the application's owner, your account has to be on its App Testers list; the owner is already covered.

Uninstall

omarchy plugin remove io.github.thisisgm.discord
rm -rf ~/.config/omarchy-discord ~/.local/state/omarchy-discord

Those two directories are the client secret and the token from voice controls, so they go with the plugin rather than outliving it. Nothing else is left behind except the tray entry you unticked, if you got that far.

Contributing

Patches and bug reports are welcome. CONTRIBUTING.md has the two-copy layout, how to test a change against a running shell, and the house rules the code is held to.

The platform facts this depends on, such as how PipeWire names Discord's streams and what the RPC handshake refuses, live in knowledge/ as an Open Knowledge Format bundle. Every one of them was measured on a running machine, so the next person does not have to rediscover them.

Support

If this saved you an afternoon, you can buy me a coffee.

License

MIT.