Skip to content

Why I built AgentDust

Published

My Mac was running hot, so I checked what my AI coding sessions had left behind. I found six processes, each 7 to 9 days old: two dev servers, a mock server, a browser driver with its MCP server, and a stale Node script. Three held ports, and all six were idle at 0% CPU. They did not explain the heat. They did show me something I had no good way to see: work from old sessions was still running.

I built AgentDust to make that work visible and offer cleanup with explicit approval. The difficult part is deciding which process belongs to an ended session, and whether it is still the same process when I approve stopping it.

Why a process name or parent is not enough

A coding agent starts more than its own command. It can launch a development server, a browser driver or a Model Context Protocol (MCP) server that gives it tools. Those helpers have their own lifetimes. Closing the coding session does not always close everything it started. Related reports remain open for Claude Code MCP servers and Codex MCP helpers.

The tempting cleanup rule is to find an old node process, or a process whose parent PID is 1, and stop it. That would also catch work I still need. A process name tells me what program is running. Its parent tells me part of its current relationship to other processes. Neither tells me whether the session that used it has ended.

In one test, a background Node job had parent PID 1 after 0.3 seconds while its agent was still running. On macOS, launchd can adopt a helper when its immediate parent exits. The coding agent can remain alive further up that original chain. That observation rules out using parent PID alone as permission to stop something. It is one measured case, not a timing guarantee for every background job.

Record ownership while the session is running

Trying to reconstruct ownership after everything has ended loses evidence. AgentDust records it while the session is active. A Claude Code hook creates a session marker and passes it to child processes through Claude Code’s environment file. Descendants inherit the marker, which gives AgentDust evidence associating them with that session even after they are reparented.

The local journal stores a keyed digest of the marker. When AgentDust inspects a process, it reads the marker, hashes it and compares the result with the journal. The raw marker is not stored in the journal. Command text and whole process environments are not recorded either.

  1. Record the session A hook journals the session and writes a marker that child processes inherit.
  2. Match the helper An inherited marker connects a process to its session.
  3. Review the evidence Doctor explains the class. A plan keeps eligible processes.
  4. Approve and recheck I type the code. AgentDust checks the process again before signaling.
Ownership is evidence for classification. Approval and a fresh identity check are separate steps in the cleanup flow.

agentdust doctor is read only. It explains whether a process is owned by a live session, owned by an ended session, suspect, managed or unknown. A launchd job or Homebrew service is managed. Missing ownership evidence does not establish that a process is abandoned. Only processes owned by ended sessions and suspects can enter a cleanup plan. Suspects need their own approval because their ownership is less certain.

Approval is a decision, not a command argument

I want the coding agent to help inspect the evidence. The cleanup flow still asks me to decide. AgentDust shows a generated code in an approval form. I type it myself. The MCP tool accepts no approval code supplied as an argument by the model. This constrains the tool interface; it does not prove human presence when a model can control the host through other means. A cancellation, wrong code or unanswered form sends no signal.

The process can change while I read that form. A session can resume. A helper can exit. The operating system can reuse its PID for another process. So approval does not make the old inventory current.

Before acting, AgentDust takes a fresh inventory and classifies the process again. It compares the boot session, PID, start time, user and executable path with the planned identity. A changed identity or classification aborts that item. On a match, it sends one SIGTERM to that PID, asking the process to exit. It does not signal a process group or escalate to SIGKILL. A process that stays alive is reported as a survivor.

There is still a narrow PID reuse race between the final identity read and the signal. Rechecking reduces the window; it does not make those operating system calls atomic. The design and remaining limits are part of the project documentation.

What I measured

A hook sits in the coding session’s path, so its cost matters. The M0 measurement recorded a hook p50 of 2.5 ms per event on a macos-15 runner. That is a result from that runner, not a promise for every Mac.

The parser reads process data returned by the macOS kernel. One fuzz run exercised 27,196,230 inputs in 61 seconds without a crash. Fuzzing searches for failures in generated inputs; that count is evidence about the run, not proof that the parser has no bugs.

The same M0 report records two clean builds that produced byte-identical binaries. The release pipeline builds and packages the binary through GitHub Actions, publishes checksums and a software bill of materials, and creates attestations linking artifacts to the workflow. The release guide explains how to verify those artifacts. Reproducibility helps check the build; it does not establish that the source is correct.

Use it with Claude Code

The 0.1.0 release supports Claude Code on Apple silicon macOS. The prebuilt binary comes from a custom Homebrew tap. Install it and connect the hooks and MCP server:

brew install hamzahamidi/agentdust/agentdust
agentdust setup
agentdust doctor

The install command names the tap owner, tap and formula. agentdust setup shows a diff and asks before changing Claude Code’s configuration. doctor lets me inspect the findings before considering cleanup.

Inside Claude Code, I can ask it to inspect leftovers and create a cleanup plan. The optional AgentDust plugin adds /agentdust:cleanup for the same workflow. It relies on the separately installed server and hooks, and uses the same approval form. In a terminal outside an agent, agentdust apply offers the approval flow directly.

Codex, Cursor and additional platforms are on the roadmap. The shipped support is narrower. For installation, removal, privacy and cleanup limits, start with the README and security policy.

All notes