DeepSeek Harness leaks workspace-changes scratch in %TEMP%

TroubleshootingPublished 2026-10-20Author: DeepSeek Plugin Market
DeepSeek HarnessDSHworkspace-changestemp directorydisk cleanupmkdtemp
DeepSeek Harness leaks workspace-changes scratch in %TEMP% when dispose is skipped. Clear the backlog, sweep at startup, reclaim by owner, or move the cache.

Open %TEMP% and you may find directories named dsh-workspace-changes-*, each 1-6 GB, adding up to tens of GB — orphans left by DSH's workspace-changes when a session never reaches dispose. On the reporter's machine they totaled 60.45 GB across 131 directories and 302,971 files, while the whole %TEMP% was 168 GB. A community check on master found the same shape, so this is not an artifact of an old version (#10336).

This leak raises no error and does not slow startup. It quietly consumes the system drive. The rest covers confirmation, cleanup, and prevention.

DeepSeek Harness scratch leak: confirm the directories and the missing dispose

Bottom line: the fingerprint is a fixed name prefix, a location under the system temp root, and modification times that line up with crashes or update restarts.

  1. In PowerShell, list directories matching the prefix and total their size. Expected: a count and GB figure in the same order as the discussion sample.
  2. Sort by modification time and see what the most recent write corresponds to. Expected: most cluster around crashes, forced quits, or update restarts.
  3. Inspect the structure. Expected: non-git workspaces show objects/ and captures/, which are file-capture data.
  4. Confirm no current DSH session uses them. Expected: DSH is fully exited, or the directory mtime predates the current session.

macOS and Linux have the same directories under the system TMPDIR; the prefix is unchanged.

Bottom line: deletion hangs only on session/disposed, which never fires on a crash, forced quit, kill, or update restart, and startup has no sweep.

  1. The first time a session uses workspace-changes, it calls mkdtemp under the temp root with a random suffix.
  2. Objects and capture files are written as needed, with each file limited by maxFileBytes.
  3. The only deletion point is dispose(), triggered by session/disposed.
  4. An abnormal exit skips the event, leaving the directory on disk.
  5. The next startup does not scan old directories, so the leak only grows.

A multiplier matters: a session that touches a few large binaries can push captures/ into the multi-GB range. In the report, single directories ran from 1.1 to 6.8 GB with up to about 15,000 files, so a daily cleanup is not enough for a machine that runs one large project a week.

How fast the leak grows

Bottom line: growth is abnormal exits multiplied by the volume of files a session touches, and is largely unrelated to how long the session ran.

  1. Every abnormally ended session leaves at least one directory, so the count tracks abnormal exits.
  2. Size depends on how many files the session touched and how large they were, not on duration.
  3. A workspace with build artifacts or image layers can leave several GB in one session.
  4. Free disk space is therefore a better cleanup trigger than elapsed days.

DSH plugin cleanup: clear the backlog safely

Bottom line: cleanup is safe once no active session is using the directories; do not delete while a long task is running.

  1. Quit DSH completely, including tray and background processes. Expected: no DSH process in the task manager.
  2. List every matching directory and record sizes before deleting. Expected: a reviewable inventory.
  3. Delete directories older than seven days and keep recent ones as a control. Expected: most space is freed and recent sessions are unaffected.
  4. Start DSH, create a session, and trigger a file change. Expected: normal behavior and a new directory.
  5. Wait a day, then decide whether to remove the rest. Expected: no active data was deleted.
  6. Record the freed space and directory count as a baseline for judging leak rate. Expected: comparable numbers next time.

Save the inventory before deleting. If a session later seems to miss change records, you will at least know what was removed. If you would rather install an existing cleaner, check DSH Plugin Hub first, but avoid anything that deletes by wildcard.

DeepSeek Harness path 1: sweep by prefix at startup

Bottom line: a single startup scan that modifies no directory content is the cheapest root fix, and mtime covers most orphans.

  1. Early in host startup, list the temp root for directories matching dsh-workspace-changes-. Expected: a candidate list.
  2. Read each directory's mtime and queue only those older than a threshold such as 24 hours. Expected: in-use directories are excluded.
  3. Log deletion failures without blocking startup. Expected: permission or lock problems do not prevent DSH from starting.
  4. Run a dry run first and print the deletion list. Expected: a human review before enabling it.
  5. Add a test with one old and one new directory. Expected: only the old one is removed.

DeepSeek Harness path 2: write an owner file and reclaim periodically

Bottom line: mtime sweeps misjudge a week-long session, so record the holder; this is the shape the discussion prefers.

  1. After creating a scratch directory, write an owner file with PID, process start time, and session id. Expected: every directory has readable holder data.
  2. On reclaim, read the owner and probe the PID; confirm with start time to handle PID reuse. Expected: a new process is not mistaken for the old owner.
  3. Run a periodic job that reclaims directories past a threshold whose owner no longer exists. Expected: leaks are found within hours, not at tens of GB.
  4. Rename with a deletion marker before recursive removal. Expected: a mid-way failure does not leave half a directory that the next sweep misreads.
  5. Log the count and bytes reclaimed. Expected: you can tell from logs whether the leak is still happening.

DeepSeek Harness path 3: move the cache into the workspace

Bottom line: moving the scratch root into a workspace cache lets workspace deletion clear it, at the cost of sync and repository pollution; it suits only specific setups.

  1. Choose a fixed cache directory inside the workspace, such as .dsh/cache/workspace-changes. Expected: a predictable path that is easy to clean.
  2. Add it to version-control ignore rules and sync-client exclusions. Expected: git status is clean and the sync client skips it.
  3. Change creation to use that root and clear it when the workspace is removed. Expected: deleting a workspace clears its cache.
  4. Evaluate the disk: do not enable this on a network or synced drive. Expected: capture latency does not rise noticeably.
  5. Keep the backlog cleanup step, or old directories still occupy the system drive. Expected: disk usage actually falls.

DeepSeek Harness: choose a path and set limits

Bottom line: clear the backlog first, then decide whether to change code; a startup sweep if you can edit startup, an owner file for long-term accuracy, and workspace-local storage only if the workspace is itself temporary.

  1. Do not treat "temporary" as "safe to delete blindly": removing an object mid-write leaves the current session's change view with holes.
  2. Spill files in the same temp root encode their holder in the filename and are easy to judge; workspace-changes directories do not, which is why an owner file matters.
  3. System cleanup tools may already have removed some directories; trust what exists on disk rather than scheduled-task logs.
  4. No official fixed version appears in the discussion; 0.1.7-rc.2 reproduces and master has the same shape.
  5. Record free space before and after cleanup and check that the freed amount matches the deleted size. For related workspace and background-job failures, see workspace and background jobs.

Source: Discussion #10336.

FAQ

DeepSeek Harness leaves many dsh-workspace-changes- directories in %TEMP% totaling tens of GB. Can I just delete them?

Yes, after confirming no DeepSeek Harness process is using them. They are per-session scratch data normally removed when a session ends; the survivors are orphans from crashes or forced quits. Quit DSH, keep directories modified in the last few hours, and delete older ones. Session history is unaffected.

Why do the directories remain after I close the DeepSeek Harness window normally?

DeepSeek Harness ties deletion to session/disposed, and closing a window does not guarantee every session reaches dispose. A killed process, an update restart, or termination after sleep skips the callback, and startup has no sweep. Check mtimes and whether a session is still running rather than assuming the window close cleaned up.

How can DeepSeek Harness clear these orphan directories at startup instead of requiring manual cleanup?

DeepSeek Harness can scan the temp root for the prefix at startup and remove directories older than a threshold, or write a pid or owner file when creating the directory and check whether the holder is still alive. The first needs no change to directory contents; the second is more accurate but must handle PID reuse and start time.

Will moving the DeepSeek Harness workspace-changes cache into the workspace pollute git or sync clients?

A DeepSeek Harness cache moved into a workspace does pollute git unless you add ignore rules; on a synced or network drive it also uploads many objects and slows capture. It fits workspaces that are themselves temporary, not long-lived project directories.

Related Terms

scratch directory
A scratch directory is the temporary workspace copy workspace-changes creates for one session, holding objects and file captures. It is isolated per session, deleted on normal disposal, and left behind when the process exits abnormally.— https://github.com/deepseek-ai/deepseek-harness/discussions/10336
mkdtemp
mkdtemp is the system call wrapper that creates a unique temporary directory with a random suffix so concurrent creation does not collide. It creates but never deletes; the caller owns the lifecycle.— https://github.com/deepseek-ai/deepseek-harness/discussions/10336
session/disposed
session/disposed is the event DeepSeek Harness emits when a session is destroyed. workspace-changes subscribes to it to remove the scratch directory, so a crash or forced quit that skips the event also skips cleanup.— https://github.com/deepseek-ai/deepseek-harness/discussions/10336
maxFileBytes
maxFileBytes is the per-file size limit workspace-changes applies when capturing file contents. It caps each capture, but total directory size still grows with the number of captured files.— https://github.com/deepseek-ai/deepseek-harness/discussions/10336

Sources