DSH Python SDK ignores ~/.dsh: dsh_home and missing plugins
“The SDK cannot read my old configuration” is usually not a bug; it is the design: the DeepSeek Harness Python SDK never silently reads ~/.dsh and uses only the explicit dsh_home. Changing the home changes the profile, plugins, credentials, settings, and sessions all at once. Most “missing plugin”, “session not found”, and “config did not apply” reports are two homes being confused.
DeepSeek Harness: Separate the three locations first
SDK data lives around the home, and the home has profile and session layers. Compare:(source)
| Content | Location | After changing home |
|---|---|---|
| profile and config | <dsh_home>/profiles/<name>/ | reinitialize |
| plugins | profile dependency directory | reinstall |
| session logs | <dsh_home>/sessions/ | old sessions invisible |
| credentials and settings | inside <dsh_home> | reconfigure |
Before calling it “missing”, decide which layer is missing instead of treating the SDK as one opaque store.
DeepSeek Harness: Why it ignores ~/.dsh
The isolation is deliberate: the SDK does not assume your global home is the current job’s home. Two reasons:(source)
- Avoid polluting the global environment — examples and tests should not write test plugins or credentials into
~/.dsh. Expected: each job can have a clean environment. - Avoid reading unrelated state — the global home may contain profiles and sessions from other projects. Expected: results are reproducible.
If you really want to reuse global configuration, point dsh_home at it explicitly. That at least makes the intent visible.
DeepSeek Harness: Three missing symptoms
The same “I cannot see it” can mean missing config, missing plugins, or missing sessions; each has a different fix. Three:(source)
- Missing config — models, providers, or tools are absent. Expected: inspect the target home’s profile patch, not the global settings.
- Missing plugins — tool list is short or startup reports resolution errors. Expected: run
dsh plugin addin the target home. - Missing sessions — old conversations do not open. Expected: confirm whether the home or session ID changed.
If all three are missing, the home is probably pointed at the wrong place; print the actual path before continuing.
DeepSeek Harness: Initialize the home correctly
Set DSH_HOME, initialize the profile, then install plugins into the same home. Steps:(source)
export DSH_HOME=/srv/dsh-home/demo
# Initialize the sdk-minimal profile
dsh --profile sdk-minimal --dump-default-config >/dev/null
# Install a plugin into the same home
dsh plugin --profile sdk-minimal add file:/srv/plugins/my-plugin
- Pin an absolute home — avoid relative paths that change with the working directory. Expected: Python and the CLI see the same home.
- Initialize the profile first — write
profiles/sdk-minimal. Expected: plugin installation has a target. - Plugin management needs pnpm — only management commands; running the SDK does not. Expected:
pnpm -vworks. - Pass the same home in Python —
DeepSeekHarness(dsh_home="/srv/dsh-home/demo"). Expected: the installed plugin is visible.
Step 4 is the most common miss: the shell exports DSH_HOME, but Python passes another path, producing “installed but invisible”.
DeepSeek Harness: The dsh_home directory map
Map config, plugins, and sessions to directories to know which layer to inspect. Compare:(source)
| Content | Typical path | After changing home |
|---|---|---|
| profile config | <home>/profiles/sdk-minimal/cordis.patch.yml | recreate |
| plugin dependencies | <home>/profiles/sdk-minimal/node_modules | reinstall |
| session logs | <home>/sessions/*.jsonl | old sessions invisible |
| credentials and settings | <home> root | reconfigure |
Run ls <home> first; do not summarize every missing item as “configuration is gone”.
DeepSeek Harness: Three isolation strategies
Per project, per task, and shared home serve different needs. Three:(source)
- Per project — one home per project, plugins and config follow it. Expected: stable environment, more disk use.
- Per task — a temporary home for one job, deleted afterward. Expected: cleanest, but no session reuse.
- Shared home — multiple jobs share one home and use session IDs to separate conversations. Expected: less disk, but plugins and credentials are shared.
When sharing a home, do not reuse session IDs; independent work gets a new ID, and only continuing the same conversation reuses harness, home, and ID together.
A minimal reproduction
Use three steps to confirm the home is wrong before changing plugin code. Steps:
- Print the actual paths — print
dsh_homein Python andecho $DSH_HOMEin the shell. Expected: they match. - Run the CLI with the same home —
dsh --profile sdk-minimal "list tools". Expected: the same tool set as the SDK. - Compare with a new home — initialize an empty home and run the same task. Expected: the default tool set appears, proving the original home’s difference came from plugins.
If all three agree, inspect the profile patch; if not, fix the path first.
DeepSeek Harness FAQ
Can the SDK fall back to ~/.dsh automatically? No. The official behavior is no silent read; pass that path explicitly if you want it.
Why does the CLI see a plugin while Python does not?
They use different DSH_HOME values or different profiles. Print both paths and compare.
Do I need to log in to the provider again after changing homes? Usually yes, because credentials also live in the home. Confirm the security boundary before reusing old credentials.
The short version: “missing” usually means the home changed; confirm the path, then inspect profile, plugins, and sessions separately.
FAQ
DeepSeek Harness: no. The SDK and its examples never silently read ~/.dsh; they use only the explicit dsh_home. To reuse existing configuration, point the home there or recreate the profile and plugins in the target home.
DeepSeek Harness: plugins are scoped by home and profile. A plugin installed in a global dsh home does not appear in the SDK home. Install it in the target home with dsh plugin --profile sdk-minimal add.
DeepSeek Harness: sessions live under the explicit dsh_home/sessions directory as uncompressed JSONL. Changing the home changes the entire session store; reuse the same home and session ID to continue an old conversation.
DeepSeek Harness: you do not have to create the directory by hand, but initialize the profile first: set DSH_HOME and run dsh --profile sdk-minimal --dump-default-config >/dev/null. That writes the profile and defaults into the home.
DeepSeek Harness: yes, but use different session IDs to separate conversations. Sharing a home shares profiles, plugins, credentials, and settings; use a separate home when you need full isolation.
Related Terms
- dsh_home
- dsh_home is the isolated DeepSeek Harness SDK home holding profiles, installed plugins, credentials, settings, and sessions. The SDK uses only the home passed explicitly.— DeepSeek Harness docs - Python SDK
- session ID
- A session ID identifies a DeepSeek Harness conversation. Independent work should use a new ID; reuse the harness, home, and ID together only to continue the same persistent conversation.— DeepSeek Harness docs - Python SDK
- sdk-minimal
- sdk-minimal is the minimal SDK profile under dsh_home/profiles/sdk-minimal. It contains no dsh-base and only the SDK protocol, adapter, local execution, and persistence.— DeepSeek Harness docs - Python SDK
- DSH_HOME
- DSH_HOME is the home environment variable used by the DeepSeek Harness CLI and SDK. Setting it makes dsh plugin and profile initialization write into that directory.— DeepSeek Harness docs - Python SDK
Sources
- DeepSeek Harness docs - Python SDK· deepseek-ai
- DeepSeek Harness reference - dsh CLI behavior· deepseek-ai