@boy_grid/dsh-mfw
v0.1.0
Published
One-command launcher for DeepSeek Harness with multi-folder workspaces: prepares a patched runtime, its own profile and the plugin, then hands every argument to dsh
Maintainers
Readme
@boy_grid/dsh-mfw
One command to run DeepSeek Harness (DSH) with multi-folder workspaces: one workspace made of several folders that live in different places, where sessions can read and write every member folder.
npx @boy_grid/dsh-mfw webThat is the whole install. Part of dsh-multi-folder-workspace — see that repository for the design, the patch set and the manual install route.
What it does
The multi-folder feature needs changes inside DSH's core packages: upstream models a workspace as exactly one folder (path: string), and that assumption reaches into the persisted record, the sandbox policy, the RPC payloads and the directory-picker contract. Those packages import each other as plain ESM, so the change cannot be a plugin alone and cannot be applied at run time — it has to exist in an install tree.
This launcher owns such a tree:
- Provisions a patched runtime in your cache directory: a pnpm install of the pinned
@deepseek-ai/dshwith the 10-package patch set applied throughpatchedDependencies. Keyed by baseline + patch payload, so it is only built once per release. - Prepares its own DSH profile (
mfw) and installs@boy_grid/multi-folder-workspaceinto it. - Boots dsh from that tree with a patch overlay that swaps the native directory picker for the multi-select flow, and forwards every remaining argument untouched.
Second and later runs skip straight to step 3.
npx @boy_grid/dsh-mfw web --port 8080 # arguments go to dsh unchanged
npx @boy_grid/dsh-mfw web --no-openWhat it does not touch
- Your
webprofile. The launcher uses a profile of its own, so plaindsh webkeeps working exactly as before and both can live in one DSH home. Nothing is written to your profile'scordis.patch.yml— the overlay is passed on the command line instead. - Your DSH data. Sessions, credentials and settings stay in
$DSH_HOME(default~/.dsh), shared with your normaldsh, so history and logins carry over both ways. - Your global package manager state. The runtime tree is self-contained in the cache directory.
Commands
| Command | What it does |
| --- | --- |
| dsh-mfw [web] [dsh args…] | Provision if needed, then boot the web UI. Arguments after the launcher's own flags go to dsh. |
| dsh-mfw provision | Do the slow part and stop — warming the cache before going offline, or in CI. |
| dsh-mfw doctor | Print what was resolved: baseline, plugin state, pnpm, DSH home, profile, cache paths. |
| dsh-mfw clean | Remove the current runtime tree. --all removes every cached tree. Your DSH data and profile stay. |
Launcher flags are namespaced so they can never collide with dsh's own:
| Flag | Meaning |
| --- | --- |
| --mfw-profile <name> | Use a different DSH profile (default mfw) |
| --mfw-force | Reprovision the runtime and reinstall the plugin |
| --mfw-help | This launcher's help. Plain --help goes to the booted app. |
Environment
| Variable | Default | Purpose |
| --- | --- | --- |
| DSH_HOME | ~/.dsh | Where DSH keeps sessions, credentials and profiles. Same variable upstream reads. |
| DSH_MFW_CACHE | ~/.cache/dsh-mfw, $XDG_CACHE_HOME/dsh-mfw, or %LOCALAPPDATA%\dsh-mfw | Where runtime trees live |
| DSH_MFW_PLUGIN | the pinned release | Install the plugin from another spec or a local path (development) |
Requirements
- Node >= 22.
- pnpm 11+, taken from
PATHif new enough, otherwise fetched through corepack (which ships with Node 22).patchedDependenciesis what makes the patch set cover every copy of a package in the tree, including peer edges; npm has no equivalent. - Network and ~300 MB of disk for the first run. Provisioning takes roughly 10–30 seconds depending on the connection; later runs start in about a second.
Security note
A multi-folder workspace widens the agent's write surface. In workspace-write mode a session in such a workspace can write to every member folder, not just its own working directory. The patch set extends DSH's sandbox accordingly (union of member roots, per-platform multi-directory grants), paths outside the member set are still denied, and every membership change is recorded as a session event. Read the security note before installing — if you only ever work in one folder at a time, you do not need this.
Uninstalling
npx @boy_grid/dsh-mfw clean --all # drop the cached runtime trees
rm -rf "${DSH_HOME:-$HOME/.dsh}/profiles/mfw"Your sessions and credentials are untouched, and a stock dsh still starts: records written by the patched side keep path pointing at the primary member, so multi-folder workspaces appear as ordinary single-folder ones. That degradation is one-way — stock DSH drops the extra member list the first time it writes a record. Back up $DSH_HOME/storages/workspace.json first if you want to keep it.
On Windows there is one more thing to clean up. Write access to member folders is granted by putting an ACE for a capability SID on the folder itself, and those ACEs live in the file system rather than in DSH_HOME — deleting the cache and the profile does not remove them. They grant nothing once no process carries the matching SID, but if you want the folders back to their original ACLs:
foreach ($d in @('C:\path\to\member-1', 'C:\path\to\member-2')) {
$acl = Get-Acl $d
foreach ($rule in @($acl.Access)) {
if (-not $rule.IsInherited -and $rule.IdentityReference.Value -like 'S-1-4-*') {
[void]$acl.RemoveAccessRule($rule)
}
}
Set-Acl -Path $d -AclObject $acl
}Version pinning
Each release of this launcher pins one DSH baseline (currently 0.1.1-rc.2), one plugin version and the exact patch payload; dsh-mfw doctor prints all three. Upstream packages reference each other with ^ ranges that would drift to a newer prerelease and leave the patches unused, so the baseline is exact by design and moves only when the patch set is rebased.
License
MIT. The patch set is derived from the MIT-licensed upstream @deepseek-ai/dsh-* npm artifacts. This is an independent community project, not affiliated with or endorsed by DeepSeek.
