DEV Community

hao li
hao li

Posted on

Your Claude Code routine left 618 sessions behind. Mine deletes them while I sleep.

Your Claude Code routine left 618 sessions behind. Mine deletes them while I sleep.

One line from a Show HN thread has been living in my head: "Claude Code's
scheduled tasks (routines) leaves a session behind on every run and in the
desktop app you can only delete them one at a time. We had 618 open sessions
in just one routine."

An hourly routine makes 700+ sessions a month. They pile up in the routine's
Runs list, eat disk, and slow the app down when it loads them — and the only
official way to remove them is clicking delete 618 times.

So I built the other shape of the fix: not a skill you drive by hand, but a
zero-dependency CLI that runs unattended on a schedule and prunes the pile by
policy.

routine-sweeper — pip install routine-sweeper
(GitHub,
PyPI)

routine-sweeper status          # paths, is the app running, counts
routine-sweeper scan            # list routine runs and their status
routine-sweeper sweep           # print the deletion plan (changes nothing)
routine-sweeper sweep --yes     # apply it
Enter fullscreen mode Exit fullscreen mode

How it finds routine runs

Every session is an append-only JSONL transcript under
~/.claude/projects/<project>/<session-id>.jsonl. A routine-started session
opens with a kickoff message of the form:

<scheduled-task name="my-routine" file="...">
Enter fullscreen mode Exit fullscreen mode

The sweeper streams each transcript once: the kickoff identifies the routine,
and any later human-typed message marks the run "engaged". Deletion removes
the transcript, its sidecar directory, and its entry in the
~/.claude/sessions/ live registry.

The safety policy (this is the whole design)

  1. Only routine runs are ever candidates. Ordinary sessions are invisible to the planner, no matter how aggressive the flags.
  2. Runs you replied in are protected. Tool results, skill loads, and harness-injected entries don't count — only something a person typed. --include-engaged opts in explicitly.
  3. Live sessions and runs active in the last 15 minutes are never touched.
  4. Whitelist routine names, session ids, or fnmatch patterns.
  5. Dry-run preview by default. sweep prints the plan and deletes nothing until --yes.

The one thing you must know

The desktop app keeps its Runs list in memory. Delete a run's files while
the app is running and the app can write its in-memory record back to disk —
the run comes back as a "Session not found on disk" ghost. So sweep --yes
refuses while the app is running. Schedule it when the app is closed:

# every night at 3:05am, keep 10 newest runs per routine
5 3 * * * routine-sweeper sweep --yes >> ~/.claude/sweeper.log 2>&1
Enter fullscreen mode Exit fullscreen mode

When the app is closed its in-memory list is rebuilt from disk on next
launch, so swept runs stay gone. If you want instant deletion while the app
is open
, that's a different tool: naw103's
claude-routine-cleanup
skill deletes through the app's own session tool with per-batch approval
cards. Ours is for the pile never growing back.

Also in the neighborhood: sdlc-skills' config-gc — a skill that garbage
collects Claude Code config bloat with a strict "never delete
autonomously, every candidate gets [y/n/skip]" rule. Different domain,
opposite posture: routine-sweeper is designed for unattended scheduled runs,
with protection expressed as policy instead of per-item prompts.

Honest limitations

The transcript format is internal and undocumented — detection rests on the
kickoff marker as observed today, and if a future Claude Code release changes
it, the tool does nothing rather than guess. Deletion is permanent; there is
no trash. And Claude Code's own cleanupPeriodDays (default 30) already
prunes old history by age — the sweeper is for the runs you want gone sooner,
or deliberately kept longer.

Stdlib only, everything local, MIT licensed. 17 fixture-based tests, all
green. If your routines have been quietly stacking up sessions for months —
this is the cron job.

Top comments (0)