Samuka007/dsh-nix
Nix-native packaging for DeepSeek Harness (dsh)
项目介绍Project Overview
dsh-nix 是 DeepSeek Harness 的 Nix 原生打包插件:提供可复现的 pkgs.dsh、构建期解析的 profile 打包器,以及声明式管理 ~/.dsh 插件组合的 Home Manager 模块。适合想用 Nix 固定 dsh 版本、混合内置/pnpm/Nix 插件并在 nix build 阶段暴露启动失败的场景。注意 pnpm spec 插件需手动更新 specsHash,运行仍需凭证。
dsh-nix is a Nix-native packaging plugin for DeepSeek Harness: it provides a reproducible pkgs.dsh CLI, a build-time profile packager for in-box, pnpm-spec, and Nix-path plugins, plus a Home Manager module that declaratively owns ~/.dsh composition. Use it when you want pinned dsh versions and profile boot failures surfaced at nix build. Caveat: pnpm spec plugins require updating specsHash, and real runs need credentials.
请帮我了解并安装插件:【dsh-nix】【https://github.com/Samuka007/dsh-nix】
把上面这条消息直接发给当前会话里的 DSH,让它帮你了解并安装。安装命令不一定准确,发给 DSH 更稳。Send this message to DSH in your current session. CLI install commands may not be accurate across systems — DSH will figure it out for you.
或使用命令行安装(适合开发者)Or use CLI install (for developers)
命令行安装CLI Install
dsh plugin --profile web add github:Samuka007/dsh-nix
把 Samuka007/dsh-nix 加入你的 DSH 配置(web profile)即可启用。
READMEREADME
dsh-nix
Nix-native packaging for DeepSeek Harness (dsh):
pkgs.dsh— the CLI as a reproducible Nix package (pnpm monorepo build, upstream pinned at47f9438).- Profile packager — compose DSH profiles from three kinds of plugins in
one ordered list, with build-time resolution instead of
dsh plugin's activation-time pnpm reconcile. programs.dshHome Manager module — declarative plugin management in the Thunderbird style: the module owns the composition under~/.dsh, the app owns its data.
Plugin model
A profile's plugins list accepts three kinds, mixed in any order:
| Kind | Example | Resolution |
|---|---|---|
| in-box bundle | "@deepseek-ai/dsh-base" |
name only; resolved from the dsh installation |
| pnpm spec | "github:someone/plugin" |
fixed-output derivation runs pnpm add at build time; pin with specsHash |
| Nix package/path | pkgs.fetchFromGitHub { ... } or ./my-plugin |
symlinked into the profile; carries its own dependency closure |
Layer registration (which plugins join dsh.profile.bundles) is a pure
build-time reconcile that reads each resolved package's dsh.bundle.patch
declaration — dsh plugin's install/resolve/reconcile is replaced wholesale,
so removal is declarative and resolution failures surface at nix build.
In-box profiles get a build-time boot check: checks.profile-boot-web
and checks.profile-boot-headless boot the composed profile with dsh's own
boot() (which runs assertEntriesActivated) inside the Nix sandbox and
dispose immediately. A profile that would fail at runtime — missing
services, failed activation — fails nix build instead. The check is the
real dsh fail-loud, not a reimplementation: scripts/check-profile.mjs
loads the profile exactly as dsh --profile would and lets dsh's own
audit decide. checks.profile-boot-web-nobase proves the check catches a
web-app-without-base composition (8 pending entries).
Usage
Overlay
# nixos configuration:
imports = [ inputs.dsh-nix.nixosModules.default ]; # or:
nixpkgs.overlays = [ inputs.dsh-nix.overlays.default ];
# now pkgs.dsh is available everywhere:
environment.systemPackages = [ pkgs.dsh ];
The Home Manager module's package option defaults to pkgs.dsh when the
overlay is applied, falling back to a self-contained callPackage build.
Home Manager
inputs.dsh-nix.url = "github:Samuka007/dsh-nix";
inputs.dsh-nix.inputs.nixpkgs.follows = "nixpkgs";
# in your home-manager config:
imports = [ inputs.dsh-nix.homeManagerModules.dsh ];
programs.dsh = {
enable = true;
profiles.headless = {
plugins = [ "@deepseek-ai/dsh-base" "@deepseek-ai/dsh-headless" ];
};
profiles.web = {
plugins = [ "@deepseek-ai/dsh-base" "@deepseek-ai/dsh-web-app" ];
};
profiles.custom = {
plugins = [
"@deepseek-ai/dsh-base"
"github:someone/cool-plugin" # build-time resolve
];
specsHash = "sha256-..."; # pin the resolution
userPatchesFile = ./patches.yml; # profile-level cordis.patch.yml
};
homePatchesFile = ./home-patches.yml; # -> ~/.dsh/cordis.patch.yml
# settings = { ... }; # seeds ~/.dsh/settings.yaml once
};
Activation materialises each immutable profile into
~/.dsh/profiles/<name> (stamp-based idempotent refresh). The module owns
only the composition layers; sessions, settings, and credentials under
~/.dsh remain the app's.
dsh --profile headless "task"
dsh --profile web # http://127.0.0.1:3080
Standalone
nix build .#packages.x86_64-linux.dsh # the CLI
nix build .#packages.x86_64-linux.tui-spec # example: spec-resolved profile
nix eval .#profiles.tui-spec --json # the declaration
The package also ships dsh-acp-demo, the ACP automation server app
(JSON-RPC over stdio; supply a leaf cordis.yml via --config, e.g. the
upstream examples/acp-agent/cordis.yml).
Verification
nix flake check # artifact shape + module assertions
./scripts/profile-smoke.sh # boot tui profile with packaged dsh,
# assert activate/dispose lifecycle
./scripts/hm-e2e.sh # module eval -> activation -> boot
Real agent runs need credentials (DEEPSEEK_API_KEY, or configure the model
in the web UI so ~/.dsh/.credentials.yaml is populated).
Notes
- The Home Manager module's default
packagebuildspkgs/dsh.nixagainst your nixpkgs, which must providefetchPnpmDepsandpnpmConfigHook. - Spec-string plugins change their resolved content only when their
specsHashis updated — deliberate lockfile-style ceremony. - Upstream
dshships no TUI surface (onlywebandheadlessprofiles); a third-party TUI bundle would slot in as one plugin entry.
License
MIT
nexu-io/open-design
freestylefly/awesome-gpt-image-2
anywhere-labs/dsh-desktop
walkinglabs/learn-harness-engineering
awesome-dsh-plugin/awesome-dsh-plugin
MemTensor/MemOS