Preface¶
When an agent needs to compare two pieces of content, the common approaches are to spawn a bash process to call the system diff tool, or implement a comparison logic from scratch. This task is frequently encountered when working with configuration snippets, API responses, tables, or document revisions. The system diff tool only operates on raw text: if you modify $.user.name in a JSON object, the output will typically show large added/removed lines without indicating the specific path. For CSV files, commas inside quoted fields, or renamed Markdown headings, writing custom comparison logic risks missing edge cases. On Windows, the overhead of spawning a new process for each comparison is even more noticeable.
DeepSeek Harness (dsh) treats models, tools, sessions, and interfaces as plugins, with the official repository’s motto being Everything is a Plugin. The community has thus developed a set of deterministic tools for model invocation. dsh-tool-diff serves a specific purpose: performing structured comparisons of text, JSON, CSV, and Markdown within the same process, outputting either unified diffs or change lists with path information, without reading from or writing to disk, and without making network requests.
First, it is important to clarify the sources. The core DeepSeek Harness repository is located at deepseek-ai/deepseek-harness. deepseek-harness-plugin.com is an independent community plugin directory, whose About page explicitly states it has no official affiliation with DeepSeek / HyperMind and should not be treated as an official app store. This article cross-references information from the directory details, GitHub repository README / package.json / LICENSE, and the official Harness repository, with verification completed on 2026-08-18.
What It Is¶
dsh-tool-diff is a “tool and capability” plugin maintained by the GitHub organization omdsh-dev, with its source code hosted at omdsh-dev/dsh-tool-diff. It is licensed under MIT and primarily written in TypeScript. As of the time of writing, both the plugin directory and GitHub repository show a 4-star rating. The package name in package.json is @deepseek-ai/dsh-tool-diff, version 0.0.1, marked with "private": true, and it is installed via GitHub source rather than as a public npm package. The engines field requires Node.js ^22.19.0 || >=24.0.0.
It registers a tool named diff for models, with the row ID in its profile being tool-diff. Its input consists of two strings before and after, with different comparers selected based on the action parameter, and it uniformly returns a JSON text envelope. The repository README positions it as: zero dependencies, pure function, read-only.
It solves three main pain points:
- No need to spawn a system process for a single comparison
- Make JSON/CSV/Markdown changes traceable to specific paths, rows, or columns, rather than just raw text diffs
- Reproducible and bounded comparison logic: reject oversized inputs directly, truncate oversized outputs and set the truncated flag
The README notes that it has been fully end-to-end validated in the isolated consumer environment of @deepseek-ai/dsh@0.1.0-rc.6: the plugin row is visible in configuration dumps, and the tool can be registered and executed. This is the repository’s own validation record, not a third-party evaluation.
Core Features¶
After installation, there is only one tool available: diff. Five comparison modes are distinguished via the action parameter, and all action envelopes include the fields { equal, truncated, beforeBytes, afterBytes, changes }.
| action | Function | Output Highlights |
|---|---|---|
text |
Line-level Myers diff | Defaults to unified diff (--- before / +++ after / @@ hunk, no timestamps) plus statistics; if format=structured, returns a list of operations with line numbers |
json |
Recursively compare two JSON values | Changes tracked via $ paths, such as $.user.name, $.items[0], $['a.b'], with summaries for add/remove/replace operations |
csv |
Parse per RFC 4180 before comparison | addedRows / removedRows / changedRows (column-level) / duplicateKeys / column set changes |
markdown |
Lightweight block-level tokenization | headingChanges (including renames) / blockChanges (such as h2[1]/p[0]) / codeBlockChanges, plus full-text diff |
patch |
Generate unified diff and validate in memory | Patch text plus valid / hunks / targetMatchesAfter / hunk-level errors |
Common parameters are listed below, all sourced from the repository README:
- before / after: Content on both sides, required for all actions
- format: unified (default for text / patch), structured (default for json / csv / markdown), both
- context: Number of context lines for unified diff, default 3, range 0..20
- key: CSV primary key column name or 1-based column number; if not provided, comparisons are made by row position
- delimiter: CSV delimiter, default ,, can also use tab
- ignoreWhitespace / ignoreCase: Ignore whitespace or case during comparison; patch will reject these options, as patches require exact text protocol compliance
- sortKeys: Sort JSON object keys, default true, to keep change lists stable
- maxChanges: Maximum number of changes to report, default 1000, hard cap at 10000
The security model is a key focus of this plugin, as explicitly detailed in the README:
- Zero dependencies: Myers line-level diff, RFC 4180 parsing, and JSON recursive comparison are all hand-implemented, with no third-party comparison libraries imported
- Read-only: No file reading, file writing, network access, or git calls; the patch action only generates and validates patches in memory, never writing to disk
- Resource budgets: Single-side input ≤ 256 KiB (rejected directly if exceeded); output ≤ 64 KiB (truncated per maxChanges and byte budget, with truncated flag set); line count ≤ 50,000; JSON nesting depth ≤ 64; CSV ≤ 50,000 rows / 512 columns; timeoutMs: 2000
- Additional Myers diff safeguards: diagonal budget of 2000, total snake step budget of 20 million, common prefix/suffix trimming, and 4000-line size limit to avoid hanging the process from malicious repetitive or fully dissimilar text
- Tool parameters are logged to session logs; do not pass sensitive data such as keys or tokens as before / after values
There are also several design boundaries that will be enforced during execution:
- If a CSV key is provided and the file has a header, comparisons are made by primary key, ignoring row order; otherwise, comparisons are made by data row number. Duplicate keys on either side are added to duplicateKeys, and equal=false will be set, with these rows excluded from matching
- JSON parsing first performs a non-recursive bracket scan, rejecting inputs with nesting depth exceeding 64; duplicate keys are detected via a state machine and logged to duplicateKeys.before/after, not silently dropped
- Markdown comparisons use Myers diff at the block level: changes to content within blocks of the same type are marked replace, while structural additions/removals are marked add/remove; changes to title text at the same path and level are recorded as rename
- For the patch action, equal only indicates that the two sides are identical under exact line and trailing newline semantics, and is unrelated to valid; valid only means that the generated patch can be applied to before to produce after. If the patch is truncated, valid:false and patchComplete:false will be set
- The entry point rejects isolated surrogates, returning an invalid Unicode error
- Unified diffs do not include timestamps for reproducibility
The repository README notes that tests are written with vitest, and there are currently 124 test cases. Peer dependencies are @deepseek-ai/cordis ^4.0.1, @deepseek-ai/dsh-tools and @deepseek-ai/dsh-invariants (>=0.0.1-rc.1 <0.2.0), which are provided via the profile’s profiles/node_modules fallback installation, and the plugin itself no longer depends on unscoped cordis.
Installation and Activation¶
The installation command provided on the directory page can be run in the DeepSeek Harness terminal:
dsh plugin add github:omdsh-dev/dsh-tool-diff
The directory page also notes that the plugin runs with the permissions of the current dsh process, and code execution may occur during installation. Inspect the source repository and license before installing; for reproducible installations, pin the commit hash. Replace #commit with the full commit hash from the repository. As of the time of writing, the latest commit on the main branch is 73c142e262275c5a278dc31e80bac7966fba168e (2026-08-14):
dsh plugin add github:omdsh-dev/dsh-tool-diff#73c142e262275c5a278dc31e80bac7966fba168e
The repository README recommends installing per profile. The web interactive interface and headless mode for dsh run use separate profiles that do not overlap:
# Interactive (web) profile
dsh plugin --profile web add github:omdsh-dev/dsh-tool-diff
# Headless profile for one-off tasks — used by default for dsh run
dsh plugin --profile headless add github:omdsh-dev/dsh-tool-diff
You can also first run npm pack to install from a local tarball:
git clone https://github.com/omdsh-dev/dsh-tool-diff
cd dsh-tool-diff
npm install && npm pack
dsh plugin --profile web add ./deepseek-ai-dsh-tool-diff-*.tgz
dsh plugin --profile headless add ./deepseek-ai-dsh-tool-diff-*.tgz
The included dsh.bundle.patch (corresponding to cordis.patch.yml in the repository) will insert the plugin into the profile’s layer stack after installation, with the ID tool-diff. Use forward slashes for Windows paths, e.g. C:/....
Verify the installation:
dsh --profile web --dump-config | grep tool-diff
The run verification command provided in the README is:
dsh run "使用 diff 工具对比两段文本"
Note: dsh run defaults to headless mode. If you only installed the plugin for the web profile but not the headless profile, this command will not show the tool. The README also recommends starting with npx -p @deepseek-ai/dsh@0.1.0-rc.6 dsh web, and advises against using npm install -g for global installation. Manually modifying profile layers or local junctions/symlinks is only suitable for source contributions or old snapshots; use the official bundle method for daily installations.
Typical Usage¶
After installation, the model calls the diff tool, passing in the action, before, and after parameters. The repository does not provide a step-by-step GUI tutorial, and the following examples and validation commands are directly sourced from the README.
1. JSON Path-Level Changes¶
When action=json, the default format is structured. The sample envelope from the README is as follows:
{"kind":"json","equal":false,"beforeBytes":42,"afterBytes":58,"changes":[
{"op":"replace","path":"$.tags[1]","before":"b","after":"c"},
{"op":"add","path":"$.user.email","after":"b@x.com"},
{"op":"replace","path":"$.user.name","before":"Alice","after":"Bob"}],
"summary":{"added":1,"removed":0,"replaced":2,"moved":0}}
This output conveys three key pieces of information: the second item in the $.tags array was changed from b to c, a new email field was added under $.user, and the name field was updated from Alice to Bob. The system diff tool would typically only show line-level additions and removals of the raw JSON, without providing these specific paths.
The sortKeys option is enabled by default, keeping the order of change lists stable for easy assertion or passing to subsequent processing steps.
2. Text Unified Diff¶
When action=text, the default format is unified. The output is a standard unified diff, with fixed file headers --- before / +++ after, hunks marked with @@, and no timestamps. If you need to show the model “what happened on which line”, change the format to structured. The number of context lines is controlled by the context parameter, with a default of 3.
Use the ignoreWhitespace or ignoreCase flags when you only care about logical equivalence and want to ignore whitespace or case differences. These switches work for text / csv / markdown actions, but are rejected by the patch action and should not be used together.
3. CSV, Markdown, and In-Memory Patches¶
For table comparisons, use action=csv. Set the key parameter to a stable primary key (such as an id column) to match rows even if their order has changed; without a primary key, comparisons are made by row position. Change the delimiter parameter if your CSV uses a non-comma separator, and use tab for tab-separated files.
For document revisions, use action=markdown. It first splits the document into blocks by title, code block, list, quote, and table, then performs Myers diff at the block level: title renames are logged in headingChanges, and changes to code block language, line count, or content are logged in codeBlockChanges.
When you need a patch that can be applied from before to after but do not want to modify disk files, use action=patch. Check the valid and hunks fields in the return value; do not use a truncated patch as a valid patch. The README explicitly states that the patch is only generated and validated in memory, never written to disk, and never calls git.
A basic smoke test can be run using the command provided in the repository to confirm the tool is registered:
dsh run "使用 diff 工具对比两段文本"
Applicable Scenarios and Notes¶
This plugin is suitable for the following situations:
- Agents need to compare configuration snippets, API responses, CSV exports, or Markdown documents, and require path/row/column-level changes rather than raw text diffs
- You want comparisons to occur within the dsh process without spawning additional diff / git child processes
- You need unified diffs or in-memory patch validation, but do not want the plugin to modify workspace files
Please note the following points, all sourced from the directory page or repository README, not additional recommendations:
1. Inspect the source code and license before installing. The directory page notes that the plugin runs with the permissions of the current dsh process, and code execution may occur during installation. Although this plugin claims to be read-only, it should still be treated as third-party code.
2. The community directory is not an official store. deepseek-harness-plugin.com is an independent site with no affiliation to DeepSeek / HyperMind.
3. Install separately for web and headless profiles. If you only install the plugin for the web profile, it will not be available in the headless profile used by default for dsh run.
4. Hard limits exist for input and output. Single-side inputs exceeding 256 KiB will fail directly; outputs exceeding 64 KiB will be truncated. For large files, slice them beforehand, do not attempt to pass the entire file to the tool in one go.
5. Do not pass sensitive data. All parameters are logged to session logs.
6. patch is not a disk-based patch tool. It does not write files or call git; ignoreWhitespace / ignoreCase cannot be used with the patch action.
7. Runtime version requirements. The README validation baseline is @deepseek-ai/dsh@0.1.0-rc.6; package.json requires Node.js 22.19+ or 24+. Older snapshots may require the manual installation path described in the repository.
8. The @deepseek-ai/ package prefix does not mean official plugin. This is the npm package name for the community repository omdsh-dev/dsh-tool-diff, and it is marked private: true.
Summary¶
dsh-tool-diff registers a read-only diff tool for DeepSeek Harness: it performs Myers line-level comparisons for text, provides $ path tracking for JSON, aligns CSV rows by primary key or position, aligns Markdown content by blocks, and generates and validates unified patches in memory when needed. The comparison logic has zero dependencies, has strict input/output budgets, and never accesses disk or network. For users who frequently need agents to verify configurations, API responses, and document revisions, it fills the gap between “system