maoqizhen/dsh-pc-manager ↗★ 0

dsh-pc-manager

PC Manager (电脑管家) — system status monitoring (model tools + right-sidebar dashboard), junk cleanup, and app uninstall for DeepSeek Harness 适合需要通过DSH监控系统性能、清理垃圾及管理软件的用户。

Package
dsh-pc-manager
Compatibility
Unverified
Harness peer range
^0.2.0-rc.1 || ^0.2.1-alpha.1
Cordis peer range
^4.0.1-rc.1
Version
0.0.1
License
MIT
Last updated
Oct 7, 2026

Install

$npx -p @deepseek-ai/dsh dsh plugin --profile web add github:maoqizhen/dsh-pc-manager

dsh-pc-manager — PC Manager

English · 简体中文

DeepSeek Harness plugin for system monitoring & junk cleanup · 系统监控、垃圾清理与应用卸载的 DeepSeek Harness 插件

A PC Manager plugin for DeepSeek Harness (dsh), shipped in the official bundle format. It provides: system status monitoring (model tools + a right-sidebar dashboard), system junk cleanup (a zero-LLM direct-execution window), and app uninstall (M3) — 5 model-visible tools in total.

Platform support: monitoring (pc_status + dashboard) and junk cleanup (pc_junk_scan/pc_junk_clean + the cleanup window) work on macOS, Linux and Windows; other platforms return unsupported_platform. On Windows, metrics come from node builtins plus a single batched PowerShell probe (see Windows data sources), the junk registry is JUNK_TARGETS_WIN32, and recycling goes to the real Recycle Bin.

It is positioned as a security-first agent system tool: scans are always dry-run; the two destructive tools default to disabled_by_config and only act after the host explicitly opts in; trash/uninstall defaults to the Trash (recoverable); if any link of the id validation chain fails, the whole call is rejected with zero deletion.

Table of contents

Quick start

Install (one line)

This repository is an official bundle plugin (dsh.bundle + dsh.client in the root package.json); the build artifacts in lib/ are committed, so a git install requires no build step:

dsh plugin --profile web add "github:maoqizhen/dsh-pc-manager#main"

After installing, restart dsh web (the bundle layer is synthesized at startup). To update: dsh plugin --profile web update dsh-pc-manager; to uninstall: dsh plugin --profile web remove dsh-pc-manager — both require a restart to take effect.

pnpm required: dsh plugin is a pnpm forwarder and fails outright if pnpm is not on the PATH (install with npm i -g pnpm; the pnpm major version must match the profile's existing store). If dsh runs under a non-login shell on a server, make sure node/pnpm are visible on that process's PATH (e.g. in /usr/local/bin).

Enable junk cleanup (optional)

Out of the box the install is safe-by-default: read-only tools work immediately, while the two destructive tools (pc_junk_clean / pc_app_uninstall) refuse to execute (disabled_by_config). To enable junk cleanup, write to a back-layer patch (the profile's cordis.patch.yml or ~/.dsh/cordis.patch.yml; the back layer replaces the whole config line, so all keys must be restated):

- insert:
    - id: pc-manager
      name: dsh-pc-manager
      config:
        enableJunkClean: true     # the per-call host approval gate still applies
        moveToTrash: true         # default to Trash (recoverable)

Manual mounting (fallback, mutually exclusive with bundle install)

No dsh plugin add needed, but a dual entry is mandatory (the package-name entry lets the client half be discovered by the clientModules scan; the file-path entry lets the host half's apply run; the official bundle install has no such issue):

# 1. Let the profile resolve the package by name (the client half is discovered
#    via require.resolve('
/package.json'))
ln -s "$PWD" ~/.dsh/profiles/web/node_modules/dsh-pc-manager

# 2. Append the dual entry to ~/.dsh/cordis.patch.yml (host: absolute path; client: package name)
# - insert:
#     - id: pc-manager
#       name: /abs/path/to/dsh-pc-manager/lib/index.js
#     - id: pc-manager-client
#       name: dsh-pc-manager

# 3. Restart dsh web

Features

Model tools

ToolPurposeStatus
pc_statusRead-only system snapshot: CPU/GPU utilization, load, temperature (capability-gated), memory breakdown (incl. swap), disk I/O and per-volume usage, battery/power, network counters, multi-key sortable process table (macOS + Linux + Windows; Windows has no load average, and the per-process network and disk columns are unobtainable — see Windows data sources)✅ Shipped
pc_junk_scanEnumerates reclaimable junk (macOS: Trash, user caches/logs, system temp, Xcode artifacts, simulator leftovers, package-manager caches, iOS backups; Linux: XDG Trash, ~/.cache, /tmp and /var/tmp, package-manager caches; Windows: the per-account Recycle Bin, %TEMP% and %SystemRoot%\Temp, WER reports and crash dumps, WinINet/D3D/NVIDIA shader/RDP caches, package-manager caches) with per-item size / safety flag / protected-exclusion records; params kinds / minItemBytes; always dry-run✅ Shipped
pc_junk_cleanTrashes items by the exact ids returned by scan; if any link of the structural validation chain (format/root containment/realpath/blocked/safeToClean) fails, the whole call is rejected with zero deletion; the trash kind is emptied in place, everything else defaults to the three-tier trash (macOS: /usr/bin/trash → rename into ~/.Trash → cross-volume cp+rm; Linux: trash-put/gio trash → freedesktop ~/.local/share/Trash/{files,info} with .trashinfo restore records → cross-volume cp+rm; Windows: the Microsoft.VisualBasic recycle API into the real Recycle Bin → fallback %LOCALAPPDATA%\pc-manager\trash → cross-volume cp+rm); refuses to delete when sizes can't be verified; tier-1 results are re-verified (success reported but source still present counts as failure and degrades); requires explicit config opt-in✅ Shipped
pc_apps_listInstalled-app inventory (app bundles + Homebrew; Linux distro packages and Windows registered programs await M3), with size / last-usedStub, M3
pc_app_uninstallUninstalls by exact id; defaults to Trash, residual items are reported rather than silently deletedStub, M3

Dashboard (right sidebar)

The "System Monitor" entry (order 30) in the web profile's right sidebar opens a narrow-column card dashboard: header (host/OS + a muted second line "local … · public IP · city" (geo shows city only; the segment collapses when lookup is off or misses) / uptime) → CPU (bar + load + temperature row* + sparkline) → GPU (whole card hidden when unavailable) → memory (swap + breakdown) → disk (usage bars for valid volumes + I/O rate) → battery (hidden when absent) → network (main-interface rate + sparkline) → process table (switchable by CPU/memory/network, top 10 by default; hovering the CPU column header explains its scale). Hand-written SVG, no chart library.

  • Capability-gated rows/columns: the CPU card's temperature row (Linux with a sensor / Windows with an ACPI thermal zone), the load line (Windows has no load average — the whole line hides instead of showing a fabricated 0), the GPU card and the process table's "GPU" column (Windows uses the vendor-agnostic engine counters, so AMD/Intel/NVIDIA all show; Linux needs NVIDIA hardware + nvidia-smi), the process table's "network" column (always present on macOS via nettop; Linux only with root-attributed ss -tinp; Windows needs ETW and stays hidden) — missing capability means hidden, no wall of "—", see Capability-gated probes. On Windows the disk card lists every volume by drive letter (C:\, Z:\, …); on POSIX it is still / plus data volumes under /Volumes, /media, /mnt. Process CPU% is per-core (multi-core processes can exceed 100%) and a process-lifetime average (macOS/Linux from ps; Windows computed from Get-Process's cumulative CPU seconds over process uptime); the column header tooltip explains this.
  • Data flows through the host half's single collection pump + SSE push: GET /pc-manager/stream (text/event-stream) is the shared foundation — one host-side timer (interval dashboardPollMs, adjustable, min 500) collects on a single path and diffs server-side (network rates available from the first frame); the dashboard, floating window and every other consumer share one connection and one frame stream; with no consumers, the connection and collection stop automatically (reference-counted; hidden tab / closed floating window releases it). GET /pc-manager/status (?processSort=&processLimit=) remains as a cache fallback: requests with the pump's sort order (default CPU) read the fresh cache directly, other sort orders collect on demand. The LLM tool pc_status does not go through the pump; its contract is unchanged.
  • Headless profiles (no webServer) skip route registration automatically; tools are unaffected. On platforms with a source, the GPU card is titled with the adapter name (Windows reads it from the display adapter, e.g. AMD Radeon(TM) Vega 8 Graphics; the narrow column truncates with an ellipsis, full name in the tooltip); platforms without a name source keep the generic GPU.

Junk cleanup (zero-LLM direct-execution window)

A dedicated "Junk Cleanup" window in the right sidebar (guide entry peer-level with System Monitor, order 31), zero LLM end to end: click "Scan" → host GET /pc-manager/junk/scan (read-only; the server filters out small items below a 1 MiB threshold) → presented by category (the checkbox unit is the category, not single items; an inline size preview with the top 2–3 item names answers "which apps does this affect"; each category's "details (N)" folds out into a scrollable list for surgical add/remove; recommended categories are pre-checked — non-regenerable Xcode archives/iOS backups and safeToClean:false pnpm store/simulator leftovers are unchecked by default with a stated reason) → "Clean selected" → an in-place two-step confirmation bar (N items · size → Trash (recoverable) / permanent delete) → POST /pc-manager/junk/clean executes directly → an in-place result briefing. The host side shares the same config gate and id validation chain as the tool path (all-or-nothing rejection, zero deletion) and emits an audit log line; the confirmation bar cannot be skipped and stands in for the tool path's approval panel. The floating window's "Scan" button invokes this window and starts scanning automatically (openTab + navigation revision; re-invoking re-scans); the five tools and all security defenses are unchanged.

Note: the conversational approval panel only appears when the session Access mode's approval policy is ask; under the danger-full-access deployment default (approval: never), in-session ask is silently auto-rejected — switch Access mode in the session or adjust the deployment preset. The UI direct-execution window is not subject to this.

Security design

  • Read-only tools work out of the box; the two destructive tools default to disabled_by_config and only act after the host flips the switches in a back-layer patch.
  • Trash/uninstall defaults to the Trash (recoverable — on Windows that is the system "Recycle Bin"; the two terms are synonyms in this document); permanent deletion requires moveToTrash: false. The trash landing has three tiers: on macOS /usr/bin/trash (invoked by absolute path, guarding against PATH hijacking) → ownership-checked rename into ~/.Trash (name conflicts get 2/ 3 suffixes) → cross-volume EXDEV cp+rm; on Linux trash-put/gio trash (probed absolute paths) → freedesktop ~/.local/share/Trash/{files,info} rename + .trashinfo restore records (name conflicts suffix both sides in sync) → cross-volume cp+rm; on Windows the Microsoft.VisualBasic.FileIO.FileSystem SendToRecycleBin (the same shell recycle as Explorer, landing in the real Recycle Bin with the original location recorded, restorable from Explorer; paths are embedded into the script as PowerShell literals rather than appended to argv — -Command re-joins arguments with spaces, so a path containing one silently splits, and a multi-statement script never sees $args at all) → fallback to %LOCALAPPDATA%\pc-manager\trash (a private holding area inside the profile, still recoverable, just not in the Recycle Bin UI) → cross-volume cp+rm. After tier-1 reports success, the source is checked to have actually disappeared, otherwise the tier counts as failed and the next one runs — a silent no-op (the shell API blocked by policy, arguments never bound) must never be reported as "reclaimed N bytes" (the Windows e2e caught exactly one such fake success). The trash kind itself is emptied in place (macOS empties ~/.Trash, Linux empties the contents of files/+info/, Windows empties this account's %SystemDrive%\$Recycle.Bin\ — exactly what "Empty Recycle Bin" means for that volume). Moving the Trash back into the Trash would be a pointless matryoshka.
  • Three-layer confirmation for junk cleanup: model conversation confirmation (the tool description instructs preferring ask_user_question) + the framework's tools/pre-execute approval gate (askBeforeJunkClean defaults to true, asked every time, fail-closed when no answerer) + the id structural validation chain (strict child paths for children kinds / exact root for whole kinds, dual-sided realpath against symlink redirection, blocked list, safeToClean; any failure rejects the whole call with zero deletion).
  • The safe target registry is the core asset: macOS 18 kinds / 19 rows, Linux 11 kinds / 12 rows (XDG), Windows 11 kinds / 18 rows (%VAR% roots), including a sensitive-cache protection list (the "caches" of password managers/IDEs/input methods/VPNs/sync drives/AI apps are actually non-regenerable state; hits are recorded as skipped and produce no item) and EDR/active-service prefix protection (deleting enterprise security agent caches triggers tamper alarms; Linux additionally protects systemd-private-* and snap-private-tmp; Windows protects AV/EDR directories and installer scaffolding); safeToClean:false entries are reported but never cleaned, with suggested commands in the rationale (xcrun simctl delete unavailable / pnpm store prune).
  • Path validation uses each literal's own path flavor: Windows paths are case-insensitive and rooted at drive letters, POSIX paths are case-sensitive; the validation chain (root containment / equality / blocked) normalizes and compares according to each path's own style, so the same code validates both C:\Users\t\AppData\Local\Temp\x and /home/t/.cache/x.
  • Domain modules (src/monitor.ts, junk.ts, apps.ts, win32.ts) do not depend on cordis; pure logic, independently unit-testable.

Appendix

Monitoring metrics and data sources

All probes dispatch per platform and degrade to null/empty + console.warn on failure — a probe failure never takes down the snapshot. Linux base metrics are all read from /proc and /sys, zero dependencies and zero privilege escalation; capability-detection enhancements (per-