AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Arr Library Hygiene

skill-t3chnaztea-arr-stack-skills-arr-library-hygiene · by t3chnaztea

>-

— No reviews yet
0 installs
22 views
0.0% view→install

Install

$ agentstack add skill-t3chnaztea-arr-stack-skills-arr-library-hygiene

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • ✓ Prompt-injection patterns
  • ✓ Secret / credential exfiltration
  • ✓ Dangerous shell & filesystem operations
  • ✓ Untrusted network calls
  • ✓ Known-malicious package signatures

What it can access

  • ● Network access Used
  • ✓ Filesystem access No
  • ✓ Shell / process execution No
  • ✓ Environment & secrets No
  • ✓ Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-t3chnaztea-arr-stack-skills-arr-library-hygiene)

Reliability & compatibility

✓ Security review passed
0 installs to date
— no reviews yet
● 2mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Arr Library Hygiene? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Arr Library Hygiene

The monitored flag drives every automated search. When it drifts from what you intended, the app either hunts for things it should ignore or sits silent when you expect it to work. Both look like bugs elsewhere.

Assumes arr-connect. In particular: deletes are permanent, there is no recycle bin unless you configured one, and a command returning queued means accepted, not successful.

Three ways monitoring drifts

1. Segment-aired shows create permanent phantom missing episodes

Cartoons and sketch shows that aired as segments are often catalogued with each segment as its own episode entry, while your files are whole broadcast episodes. The app counts the extra segment entries as missing forever. Every night it re-searches, grabs a season pack, fails to import with episode file already imported, and refills the queue. The queue length looks alarming and never drops.

Diagnose by comparing counts, not by reading the queue:

curl -sf -H "X-Api-Key: $ARR_KEY" "$ARR_URL/api/v3/series/$SID?includeSeriesStats=true" \
  | jq '{title, episodeCount: .statistics.episodeCount,
         episodeFileCount: .statistics.episodeFileCount,
         pct: (.statistics.episodeFileCount / .statistics.episodeCount * 100 | floor)}'

A gap that never closes across days, on a show that finished airing years ago, is this pattern rather than a sourcing problem.

Fix: unmonitor only the monitored-but-file-less episodes, then clear the stuck queue.

# the episodes that will never arrive
IDS=$(curl -sf -H "X-Api-Key: $ARR_KEY" "$ARR_URL/api/v3/episode?seriesId=$SID" \
  | jq -c '[.[] | select(.monitored and (.hasFile | not)) | .id]')

curl -sf -X PUT -H "X-Api-Key: $ARR_KEY" -H 'Content-Type: application/json' \
  -d "{\"episodeIds\": $IDS, \"monitored\": false}" \
  "$ARR_URL/api/v3/episode/monitor"

For a finished show this stops the grabbing and keeps every existing file. For a still-airing show, do not do this: you would unmonitor genuinely missing episodes. Check the series status first.

2. Deleting episode files auto-unmonitors them

DELETE /api/v3/episodefile/{id} flips those episodes to monitored: false. It does this per episode, so the season and series flags still read as monitored and everything looks fine in the UI. A subsequent search matches zero episodes and reports success.

This is the "I deleted the bad files so it would grab better ones, and nothing happened" case. The delete worked. The re-arm step is missing.

Correct sequence when pruning files for a re-grab:

# 1. delete the files
curl -sf -X DELETE -H "X-Api-Key: $ARR_KEY" "$ARR_URL/api/v3/episodefile/$FID"

# 2. RE-ARM. this is the step everyone skips
curl -sf -X PUT -H "X-Api-Key: $ARR_KEY" -H 'Content-Type: application/json' \
  -d "{\"episodeIds\": [$EID], \"monitored\": true}" \
  "$ARR_URL/api/v3/episode/monitor"

# 3. now search
curl -sf -X POST -H "X-Api-Key: $ARR_KEY" -H 'Content-Type: application/json' \
  -d "{\"name\": \"MissingEpisodeSearch\", \"seriesId\": $SID}" \
  "$ARR_URL/api/v3/command"

Diagnostic when a search returns queued and the indexers stay quiet: count how many episodes are actually monitored. Zero means step 2 was skipped.

curl -sf -H "X-Api-Key: $ARR_KEY" "$ARR_URL/api/v3/episode?seriesId=$SID" \
  | jq '[.[] | select(.monitored)] | length'

3. A metadata refresh can re-monitor seasons you turned off

The daily series refresh re-syncs from the metadata provider. When the provider restructures a series or adds episodes, seasons you deliberately unmonitored have been observed flipping back to monitored, sometimes within a day. If an automated queue cleaner is running, this produces a delete-and- re-search loop that repeats on the cleaner's interval.

Practical consequences:

  • Never trust a previous session's outcome. When asked "did that stay

unmonitored", re-query and inspect seasons[].monitored rather than citing what you set last week.

  • For a decision you want to be permanent, prefer a stronger mechanism than a

per-season toggle: remove the series, or set the series-level monitor option so new content is not picked up at all.

curl -sf -H "X-Api-Key: $ARR_KEY" "$ARR_URL/api/v3/series/$SID" \
  | jq '{title, monitored, monitorNewItems, seasons: [.seasons[] | {seasonNumber, monitored}]}'

Replacing a file with a better one

An arr will not downgrade in place, and will not re-grab something it already considers satisfied. To deliberately replace a file with a different one (usually smaller, occasionally a different edition), the existing file has to go first.

This is destructive and it is where agents cause real damage. The guarded sequence:

  1. Confirm a satisfactory replacement actually exists before deleting

anything. Run an interactive search and read the results.

``bash curl -sf -H "X-Api-Key: $ARR_KEY" "$ARR_URL/api/v3/release?movieId=$ID" \ | jq '.[] | {title, quality: .quality.quality.name, size, customFormatScore, rejected, rejections}' ``

  1. Check why candidates were rejected. A release rejected only by

upgrade protection will become grabbable once the file is gone. A release rejected for size, format score, or an indexer rule will still be rejected afterwards, and deleting leaves you with a gap.

  1. Set a profile that excludes the current quality, otherwise the app may

simply re-grab what you just deleted.

  1. Delete the file, re-arm monitoring, then **grab the specific release by

its guid** rather than firing a blind search. A blind search can pull a different cut, an extended edition, or a worse encode.

  1. Verify by polling the queue about 20 seconds later. Checking

immediately false-negatives because the grab has not registered yet.

If step 1 or 2 fails, skip the title. Leaving a large file in place is always better than creating a hole in the library. Say which titles you skipped and why.

For bulk passes, write the target list to a file, print it, and have a human read it before anything is deleted. Mass irreversible media deletion is not an operation to run on inference.

Edition traps worth knowing before a downsize pass: for some catalogue titles the only 4K release is an extended cut that is larger than the standard remux you were trying to shrink, so the swap is a net loss. Compare actual sizes, not quality labels.

Clearing a stuck queue

# what is actually in there and why
curl -sf -H "X-Api-Key: $ARR_KEY" "$ARR_URL/api/v3/queue?pageSize=100" \
  | jq '.records[] | {title, status, trackedDownloadStatus, trackedDownloadState,
                      errorMessage, statusMessages}'

trackedDownloadState: importBlocked or importFailed is the app telling you the download finished but could not be moved into the library. Common causes: a permissions mismatch between the download directory and the library, a path mapping the app cannot resolve, or the phantom-episode loop above.

To flush stuck items, remove them from the client and blocklist the releases so the same bad grab is not immediately retried:

curl -sf -X DELETE -H "X-Api-Key: $ARR_KEY" \
  "$ARR_URL/api/v3/queue/bulk?removeFromClient=true&blocklist=true&skipRedownload=true"

Drop skipRedownload if you do want it to hunt a replacement. Keep it when you are clearing a loop, or you restart the loop.

What an automated queue cleaner actually needs

If you run a queue-cleaning companion, understand what drives it: the arr API, not the download client. Failed-import detection reads the arr queue for import-blocked states, strikes items over repeated passes, and on the limit calls the arr's own queue delete with removal and blocklisting. The arr then handles removal from whichever client held it.

Two consequences that save wasted effort:

  • Such tools commonly support only torrent clients in their client config.

That does not mean Usenet downloads go unhandled. Usenet items bypass the client-matching branch and are handled through the arr API path anyway. Do not go looking for a Usenet download-client integration that does not exist and is not needed.

  • A per-app strike setting of -1 usually means "inherit the global", not

"disabled". Read the tool's own resolution logic before concluding a feature is off.

More blocklisting is not the fix for content that has genuinely aged out of your sources. That is a source diversity problem: add indexers.

Media server side effects

If a media server indexes your download directory as a library location (the watch-while-downloading setup), in-flight downloads get indexed as extra versions of the same title. When the arr imports and the download directory disappears, a client can still select the now-dead version and fail playback with a not-found error on the file part.

Resolve that with a library rescan and empty-trash, or by simply waiting for the next scan. Do not resolve it by deleting the media entry through the media server's API: on at least one major media server that call deletes the underlying file from disk, and it re-points parts to renamed or moved files, so an entry that looked orphaned a minute ago may now point at a live import. That combination has destroyed freshly imported files.

Related: if you inspect a media server's SQLite database directly, copy the write-ahead log alongside it or you will read stale rows and act on them. Querying the API is safer than copying a live database.

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.