* claude-companion: v1.3.0 — headless aggregator, user settings, sessions panel Catalog-side update for lowcache/claude-companion, from 1.0.1 to 1.3.0. Architecture: the pulse aggregator moved out of the bar widget into a headless [[service]] (pulse-svc.luau). Capture no longer depends on the bar dot being placed — the service starts with the shell and listens regardless of surfaces, retiring the plugin's old "pulse must sit on a bar" deployment invariant. The bar widget and desktop orb are now independent subscribers of the claude.pulse rollup, rendering only. Noctalia 5 beta also fixed the older limitation where bar widgets did not receive state.watch callbacks, so the bar dot is event-driven like the orb; both docs are updated accordingly. New: a `sessions` panel on right-click of the pulse (left-click still opens the answer panel) — one row per live session with state, model and token burn, plus a Retire control for a session whose SessionEnd hook never fired and which would otherwise sit at idle indefinitely. It introduces no new IPC verb: only the trailing `session` payload field is read for routing, so `session_end` with `,,,,,<sid>` is already a well-formed single-session retire. PROTOCOL.md now documents that property so any adapter can use it. Session ids are allowlisted before reaching a shell command. New: three animation settings (breath_speed, pulse_glow_floor, orb_swell), each declaring an explicit `step` — an omitted step defaults to 1.0 in the manifest parser, which collapses a fractional range to a couple of preset stops instead of a slider. plugin_api stays at 3. Everything used here is ungated at that level, and the contributing guidance is to raise it only when adopting a capability from a newer level. Verified against the installed build rather than assumed. Also ships tests/manifest_spec.py, which pins the settings contract: every numeric setting must declare an explicit step finer than its range, defaults must land on a step boundary, label/description must use the *_key form, and every key must resolve in translations/en.json. Neither the linter nor a widget spec can catch a bad step, which is how the slider bug shipped in the first place. Validated: catalog validator 54/54 exit 0, its own 54 self-tests pass, and the plugin's suite (5 luau + shim + manifest) is green. Live-tested on niri against Noctalia 5 beta; the compositor shim is unchanged in this update. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * claude-companion: tint the sessions retire control, fix singular header Follow-up on the v1.3.0 submission from live review: the retire button carried no variant and rendered at the background colour; a single session read "1 sessions". The panel root stays unfilled by design — noctalia panels are translucent under the glass style, so the backdrop is the shell's, not the plugin's. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: lowcache <drawpdeadredd@gmail.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
121 lines
5.2 KiB
TOML
121 lines
5.2 KiB
TOML
# Claude Companion — a Claude Code companion for Noctalia v5.
|
|
# Not a chat client: the terminal does the agentic work; this is the shell-side
|
|
# body — senses, hands, and an attention pulse. See README.md for the design.
|
|
|
|
id = "lowcache/claude-companion"
|
|
name = "Claude Companion"
|
|
version = "1.3.0"
|
|
# Plugin API level this manifest targets — mandatory as of the Noctalia 5 beta
|
|
# manifest parser (replaces the older min_noctalia gate). 3 is the oldest-supported
|
|
# level and covers every feature this plugin uses ([[panel]], ui controls, plugin IPC
|
|
# dispatch, barWidget/onIpc). The [[service]] entry additionally needs a build that
|
|
# ships the Service entry kind (Noctalia 5 beta, upstream rev da014f72 or newer).
|
|
plugin_api = 3
|
|
author = "lowcache"
|
|
license = "MIT"
|
|
icon = "robot"
|
|
description = "Claude Code companion: /claude launch + a telemetry-driven attention pulse."
|
|
# The compositor CLI (niri / hyprctl / swaymsg) is not listed: the shim detects and
|
|
# speaks whichever of the three supported compositors is running Noctalia, so exactly
|
|
# one is inherently present. See README "Requirements".
|
|
dependencies = ["claude", "python3", "playerctl", "notify-send", "nmcli", "ps", "tr", "timeout"]
|
|
tags = ["ai", "productivity", "bar", "desktop", "panel", "launcher"]
|
|
|
|
# ── User settings ─────────────────────────────────────────────────────────────
|
|
# Breath-speed multiplier for the pulse dot + orb animation (plugin-level, so both
|
|
# surfaces read the same value via noctalia.getConfig). 1.0 is the tuned default;
|
|
# higher breathes faster, lower slower. Rendered as a slider; `step` MUST be set
|
|
# explicitly on every double — the manifest parser defaults step to 1.0
|
|
# (plugin_manifest.h: `double step = 1.0`), which snaps a fractional range to a
|
|
# handful of preset stops instead of sliding.
|
|
[[setting]]
|
|
key = "breath_speed"
|
|
type = "double"
|
|
label_key = "settings.breath_speed.label"
|
|
description_key = "settings.breath_speed.description"
|
|
default = 1.0
|
|
min = 0.25
|
|
max = 3.0
|
|
step = 0.05
|
|
|
|
# Minimum brightness the bar dot dims to at the trough of its breath (0 = fully dark,
|
|
# 0.9 = barely dims). 0.45 is the tuned default. (Plugin-level so it sits with the
|
|
# other look controls; pulse.luau reads it via getConfig.)
|
|
[[setting]]
|
|
key = "pulse_glow_floor"
|
|
type = "double"
|
|
label_key = "settings.pulse_glow_floor.label"
|
|
description_key = "settings.pulse_glow_floor.description"
|
|
default = 0.45
|
|
min = 0.0
|
|
max = 0.9
|
|
step = 0.05
|
|
|
|
# How far the orb glyph magnifies as it breathes (0 = static size, 1.0 = the tuned
|
|
# default, higher = a bigger swing). orb.luau reads it via getConfig.
|
|
[[setting]]
|
|
key = "orb_swell"
|
|
type = "double"
|
|
label_key = "settings.orb_swell.label"
|
|
description_key = "settings.orb_swell.description"
|
|
default = 1.0
|
|
min = 0.0
|
|
max = 3.0
|
|
step = 0.05
|
|
|
|
# The pulse aggregator (headless) — the single source of truth for Claude session
|
|
# state. Receives hook events via onIpc (noctalia msg plugin …:pulse-svc all <event>)
|
|
# and the launcher quick-ask via state.watch("claude.state"), rolls all sessions up,
|
|
# and publishes the snapshot to noctalia.state ("claude.pulse"). Runs at shell launch
|
|
# with no surface, so capture never depends on the bar widget being placed — this
|
|
# retires the old "pulse must sit on a bar" invariant (see PROTOCOL.md). Needs the
|
|
# [[service]] entry kind (Noctalia 5 beta / post-5.0.0).
|
|
[[service]]
|
|
id = "pulse-svc"
|
|
entry = "pulse-svc.luau"
|
|
|
|
# The attention pulse (bar) — the visual centerpiece. A pure subscriber: watches
|
|
# noctalia.state ("claude.pulse") published by pulse-svc and reflects it in the bar as
|
|
# a glyph + a sine-breath brightness glow (folded in from the barpulse A/B prototype;
|
|
# barpulse.luau stays in-repo as the experiment record, unregistered).
|
|
[[widget]]
|
|
id = "pulse"
|
|
entry = "pulse.luau"
|
|
|
|
# The presence orb — the ambient desktop half of the pulse. A softly breathing disc
|
|
# that mirrors the bar dot's rollup (published to noctalia.state "claude.pulse"); pure
|
|
# view, no hooks of its own. Per-frame motion via setNeedsFrameTick/onFrameTick.
|
|
[[desktop_widget]]
|
|
id = "orb"
|
|
entry = "orb.luau"
|
|
|
|
# The answer panel — full-length scrollable surface for /claude ? quick-ask answers
|
|
# (a notification toast clips long bodies; it carries only a preview). Opens on
|
|
# a click on the bar pulse, from the "Show last answer" launcher row, or via
|
|
# `noctalia msg panel-toggle lowcache/claude-companion:answer`.
|
|
[[panel]]
|
|
id = "answer"
|
|
entry = "answer.luau"
|
|
width = 460
|
|
height = 420
|
|
|
|
# The sessions panel — the actionable form of the bar tooltip. One row per live
|
|
# session (state, model, token burn) plus a retire control for a session whose
|
|
# SessionEnd hook never fired. Opens on a RIGHT-click of the bar pulse (left-click
|
|
# stays the answer panel), or via
|
|
# `noctalia msg panel-toggle lowcache/claude-companion:sessions`.
|
|
[[panel]]
|
|
id = "sessions"
|
|
entry = "sessions.luau"
|
|
width = 440
|
|
height = 360
|
|
|
|
# /claude — launch a real Claude Code session in the terminal, or a one-shot ask.
|
|
# The single backend chokepoint (invoke/parse) is inlined here: v5 has no plugin
|
|
# module system, and this is the only entry that talks to a model.
|
|
[[launcher_provider]]
|
|
id = "claude"
|
|
entry = "claude.luau"
|
|
prefix = "claude"
|
|
glyph = "robot"
|