Repository navigation
Releases: HenryGetz/LustLess
Release list
v0.1.11 — LustLess (screen accountability actually captures and scores)
Screen accountability actually captures and scores
v0.1.10 shipped with screen capture not working at all — on either backend, on any machine where the user logs in after the daemon starts (i.e. every normal boot). If you installed 0.1.10, upgrade.
v0.1.10 shipped the Wayland backend but screen capture did not work at all on
a real machine, on either backend. Three bugs, all found by running the daemon
on a real X11 desktop rather than a VM, plus one that made a working capture
score nothing:
- Sessions discovered after startup were silently dropped. logind's
User
property is the struct(uo); the watcher read it as a bareu32, so the read
always failed andwatch_sessionreturned early. Sessions present at daemon
start come fromListSessions(which already carries the uid) and were fine —
but every session created after that arrives via theSessionNewsignal and
needs the property. On a normal boot the daemon starts before anyone logs in,
so every session was dropped and capture skipped every tick as "session
inactive" forever. Fixed by reading the struct, with a regression test that
reads the property off real logind and pins the old shape as failing. - An ssh session could shadow the desktop. Session selection ranked by
liveness only, so on any machine the operator was also ssh'd into, the tty
session won and the capture path then refused it as a text session. Selection
now prefers a local graphical session (x11/wayland, not remote) first. - The gate and the backend could disagree.
gate()allowed a tick if any
session for the uid was active+unlocked, while the backend captured the
session selection picked. Both now judge the same session. - A capture with no window list was never scored. When the X11 backend could
not read_NET_CLIENT_LISTit wroteapps: []and only logged a warning
claiming a full-frame fallback that did not exist. The classifier scores the
apps in the manifest, so every capture was analyzed as zero windows — the
daemon looked perfectly healthy while doing nothing. It now synthesizes one
full-frame entry per monitor, as the Wayland backend always has. - Capture failure is no longer silent: "no session tracked for a signed-in uid"
is a warning naming the defect, not an indistinguishable "session inactive".
Verified on a real X11 session (Display=:0, Type=x11, alongside five ssh
sessions for the same uid): session env applied (uid 1000, type X11, display Some(":0")) → backend selected (X11) → a real 1280×800 capture with 3069
distinct colours, written as a complete spool transaction (PNG + manifest +
ready), consumed by the classifier, and scored:
{"analyzed_count":1,"top_score":0.06666}. The client_screenshot metric row
in the daemon's ledger corroborates the write.
How this was found and verified
Found by running the daemon on a real X11 desktop (this workstation:
Type=x11, Display=:0, active) which also has five ssh sessions for the same
uid — a configuration that exposed two of the three bugs at once.
Verified end to end on that machine, unprivileged, with a test config:
capture: session env applied (uid 1000, type X11, display Some(":0"))
capture: backend selected (X11)
im0.png 1280x800, 3069 distinct colours
manifest.json + ready (complete transaction)
{"analyzed_count":1,"top_score":0.06666} (classifier result)
plus the client_screenshot metric row in the daemon's ledger corroborating the
write. Workspace: 355 tests pass, clippy -D warnings clean.
Packages
lustless_0.1.11_amd64.deb, lustless-0.1.11-1.x86_64.rpm,
lustless-0.1.11-1-x86_64.pkg.tar.zst, lustless-0.1.11-r0.apk, plus
install.sh and lustless.rsa.pub.
Correction: Wayland capture does not work in 0.1.11
This release fixed screen capture for X11 sessions and says "captures and
scores", which is true there. On a Wayland session it does not: the daemon
makes the xdg-desktop-portal ScreenCast grant as root, and a stock D-Bus
session bus rejects uid 0 (portal request failed: session bus … I/O error: failed to read from socket), so nothing is captured. Reproduced on Debian 13.7
(GNOME/Wayland) with no host changes, and on Ubuntu 24.04 only after a
hand-written allow-root bus policy plus setcap cap_sys_ptrace+ep on the portal
binaries — which is why it looked fine during this release's verification.
v0.1.12 fixes this properly: the grant is made by a privilege-dropped helper
running as the session user, which hands the PipeWire fd to the daemon. No host
policy changes, no capabilities added to system binaries. Upgrade if you are on a
Wayland desktop (Zorin Core, Ubuntu, Fedora, Debian GNOME).
v0.1.10 — LustLess (Wayland capture on GNOME: version-tolerant PipeWire bindings)
Wayland capture ships on GNOME (Zorin Core, Ubuntu, Fedora)
Screen capture on a Wayland session now uses the compositor's ScreenCast portal instead of falling back to X11/XWayland root capture.
Screen capture on a Wayland session (GNOME: Zorin Core, Ubuntu, Fedora) now uses
the compositor's ScreenCast portal instead of falling back to X11/XWayland root
capture. The backend existed since v0.1.7 but could not ship, and the reason was
structural rather than a flag: the pipewire crate cannot build against the
Zorin 17 / Ubuntu 22.04 baseline. Its libspa bindings need symbols and struct
fields that do not exist in libspa 0.3.48 (spa_meta_first,
spa_meta_region_is_valid, spa_video_info_raw.flags), and
struct spa_video_info_raw changed layout between 0.3.48 and current PipeWire
(flags inserted after format, modifier widened), so no single linked build
could be correct on both 0.3.48 and 1.0.x — and one .deb has to cover both.
- Our own version-tolerant PipeWire bindings replace the crate
(crates/lustless-capture/src/pipewire_sys.rs):libpipewire-0.3.so.0is
dlopened and the 25 entry points that exist in 0.3.48 and 1.0.x are
resolved at runtime. The two calls we need that are header macros
(pw_core_get_registry,pw_registry_add_listener) are reached through the
realspa_interfacevtable — its layout and thepw_core_methodsmember
order were verified identical across 0.3.48, 1.0.5 and master. Event tables
carry trailing padding and the 0.3.x version so a newer library's copy stays
inside our allocation. No spa struct ever crosses the boundary: only
byte-level SPA pods do, which is what makes one build correct on both
baselines. Consequences: the release build needs neitherlibpipewire-0.3-dev
norlibclang-dev, no shipped binary has alibpipewire/libspa
DT_NEEDED, and the packages declare PipeWire as a weak dependency
(Recommends/optdepends) — absent PipeWire degrades to the X11 path
instead of failing to install. - Our own SPA pod codec (
pipewire_pod.rs) replaces the crate's
PodSerializer/VideoInfoRaw: it builds the EnumFormat we negotiate and
parses the format the compositor picks, with every constant read from the
real headers and independently probed on 22.04 and 24.04 (all 24 print
identically). - Backend fixes found while porting: the stream no longer asks for
PW_STREAM_FLAG_DRIVER(wrong for a capture stream, and a way to get no
frames); frame extraction honourschunk.offset/chunk.size/chunk.stride
instead of assuming a packed stride, rejects DMA-BUF buffers with a log
instead of reading them, and queues buffers back (the old code leaked
every one); the PipeWire thread builds the whole graph itself instead of
taking a command channel. - Portal permission persistence. The ScreenCast restore token is stored per
user (<state_dir>/<uid>/portal-restore-token, 0600) and sent back with
PersistMode, so the compositor re-uses the grant instead of re-prompting on
every login. The portal session is opened on the session bus explicitly
(Screencast::with_connection), which is what a root system service needs. - The daemon now chooses its backend from the logind session, not from its
own environment. A system service has no session environment, so
XDG_SESSION_TYPEwas always absent: an X11 desktop would have picked the
Wayland backend, and the X11 backend could not see$DISPLAYat all.
sessions.rsreads the session'sType/Display/Remote/Leaderand
derives the environment (DISPLAY,XAUTHORITY,XDG_RUNTIME_DIR,
DBUS_SESSION_BUS_ADDRESS); text and remote sessions are never captured. - X11 capture can connect now. A live run showed the daemon resolving the
session correctly and then failing with$DISPLAY variable not set, because
logind's per-sessionDisplayproperty is empty on real machines (verified on
Ubuntu 24.04 and Zorin 17.3). DISPLAY/XAUTHORITY are recovered from the
session leader's/proc/<pid>/environ, then from a bounded walk of its
descendants, then from the orderedXAUTHORITYfile probe — and only then
does an X11 session fall back to:0.
Not fixed by this: in the same live run the daemon never got past its logind
gate (Skip capturing Screenstate (session inactive)on every tick) even
thoughloginctlreportedActive=yesfor that session — so no screenstate
has ever been observed to be captured on a real desktop, on either backend.
See gap 0 indocs/impl/PARITY.md.
Verification: 350 workspace tests pass and clippy -D warnings is clean; the
FFI layer is covered by an integration test that compiles a stub
libpipewire-0.3.so.0 from the real headers and drives the wrappers end to end
(registry vtable, pod negotiation, padded-stride extraction, buffer queueing),
plus a test that resolves the real system library when one is installed. The
build was verified in the ubuntu:22.04 container without any PipeWire
headers, and the resulting release binaries were checked for the absence of a
libpipewire link dependency. Live VM evidence collected so far (daemon
session resolution, classifier artifact loading) is in docs/impl/TEST-MATRIX.md;
the remaining live step — a real compositor granting ScreenCast — is gap 0 in
docs/impl/PARITY.md.
What is proven, and what is not
Proven: 350 workspace tests pass, clippy -D warnings clean; the SPA pod
constants print identically on ubuntu:22.04 (libspa 0.3.48) and ubuntu:24.04
(1.0.x); all 25 symbols resolve against a real libpipewire-0.3.so.0 1.0.5; an
integration test compiles a stub libpipewire-0.3.so.0 from the real 0.3.48
headers and drives the wrappers end to end; the release builds in the
ubuntu:22.04 container with no libpipewire-0.3-dev and no
libclang-dev; no shipped binary has a libpipewire/libspa DT_NEEDED; and
a live install of 0.1.10 reached a running daemon, offline sign-in, a fresh
logind registry and classifier v0.1.10 ready with all six CE artifacts.
Not proven — read this before relying on screen accountability:
- No capture has ever been observed end-to-end, on either backend. In the
one live run that got that far, every tick logged
Skip capturing Screenstate (session inactive)whileloginctlreported the
sessionActive=yes, so the daemon never reached the portal at all. That is
gap 1 indocs/impl/PARITY.md, and it outranks everything v0.1.10 added. - The portal ScreenCast grant and real frame extraction are unverified against a
compositor (gap 0); the FFI proof is against a stub built from the same
headers, which is self-consistency rather than independent ground truth — the
real library check covers symbol resolution only. - X11 capture on a real desktop is unverified for the same reason as (1).
Packages
lustless_0.1.10_amd64.deb, lustless-0.1.10-1.x86_64.rpm,
lustless-0.1.10-1-x86_64.pkg.tar.zst, lustless-0.1.10-r0.apk, plus
install.sh and lustless.rsa.pub. PipeWire is a weak dependency now
(Recommends/optdepends): without it the client still installs and falls back
to X11 capture.
v0.1.9 — LustLess (hardening: local tamper, fail-open DNS, poisoned queues)
Linux accountability client (Covenant Eyes-compatible, clean-room reimplementation).
Install
curl -fsSL https://github.com/HenryGetz/LustLess/releases/latest/download/install.sh | sudo bashDetects your distro, downloads the matching package, installs it with the
native tool, starts the agent — and the sign-in window opens. Log in there.
Other ways:
| Distro | File | Command |
|---|---|---|
| Debian / Ubuntu / Zorin / Mint | lustless_0.1.9_amd64.deb |
sudo apt install ./lustless_0.1.9_amd64.deb |
| Fedora | lustless-0.1.9-1.x86_64.rpm |
sudo dnf install ./lustless-0.1.9-1.x86_64.rpm |
| Bazzite / immutable Fedora | lustless-0.1.9-1.x86_64.rpm |
sudo rpm-ostree install ./lustless-0.1.9-1.x86_64.rpm && reboot |
| Arch / EndeavourOS / SteamOS | lustless-0.1.9-1-x86_64.pkg.tar.zst |
sudo pacman -U ./lustless-0.1.9-1-x86_64.pkg.tar.zst |
| Alpine | lustless-0.1.9-r0.apk |
sudo apk add --allow-untrusted ./lustless-0.1.9-r0.apk |
Uninstall: sudo apt purge lustless (or the dnf/rpm-ostree/pacman/apk
equivalent) — restores the DNS, browser-policy and polkit state exactly as
found.
What's new — hardening
Two focused reviews (local attack surface; error paths) were run against the
shipped code and everything they found is fixed here. In an accountability
client the person at the keyboard is the adversary, so the tamper findings are
as important as crashes.
Local tamper, previously possible for any unprivileged user:
- Dashboard tokens were validated and then discarded, so any local user could
fetch a token over the 0666 IPC socket and drive the signed-in session: sign
it out, set the weakest filter level, or allow-list*. Mutations now require
the token to own the session. 0x4c USER_LOGOUThad no ownership check — any uid could force a sign-out
(and withfail_closed_when_signed_out = false, stop the filter).0x61/0x43/0x4d/0x54/0x67leaked the signed-in username, filter
state and outbox path to any uid, minted a dashboard token for them, and let
them trigger diagnostics, outbox flushes and a feed fetch.- The break-glass audit line now carries the promised
org.lustless.break-glass uid=… reason=…tag; denials are distinguishable. - The agent's session-token file no longer falls back to world-writable
/tmp
(symlink capture) and refuses a symlinked directory.
Fail-open and queue defects:
- Filtering could silently be off while the daemon looked healthy: a DNS
forwarder that failed to build or bind only logged. It is now markedOutage
and reported,dns.listen/ports are validated at startup, and an unparsable
config refuses to start instead of quietly using defaults. - Block pages never loaded: the synthesized CNAME was owned by the block
host instead of the queried name, so a stub resolver returned NODATA. Now
RFC 1034-shaped. - A fail-closed classifier exit counted as clean (it prints
byeand
returns 1), bypassing the crash budget, metric and escalation and respawning
every 5 s forever with screen accountability off. - Rejected (4xx) batches poisoned the upload queue forever (
drop_invalid
matched only locally-invalid rows, so nothing was deleted and the batch was
re-claimed oldest-first). Deterministic rejections now delete exactly the
claimed rows. - A second daemon could run, sharing the outbox/spool/crash ledger and
reporting a false crash:lustlessdnow holds an exclusiveflock. - Spool orphans are swept by the daemon (previously only at classifier
startup), shutdown aborts overrunning tasks, and the staged update payload is
removed after install.
Workspace suite: 313 passed, 0 failed. Everything from 0.1.8 (crash
pipeline), 0.1.7 (parity audit, real-model proof), 0.1.6 (Zorin Lite branding),
0.1.5 (DNS that stays alive) and 0.1.4 (agent main loop) is unchanged.
v0.1.8 — LustLess (crash-reporting pipeline, CE parity minus the databases)
Linux accountability client (Covenant Eyes-compatible, clean-room reimplementation).
Install
curl -fsSL https://github.com/HenryGetz/LustLess/releases/latest/download/install.sh | sudo bashDetects your distro, downloads the matching package, installs it with the
native tool, starts the agent — and the sign-in window opens. Log in there.
Other ways:
| Distro | File | Command |
|---|---|---|
| Debian / Ubuntu / Zorin / Mint | lustless_0.1.8_amd64.deb |
sudo apt install ./lustless_0.1.8_amd64.deb |
| Fedora | lustless-0.1.8-1.x86_64.rpm |
sudo dnf install ./lustless-0.1.8-1.x86_64.rpm |
| Bazzite / immutable Fedora | lustless-0.1.8-1.x86_64.rpm |
sudo rpm-ostree install ./lustless-0.1.8-1.x86_64.rpm && reboot |
| Arch / EndeavourOS / SteamOS | lustless-0.1.8-1-x86_64.pkg.tar.zst |
sudo pacman -U ./lustless-0.1.8-1-x86_64.pkg.tar.zst |
| Alpine | lustless-0.1.8-r0.apk |
sudo apk add --allow-untrusted ./lustless-0.1.8-r0.apk |
Uninstall: sudo apt purge lustless (or the dnf/rpm-ostree/pacman/apk
equivalent) — restores the DNS, browser-policy and polkit state exactly as
found.
What's new
The crash-reporting pipeline exists now (it was the biggest parity gap):
- Detection: a clean-shutdown marker; a missing marker at startup means the
previous run died — systemd'sRestart=alwaysis CE's restart helper, so the
report is made by the next start (CE's timing). A first-ever start reports
nothing. - Type: a panic hook plus fatal-signal handlers (SIGSEGV/SIGABRT/SIGBUS/
SIGILL/SIGFPE) record the reason, so the metric'scrash_typeis
PANIC/SIGNALwhere CE hardcodesGENERIC. - Attachments: CE's log groups under CE's caps (5 MB per file, 19 MB
total).state-summary.jsonreplaces CE'sdebugDB.zip— the activity
databases are never attached, which is deliberately stricter than CE. - Counters and metric: CE's
ClientCrashesAt/ClientCrashesSincepair,
theclient_crashestelemetry row, and CE's
client_crash{crash_type=…,count=…}metrics event, cleared after reporting. - Test hooks:
--crashatonce=true(CE's command-line switch) and
[daemon] crash_test_hook = "force"(CE'sForceCrashClientsetting).
Verified end to end: forced SIGABRT → last-reason=SIGNAL → next start logs
previous run crashed (SIGNAL, 1 in window), writes the attachments, emits the
metric row with crash_type=SIGNAL, inserts client_crashes=SIGNAL:1, clears
the counter; a clean run reports nothing.
Also in this release: the config loader's known-key list now accepts
crash_test_hook (it silently ignored unknown keys before). Everything from
0.1.7 (parity audit, real-model proof, spool fallback), 0.1.6 (branded sign-in
window, Zorin Lite verification), 0.1.5 (DNS that stays alive) and 0.1.4 (agent
main loop) is unchanged.
v0.1.7 — LustLess (parity audit, real-model proof, spool fallback)
Linux accountability client (Covenant Eyes-compatible, clean-room reimplementation).
Install
curl -fsSL https://github.com/HenryGetz/LustLess/releases/latest/download/install.sh | sudo bashDetects your distro, downloads the matching package, installs it with the
native tool, starts the agent — and the sign-in window opens. Log in there.
Other ways:
| Distro | File | Command |
|---|---|---|
| Debian / Ubuntu / Zorin / Mint | lustless_0.1.7_amd64.deb |
sudo apt install ./lustless_0.1.7_amd64.deb |
| Fedora | lustless-0.1.7-1.x86_64.rpm |
sudo dnf install ./lustless-0.1.7-1.x86_64.rpm |
| Bazzite / immutable Fedora | lustless-0.1.7-1.x86_64.rpm |
sudo rpm-ostree install ./lustless-0.1.7-1.x86_64.rpm && reboot |
| Arch / EndeavourOS / SteamOS | lustless-0.1.7-1-x86_64.pkg.tar.zst |
sudo pacman -U ./lustless-0.1.7-1-x86_64.pkg.tar.zst |
| Alpine | lustless-0.1.7-r0.apk |
sudo apk add --allow-untrusted ./lustless-0.1.7-r0.apk |
Uninstall: sudo apt purge lustless (or the dnf/rpm-ostree/pacman/apk
equivalent) — restores the DNS, browser-policy and polkit state exactly as
found.
What's new
Parity work, driven by a subsystem-by-subsystem audit now recorded in
docs/impl/PARITY.md (Windows surface → Linux status → evidence → gaps).
- The spool consumer survives a missing inotify instance. Previously the
classifier exited (Too many open files) on a machine at the per-user
inotify limit; it now falls back to polling with the same semantics — only
newly-ready folders, and renames still reported asRenamed(matched by
folder inode). All 28 capture tests pass, including the ones the host limit
was breaking. - The real CE classifier bundle is proven end to end: decrypt → load
(threshold 0.467 from the calibration artifact) → score a 640×480 capture →
{"app":"firefox","score":0.0,"flagged":false,"scored_windows":1}. - Wayland capture is characterised, not hand-waved: the portal backend is
implemented but cannot ship on this baseline — thepipewirecrate's spa
bindings need libspa newer than Ubuntu 22.04 / Zorin 17 provides, and a
binary linked against a newer libspa would not load on the target. Named as
gap 0 with the work required (dlopen-style bindings or a crate pin).
Everything from 0.1.6 (branded sign-in window, Zorin Lite verification), 0.1.5
(DNS that stays alive) and 0.1.4 (agent main loop) is unchanged.
v0.1.6 — LustLess (branded sign-in window, verified on Zorin OS Lite)
Linux accountability client (Covenant Eyes-compatible, clean-room reimplementation).
Install
curl -fsSL https://github.com/HenryGetz/LustLess/releases/latest/download/install.sh | sudo bashDetects your distro, downloads the matching package, installs it with the
native tool, starts the agent — and the sign-in window opens. Log in there.
Other ways:
| Distro | File | Command |
|---|---|---|
| Debian / Ubuntu / Zorin / Mint | lustless_0.1.6_amd64.deb |
sudo apt install ./lustless_0.1.6_amd64.deb |
| Fedora | lustless-0.1.6-1.x86_64.rpm |
sudo dnf install ./lustless-0.1.6-1.x86_64.rpm |
| Bazzite / immutable Fedora | lustless-0.1.6-1.x86_64.rpm |
sudo rpm-ostree install ./lustless-0.1.6-1.x86_64.rpm && reboot |
| Arch / EndeavourOS / SteamOS | lustless-0.1.6-1-x86_64.pkg.tar.zst |
sudo pacman -U ./lustless-0.1.6-1-x86_64.pkg.tar.zst |
| Alpine | lustless-0.1.6-r0.apk |
sudo apk add --allow-untrusted ./lustless-0.1.6-r0.apk |
Uninstall: sudo apt purge lustless (or the dnf/rpm-ostree/pacman/apk
equivalent) — restores the DNS, browser-policy and polkit state exactly as
found.
What's new
Branding polish, verified on a Zorin OS 17.3 Lite live VM (the primary
target desktop):
- The sign-in window now shows the CE shield (the real artwork from the
Windows build, native size) with the product name and a one-line subtitle —
the login screen looks like the client it reimplements. - The shield is installed as
/usr/share/lustless/lustless-mark.png(same
artwork the dashboard embeds) in every format. StartupWMClass=lustless-agentin both.desktopentries, so Xfce's
taskbar/window list and the Whisker/Zorin menu use the CE icon for the
running window instead of a generic one.- polkit prompts (
org.lustless.break-glass,org.lustless.disable-protection)
now carry the CE shield as their icon.
Carried over from 0.1.5: DNS that stays alive (installer probes the filter
before redirecting, daemon restarts forever) and instant blocked answers;
from 0.1.4: the agent's main loop actually runs and the sign-in window opens
by itself on install and at login.
v0.1.5 — LustLess (DNS that stays alive, and answers instantly)
Linux accountability client (Covenant Eyes-compatible, clean-room reimplementation).
Install
curl -fsSL https://github.com/HenryGetz/LustLess/releases/latest/download/install.sh | sudo bashDetects your distro, downloads the matching package, installs it with the
native tool, starts the agent — and the sign-in window opens. Log in there.
Other ways:
| Distro | File | Command |
|---|---|---|
| Debian / Ubuntu / Zorin / Mint | lustless_0.1.5_amd64.deb |
sudo apt install ./lustless_0.1.5_amd64.deb |
| Fedora | lustless-0.1.5-1.x86_64.rpm |
sudo dnf install ./lustless-0.1.5-1.x86_64.rpm |
| Bazzite / immutable Fedora | lustless-0.1.5-1.x86_64.rpm |
sudo rpm-ostree install ./lustless-0.1.5-1.x86_64.rpm && reboot |
| Arch / EndeavourOS / SteamOS | lustless-0.1.5-1-x86_64.pkg.tar.zst |
sudo pacman -U ./lustless-0.1.5-1-x86_64.pkg.tar.zst |
| Alpine | lustless-0.1.5-r0.apk |
sudo apk add --allow-untrusted ./lustless-0.1.5-r0.apk |
Uninstall: sudo apt purge lustless (or the dnf/rpm-ostree/pacman/apk
equivalent) — restores the DNS, browser-policy and polkit state exactly as
found.
What's new
Fail-closed is about filtering decisions, not about taking the machine off
the network. Three fixes:
- DNS is never broken by an install: the installer probes the filter on
127.0.0.2:53 and, when nothing answers, leaves your/etc/resolv.conf
untouched and tells you why (previously a machine where the daemon could not
start lost all name resolution — no package manager, no updates). - The daemon is never left dead:
Restart=always, no restart limit (was
3 restarts per 10 s, after which systemd gave up and the box had no
resolver), OpenRCrespawn_max=0. The service re-applies the DNS redirect
on every start, so a machine installed while the filter was broken becomes
filtered as soon as it runs. - Blocked answers are instant: signed-out lookups took ~2 s because
per-query process attribution (a SOCK_DIAG netlink dump with a 2 s timeout)
ran before the fail-closed shortcut. Reordered, plus a 30 s circuit breaker
on netlink failures. Measured: 2055 ms → 4-20 ms per query, verdict
unchanged (blocked.lustless.local→ 127.0.0.2).
Carried over from 0.1.4: the agent's main loop actually runs (gio hold guard),
the sign-in window opens by itself on install and at login, the CE shield at
every icon size, and the application-menu launcher.
v0.1.4 — LustLess (agent main loop fixed: install → sign-in window)
Linux accountability client (Covenant Eyes-compatible, clean-room reimplementation).
Install
curl -fsSL https://github.com/HenryGetz/LustLess/releases/latest/download/install.sh | sudo bashDetects your distro, downloads the matching package, installs it with the
native tool, starts the agent — and the sign-in window opens. Log in there.
Other ways:
| Distro | File | Command |
|---|---|---|
| Debian / Ubuntu / Zorin / Mint | lustless_0.1.4_amd64.deb |
sudo apt install ./lustless_0.1.4_amd64.deb |
| Fedora | lustless-0.1.4-1.x86_64.rpm |
sudo dnf install ./lustless-0.1.4-1.x86_64.rpm |
| Bazzite / immutable Fedora | lustless-0.1.4-1.x86_64.rpm |
sudo rpm-ostree install ./lustless-0.1.4-1.x86_64.rpm && reboot |
| Arch / EndeavourOS / SteamOS | lustless-0.1.4-1-x86_64.pkg.tar.zst |
sudo pacman -U ./lustless-0.1.4-1-x86_64.pkg.tar.zst |
| Alpine | lustless-0.1.4-r0.apk |
sudo apk add --allow-untrusted ./lustless-0.1.4-r0.apk |
Uninstall: sudo apt purge lustless (or the dnf/rpm-ostree/pacman/apk
equivalent) — restores the DNS, browser-policy and polkit state exactly as
found.
What's new
v0.1.3 was broken and is superseded: its agent's GTK main loop returned the
instant it started, so the tray menu, the notifications and the promised
sign-in window all did nothing. Fixed here:
gio'shold()returns an RAII guard that releases the application on
drop; called as a bare statement it released a line later, and a windowless
GtkApplicationwith a zero use count returns fromrun()immediately. The
guard now lives for the process lifetime — the main loop, tray menu,
notifications and dialogs all work.- The program name is kept in the argv passed to
run_with_args(an empty
slice leaves GApplication at argc 0, which returns immediately too). lustless-maintainerwroteuser_resolvers = ["a", "b]— invalid TOML,
which made the daemon discard the entire configuration file. Quoting fixed.- The sign-in dialog's default button pointed at a temporary widget (GTK
critical); it now sets a default response.
Carried over from 0.1.3: the install ends on the sign-in window, the CE shield
at every icon size (menu, window icon, dashboard favicon, tray), and
lustless-agent --show / the application-menu entry to reopen it.
v0.1.3 — LustLess (install → sign-in window, original icons)
Linux accountability client (Covenant Eyes-compatible, clean-room reimplementation).
Install
curl -fsSL https://github.com/HenryGetz/LustLess/releases/latest/download/install.sh | sudo bashDetects your distro, downloads the matching package, installs it with the
native tool, starts the tray agent. Other ways:
| Distro | File | Command |
|---|---|---|
| Debian / Ubuntu / Zorin / Mint | lustless_0.1.3_amd64.deb |
sudo apt install ./lustless_0.1.3_amd64.deb |
| Fedora | lustless-0.1.3-1.x86_64.rpm |
sudo dnf install ./lustless-0.1.3-1.x86_64.rpm |
| Bazzite / immutable Fedora | lustless-0.1.3-1.x86_64.rpm |
sudo rpm-ostree install ./lustless-0.1.3-1.x86_64.rpm && reboot |
| Arch / EndeavourOS / SteamOS | lustless-0.1.3-1-x86_64.pkg.tar.zst |
sudo pacman -U ./lustless-0.1.3-1-x86_64.pkg.tar.zst |
| Alpine | lustless-0.1.3-r0.apk |
sudo apk add --allow-untrusted ./lustless-0.1.3-r0.apk |
Uninstall: sudo apt purge lustless (or the dnf/rpm-ostree/pacman/apk
equivalent) — restores the DNS, browser-policy and polkit state exactly as
found.
What's new
- The install ends on the sign-in window: a signed-out agent opens the
login window by itself a couple of seconds after it starts, and the
installer starts it for you (and at every graphical login until you sign
in). Fresh machine → one command → log in in the GUI. lustless-agent --show, the application-menu entry and re-activation of a
running agent all present the same window.- Icons are the original client's: the CE shield at every size the desktop
asks for (hicolor 16/24/32/48/256), as the sign-in window's icon, as the
dashboard favicon and the tray icon. - Carried over from 0.1.2: application-menu launcher, one-liner installer with
Recommends, bind-mounted/etc/resolv.conffix, honest version numbers.
Superseded by v0.1.4 — do not use this release. Its agent's GTK main loop returned immediately on start, so the tray menu, notifications and the sign-in window this release advertised did nothing. v0.1.4 fixes that (gio hold guard, argv, config quoting).
v0.1.2 — LustLess (accountability client, Covenant-Eyes-compatible Linux edition)
Linux accountability client (Covenant Eyes-compatible, clean-room reimplementation).
Install
curl -fsSL https://github.com/HenryGetz/LustLess/releases/latest/download/install.sh | sudo bashDetects your distro, downloads the matching package, installs it with the
native tool, starts the tray agent. Other ways:
| Distro | File | Command |
|---|---|---|
| Debian / Ubuntu / Zorin / Mint | lustless_0.1.2_amd64.deb |
sudo apt install ./lustless_0.1.2_amd64.deb |
| Fedora | lustless-0.1.2-1.x86_64.rpm |
sudo dnf install ./lustless-0.1.2-1.x86_64.rpm |
| Bazzite / immutable Fedora | lustless-0.1.2-1.x86_64.rpm |
sudo rpm-ostree install ./lustless-0.1.2-1.x86_64.rpm && reboot |
| Arch / EndeavourOS / SteamOS | lustless-0.1.2-1-x86_64.pkg.tar.zst |
sudo pacman -U ./lustless-0.1.2-1-x86_64.pkg.tar.zst |
| Alpine | lustless-0.1.2-r0.apk |
sudo apk add --allow-untrusted ./lustless-0.1.2-r0.apk |
Uninstall: sudo apt purge lustless (or the dnf/rpm-ostree/pacman/apk
equivalent) — restores the DNS, browser-policy and polkit state exactly as
found.
What's new
- Sign-in works without a tray: every package ships a
LustLessentry in
the application menu (lustless-agent --show) — sign-in dialog when signed
out, dashboard when signed in. Headless:lustlessctl signin <username>. - One-liner installer (
install.shis attached below), installing with
Recommends (pulls the Xfce SNI host) and starting the per-user tray agent
immediately instead of waiting for a re-login. - Fixed: the maintainer helper no longer aborts
configureon a bind-mounted
/etc/resolv.conf(containers, WSL). - Version numbers are real again: package/CLI version
0.1.2, matching this
release tag (previously the same0.1.0was replaced in place, so upgrades
printed "Unpacking 0.1.0 over 0.1.0").