Omahub
← All plugins
J

Listening Post

by Jeremy Longshore

Listening Post brings your Perception signal room into the Omarchy bar: ranked AI releases, pricing changes, incidents, engineering notes, and a five-item daily brief. Open its panel, pair with a device token from oma.intentsolutions.io/perception/. Your token stays out of process arguments and logs. It retains its last good field through outages and syncs read state to your account. Without a token, 33 curated HTTPS feeds remain available as a migration fallback. No article bodies or telemetry.

Security review

Potentially dangerous behavior detected · 10 findings

Deterministic scan — not a security guarantee

High
Risk level
High
Analyzed commit
02da2d0
Scanned
1 week ago
  • high destructive_filesystem api/Dockerfile:5

    Destructive operation on the root filesystem or a block device.

    rm -rf /var/lib/apt/lists/*
  • high destructive_filesystem scripts/rig-verify.sh:77

    Destructive operation on the root filesystem or a block device.

    rm -rf /tmp/$NAME && mkdir -p /tmp/$NAME && tar xzf /tmp/$NAME.tgz -C /tmp/$NAME' || exit 3
  • high destructive_filesystem scripts/rig-verify.sh:98

    Destructive operation on the root filesystem or a block device.

    rm -rf /tmp/$NAME /tmp/$NAME.tgz >/dev/null 2>&1
  • medium package_manager api/Dockerfile:3

    System package manager operation.

    apt-get update \
  • medium package_manager api/Dockerfile:4

    System package manager operation.

    apt-get install -y --no-install-recommends python3 make g++ \
  • Command runs with sudo, elevating the process beyond the plugin environment.

    sudo by <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/ErikMelton/hovercard" data-octo-click="hovercard-link-click&quot
  • low obfuscation tests/model.test.js:30

    Augments a command with octal/hex escape sequences.

    \x7fd"), "abcd")
  • Augments a command with octal/hex escape sequences.

    \x89PNG\r\n\x1a\n" or raw[12:16] != b"IHDR":
  • Docs curl_pipe_sh .beads/README.md:64

    curl output is executed by a shell (curl | sh pattern).

    curl -sSL https://raw.githubusercontent.com/steveyegge/beads/main/scripts/install.sh | bash
  • Docs external_hosts .beads/README.md:64

    Downloads or connects to an external HTTP(S) host.

    curl -sSL https://raw.githubusercontent.com/steveyegge/beads/main/scripts/install.sh | bash

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
02da2d0
Reviewed
1 week ago

The deterministic scan's high-risk findings are false positives: the curl|sh is in Beads documentation, the rm -rf commands are in a Dockerfile and CI temp cleanup, and the sudo/obfuscation hits are in test fixtures and PNG magic checks. The plugin's actual runtime code (QML, Model.js) is carefully written with URL validation, output sanitization, bounded reads, and no shell interpolation of untrusted data. The only unexamined pieces are the Perl state helper and connect-perception.sh credential script, which should be reviewed before publishing.

  • bin/listening-post-secure-state (Perl helper) was not included in the sample; it handles credentials and state writes and should be reviewed.
  • connect-perception.sh was not included in the sample; it writes the device token and should be reviewed for safe handling (no argv exposure, mode 0600).
  • The plugin fetches from a fixed list of curated hosts and the Perception API; no user-controlled hosts, but network access is inherent to the plugin's function.
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/jeremylongshore/omarchy-listening-post-entry --enable
Widgets #bar #quickshell #ai
<p align="center"><img src="assets/banner.svg" alt="Listening Post" width="720"></p>

Listening Post

The Omarchy companion for Perception, the private web signal room at oma.intentsolutions.io/perception/. Listening Post carries the same ranked field, five-item brief, and read state into the bar. The pill only speaks when a model shipped, the bill changed, or a provider is down.

The bar has three deliberate states:

  • Nothing new: the slot collapses completely.
  • AI: 3 new: unseen releases or pricing changes need a look.
  • OpenAI incident: a provider status page has an open incident.

ko-fi

Why this is not another RSS reader

  • The source list is the product. Thirty-three curated feeds across every major lab, provider, and AI tool. For the vendors that publish no first-party blog feed (Anthropic, xAI, Mistral, Meta, and more), Listening Post pulls a curated community RSS mirror for news plus their GitHub release atoms for SDK versions, so the radar keeps working where marketing sites drop RSS. Every shipped URL was fetched live before release.
  • Lanes, not folders. Every item is classified: Model releases, Pricing and limits, Status incidents (louder, first), and Engineering posts (shown, never counted, never notified). A vendor's same-week release burst clusters into one row.
  • Optionally ranked by local agent-usage filenames. With the first-party Agents plugin installed, Listening Post reads only the file names in its usage folder (read-only, nothing parsed, degrades to off) and can float matching vendors to the top.
  • Quiet by design. Install starts read. Engineering chatter never reaches the pill. Nothing new means no pill at all.

Install

omarchy plugin add https://github.com/jeremylongshore/omarchy-listening-post-entry --enable

Then add Listening Post to your bar layout (Omarchy menu, Bar, or ~/.config/omarchy/shell.json). Sign in to Perception with the email used for your Lemon Squeezy purchase, open Omarchy, create a device, and paste the one-time token into the plugin's private connector:

~/.config/omarchy/plugins/io.github.jeremylongshore.listening-post/connect-perception.sh

The script prompts without echo and writes the credential to a mode-0600 file; the token never enters shell history, process arguments, shell.json, or QML. Refresh Listening Post and it will use your account's ranked snapshot and brief.

Until a device token is added, the original 33-source local radar remains available as a migration fallback. After the first valid Perception response, the plugin stays on that account field and preserves its last-good snapshot through offline, malformed-response, entitlement, or API failures.

Remove

omarchy plugin remove io.github.jeremylongshore.listening-post

State lives in ~/.local/state/omarchy/listening-post/ and is safe to delete at any time; the next poll rebuilds it.

The panel

Standard Omarchy panel keys, same as the Herald and the first-party panels:

Key Action
j / k or arrows Move the cursor
Enter or o Open the source in your browser
w Open the selected signal in Perception
p Open Perception
x or a Mark the selected row read
c Mark everything read
r Refresh now
Esc Close
Tab / Shift+Tab Switch to the neighboring bar panel

Left-click opens, right-click marks read. Middle-click the pill to refresh.

Sources

Thirty-three curated sources.

  • Vendor news (first-party RSS): OpenAI, Google AI, Google DeepMind, Hugging Face, Together AI.
  • Vendor news (community RSS mirror, for vendors with no first-party feed): Anthropic (news, engineering, research), xAI, Mistral, Meta, Cohere, Groq, Perplexity.
  • AI commentary and research: The Batch, The Verge AI, Chip Huyen, Lil'Log.
  • Status incidents: Claude Status, OpenAI Status.
  • Releases and changelogs: Claude Code (releases and changelog), the Anthropic / xAI / Mistral SDKs, Ollama, vLLM, MCP Servers, Cursor.
  • Omarchy platform: Omarchy, Hyprland and Quickshell releases, and DHH's blog. This plugin lives in the Omarchy bar, so it should notice when the desktop, its compositor or its shell toolkit ships. Releases land in the release lane and the blog in engineering.

The community RSS mirror (Olshansk/rss-feeds) is third-party and labeled as such; every source is polled independently, so if the mirror lags, only those rows go quiet.

A changelog feed (Claude Code, Cursor) never headlines the release lane: its entries collapse into one quiet "Cursor changelog · N this week" row, so a routine version bump never masquerades as a model release.

Custom feeds were removed in 1.1.0

Earlier versions let you add your own feed URLs through an extra-sources.json file. That feature is gone, and it is not coming back in the same shape.

It was the only place this plugin fetched a host it did not ship, and it was guarded by a host allowlist. A marketplace reviewer took that allowlist apart in three rounds: first a userinfo bypass (https://user@127.0.0.1/feed), then the alternate IPv4 spellings inet_aton accepts (127.1, 0177.0.0.1), and finally the one that ended it. A host policy can only check the name. An ordinary hostname an attacker controls resolves to whatever they point it at, and DNS rebinding can change that after any separate lookup. The parsing was never the problem, because the resolution belongs to curl and no amount of regex reaches it.

Making it safe would have meant resolving each host, rejecting every non-public result, pinning the validated address to the request, and revalidating every redirect hop. That is a real amount of machinery to protect a field nobody installs this plugin for. Thirty-three curated sources is the pitch.

Every source is now a compile-time constant. If a feed you want is missing, open an issue and it can be added to the curated list where it gets reviewed like everything else.

Notifications

Only two things notify: a new model release and a new unresolved status incident. Notifications ride omarchy-notification-send, so they land in whatever notification center you run, click-to-open included. More than three new items in one poll collapse into a single summary. Changelog commits and engineering posts never notify. Turn it all off in settings.

Settings

Setting Default What it does
Desktop notifications On New releases and unresolved incidents only
Rank by agents you use On Read-only file listing of the Agents plugin usage folder
Perception API https://api.perception.intentsolutions.io Canonical endpoint; other origins fail closed
Perception credential file ~/.config/perception/listening-post.curlrc Managed by connect-perception.sh; other paths fail closed

Polling cadence is fixed at 15 minutes, the same house rate the first-party Agents plugin uses. Feed publishing cadence is hours; polling harder buys nothing and costs the publishers.

Architecture

Service.qml   account snapshot + local migration poller, no Node/Python daemon
        |  short-lived descriptor helper -> curl header on stdin
        |  Model.js validates contract v1 on Quickshell's JS engine
        v
~/.local/state/omarchy/listening-post/state.json   descriptor-bound atomic write
        ^
        |  last-good render + queued read sync
BarWidget.qml + Panel.qml (render + keys)

No Node.js or Python service. Polling and rendering stay inside Quickshell. A short-lived absolute-system-Perl helper opens settings, state, locks, and credentials with descriptor-bound no-follow operations, then invokes the stock curl for authenticated requests. The optional pairing command uses the same helper for mode-0600 credential publication. Nothing remains running afterward.

Service.qml owns the item store: it fetches, merges, persists through the bounded helper, and notifies. The panel renders that store and calls straight into the service, so marking an item read takes effect immediately instead of round-tripping through a subprocess. Parsing, classification, merging, and sanitizing live in Model.js, pure ES5 functions loaded identically by Quickshell and by the offline unit suite.

When paired, the plugin contacts only api.perception.intentsolutions.io for snapshot reads and read-state writes. The helper reads the bearer token from a mode-0600 config inside the mode-0700 Perception config directory and passes its HTTP header to curl on standard input. It is never loaded into QML or put in shell.json, process arguments, notifications, links, logs, or state.json. API endpoints from settings are accepted only when they equal the canonical origin.

In unpaired migration mode, network hosts contacted are the curated feed hosts (openai.com, blog.google, deepmind.google, huggingface.co, together.ai, raw.githubusercontent.com, theverge.com, huyenchip.com, lilianweng.github.io, status.claude.com, status.openai.com, code.claude.com, cursor.com, github.com, world.hey.com). That list is fixed at build time and there is no way for a user, a config file or a feed body to add a host to it. No telemetry is collected in either mode.

Testing

npm run test:product
npm run build:product

The root CI workflow runs the following exact validation commands when the change-scope classifier selects the full lane:

npm test
npm run test:race
npm run test:mutation
npm run audit
shellcheck --severity=warning scripts/*.sh e2e/*.sh .githooks/pre-push

The product lane runs 117 plugin tests, 7 shared-contract tests, 8 web tests, and 65 API tests (192 total), then builds both product surfaces. The plugin lane requires at least 95% line, statement, and function coverage, 90% branch coverage, a 90% mutation score, and three concurrent race passes. Parser tests exercise RSS and Atom against captured bodies from all thirty-three live sources, lane classification, week clustering, merge and retention, read-state, notification gating, personalization mapping, the feed-list parser, and the state record. Offline by design; the capture procedure is in docs/FIXTURES.md. CI also runs the vendored Omarchy gate lane and builds the deployable Docker image.

Perception operators should also use docs/PERCEPTION-OPERATIONS.md for production secrets, privacy handling, backup and restore, smoke checks, credential containment, and rollback; docs/PERCEPTION-ROLLOUT.md for the fail-closed go-live sequence; and docs/PERCEPTION-ANALYTICS.md for the minimal first-party funnel and retention boundary.

Maintainers wanted

These plugins are growing, and we are looking for dependable Omarchy users who want to review issues, test releases, and keep a plugin healthy over time. Start with a small pull request or open a maintainer interest issue titled Maintainer interest. Tell us which plugin you use and how you want to help. Consistent contributors can earn maintainer responsibility.

License

MIT