dsh-pc-manager
PC Manager (电脑管家) — system status monitoring (model tools + right-sidebar dashboard), junk cleanup, and app uninstall for DeepSeek Harness 适合需要通过DSH监控系统性能、清理垃圾及管理软件的用户。
Install
npx -p @deepseek-ai/dsh dsh plugin --profile web add github:maoqizhen/dsh-pc-managerREADME
Read the full README ↗dsh-pc-manager — PC Manager
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
- Features
- Security design
- Appendix
- Repository layout
- Local development
- Milestones
- License
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 pluginis a pnpm forwarder and fails outright if pnpm is not on the PATH (install withnpm 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 surenode/pnpmare 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
| Tool | Purpose | Status |
|---|---|---|
pc_status | Read-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_scan | Enumerates 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_clean | Trashes 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_list | Installed-app inventory (app bundles + Homebrew; Linux distro packages and Windows registered programs await M3), with size / last-used | Stub, M3 |
pc_app_uninstall | Uninstalls by exact id; defaults to Trash, residual items are reported rather than silently deleted | Stub, 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-attributedss -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 fromGet-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 (intervaldashboardPollMs, 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 toolpc_statusdoes 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 genericGPU.
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_configand 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 get2/3suffixes) → cross-volume EXDEV cp+rm; on Linuxtrash-put/gio trash(probed absolute paths) → freedesktop~/.local/share/Trash/{files,info}rename +.trashinforestore records (name conflicts suffix both sides in sync) → cross-volume cp+rm; on Windows theMicrosoft.VisualBasic.FileIO.FileSystemSendToRecycleBin(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 —-Commandre-joins arguments with spaces, so a path containing one silently splits, and a multi-statement script never sees$argsat 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). Thetrashkind itself is emptied in place (macOS empties~/.Trash, Linux empties the contents offiles/+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'stools/pre-executeapproval gate (askBeforeJunkCleandefaults to true, asked every time, fail-closed when no answerer) + the id structural validation chain (strict child paths forchildrenkinds / exact root forwholekinds, 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 asskippedand produce no item) and EDR/active-service prefix protection (deleting enterprise security agent caches triggers tamper alarms; Linux additionally protectssystemd-private-*andsnap-private-tmp; Windows protects AV/EDR directories and installer scaffolding);safeToClean:falseentries 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\xand/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-