The Problem: Defined Agents Outpace Actual Use

In the world of AI development, ease of use often leads to accumulation. Claude Code, a powerful tool for building AI workflows, allows users to define custom subagents with frontmatter in ~/.claude/agents/*.md files. This simplicity, however, has a hidden cost: the proliferation of “zombie agents” – those defined but never invoked. A recent personal audit by developer Lily (bokuwalily on Dev.to) revealed a startling statistic: 44 agents that had not been invoked even once in the past 30 days. This isn’t a theoretical problem; it’s a tangible issue of tool bloat that can obscure functionality and slow down development.

The core issue lies in the gap between defining a capability and actively using it. Developers might define an agent for a potential future need, or out of a desire to keep their options open. Over time, these agents become digital clutter, taking up space and potentially causing confusion without providing any current value. This practice mirrors how developers might create numerous utility functions or libraries “just in case,” which then languish unused in their projects.

Lily’s series on her Claude Code environment aims to address these kinds of practical management challenges, following her previous work on automatic terminal window tiling. The goal is to maintain a lean and efficient setup, free from the drag of obsolete or unused components. This specific post tackles the “zombie agent” problem head-on by implementing a system to track subagent invocations.

Implementing a Claude Code Stop Hook for Usage Logging

The solution involves leveraging Claude Code’s “stop hook” functionality. A stop hook is a mechanism that executes a specified command or script when an agent’s execution finishes. By strategically placing a logging script within this hook, it becomes possible to record every time a subagent is called.

The logging mechanism is designed to write data to a JSON Lines (JSONL) file. JSONL is a format where each line is a valid JSON object, making it efficient for streaming and processing log data. The information logged for each invocation includes essential details like the agent name, the timestamp of invocation, and potentially other relevant metadata about the execution context.

The specific implementation details involve creating a script that will be triggered as the stop hook. This script needs to parse the necessary information from the Claude Code execution environment and format it into a JSON object before appending it to the designated JSONL log file. This process ensures that a comprehensive history of subagent usage is maintained.

Diagram illustrating the Claude Code stop hook triggering a logging script to record subagent usage.

Automating the Identification and Culling of Zombie Agents

Mere logging isn't enough; the collected data must be acted upon. Lily’s system incorporates a daily reporting mechanism that processes the JSONL log file. This report consolidates the usage data, making it easy to identify which agents have been invoked and how frequently.

The script then analyzes this report to flag agents that have zero invocations within a defined period, such as the 30-day window Lily used. This automated identification process transforms raw log data into actionable insights. Once identified, these “zombie agents” can be systematically culled from the ~/.claude/agents/ directory, decluttering the environment and improving clarity.

The process can be automated further. After a period of flagging, a script could even prompt the user for confirmation before deleting the identified unused agents. This provides a safety net, preventing accidental deletion of agents that might have a legitimate, albeit infrequent, use case. The ultimate goal is a self-maintaining Claude Code environment where only active and useful agents remain.

Broader Implications for AI Development Workflows

The problem of accumulating unused components is not unique to Claude Code. It’s a common challenge across many software development and AI tooling ecosystems. As developers adopt new tools and frameworks, the temptation to define and configure more than is immediately necessary can lead to significant technical debt.

Lily’s approach offers a practical blueprint for addressing this. By instrumenting the system to log usage and providing automated reporting, developers gain visibility into their actual tool usage. This visibility is crucial for effective maintenance and optimization. It encourages a more mindful approach to agent definition, shifting the focus from “what if” to “what is actually being used.”

This methodology can be adapted to other AI frameworks and even general software development practices. Any system where components can be easily defined but are difficult to track for actual usage could benefit from similar logging and reporting mechanisms. The key takeaway is that proactive measurement and automated cleanup are essential for maintaining efficient and productive development environments in the long term.

The Unanswered Question: Long-Term Maintenance Strategies

While Lily’s solution effectively tackles the immediate problem of identifying and culling zombie agents, it raises a larger question: what are the most effective long-term strategies for managing the lifecycle of custom agents in evolving AI development environments? This system requires manual setup and periodic review, but as Claude Code and its agent ecosystem grow, more robust, perhaps even automated, lifecycle management tools might become necessary. The challenge is to balance flexibility with maintainability, ensuring that powerful customization options don’t become a burden.