Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds
👥 Community & Social
Sichere ProgrammierungRAD Studio 13.2 Gives Delphi a Modern Linux Compiler(22.09.2026 um 16:02 Uhr)
Linux Tipps & HardeningFluidCAD - Open Source CAD that works on Linux(22.09.2026 um 17:45 Uhr)
Linux Tipps & HardeningUbuntu wiki gets its first overhaul in 16 years(22.09.2026 um 20:08 Uhr)
Sicherheitslücken (CVE)Security Weekly - A CRA Resource: Patch Less, Mitigate More(22.09.2026 um 21:00 Uhr)
Sichere ProgrammierungRAD Studio 13.2 Gives Delphi a Modern Linux Compiler(22.09.2026 um 16:02 Uhr)
Linux Tipps & HardeningFluidCAD - Open Source CAD that works on Linux(22.09.2026 um 17:45 Uhr)
Linux Tipps & HardeningUbuntu wiki gets its first overhaul in 16 years(22.09.2026 um 20:08 Uhr)
Sicherheitslücken (CVE)Security Weekly - A CRA Resource: Patch Less, Mitigate More(22.09.2026 um 21:00 Uhr)
Intelligence View
⚡ tsecurity.de Intelligence

Unused MCP Plugins Are Quietly Eating Your Context: A Weekly Auto-Disable Pipeline

This is a continuation of my "Claude Code environment" series. After the previous post on automating git-config backups, this time I'm tackling a problem that sneaks up on you: MCP plugins you enabled once and forgot about keep chipping…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!

This is a continuation of my "Claude Code environment" series. After the previous post on automating git-config backups, this time I'm tackling a problem that sneaks up on you: MCP plugins you enabled once and forgot about keep chipping away at your context, and I'll walk through the three-stage pipeline that auto-disables them on a weekly schedule.



When you enable a plugin, its tool schema is injected at startup even if it's never called once. As these "just leave it on" plugins pile up, the token budget Claude actually has to work with quietly shrinks. In this article I connect detection, auto-disable, and cache archiving into a single flow with real code.






The problem: plugin management that adds but never subtracts



The motivation to install a new plugin is clear. "I want to use this tool" is an active urge. There's no equivalent motivation to remove one. You never get a moment where you notice "hmm, I haven't used that plugin lately."



At the start of every session, Claude Code injects the tool schemas of every plugin marked true under enabledPlugins in settings.json into the context. The more plugins that are "enabled but haven't been invoked once in 30 days," the more the top of your context gets filled with zero-contribution schema on every single run.



After a few months of trying things out and leaving them enabled, the count of Dormant plugins (enabled but unused) can climb past 30.






Architecture: a three-stage pipeline






plugin-usage.sh       → visualize dormant plugins (manual run / weekly report)
plugin-auto-disable.sh → auto-disable anything unused for 30 days, weekly
cleanup-plugin-cache.sh → archive disabled caches into .disabled-cache/






The tail of plugin-auto-disable.sh apply chain-calls cleanup-plugin-cache.sh apply, so there's a single entry point for launchd to start.






Step 1 — Visualize dormant plugins with plugin-usage.sh



~/.claude/scripts/plugin-usage.sh aggregates, from the session JSONL of the past N days (14 by default), only the plugins that were actually invoked as a tool_use.




# plugin-usage.sh excerpt
LOG_DIR="$HOME/.claude/projects/-Users-matsubara"
DAYS="${1:-14}"

find "$LOG_DIR" -maxdepth 1 -name "*.jsonl" -mtime -"$DAYS" -print0 2>/dev/null | xargs -0 cat 2>/dev/null \
| jq -R -r 'fromjson? | select(.type=="assistant") | .message.content[]? | select(.type=="tool_use")
| if .name=="Skill" then ((.input.skill // "") | select(contains(":")) | split(":")[0])
else (.name | select(startswith("mcp__plugin_")) | sub("^mcp__plugin_";"") | split("_")[0]) end'
2>/dev/null \
| sort | uniq -c | sort -rn > "$TMP"






It reports the gap between the number of enabled plugins and the number of distinct invocations as Dormant.




TOTAL_ENABLED=$(jq -r '[.enabledPlugins // {} | to_entries[] | select(.value)] | length' "$SETTINGS")
# Dormant = TOTAL_ENABLED - USED_COUNT







Why aggregate with jq instead of grep



The old implementation used grep for substring matching. It miscounted the "full list of deferred tools" lines in the JSONL (a very long list of available tool names) as "invocations," which made things like terraform show up near the top even though they were never called, and could even make the Dormant count go negative. Passing everything through select(.type=="tool_use") fixes this so that only calls that were actually invoked are counted.




Sample output:




## Summary
- Enabled plugins: **62**
- Distinct plugins referenced in logs: **29**
- Dormant (enabled but never invoked): **33**

## Dormant Plugins (enabled, no recent invocation)
_Candidates for disabling to reduce context tax_
...

## Recommendation
- 33 plugins enabled but unused in last 14 days
- Heavy dormant load — disabling these could free significant context budget
- To disable a plugin: edit `enabledPlugins` in ~/.claude/settings.json






Once Dormant exceeds 30, it prints "Heavy dormant load". This threshold is hardcoded inside the script.






Step 2 — plugin-auto-disable.sh disables automatically, weekly



~/.claude/scripts/plugin-auto-disable.sh is the core. It defaults to dry (no changes); pass apply and it actually disables plugins.




# plugin-auto-disable.sh excerpt
MODE="${1:-dry}"
DAYS="${DAYS:-30}" # observation window (default 30 days)
MIN_CACHE_MB="${MIN_CACHE_MB:-5}" # skip caches smaller than 5MB
WEEKLY_MAX="${WEEKLY_MAX:-5}" # at most 5 per run






Operational flow:




  1. Index the MCP calls and Skill calls from the past 30 days of JSONL

  2. Get the list of plugins marked true in enabledPlugins via python3

  3. Exclude anything in the PROTECTED list

  4. Sort candidates by cache size descending, and narrow to those at least MIN_CACHE_MB, up to WEEKLY_MAX entries

  5. In apply mode, run plugin-disable.sh applycleanup-plugin-cache.sh apply in sequence




# sort candidates by size and pick up to WEEKLY_MAX
SIZED=()
for p in "${CANDIDATES[@]}"; do
size=$(du -sm "$HOME/.claude/plugins/cache/claude-plugins-official/$p" 2>/dev/null | awk '{print $1}')
size="${size:-0}"
[ "$size" -lt "$MIN_CACHE_MB" ] && continue
SIZED+=("${size}\t${p}")
done

SELECTED=()
while IFS=$'\t' read -r sz p; do
SELECTED+=("$p")
[ "${#SELECTED[@]}" -ge "$WEEKLY_MAX" ] && break
done < <(printf '%b\n' "${SIZED[@]}" | sort -rn)






Prioritizing by cache size descending is so the ones that free up the most context get processed first.






Designing the PROTECTED list



The biggest risk of auto-disabling is false positives. The PROTECTED array exists to protect plugins that are "barely used but painful to lose."




PROTECTED=(
remember plugin-dev hookify skill-creator session-report
security-guidance superpowers context7 explanatory-output-style
learning-output-style code-review feature-dev claude-md-management
# LSPs: Claude Code may call these transparently. They don't appear as tool_use
typescript-lsp pyright-lsp php-lsp ruby-lsp rust-analyzer-lsp swift-lsp
# Process tools: may be called ad-hoc
code-simplifier code-modernization ralph-loop agent-sdk-dev mcp-server-dev
playground commit-commands pr-review-toolkit
# Known false positive (trouble in a past session)
azure-cosmos-db-assistant
)






Why each category is protected:

































Category Examples Reason to protect
Infrastructure
hookify superpowers remember
Core of startup hooks and skill invocation. Don't appear as tool_use in the JSONL
LSP
typescript-lsp, etc.
Claude Code itself calls them transparently, internally. Not recorded in logs
Dev support
code-review feature-dev
Used ad-hoc. Needed even after long stretches of no calls
Known false positive azure-cosmos-db-assistant Caused trouble when auto-disabled in the past



If you don't put the LSPs in PROTECTED, you jam up immediately



typescript-lsp and friends are used internally by Claude Code itself. Since the user never explicitly invokes them as a Skill tool or MCP tool, they don't appear in the tool_use logs. If they aren't in PROTECTED, they get auto-disabled while you're using them normally.







Step 3 — Archive caches with cleanup-plugin-cache.sh



Even after you disable a plugin, its cache remains under ~/.claude/plugins/cache/. cleanup-plugin-cache.sh moves those into ~/.claude/plugins/.disabled-cache/.




# cleanup-plugin-cache.sh excerpt
CACHE_DIR="$HOME/.claude/plugins/cache/claude-plugins-official"
ARCHIVE_DIR="$HOME/.claude/plugins/.disabled-cache"
PURGE_DAYS="${PURGE_DAYS:-30}"

for dir in "$CACHE_DIR"/*/; do
name=$(basename "$dir")
if ! echo "$ENABLED" | grep -qx "$name"; then
if
[ "$MODE" = "apply" ]; then
mv "$dir" "$ARCHIVE_DIR/" && echo " archived: $name"
fi
fi
done







It never actually deletes. It only moves things aside with mv, so restoring is reversible with a single mv.



On top of that, the purge submode can physically delete only those items left in .disabled-cache/ for at least PURGE_DAYS (default 30 days).




# physically delete 30 days after archiving
~/.claude/scripts/cleanup-plugin-cache.sh purge









Automate it with launchd at 06:45 on Sundays



I set the weekly schedule in ~/Library/LaunchAgents/com.shun.plugin-auto-disable.plist.




<key>StartCalendarInterval</key>
<dict>
<key>Hour</key>
<integer>6</integer>
<key>Minute</key>
<integer>45</integer>
<key>Weekday</key>
<integer>0</integer> <!-- 0 = Sunday -->
</dict>






Every Sunday at 06:45, plugin-auto-disable.sh apply runs, and its logs are appended to ~/.claude/logs/plugin-auto-disable.log.



Registering and checking:




# register
launchctl load ~/Library/LaunchAgents/com.shun.plugin-auto-disable.plist

# check it's running
launchctl list | grep plugin-auto-disable

# manual test (no changes)
~/.claude/scripts/plugin-auto-disable.sh dry

# manual run
~/.claude/scripts/plugin-auto-disable.sh apply









Pitfalls I hit





  • grep's substring matching picked up the deferred-tools listing lines as "invocations" → until I made jq explicitly filter type=="tool_use", the Dormant count went negative. Things like terraform showed up near the top as ghosts.


  • Forgetting to put the LSPs in PROTECTED, so they get disabled → after typescript-lsp was removed, type checking stopped working. Added it to PROTECTED and restored it.


  • Without setting MIN_CACHE_MB, plugins with tiny caches become targets → anything under 5MB has small impact and only carries risk. Filtered at a 5MB default.


  • Setting WEEKLY_MAX too high drags in plugins you need → capped at 5 per week. There's no need to rush and do it all at once.


  • launchd skips jobs while the Mac is asleep → Sunday morning at 06:45 is a time the machine is often awake. Even if it's skipped, it just carries over to the next week, with no real harm.


  • If plugin-disable.sh doesn't exist, apply is a no-opplugin-auto-disable.sh is a wrapper that calls this script internally. It won't work unless you have the full set of scripts in place.






Summary





  • plugin-usage.sh aggregates the real tool_use events from session JSONL and visualizes dormant plugins

  • The old grep implementation miscounts the deferred-tools listing lines. The right fix is to make jq explicitly filter type=="tool_use"


  • plugin-auto-disable.sh auto-disables based on 30-day inactivity, a 5MB-plus cache, and a cap of 5 per week

  • Always put LSPs, infrastructure plugins, and known false positives in the PROTECTED list. If you don't, plugins you need get removed


  • cleanup-plugin-cache.sh archives caches into .disabled-cache/, with physical deletion via purge after 30 days

  • launchd with Weekday=0 / Hour=6 / Minute=45 runs it unattended every Sunday at 06:45



Next time, to verify the context headroom this buys back, I'll write about the real-time context-usage meter in the statusline that I built.






Written by **Lily* — I ship iOS apps and automate my content stack with Claude Code.

Follow along: Portfolio · X · GitHub*

Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Unused MCP Plugins Are Quietly Eating Your Context: A Weekly Auto-Disable Pipeline

Thematisch verwandte Begriffe: Unused, Plugins, Quietly, Eating · 6 Treffer

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-77259 | MCP Atlassian is a Model Context Protocol (MCP) server for Atlassian pro…
Advisory →
TTS Reader • tsecurity.de Voice
tsecurity.de Icon
tsecurity.de App
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
🔖 Gespeicherte Artikel
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel Rechts: nächster Artikel unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...

Zurück: vorheriger Vor: nächster
↗ Original-Quelle
Social Reaktionen Deine Reaktion zählt
Einstufung & Relevanz-Poll 0 Stimmen
In sozialen Netzwerken teilen 1-Klick