DeepSeek Harness: Loading Local Plugins

Last updated: 2026-08-31

Understanding the plugin loading mechanism is the key leap from "wrote a plugin" to "efficiently developing plugins." cordis.yml is DSH's configuration hub, and the --patch overlay mechanism lets you flexibly layer local plugins without modifying the default configuration.

💡 Tip: The core idea of the --patch mechanism is "layering, not replacing" — the default configuration stays unchanged, and your local modifications are overlaid on top. This lets development debugging and production deployment share the same base configuration.

📋 Prerequisites: Completed 11-first-plugin.md, able to create a minimal plugin

1. What You'll Learn


Patch Load

2. cordis.yml Configuration Details

(1) Configuration File Location

cordis.yml is DSH's core configuration file, located at the project root:

TEXT 📖 Display only
my-dsh-project/
├── cordis.yml        ← Main configuration
├── cordis.patch.yml  ← Patch configuration (optional)
├── package.json
└── src/

(2) ▶ Example 2

YAML
# cordis.yml basic structure
plugins:
  plugin-name:
    # Plugin configuration items
    enabled: true
    config:
      key: value

# Global configuration
hostname: localhost
port: 5173

(3) Plugin Entry Format

Each plugin entry contains three pieces of information:

Field Description Example
Plugin name The key is the plugin identifier my-plugin:
Path Where to load from $insert or npm package name
Configuration Parameters passed to the plugin Fields under config:
YAML
plugins:
  # npm package plugin
  @dsh-plugin/database:
    config:
      connection: "postgresql://localhost/mydb"
  
  # Local plugin
  my-local-plugin:
    $insert: /home/alice/dev/my-plugin
    config:
      debug: true

3. $insert and $replace Operations

(1) $insert: Append a Plugin

$insert adds a plugin to the existing plugin list:

YAML
plugins:
  my-tool:
    $insert: /home/alice/dev/dsh-plugin-my-tool

Effect is equivalent to:

TEXT 📖 Display only
Default plugin list: [core, llm, tools, shell, ...]
After insert:       [core, llm, tools, shell, ..., my-tool]

(2) $replace: Replace a Plugin

$replace replaces an existing plugin with a new implementation:

YAML
plugins:
  # Replace the default LLM adapter with a custom one
  llm:
    $replace: /home/alice/dev/custom-llm-adapter

Effect:

TEXT 📖 Display only
Default: llm → @deepseek-ai/dsh-plugin-llm
Replaced: llm → /home/alice/dev/custom-llm-adapter

⚠️ $replace must specify an existing plugin name; you cannot replace a non-existent entry.

(3) ▶ Example 3

YAML
plugins:
  # Append local tool
  my-tool:
    $insert: /home/alice/dev/dsh-plugin-my-tool
  
  # Replace default shell with a secure version
  shell:
    $replace: /home/alice/dev/dsh-plugin-safe-shell
  
  # Append another local plugin
  my-monitor:
    $insert: /home/alice/dev/dsh-plugin-monitor

(4) Operation Priority

When the same plugin has both $insert and $replace:

TEXT 📖 Display only
Priority: $replace > $insert

If the $replace target doesn't exist, it falls back to $insert behavior.


4. Path Strategy

(1) ▶ Example 1

YAML
plugins:
  my-plugin:
    $insert: /home/alice/dev/my-plugin

Advantages:

Disadvantages:

(2) Relative Paths

YAML
plugins:
  my-plugin:
    $insert: ./plugins/my-plugin

Relative paths are resolved based on the directory containing cordis.yml.

Advantages:

Disadvantages:

(3) Path Selection Recommendations

Scenario Recommended Reason
Personal development Absolute path Clear, unambiguous
Team collaboration Relative path Portable, consistent across environments
CI/CD Relative path Build environment paths vary
Temporary debugging Absolute path Quick to locate, no path issues

5. --patch Overlay Mechanism

(1) Configuration Layering Model

DSH configuration is built from multiple layers:

100%
graph TB
    BASE[Base Layer<br/>Default Configuration] --> BUNDLE[Bundle Layer<br/>dsh-base / dsh-web-app]
    BUNDLE --> PROFILE[Profile Layer<br/>web / headless]
    PROFILE --> PATCH[Patch Layer<br/>cordis.yml + --patch]
    PATCH --> FINAL[Final Configuration]

Each layer overrides same-named configuration items from the previous layer, similar to CSS cascade priority.

(2) --patch Parameter

BASH
# Apply patch layer at startup
pnpm dsh web --patch

Without --patch, DSH only reads the default configuration and ignores $insert/$replace in cordis.yml. With --patch, the override operations in cordis.yml take effect.

(3) cordis.patch.yml

In addition to the main configuration, you can use cordis.patch.yml as an extra patch layer:

YAML
# cordis.patch.yml — only for development environments
plugins:
  debug-tools:
    $insert: ./dev-plugins/debug-tools

--patch reads both cordis.yml and cordis.patch.yml, with the latter having higher priority.

(4) Overlay Merge Rules

TEXT 📖 Display only
Base config:  { a: 1, b: 2, c: 3 }
Patch layer:  { b: 20, d: 4 }
─────────────────────────────
Final config: { a: 1, b: 20, c: 3, d: 4 }

6. --dump-config to View Final Configuration

(1) Basic Usage

BASH
pnpm dsh web --patch --dump-config

Outputs the fully merged final configuration:

YAML
# === Merged Configuration ===
hostname: localhost
port: 5173
plugins:
  core:
    enabled: true
  llm:
    enabled: true
    config:
      provider: deepseek
  tools:
    enabled: true
  my-tool:              # ← Your insert
    $insert: /home/alice/dev/my-tool
    config:
      debug: true
  debug-tools:          # ← Added by patch.yml
    $insert: ./dev-plugins/debug-tools

(2) Debugging Configuration Issues

When a plugin doesn't load as expected, use --dump-config to troubleshoot:

BASH
# Troubleshooting steps
pnpm dsh web --patch --dump-config > config-dump.yml
# Check if your plugin appears in the final configuration
# Check if $insert path is correct

(3) View Specific Plugin Only

BASH
# Filter to view specific plugin configuration
pnpm dsh web --patch --dump-config | grep -A 10 "my-plugin"

7. Local Development and Debugging Workflow

(1) Standard Development Loop

100%
graph LR
    CODE[Write Plugin Code] --> REG[Register in cordis.yml]
    REG --> START[Start dsh web --patch]
    START --> TEST[Test Plugin Behavior]
    TEST --> BUG{Bugs?}
    BUG -->|Yes| CODE
    BUG -->|No| DONE[Done]

(2) Quick Iteration Tips

Alice's typical workflow when developing a tool plugin:

BASH
# 1. One-time cordis.yml configuration
cat > cordis.yml << 'EOF'
plugins:
  my-tool:
    $insert: /home/alice/dev/dsh-plugin-my-tool
EOF

# 2. Development loop
# Edit code → restart → test
pnpm dsh web --patch
# When done testing, Ctrl+C to stop

# 3. Verify configuration
pnpm dsh web --patch --dump-config | grep my-tool

(3) Multi-Plugin Parallel Development

Bob developing two plugins simultaneously:

YAML
# cordis.yml
plugins:
  tool-a:
    $insert: /home/bob/dev/dsh-plugin-a
  tool-b:
    $insert: /home/bob/dev/dsh-plugin-b

Develop in separate terminals; both plugins load when restarting DSH.

(4) Temporarily Disabling a Plugin

No need to uninstall — just comment it out in the configuration:

YAML
plugins:
  my-tool:
    $insert: /home/alice/dev/my-tool
  # experimental-tool:       # Temporarily disabled
  #   $insert: /home/alice/dev/exp-tool

❓ FAQ

Q What's the difference between cordis.yml and dsh.config.yaml?
A cordis.yml is the Cordis framework's configuration, managing plugin loading and overrides. dsh.config.yaml is the DSH application's configuration, managing modes, approval policies, etc. They complement each other and don't conflict.
Q What happens if the $insert path points to a directory without package.json?
A DSH will try to load the directory as a plugin. If required fields (like the main entry) are missing, it will report an error and skip. We recommend always ensuring local plugin directories have a package.json.
Q Will cordis.yml be read without --patch?
A No. Without --patch, DSH uses the default configuration and ignores cordis.yml. This is intentional — to prevent development configuration from accidentally affecting production.
Q Can cordis.patch.yml be placed elsewhere?
A Currently only cordis.patch.yml in the project root is supported. If you need multiple patch sets, you can manually switch file contents.
Q Do I need to restart after modifying configuration?
A Yes, you need to restart dsh web --patch for cordis.yml changes to take effect. See 18-hot-reload.md for HMR mechanisms.

📖 Summary


📝 Exercises

1. ⭐ Basic: Register the hello-world plugin from the previous lesson using $insert in cordis.yml, and use --dump-config to confirm it appears in the final configuration.

2. ⭐⭐ Intermediate: Register the same plugin using both absolute and relative paths, and use --dump-config to compare the output differences between the two configurations.

3. ⭐⭐⭐ Challenge: Create two local plugins A and B, and $insert both in cordis.yml. Try using $replace to replace one of DSH's built-in tool plugins with your custom version, and verify the replacement with --dump-config.

Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏