#334·aisuite

Empty per-conversation scratch directories accumulate in the scratch base and are never cleaned up

Author: WalliieeCreated Jun 22, 2026Updated Jun 22, 2026

Summary

OpenCoworker creates a per-conversation scratch directory under the configured scratch base (default ~/OpenCoworker) for every cowork session, but never removes it — even when the conversation writes no files and even after the session is deleted. Over normal use the base fills with empty UUID-named folders.

Environment

  • OpenCoworker desktop (platform/), macOS
  • Default agent (cowork), no project folder bound

Steps to reproduce

  1. Complete onboarding, choosing a scratch folder (e.g. ~/OpenCoworker).
  2. Start a few cowork conversations that only chat (no file-producing tasks).
  3. Optionally delete some of those conversations in the UI.
  4. Open the scratch folder in Finder.

Expected: the folder reflects actual agent output; conversations that produced no files leave nothing behind, and deleting a conversation removes its (empty) scratch dir. Actual: one empty <12-char-session-id>/ directory per conversation, persisting indefinitely; deleting the conversation does not remove it.

Root cause

  • SessionManager._provision_scratch (platform/coworker/server/manager.py) eagerly mkdirs the scratch dir, called from get_engine when a cowork session starts.
  • get_roots also calls _provision_scratch as a side effect, so merely inspecting a session's roots re-creates the directory.
  • delete_session removes the session row but never touches the scratch dir on disk.

Note for others hitting this (it is not data loss)

Conversations and memory persist in the app-data dir (~/.config/coworker/coworker.db + conversations/*.jsonl), not in the chosen scratch base. The scratch base only ever holds files the agent explicitly writes during a task. The empty folders are harmless litter, but they're confusing — several users may read "my chosen folder is empty" as "my work wasn't saved."

Proposed fix

Conservative, in priority order:

  1. On delete_session, remove the session's scratch dir only if it exists, is empty, and its name matches the session id (never recurse, never delete a dir containing agent output).
  2. Stop get_roots from creating the dir as an inspection side effect — return the intended path with exists: false instead.
  3. (Optional) Provision the scratch dir lazily on first write rather than at engine build, so chat-only conversations never create one.

Happy to open a PR with (1) + (2) plus tests. Would you prefer cleanup-on-delete, lazy provisioning, or both? I'd also clarify the storage-location distinction in the onboarding copy if that's welcome.