Secondary working directories for a DSH project: the agent keeps the primary workspace as cwd and gains equal read/write/exec permissions on configured secondary directories, configurable from the session header and the new-session page.
Install
# from npm (prebuilt)
dsh plugin --profile web add dsh-multi-folder
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:AngelosZou/dsh-multi-folder
Any plugin you install runs third-party code with your own permissions — it can read your files, use your credentials, and reach the network, and tool approvals don’t sandbox it. GitHub-sourced plugins also run build scripts at install time. Only install sources you trust, and pin a commit (github:owner/repo#sha).
README
English | 中文
Secondary working directories for a DeepSeek Harness project — edit a source repo, a test repo, and a docs repo side by side without leaving the primary workspace.
A DeepSeek Harness plugin bundle that gives one project (workspace) a set of secondary working directories:
- The agent's core
cwdand every other core attribute keep pointing at the primary workspace. - Under Workspace Write mode the agent gains the same read / write / edit / execute permissions on the configured secondary directories as on the primary workspace — enforced by re-rooting the session's own sandbox policy, so every mode keeps its semantics (
read-onlystill denies,workspace-writeallows,danger-full-accessallows). - The directory list is injected into the system prompt and re-rendered per session assembly.
- Configuration changes notify the agent through a non-interrupting message queue — delivered at the next message boundary (user send or tool-call end), and only when the directory set actually changed.
- Configurable before the session starts: the session-creation page (new-session screen) offers a Multi-folder entry (「多工作目录」 in the Chinese UI) that reads and edits the same per-workspace configuration through a sessionless remote API (
multiFolder/*endpoints) — no session id required. - Localized UI. The button, panel, and creation-page entries follow the DSH locale (the browser language or the Language setting in Settings): "Multi-folder" in English, 「多工作目录」 in Chinese.
- No new tools. Everything is a framework-level change (tool-pipeline interception) plus a UI-level change (a session-scoped header entry).
Requirements
- Node.js >= 20
- A DSH profile composed from
@deepseek-ai/dsh-base+@deepseek-ai/dsh-web-app
Install
Link this repository into a DSH profile:
dsh plugin --profile web add dsh-multi-folder
Then restart the DSH backend (host composition loads at process start) and refresh the browser page (the client bundle is served no-cache).
Usage
A Multi-folder button (「多工作目录」 in the Chinese UI) appears in the session header, and a second entry appears on the session-creation page (fixed launcher in the bottom-right corner while the new-session screen is shown; an inline chip beside the workspace picker once the upstream conversation.hero.workspaceExtras slot is available). The panel lets you:
| Action | Behavior |
|---|---|
| Add directory | Opens the native directory picker |
| Remove / refresh | Applies immediately |
| Switch session | The panel auto-switches to that session's directories |
| Reopen panel | Uses the per-session cache — no redundant command rows |
Equivalent slash command for the user:
/multi-folder list
/multi-folder add "D:\path\to\repo"
/multi-folder remove "D:\path\to\repo"
/multi-folder set "D:\a" "D:\b"
The agent needs nothing extra: read / glob / grep work everywhere, and write / edit / pwsh / bash are intercepted and re-rooted automatically when the target path (or workdir) falls inside a configured secondary directory.
How it works
- Interception — a listener on the
tools/executearound-dispatch waterfall short-circuitswrite/edit/pwsh/bashcalls whose resolved path (orworkdir) lands inside a configured secondary directory, and executes them with the session's standing sandbox policy re-rooted to that directory ({ ...standingPolicy, workspaceRoot: secondaryDir }). The mode itself is untouched, which is what gives every sandbox mode its identical primary-workspace semantics for free. Paths are canonicalized throughfs.resolve+processPathbefore matching, so.., symlinks, and case differences behave correctly. - Prompt injection — one ordered
systemPromptsection with a text provider evaluated per assembly, rendering only for sessions whose workspace has configured directories. - Notifications — a pending notice armed by the command handler (only on actual change) is consumed at the next boundary by either the
agent/pre-stepwaterfall (prepend into the entering message batch) or thetools/post-executewaterfall (attach asadditionalContexts), whichever fires first — the framework's native plugin-sourcednoticecontext. - Configuration & security boundary — per-workspace config lives in a host-owned store outside every agent sandbox root (
<DSH_HOME>/storages/multi-folder/<workspace-key>.json). Directwrite/editattempts against the config file are rejected with an explicit message — the agent can never self-grant directories; configuration is user-managed by design. See SECURITY.md. - Sessionless remote API — a
multiFoldernamespace registered throughctx.typert.register(hand-writtensrc-jsondescriptors) plus a plain-object service provided asmultiFolder. Itslist/add/remove/setmethods are keyed by workspace path and share one validated core with the/multi-foldercommand, so the creation page can configure directories before any session exists. - Client — a hand-maintained factory bundle (
window.__ModuleLoader__.load), no build toolchain required. The panel drives the host through two channels: the Remote BFF (ctx.remote.commands.execute) for sessions, and the shared/apiRPC channel (ctx.connection.rpc.call) for the sessionless endpoints.
Project layout
| Path | Purpose |
|---|---|
cordis.patch.yml |
Profile patch layer inserting the dsh-multi-folder row |
lib/index.js |
Host plugin: config store, tool-pipeline interception, prompt injection, dual-channel notifications, /multi-folder command, sessionless multiFolder/* remote API |
lib/client.js |
Client plugin (factory bundle): session-header button + overlay panel + session-creation page entry (hero launcher / upstream hero chip) |
test/ |
Runtime-free behavior tests (see Development) |
docs/ |
Design and analysis documents |
Development
No build step: the host half is plain ESM and lib/client.js is a hand-maintained factory bundle in the DSH client-modules format. Tests run with Node directly:
node test/smoke-host.mjs # host apply smoke test + remote API behavior
node test/intercept.mjs # interception / command / notification behavior
node test/smoke-client.mjs # client bundle + panel flows (React shim)
Before modifying lib/client.js, see docs/design.md for the bundle contract.
Documentation
- docs/design.md — architecture and security model
- docs/upstream-hero-slot.md — the upstream
conversation.hero.workspaceExtrasslot change (B1) and its plugin-side consumption
Contributing
See CONTRIBUTING.md. Issues and pull requests are welcome.
License
Links
More in this category
liustack/modlens★ 1582
Vision bridge for text-only models: paste an image, get structured JSON evidence (OCR, layout, semantics).
superdesigndev/treg★ 412
Tool catalog for agents: search ~2,600 external endpoints (SEO and SERP, backlinks, social, people and company enrichment, ad libraries, scraping) by the task you want done, read each one's parameters and per-call price, then call it with the credential injected server-side. Ships the skill plus an MCP row that stays disabled until TREG_TOKEN is set.
Anionex/dsh-vision-toolkit★ 395
Vision tasks for text-only models: intent-aware image Q&A, long-screenshot OCR, UI reproduction, grounding, and pixel diff.
zhaoolee/notes★ 141
Export DSH conversations as Smartisan Notes-style PNGs, or create and update Markdown notes in a configured account-scoped workspace.
Lum1104/dsh-browser★ 129
Chrome sidebar extension that lets DSH operate your browser directly, no vision capabilities required.
liustack/modsearch★ 101
Web search bridge for text-only agents: ask the web or X, get structured JSON evidence (search, fetch, citations).