# Conflicts: # .agents/notes/archived/architecture/2026-06-18-shared-persistence-write-coordinator.i18n.yaml # .agents/notes/implemented/architecture/2026-06-14-session-persistence.i18n.yaml # .agents/notes/implemented/architecture/2026-06-14-session-persistence.md # .agents/notes/implemented/architecture/2026-06-14-session-persistence.zh.md # .agents/notes/implemented/architecture/2026-07-24-project-session-directories.i18n.yaml # .agents/notes/implemented/architecture/2026-07-24-project-session-directories.md # .agents/notes/implemented/architecture/2026-07-24-project-session-directories.zh.md # .agents/notes/implemented/architecture/2026-08-05-session-preparation.i18n.yaml # .agents/notes/implemented/architecture/2026-08-05-session-preparation.md # .agents/notes/implemented/architecture/2026-08-05-session-preparation.zh.md # .agents/notes/implemented/architecture/2026-08-10-message-feedback-sidecar.i18n.yaml # .agents/notes/implemented/architecture/2026-08-10-message-feedback-sidecar.md # .agents/notes/implemented/architecture/2026-08-10-message-feedback-sidecar.zh.md # .agents/notes/implemented/architecture/2026-08-27-handle-based-session-persistence.i18n.yaml # .agents/notes/implemented/bug-fix/2026-07-28-load-pre-identity-session-messages.md # .agents/notes/implemented/bug-fix/2026-07-28-load-pre-identity-session-messages.zh.md # .agents/notes/implemented/bug-fix/2026-08-04-load-pre-react-loop-sessions.md # .agents/notes/implemented/bug-fix/2026-08-04-load-pre-react-loop-sessions.zh.md # .agents/notes/implemented/bug-fix/2026-09-01-host-goal-pause-aborts-turn.i18n.yaml # .agents/notes/implemented/feature/2026-08-10-web-session-log-export.i18n.yaml # .agents/notes/implemented/feature/2026-08-10-web-session-log-export.md # .agents/notes/implemented/feature/2026-08-10-web-session-log-export.zh.md # apps/cli/tests/profiles/headless/tests/session-format-guard.expected.e2e.ts # apps/web/tests/cold-blank-session.e2e.ts # apps/web/tests/message-actions.e2e.ts # apps/web/tests/scaffold.ts # apps/web/tests/workspace-management.e2e.ts # docs/config-catalog.i18n.yaml # docs/config-catalog.md # docs/config-catalog.zh.md # docs/event-producer-consumer.i18n.yaml # docs/event-producer-consumer.md # docs/event-producer-consumer.zh.md # docs/persistence-catalog.i18n.yaml # docs/persistence-catalog.md # docs/subsystems/feedback.i18n.yaml # docs/subsystems/feedback.md # docs/subsystems/feedback.zh.md # docs/subsystems/persistence.i18n.yaml # docs/subsystems/persistence.md # docs/subsystems/persistence.zh.md # packages/acp/acp/src/index.ts # packages/acp/acp/tests/bridge.spec.ts # packages/api/session-controller/src/list.ts # packages/api/session-controller/tests/agent.host.spec.ts # packages/api/session-controller/tests/session-cold.host.spec.ts # packages/api/session-controller/tests/session-projections.host.spec.ts # packages/api/session-controller/tests/session-search.host.spec.ts # packages/api/session-controller/tests/test-remote.ts # packages/api/session-controller/tests/transport.host.spec.ts # packages/core/agent-loop/src/index.ts # packages/core/agent-loop/tests/config-session-id.spec.ts # packages/core/agent-loop/tests/resume.spec.ts # packages/extensions/tool-cordis/src/api-catalog.ts # packages/feedback/message-feedback/src/index.ts # packages/feedback/message-feedback/tests/helpers.ts # packages/feedback/message-feedback/tests/message-feedback.spec.ts # packages/session-query/session-log-export/src/archive.ts # packages/session-query/session-log-export/tests/archive.host.spec.ts # packages/session-query/session-log-export/tests/route.host.spec.ts # packages/session-query/session-query-sqlite/README.i18n.yaml # packages/session-query/session-query-sqlite/README.md # packages/session-query/session-query-sqlite/README.zh.md # packages/session-query/session-query-sqlite/src/index.ts # packages/session-query/session-query-sqlite/tests/sqlite.spec.ts # packages/session-query/session-query/README.i18n.yaml # packages/session-query/session-query/README.md # packages/session-query/session-query/README.zh.md # packages/session-query/session-query/src/corpus.ts # packages/session-query/session-query/tests/observation.spec.ts # packages/session-query/session-query/tests/session-query.spec.ts # packages/session-query/session-query/tests/tracing.spec.ts # packages/session/session-checkpoint-policy/tests/session-checkpoint-policy.spec.ts # packages/session/session-persistence-jsonl/README.i18n.yaml # packages/session/session-persistence-jsonl/README.md # packages/session/session-persistence-jsonl/README.zh.md # packages/session/session-persistence-jsonl/src/index.ts # packages/session/session-persistence-jsonl/tests/jsonl.spec.ts # packages/session/session-persistence-jsonl/tests/zstd.spec.ts # packages/session/session-persistence/README.i18n.yaml # packages/session/session-persistence/README.md # packages/session/session-persistence/README.zh.md # packages/session/session-persistence/src/coordinator.ts # packages/session/session-persistence/src/index.ts # packages/session/session-persistence/tests/contract.ts # packages/session/session-persistence/tests/coordinator-contract.ts # packages/session/session-persistence/tests/persistence.spec.ts # packages/session/session-telemetry/package.json # packages/shell/tool-bash/tests/tools.spec.ts # packages/subagent/subagent/src/continuation.ts # packages/subagent/subagent/tests/list-children.spec.ts # packages/workspace/workspace/src/index.ts # packages/workspace/workspace/tests/workspace.spec.ts # scripts/gen-cordis-catalog.ts
description, kind
| description | kind |
|---|---|
| The managed DSH_* shell environment for users and maintainers choosing, configuring, or extending the environment every model shell call runs with. | package-reference |
@deepseek-ai/dsh-shell-env
English | 中文
Summary
dsh-shell-env provides the trusted DSH_* environment that every model shell call — bash or pwsh — runs with: built-in facts such as DSH_HOME, DSH_SHELL=1, and the agent's DSH_SESSION_ID. Plugin authors can register their own facts with declared keys, collected per execution and disposed with their plugin; duplicate ownership or undeclared runtime keys fail loudly instead of silently overwriting. The registry changes nothing else the model sees — the shell tools own their own schemas and prompts. Choose it in any composition that mounts a model shell tool; configuration only picks the Harness home directory.
Table of Contents
- Use this package
- Understand the implementation
- Further Exploration
- Model Experience
- Known Limitations and Deferred Work
- Dev Note
Use this package
Load this plugin in any composition that mounts a model shell tool (dsh-tool-bash or dsh-tool-pwsh): each foreground or background shell call then runs with a freshly collected managed environment instead of whatever DSH_* values the process inherited.
What every shell call receives
Every call receives DSH_HOME (the absolute Harness home), DSH_SHELL=1, and, for agent calls, DSH_SESSION_ID (the calling session's id).
Adding your own environment facts
Other plugins contribute facts by registering a contributor with a stable name, the complete set of DSH_* keys it may return, a description per key, and a resolver that computes values for one execution:
import type { Context } from '@deepseek-ai/cordis'
import type {} from '@deepseek-ai/dsh-shell-env'
export const inject = ['shellEnv']
export function apply(ctx: Context): void {
ctx.shellEnv.register({
name: 'deployment-region',
variables: { DSH_DEPLOYMENT_REGION: { description: 'Current deployment region.' } },
resolve: execution => execution.agent === undefined ? {} : { DSH_DEPLOYMENT_REGION: 'cn-north' },
})
}
Contributors must declare every key they return; returning an undeclared or non-string value fails the call. Registration is disposed with the registering plugin, so hot-reloading a plugin removes its facts.
Choosing the Harness home
The single config field picks the home directory exposed as DSH_HOME; the default resolution order is the dshHome config, then ambient $DSH_HOME, then ~/.dsh.
| Field | Default | Meaning |
|---|---|---|
dshHome |
$DSH_HOME, then ~/.dsh |
Absolute Harness home exposed as DSH_HOME |
The generated configuration catalog is the exhaustive source for every accepted field and its JSDoc.
What can go wrong
Two contributors declaring the same key, or a contributor claiming a reserved built-in (DSH_HOME, DSH_SHELL, DSH_SESSION_ID), fails plugin load loudly. A DSH_* key must be all-caps with underscores (for example DSH_REGION), and a missing description fails registration.
Understand the implementation
Implementation internals — click to expand
This section explains the design decisions behind the registry and points at the code that realizes them; the observable behavior is fully covered in Use this package.
Design philosophy
- Trusted namespace, rebuilt per call. The environment is a Harness-owned
DSH_*namespace: the shell executor discards inheritedDSH_*values and merges the registry's current snapshot for each execution, so nested harnesses and concurrent parent/child agents cannot leak stale identities, andprocess.envis never modified. - Declared ownership, loud conflicts. Contributors declare their keys up front so duplicate ownership is detected before the first command; resolvers may only return declared keys.
- Built-ins stay here.
DSH_HOME,DSH_SHELL, andDSH_SESSION_IDare reserved for the registry; contributors cannot claim them.
Source map
| File | Role |
|---|---|
src/index.ts |
Plugin entry, ShellEnvRegistry service, and the built-in facts |
| — | No runtime invariant companion is published; the environment registry validates ownership and collected values at each registration/collection; it publishes no independent snapshot that a companion could cross-check. |
Collection
collect(execution) starts from the built-ins, adds the session id when the execution carries an agent, then merges each registered contributor's resolved values sorted by contributor name. The result is a frozen, key-sorted snapshot passed through ShellExecRequest.dshEnv. list() enumerates declarations without running resolvers, so it cannot reflect execution-dependent values.
Further Exploration
Read these pages when the package-level contract is not enough. They move from the shell family to the executor seam and the generated catalogs.
- shell package map — the bash capability family and its roles.
- Bash executor subsystem — the
ctx.shellseam the tools execute through. - tool-bash — the bash tool that consumes this environment.
- tool-pwsh — the pwsh tool that consumes this environment.
- home paths package — how
DSH_HOMEis resolved. - Generated configuration catalog — every accepted config field and its source declaration.
Model Experience
Indirectly, through the shell tools (dsh-tool-bash, dsh-tool-pwsh), which expose this registry's managed DSH_* facts in every shell-tool call.
KV Cache effect
The managed environment never enters the request prefix, so it does not invalidate provider cache reuse; the shell tools' definitions and the current request envelope own any prefix change.
Known Limitations and Deferred Work
These limits define when the registry is a poor fit or needs care. They are current package constraints, not a task backlog.
list()enumerates plugin-contributed variables only — registry-owned built-ins (DSH_HOME,DSH_SHELL,DSH_SESSION_ID) are not included, so diagnostics, prompt, or UI code must not treatlist()as an exhaustive environment catalog.
Dev Note
Working context for maintainers — click to expand
None.