|
Some checks are pending
CI / Test & Clippy (push) Waiting to run
M1-M25 are shipped and the submission is closed, but §8 said so only in prose. Without the terminal marker the loop would hard-pause here as an ambiguous §8 instead of exiting clean. milestone-cycle v1.12.0 writes one canonical marker and re-parses it before committing, so this file is now round-trip clean against the loop's own parser. |
||
|---|---|---|
| .github/workflows | ||
| crates | ||
| docs | ||
| evals | ||
| fixtures/fake-library | ||
| packaging | ||
| .gitignore | ||
| AGENTS.md | ||
| Cargo.lock | ||
| Cargo.toml | ||
| CHANGELOG.md | ||
| CLAUDE.md | ||
| GEMINI.md | ||
| LICENSE | ||
| README.md | ||
| ROADMAP.md | ||
| rust-toolchain.toml | ||
MediaLint
MediaLint audits movie and TV libraries for Plex naming problems. It emits terminal, JSON, or self-contained HTML reports. Fixes are dry-run by default; applying a fix requires an explicit command and produces an undo journal.
The source workspace is version 0.23.2. Its reusable core supplies the scan pipeline, an SQLite history store, and tracked multi-batch undo. The GUI crate opens a frameless desktop shell with a custom titlebar and five-item navigation rail. Its Dashboard shows scoped severity deltas, distinct-file library health, the healthy-file count, a green percentage/progress bar, and up to 30 complete scans of trend history. Re-scan reports live progress and supports cancellation through a bounded Tokio worker bridge; the footer retains the latest scan's date, file count, and finding count and shows TMDB/AI configuration readiness. Slint remains on the main thread. The Findings view combines Rule, Library, severity, and search filters; Approve all approves every fixable row currently shown by those filters. It also records deterministic alternatives. Dividers resize all five data columns. Optional GPT-5.6 advice appears in the Suggested column and finding detail, but never feeds model output into the fix planner.
The Fix view rebuilds approved moves against the current filesystem, shows unsafe rows before apply, confirms one journaled batch, reports progress, and offers immediate undo or a fresh plan for remaining approvals. A prepared plan can be cleared without applying it; no-op suggestions are labeled already correct.
History lists saved scans and applied batches below a fixed tab strip. Rows show date and time with semantic error, warning, and unverifiable colors. Its Snapshot action opens a saved report read-only; the Findings banner explains that approvals are disabled and can replace it with a live scan. Saved reports also export to private JSON and HTML files. Scan deletion is confirmed, and batches with a current valid journal can be restored against the active library paths.
Settings shows each Movie, UHD movie, and TV location as command-line, MediaLint-owned, or inherited. It supports multiple locations per media kind, native folder selection, explicit inherit/remove actions, and unknown TOML preservation. Stored TMDB and AI service keys are never projected into the UI. The GUI can select hosted OpenAI or a local Responses-compatible endpoint, change the review model, replace credentials, verify TMDB, change saved-scan retention, and open the data folder.
Version 0.23.2 is the selected OpenAI Build Week submission release. The
scanner, deterministic rules, metadata resolver, reports, fix planner, apply,
and undo predate the event baseline commit 08b0868. The Build Week range ends
at the v0.23.2 tag.
It adds structured partial-scan issues, optional GPT-5.6 review for
parser edge cases, compatibility and AI-isolation tests, a local Gemma quality
evaluation, Linux AppImages, a reusable scan pipeline,
SQLite history, and the desktop GUI. Version 0.17.0 added
the first complete view and connected it to the scan pipeline and history
store; version 0.18.0 shipped the Findings review workbench at 6c90259;
version 0.19.0 shipped staged Fix and Undo at 27edaf0. Version 0.20.0 shipped
the History view at 12d9426. Version 0.21.0 shipped provenance-aware Settings,
private atomic config persistence, and immediate configurable retention at
3980a54. Version 0.22.0 shipped the production-bridge workflow, cancellation,
and history-degraded hardening at e817a9b. Version 0.23.0 incorporates the
owner-driven GUI dogfood fixes and the safe 500-title mock-library cycle at
3dad528. Version 0.23.1 at 9a5b734 fixes individual approval toggles in
Findings and local Responses compatibility. Version 0.23.2 shows returned AI
advice in the Suggested column and selects a reviewed row so its rationale is
immediately visible. The v0.23.2 source tag and generated archives are
available on Codeberg
and GitHub. The public
2:19 Build Week demonstration
shows the desktop workflow, AI review, and configuration.
The custom milestone-cycle v1.10.0 skill used to execute most of the roadmap
is available as a
judge archive.
It contains the source template, Claude and Codex renders, host scripts, resume
hook, 152-check test suite, and MediaLint usage notes.
Install
Download the current Linux x86_64 AppImage and checksum, then run:
sha256sum -c MediaLint-0.23.2-x86_64.AppImage.sha256
chmod +x MediaLint-0.23.2-x86_64.AppImage
./MediaLint-0.23.2-x86_64.AppImage
The default entry point opens the GUI. Pass --cli before normal CLI
arguments, or run the bundled credential-free fixture with:
./MediaLint-0.23.2-x86_64.AppImage --demo --format terminal --no-history
If FUSE is unavailable, add --appimage-extract-and-run before the MediaLint
arguments. The AppImage SHA-256 is
1e02cf6c54ab2326706ed6a21a6cc819275c7a2ce03ad070153c0644fec7834c.
Build the CLI from source
MediaLint v0.23.2 uses two crates from avatarr, so clone both repositories into the same parent directory. The avatarr commit below matches the release build.
mkdir medialint-build
cd medialint-build
git clone https://codeberg.org/alan090/avatarr.git
git -C avatarr checkout a00ff54e9da46369fceaaa9f0d5c35c8d0cd6ee4
git clone --branch v0.23.2 https://codeberg.org/alan090/medialint.git
cd medialint
rustup toolchain install 1.96 --profile minimal
cargo +1.96 build --release --locked -p medialint
./target/release/medialint --help
Run the included fixture without credentials:
./target/release/medialint \
--movie-dir fixtures/fake-library/Movies \
--uhd-movie-dir "fixtures/fake-library/UHD Movies" \
--tv-dir fixtures/fake-library/TV \
--format terminal --no-history
Build the GUI from the same checkout with
cargo +1.96 build --release --locked -p medialint-gui.
packaging/build-appimage.sh requires Docker, mksquashfs, and curl. It is
the reproducible builder for the earlier v0.11 CLI-only artifact; the v0.23.2
GUI artifact's build and smoke-test record is in
docs/qa/v0.23.2-appimage-smoke.md.
Usage
Audit configured roots or pass them directly:
medialint --format terminal
medialint --movie-dir /media/Movies --tv-dir /media/TV --format json > report.json
medialint --format html > report.html
medialint history list
medialint history show 1 --format json
medialint history prune --keep 30
Completed scans are saved under $XDG_DATA_HOME/medialint/medialint.db.
Pass --no-history to skip one scan. History failures produce a warning but do
not discard the report.
Desktop GUI
Build and launch the desktop application from the source checkout:
cargo run -p medialint-gui
cargo build --release -p medialint-gui
./target/release/medialint-gui
The navigation rail opens Dashboard for library health and scan progress, Findings for review and approval, Fix for the apply/undo workflow, History for saved scans and batches, and Settings for library paths, credentials, and retention. Library locations can be typed or selected with Browse…. Add Movie/UHD movie/TV location keeps existing locations and adds another scan root.
Settings also configures advisory AI review. OpenAI uses the hosted
Responses API and requires a stored key or OPENAI_API_KEY. Local accepts
an OpenAI-compatible Responses API URL and model name; its API key is optional.
MediaLint writes stored credentials to its owner-only config and never displays
their values after entry. The footer lights are green when the corresponding
TMDB or AI configuration is usable; they are configuration indicators, not
continuous network probes.
Without a TMDB key, deterministic filename parses appear as ParsedLocal
suggestions. Rows that need metadata stay unavailable for approval and explain
that a key can expand lookup. Completed scans live at
$XDG_DATA_HOME/medialint/medialint.db; each applied batch gets a private
journal under $XDG_DATA_HOME/medialint/journals/.
If the history database cannot open, Dashboard and History show the storage error. Scanning remains available, and approved moves can be applied and undone through their journal. Cancelling a scan discards its partial report and writes no history row; a new scan can start after cancellation completes.
Review qualifying parser edge cases with GPT-5.6:
OPENAI_API_KEY=... medialint --ai-review --format json
--ai-review is explicit opt-in. It sends media kind, deterministic
rules/messages, any deterministic suggestion, and paths relative to configured
library paths. Requests use gpt-5.6, store: false, strict Structured Outputs,
and sequential batches of at most 20. Keys, absolute roots, prompts, and raw
responses are not logged. Model advice is stored separately from Resolution;
the fix planner does not turn it into a move.
Preview, apply, and undo a report:
medialint fix report.json
medialint fix report.json --apply --trusted-root /media/Movies
medialint undo --trusted-root /media/Movies
Configured medialint and avatarr library paths are trusted automatically.
Use repeatable --trusted-root arguments for roots supplied only through scan
directory overrides. Apply and undo reject paths outside those current roots,
and never replace an occupied destination. Default apply runs create separate
private journals. medialint undo selects the newest existing journal; use
--journal to choose one explicitly.
The AppImage demo library contains tiny placeholder .mkv files and exercises
filenames only.
Contributing
Run the pinned workspace gate before submitting changes:
cargo test --workspace
cargo clippy --workspace --all-targets -- -D warnings
Commits use Alan <alan.c.gaudet@gmail.com> through the global Git config.
License
GPL-3.0-or-later. See LICENSE.