opencode icon indicating copy to clipboard operation
opencode copied to clipboard

[BUG/FEATURE]: Subagent sessions accumulate without cleanup option - causes storage bloat and UI clutter

Open NachoFLizaur opened this issue 1 month ago • 1 comments

Feature hasn't been suggested before.

  • [x] I have verified this feature I'm about to request hasn't been suggested before.

Describe the enhancement you want to request

Summary

Subagent sessions (spawned via the Task tool / @agent mentions) accumulate in storage and the session switcher UI (ctrl+x left/right) without any automatic cleanup or manual deletion option. This causes:

  1. UI clutter - Session switcher fills with completed subagent sessions
  2. Storage bloat - Session data, messages, and parts accumulate indefinitely
  3. Errors on manual deletion - Deleting session files directly causes "Session not found" errors due to orphaned data

Environment

  • OpenCode Version: 1.0.164
  • OS: macOS (also affects Linux)
  • Terminal: Any

Steps to Reproduce

  1. Start OpenCode in any project
  2. Use the Task tool multiple times (e.g., @code-explorer find all files related to...)
  3. Complete several subagent tasks
  4. Press ctrl+x left or ctrl+x right to view sessions
  5. Observe: Completed subagent sessions accumulate with no way to close/delete them
  6. Check storage: ls ~/.local/share/opencode/storage/session/global/
  7. Observe: Subagent session files keep accumulating

Expected Behavior

  • Completed subagent sessions should either be auto-cleaned or have a UI option to close/delete
  • Deleting a session should clean up all related data (messages, parts, diffs)

Actual Behavior

  • Subagent sessions persist indefinitely
  • No UI option to close or delete them
  • Manual file deletion causes orphaned data and "Session not found" errors

Root Cause Analysis

When a subagent is spawned, OpenCode creates multiple related data files:

~/.local/share/opencode/storage/
├── session/<project>/ses_xxx.json      # Session metadata (has parentID field)
├── message/ses_xxx/                     # Messages for the session
├── part/msg_xxx/                        # Message parts (tool calls, etc.)
└── session_diff/ses_xxx.json           # File change tracking

Key identifier: Subagent sessions have a parentID field in their JSON:

{
  "id": "ses_xxx",
  "parentID": "ses_parent",  // <-- This indicates it's a subagent
  "title": "Task description (@agent-name subagent)"
}

When manually deleting only the session file, the message/, part/, and session_diff/ data becomes orphaned, causing the "Session not found" error when the UI tries to access them.

Workaround

Option A: Custom OpenCode Command

Create a custom command at ~/.config/opencode/command/cleanup-subagents.md:

cleanup-subagents.md

---
description: Clean up completed subagent sessions for current project
---

Clean up all completed subagent sessions. These are child sessions spawned by the Task tool that accumulate over time.

## Task

Execute the cleanup based on the scope argument:
- Default (no args): Clean current project's subagents only
- `all`: Clean ALL subagent sessions (global + all projects)  
- `global`: Clean only global subagents
- `list`: Just list subagent sessions without deleting

## Step 1: Identify Current Project

First, check what projects exist and find the current one:

!`cat ~/.local/share/opencode/storage/project/*.json 2>/dev/null | grep -E '"(id|worktree)"' | paste - - | head -20`

## Step 2: Determine Scope

The user's argument is: `$ARGUMENTS`

Based on this:
- If empty or "project": Find the project matching the current working directory and clean only that
- If "global": Clean only `~/.local/share/opencode/storage/session/global/`
- If "all": Clean all session directories
- If "list": Just show what would be deleted

## Step 3: Execute Cleanup

For the determined scope, run the cleanup script. Here's the pattern:

```bash
cd ~/.local/share/opencode/storage

# For each target directory (e.g., session/global/ or session/<project-hash>/)
# Find sessions with parentID (subagent sessions)
for f in session/<TARGET>/*.json; do
  if grep -q '"parentID"' "$f" 2>/dev/null; then
    ses_id=$(basename "$f" .json)
    # Delete: session file, message dir, session_diff
    rm -f "$f"
    rm -rf "message/${ses_id}"
    rm -f "session_diff/${ses_id}.json"
  fi
done

# Clean orphaned part directories
for part_dir in part/msg_*/; do
  msg_id=$(basename "$part_dir")
  # Check if any message dir references this
  found=$(find message -name "${msg_id}.json" 2>/dev/null | head -1)
  [ -z "$found" ] && rm -rf "$part_dir"
done
```

## Step 4: Report Results

After cleanup, report:
1. How many subagent sessions were deleted
2. How many orphaned part directories were cleaned
3. Remaining session count

## Important

- ONLY delete sessions with `"parentID"` field - these are subagents
- Sessions WITHOUT parentID are main conversations - NEVER delete these
- Storage path: `~/.local/share/opencode/storage/`
```

Then use it with:

/cleanup-subagents          # Clean current project
/cleanup-subagents all      # Clean all projects  
/cleanup-subagents global   # Clean only global
/cleanup-subagents list     # List without deleting

Option B: Standalone Bash Script

#!/bin/bash
cd ~/.local/share/opencode/storage

# Delete subagent sessions (those with parentID)
for f in session/*/*.json; do
  if grep -q '"parentID"' "$f" 2>/dev/null; then
    ses_id=$(basename "$f" .json)
    rm -f "$f"
    rm -rf "message/${ses_id}"
    rm -f "session_diff/${ses_id}.json"
  fi
done

# Clean orphaned part directories
for part_dir in part/msg_*/; do
  msg_id=$(basename "$part_dir")
  found=$(find message -name "${msg_id}.json" 2>/dev/null | head -1)
  [ -z "$found" ] && rm -rf "$part_dir"
done

Suggested Fixes

Option 1: Auto-cleanup on completion When a subagent task completes, automatically clean up its session data.

Option 2: Add UI controls

  • Add "Close" or "Delete" action in the session switcher for subagent sessions
  • Visual distinction between main sessions and subagent sessions
  • "Clean all completed subagents" bulk action

Option 3: Add built-in command

/cleanup-subagents    # Clean completed subagent sessions
/gc                   # Garbage collect orphaned data

Option 4: TTL-based cleanup Configuration option for subagent session TTL:

{
  "subagent": {
    "sessionTTL": "24h"
  }
}

NachoFLizaur avatar Dec 18 '25 10:12 NachoFLizaur

This issue might be a duplicate of existing issues. Please check:

  • #4980: Does OpenCode automatically clean up old session/conversation data? - Similar concern about session data accumulation and lack of automatic cleanup
  • #5667: LSPs keep accumulating, how do I remove them? - Related issue about resources accumulating in storage without cleanup mechanism

Feel free to ignore if none of these address your specific case.

github-actions[bot] avatar Dec 18 '25 10:12 github-actions[bot]