omarchy-agentsview
An Omarchy shell plugin for AgentsView: your coding-agent sessions in the bar — what is running now, today's scoreboard, search across every session you have ever had, and a click to resume any of them in luvus, in its own project.
One glyph and one number. While anything is active the number is how many, in the accent colour; otherwise it is today's count, quietly.
3 three sessions active right now
11 nothing active, eleven sessions today
× AgentsView is not running
Click for the panel. Middle click to refresh. Right click to open AgentsView itself.
<p align="center"> <img src="preview.png" alt="The AgentsView widget in the Omarchy bar with its panel open: a search box, today's scoreboard, the sessions active now, and today's sessions grouped by project" width="420"> </p>Requires
- AgentsView 0.41 or newer, running as a server
this plugin can reach —
agentsview serve, or better, supervised so it never idle-exits (systemd --userunit: see Keeping the server up). Tested against v0.41.1. - luvus, for the resume button, and
jq(already on Omarchy) for the one place a script reads luvus's JSON. Everything else works without either. - The Omarchy shell, and a Nerd Font for the glyphs — Omarchy's bar font already is one.
The only other programs it runs are curl, and the ones that bound what the
server is allowed to hand back and how long it may outlive the bar — timeout,
head, fold and stdbuf from coreutils, setpriv from util-linux — all of
which are already on any machine running Omarchy.
Install
omarchy plugin add https://github.com/riclib/omarchy-agentsview.git --enable
omarchy restart shell
--enable places the widget for you and writes ~/.config/omarchy/shell.json
itself. To place it later, or to move it:
omarchy plugin enable riclib.agentsview --section center
Omarchy plugins are unsandboxed code running inside the long-lived shell process. Read the source before installing this or any other one.
Update
omarchy plugin update riclib.agentsview --yes
omarchy restart shell
Remove
omarchy plugin remove riclib.agentsview
omarchy restart shell
That is the whole removal. The plugin creates no files, writes no configuration of yours, installs no service and stores nothing on disk — it reads AgentsView and draws. AgentsView itself, its archive and its server are untouched.
The panel
Top to bottom:
- Search — type, press Enter, and every session AgentsView has is
searched, including the agents' own replies. One row per session, however
many messages matched, with the count.
/focuses the box from anywhere in the panel;Escapeclears it, then closes. - Today — sessions, agent time, output tokens and cost so far today, with the peak number of agents running at once and the all-time totals under it. These are AgentsView's own numbers, from its activity report, in your local timezone.
- Active now — every session that wrote anything in the last 15 minutes
(the
activeMinutessetting), across every agent AgentsView knows. - Sessions today — grouped by project, most recent first. Each row is the session's first prompt, then agent, branch and how many prompts you gave it. The badge on the left is AgentsView's health grade for the session; a dot means it is active.
Clicking any row opens that session in AgentsView, as an Omarchy web app. The
button on the right takes you to it in luvus: ↗ when luvus already has it on
screen (the click focuses that pane), when it does not (the click resumes
it in a fresh one).
Keys, while the panel has focus: / search, r refresh, o open AgentsView,
Escape close.
Resuming a session in luvus
luvus reports the agent session id of every pane it hosts, and the panel reads
that list with every refresh — so a session that is already open, even one
working right now, is never opened a second time beside itself. Its button
shows ↗, and clicking it is luvus pane focus. The spawn path below checks
again on its way, for a pane that appeared since the last refresh.
For a session that is not on screen, the button asks AgentsView for the
command that would resume the session — claude --resume <id>, or whatever the
agent's own flag is; AgentsView knows — and takes it to luvus in three steps:
luvus workspace open <the session's directory> # opens the project, or focuses it if already open
luvus pane split --no-focus # a fresh pane in it
luvus pane run <that pane> cd '<dir>' && <agent> <args…> # the agent comes back, mid-conversation
The server's command is never run as it came. luvus pane run types its
words into a shell, so the plugin takes AgentsView's answer apart and only
rebuilds it if every piece passes: the shape must be exactly
cd '<dir>' && <agent> <args…> with <dir> the very directory the same answer
reports; <agent> must be a bare name from a built-in allowlist of agent CLIs
(claude, codex, gemini, grok, opencode, copilot, kimi, omp, cursor-agent, amp,
droid, pi, crush, ori, agy, qwen, goose, aider, cline — extend it with the
resumeAgents setting); and every argument must be a word a shell passes
through untouched — no quotes, spaces, ;, $, |, &, > or globs.
Anything else is refused with the reason shown, including a shape AgentsView
might adopt in a later version. A compromised server, or a wrong serverUrl,
can therefore make the button do nothing — not run something.
So a session from a project you do not currently have open gets its workspace created on the way. The outcome — or the reason it failed — appears at the bottom of the panel.
luvus focuses the new pane inside its TUI but cannot raise the terminal window
that hosts it; nothing running inside a terminal can. Set focusWindowClass to
that terminal's Hyprland class (find it with hyprctl clients) and the plugin
raises the window too.
luvus's own agent resume is not used here, on purpose: it only knows the
sessions luvus itself has watched, and AgentsView knows every session on the
disk.
Settings
All of these are also editable in the shell's widget settings UI.
| Key | Type | Default | Meaning |
|---|---|---|---|
serverUrl |
string | http://127.0.0.1:8080 |
Where AgentsView is listening. Change it only for a remote or proxied server. |
token |
string | (empty) | Only for a server running with require_auth. Sent as a bearer header, carried in the environment rather than on a command line. |
activeMinutes |
integer | 15 |
A session counts as active if it wrote anything this recently. |
pushUpdates |
boolean | true |
Hold the server's event stream open and refresh the moment its data changes. Off falls back to polling alone. |
hideWhenIdle |
boolean | false |
Show the widget only while a session is active. It stays visible while the panel is open, and while the server is unreachable. |
resumeAgents |
string | (empty) | Extra agent CLIs the resume button may run, comma-separated bare names, on top of the built-in allowlist. |
luvusBin |
string | luvus |
Resolved on PATH as a bare name. Set an absolute path if resume says the binary is missing while your terminal finds it — the shell does not always inherit a login PATH. |
focusWindowClass |
string | (empty) | The Hyprland class of the terminal hosting luvus. See above. |
Keeping the server up
AgentsView's CLI starts a detached daemon on demand, and that daemon exits
after an idle timeout. A bar widget pointed at a port with nothing behind it
shows ×, which is honest but not useful. A supervised server never creates
that idle tracker — upstream documents this — so run it as a user service:
# ~/.config/systemd/user/agentsview.service
[Unit]
Description=AgentsView — local viewer for AI agent sessions
After=graphical-session-pre.target
[Service]
ExecStart=/usr/bin/agentsview serve --no-browser
Restart=on-failure
[Install]
WantedBy=default.target
systemctl --user enable --now agentsview.service
It reads port, bind address and sync roots from ~/.agentsview/config.toml
like any other launch, and agentsview daemon status recognises it as the
daemon.
How it stays current
Two ways in, deliberately:
bin/agentsview-snapshot— the whole truth, on demand: four HTTP reads in one process, one answer for the panel to reason about.GET /api/v1/events— a held-open server-sent-events stream that says when to ask again. The server broadcastsdata_changedwith a scope and nothing else, coalesced to one every ten seconds, so events are a doorbell here, not a data source.
Both are bounded before the answer reaches the shell rather than after it
arrives: the read through timeout and head -c, the stream through fold,
which caps how long a single line can grow. The bar is one widget inside a
shell that draws the whole desktop, and a line that never ends is otherwise
buffered in that shell's memory while it waits for a newline that may never
come. Neither outlives the bar: both carry a parent-death signal, so closing
the stream — or the shell quitting, or crashing — takes curl with it.
A 60-second timer sits behind all of it. It is not the update mechanism; it is the thing that notices the doorbell has stopped working. When the subscription is down the panel says so.
Lineage
The service, the bar slot and most of the panel's shape are taken from
omarchy-luvus, which in turn took
its panel from io.github.fabean.herdr (MIT, Josh Fabean). The bounding of
what a server may hand a shell, and the process-lifecycle handling, were
learned there the hard way and are carried over whole.
License
MIT.