feat: Add lightweight web UI for monitoring, activity history & runtime control#337
Open
lolimmlost wants to merge 7 commits intoManiMatter:latestfrom
Open
feat: Add lightweight web UI for monitoring, activity history & runtime control#337lolimmlost wants to merge 7 commits intoManiMatter:latestfrom
lolimmlost wants to merge 7 commits intoManiMatter:latestfrom
Conversation
Added note about Decluttar V2 release and breaking changes.
AttributeError: 'Response' object has no attribute 'get'
…ntime control
Adds a FastAPI-based web interface that runs alongside the existing job loop
as a sibling asyncio task. Zero new required config — defaults to enabled on
port 9999 and can be disabled via `web.enabled: false` or `WEB_ENABLED=false`.
Key features:
- Dashboard with real-time queue view, instance cards, and live activity feed
- Activity log with search, filtering (by job/arr/action/date), and pagination
- Runtime settings editor (toggle test_run, enable/disable jobs, adjust strikes)
- Download protection via UI (supplements qBit "Keep" tag)
- "Run Now" button to manually trigger a cycle
- SSE-powered live updates — no polling needed for real-time state
- Full REST API with auto-generated OpenAPI docs at /api/docs
Architecture:
- EventBus decouples job system from web layer (no-op when web disabled)
- SQLite via aiosqlite for activity history and config overrides
- Jinja2 + HTMX + Alpine.js frontend — no build step, no Node tooling
- Pico CSS for dark-theme styling
New files: src/web/ (events, database, app, routes, config_manager, templates)
Modified: main.py, job_manager, removal_job, removal_handler, strikes_handler,
settings (_general, _user_config, _instances), Dockerfile, requirements
All 192 existing tests pass unchanged.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ponent Inline Jinja2 tojson in @click attributes was getting double-escaped, causing raw JS to render as button text. Moved to a queueRow() Alpine component function instead. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Can we get this reviewed and merged please? |
Author
I appreciate your enthusiasm but definitively needs testing as I'm getting webui errors after a weeklong usage. I'll review the code once again this weekend. |
|
Amazing, thanks 🙏 |
Author
|
I'm attempting this fix for the crashing. |
Wrap per-instance job runs and download client jobs in try/except so a Sonarr/Radarr timeout logs an error and continues instead of crashing. Add main_with_restart() wrapper so even unexpected failures auto-recover after 30s while the web server stays up independently. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Author
|
Pushed a fix for a crash that was happening after ~1 week of uptime. Root cause: When Sonarr/Radarr timed out (read timeout=15s), the unhandled exception propagated up through Fix (commit 25f3e2f):
Verified running 24hrs+ on production with multiple Sonarr/Radarr timeouts — all recovered cleanly on the next cycle, no crashes. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Decluttarr currently has zero visibility into what it's doing — all config is YAML, all output is logs. This PR adds a lightweight web UI for monitoring, activity history, and runtime control without changing the existing daemon behavior.
test_run, enable/disable jobs, adjustmax_strikes/min_speedat runtime without editing YAML or restarting/api/docsTech Choices
Architecture
The web server runs as a sibling asyncio task alongside the existing main loop — both share the same event loop and process memory. An
EventBusclass decouples the job system from the UI: jobs emit events at decision points, the web layer (ActivityRecorder + SSE) consumes them. When web is disabled, aNoOpEventBusis used with zero overhead.Database Schema (SQLite)
Three tables:
activity_log(action history),protected_downloads(UI-managed protection),config_overrides(runtime config layered on top of YAML). Auto-created at./data/decluttarr.db.API Endpoints
/api/status/api/queue/api/activity/api/strikes/api/protected/{id}/api/config/api/config/test-run/api/config/reload/api/events/api/triggerConfiguration
Zero new required config. Defaults to enabled on port 9999.
Migration / Backward Compatibility
New Dependencies
Files Changed
New (15 files in
src/web/): events.py, database.py, app.py, routes.py, config_manager.py, templates (base, dashboard, activity, settings, 4 partials), static/style.cssModified (11 files): main.py, job_manager.py, removal_job.py, removal_handler.py, strikes_handler.py, _general.py, _user_config.py, _instances.py, Dockerfile, requirements.txt, config_example.yaml
Screenshots
The UI uses Pico CSS dark theme with color-coded badges for arr instances (Sonarr=blue, Radarr=yellow, etc.), action types (removed=red, recovered=green, flagged=amber), and strike counts.
Test Plan
pytest tests/— all 192 existing tests passhttp://localhost:9999test_runtoggle via settings page takes immediate effectEXPOSE 9999WEB_ENABLED=falsethat web is fully disabled🤖 Generated with Claude Code