* chore(nix): update nixpkgs to e62746b and fix 26.11 breakage Bump nixpkgs to e62746b and preservation to 00be7f7, then adapt to the removals and renamed options in the new revision: drop the removed boot.initrd.systemd.enable settings, trim the stale emSign CA blacklist on Linux while keeping it for the older Darwin input, and migrate Avahi publishing to settings.publish. Work around sunshine still setting the legacy Avahi options and keep dsh-nu on its tested Nushell 0.115.1. Patch NUR dsh's pnpm call to pass nodejs = null, and update pyclipsync for the stdenv.hostPlatform.system rename. * chore(nix): refresh flake inputs for 26.11 - update nixpkgs-darwin to the same e62746b revision as nixpkgs - make dsh-nu follow main nixpkgs and patch its testedWith manifest for the resolved Nushell - refresh floating inputs; update lanzaboote, tuios, and ponytail - drop the nixpkgs-2505 and rust-overlay workarounds - keep pyclipsync on main and simplify the cross-platform CA blacklist - adopt home-manager's Nushell loadSessionVariables default * fix(gitea): use ROOT_URL for nixpkgs 26.11 nixpkgs removed the legacy settings.server.DOMAIN option; the existing ROOT_URL already carries the public URL. * chore(nix): update dsh-nu to 0.7.0 Assisted-by: DeepSeek Harness (deepseek-flash)
5.6 KiB
dsh configuration
dsh is installed by this module (packages.nix) and configured at runtime, not by Nix. It boots a
profile: an ordered stack of patch layers over an empty root entry list, where later layers win.
| # | Layer | Path | Writer |
|---|---|---|---|
| 1 | bundles | shipped with the profile | upstream |
| 2 | profile | $DSH_HOME/profiles/<name>/cordis.patch.yml |
dsh, at runtime |
| 3 | home | $DSH_HOME/cordis.patch.yml |
you |
| 4 | --patch |
whatever the launcher passes | package wrapper |
$DSH_HOME defaults to ~/.dsh. Settings UI changes are written to the profile patch; a home-layer
row outranks it, so the UI rejects that setting with
Configuration for "..." is overridden by a home patch. This repository ships no home layer:
profile patches remain machine-local runtime state, the place for private endpoints (LAN servers,
staging gateways) too. The shell swap is a package concern instead: Nix installs dsh from
nur-ryan4yin with dsh.withPlugins, which adds a --patch overlay after the profile layer.
Three behaviours that are easy to get wrong:
- A patch row's
configreplaces the row's config object instead of deep-merging into it. Repeat every key you mean to keep; the shippedagent-looprow repeatsagents: []for this reason. - The web and desktop surfaces give each agent preset its own compaction service, so a top-level
compaction-basicrow never reaches a session. Compact by setting the route's modelcontextWindowandmaxTokensinstead. dsh-llm-pi-airegisters its providers once, so mount only one instance: a second one fails withprovider "..." is already declared.
To see what your own patches actually change:
dsh <profile> --dump-config # composed tree with every layer applied
dsh <profile> --dump-default-config # the same tree without the home layer or --patch overlays
The dsh-base bundle sets agent-default-model to the API-key route (deepseek-official /
deepseek-flash). The account route never falls back to an API key, so a host holding only
DEEPSEEK_API_KEY fails new sessions with ACCOUNT_SIGN_IN_REQUIRED.
In this repository, just dsh-web boots the web profile through mihomo's mixed port.
Global rules
dsh-base already mounts dsh-agent-instructions (maxBytes: 65536) and rules.nix links
agents/global-rules.md into both scopes it reads — $DSH_HOME/AGENTS.md and, from 0.2.1-alpha.2
on, $DSH_AGENTS_HOME/AGENTS.md — so no patch row is needed; identical content renders once.
- The scopes come from the environment:
0.2.1-alpha.2removed the row'sdshHome/agentsHome. - Nested
AGENTS.mdfiles are discovered byread/write/edit, not bycdinsidebash, and nothing is watched: an external edit lands on the next such call, or on resume.
Nushell-only shell
dsh-nu's flake builds the bundle and nur-ryan4yin's dsh.withPlugins applies it: every
ctx.shell consumer (model shell tools, background jobs, hook bridges, in-process callers) runs
nu --no-config-file -c, and a command that hands execution to another shell is refused before it
spawns. The plugin adds Nushell rules and a syntax guide, and rewrites the shell-tool descriptions,
so the model is told what actually runs. nu is the Nushell dsh-nu's flake resolves — Nixpkgs',
through inputs.nixpkgs.follows — substituted into the rendered patch at build time, so it does not
depend on PATH. The bundle still records Nushell 0.115.1 as its tested release; nix-config follows
the main nixpkgs and rewrites that manifest field to the resolved Nushell in outputs/default.nix
until dsh-nu retests, rather than pinning an older nixpkgs for the whole plugin. A command that
hands a script file to a shell (bash scripts/build.sh) is refused, and the refusal names the
direct ./scripts/build.sh spelling; the guard itself is unchanged.
home/base/tui/agents/packages.nix calls dsh-nu.lib.mkDshNuPackage { inherit pkgs dsh; } and
passes the result to withPlugins; flake.lock pins both inputs. dsh.withPlugins wraps the
binary: each invocation gets a generated --patch <file> overlay after the profile layer, while
dsh plugin stays untouched. No $DSH_HOME/cordis.patch.yml is written, so there is no home-layer
state to resolve or roll back. Boundaries: preset rows that spawn a shell themselves
(custom-bash.mjs, persistent-shell) bypass ctx.shell. So does
@deepseek-ai/dsh-experimental-terminal-bundle: its terminal_* tools use a separate
ctx.terminals seam and run the platform shell (bash on the POSIX hosts this repository manages),
so they coexist with this plugin but stay outside the Nushell-only guarantee — keep the bundle off
for a strict Nu-only machine. Bash hooks now run under Nushell and need rewriting; remote hosts
still run their own POSIX shell. Rollback: install plain dsh or pass an empty plugin list; there
is no home file to delete. Tested on Linux; the same package also builds for Darwin, where it has
not been boot-tested.
Verify after a switch:
dsh --profile web --dump-config | grep -nE 'nu-executor|nu-teaching'
# expect the first-party shell rows disabled, nu-executor and nu-teaching inserted
A dsh bump can disable a row whose manifest no longer matches. That compatibility check runs only
when a profile boots, not under the boot-free --dump-config, so read the stderr of the next boot
(for example just dsh-web) for disabling profile plugin; nothing prints when healthy.