DeepSeek Harness plugin

dsh-lens-lite

Post-edit diagnostics for DeepSeek Harness: runs configured type-checkers and linters after a successful write/edit and feeds the findings back to the model as tool-result context

Jump to install

Source facts

Repository
ben7am1n/dsh-lens-lite
Latest update
Aug 13, 2026
Category
Tools & Capabilities
GitHub stars
1
Format
plugin
Catalog evidence
Upstream dsh.bundle evidence
Evidence path
package.json#dsh.bundle
Checked against
0.1.0-rc.8
Upstream check date
2026-08-20

This evidence comes from the upstream catalog. This site has not installed, run, or security-reviewed the plugin.

Install

Start with a prompt that asks an agent to review the GitHub repository and source. Switch to the command if you want to install it yourself.

Copy this prompt into DSH, Codex, or another agent and ask it to review the GitHub repository and source first.

Do not install or run any commands yet. Read this plugin's GitHub repository, README, and relevant source code. Then answer the questions below clearly and directly so I can decide whether it fits my needs:

1. What is this plugin, and what problem does it solve?
2. Who is it for, and what are its typical use cases?
3. How is it used after installation? Include one minimal example.
4. What known limitations or privacy, security, compatibility, or maintenance risks does it have?
5. Give a clear recommendation: recommend, conditionally recommend, or do not recommend, with reasons.

Distinguish statements documented by the repository, inferences from source code, and unknowns. If evidence is insufficient, say so explicitly. Do not guess or simply repeat the README.

GitHub: https://github.com/ben7am1n/dsh-lens-lite
Plugin: dsh-lens-lite
Author: ben7am1n

Check the source files

Read the README and other files from this plugin directory before installing.

File explorer3 files
README.mdSource · read only

dsh-lens-lite

Post-edit diagnostics for DeepSeek Harness.

After a file-mutating tool succeeds, this plugin runs the checkers you configured for that file's extension and attaches their output to the same tool result as model-visible context. The next model request therefore already carries the type errors or lint findings the edit introduced, instead of the model discovering them a few turns later.

dsh-lsp covers semantic navigation (definition, references, hover). It does not surface diagnostics, and nothing in the shipped harness runs a type-checker after an edit. This plugin fills that gap.

Install

dsh plugin --profile web add dsh-lens-lite

Then override the row in your profile's cordis.patch.yml with the checkers your toolchain actually has (the shipped row has none — see [Configuration](#configuration)).

How it behaves

  • Runs only after a successful call to a watched tool (write, edit, str_replace_editor by default).
  • Takes the edited path from the tool's canonical path value — the path the filesystem backend actually resolved — and falls back to the file_path argument for tools that declare no such value.
  • Runs every checker claiming that file's extension, concurrently.
  • Attaches nothing when every checker exits with a configured clean code and prints nothing.
  • Never vetoes and never rewrites a call. It delegates the tools/post-execute waterfall first and only folds context onto whatever decision came back, preserving every downstream context's own source and metadata.
  • Skips linting entirely when a downstream listener blocked the call — that blocked call is already the feedback the model must react to.
  • Honours the tool call's cancellation signal, and terminates a checker's whole process tree when its own timeout expires.

Findings arrive as a notice-form plugin context, so the transcript shows a collapsed one-line summary rather than a wall of compiler output.

Configuration

Every deployment-varying value is a config field. The plugin ships no built-in commands: which checkers exist is a property of your toolchain, not of this package.

- id: lens-lite
  name: dsh-lens-lite
  config:
    tools: [write, edit, str_replace_editor]
    maxDiagnosticChars: 4000
    checkers:
      - name: tsc
        extensions: ['.ts', '.tsx']
        argv: ['npx', '--no-install', 'tsc', '--noEmit']
        cwd: '.'
        timeoutMs: 60000

      - name: eslint
        extensions: ['.ts', '.tsx', '.js', '.jsx']
        argv: ['npx', '--no-install', 'eslint', '--format', 'compact', '{file}']
        cleanExitCodes: [0]

      - name: ruff
        extensions: ['.py']
        argv: ['ruff', 'check', '--output-format', 'concise', '{file}']

      - name: go-vet
        extensions: ['.go']
        argv: ['go', 'vet', '{dir}']
        streams: [stderr]

Checker fields

FieldDefaultMeaning
name— (required)Label shown to the model above this checker's output
extensions— (required)Lowercase, leading-dot extensions this checker claims
argv— (required)Executable + arguments. argv[0] resolves against the subprocess provider's scrubbed PATH. Never shell-interpreted
cwd.Working directory, resolved against the harness process directory (your workspace root)
timeoutMs30000Wall-clock bound; the process tree is terminated when it expires
graceMs2000SIGTERM→SIGKILL grace for that termination
maxOutputBytes65536In-memory cap per collected stream; overflow keeps the tail
cleanExitCodes[0]Exit codes meaning "no findings"
streams[stdout, stderr]Which streams carry findings, in concatenation order

argv entries support three placeholders, substituted per run:

PlaceholderValue
{file}Absolute path of the edited file
{relFile}That path relative to cwd
{dir}Its containing directory

Plugin fields

FieldDefaultMeaning
tools[write, edit, str_replace_editor]Tool names whose successful results are inspected
checkers[]Checkers, all consulted; empty means the plugin does nothing (it says so once at load)
maxDiagnosticChars4000Cap on model-visible diagnostic text per result; overflow keeps the head, because the first error is usually the cause of the rest

Cost

Whole-project checkers run on every edit. npx tsc --noEmit on a large repo can add seconds to each write. Prefer single-file invocations ({file}) where the tool supports them, and raise timeoutMs only for the checkers that genuinely need it.

Failure behavior

Load-time misconfiguration fails loud: an empty argv, a checker claiming no extensions or reading no streams, a duplicate checker name, or a non-positive bound throws at plugin load.

Environment failures do not fail the edit — the call already succeeded — and become findings instead:

  • An unresolvable executable is reported once as checker unavailable: …, then that checker stays quiet for the rest of the fiber's life.
  • A timeout is reported as checker timed out after Nms.
  • A spawn-level failure is reported as checker failed to start: ….

Extension point

One listener on tools/post-execute, plus ctx.subprocess for spawning. No core changes, no agent-loop changes.

Development

pnpm install --ignore-workspace
pnpm run typecheck
pnpm test
pnpm run build

The test suite drives the real tools/post-execute waterfall against the real local subprocess provider, using node -e programs as checkers, so it covers actual spawning, exit-code classification, stream selection, and timeouts without requiring any toolchain.

License

MIT

Prior art

The post-edit-feedback idea comes from pi-lens (MIT) in the Pi ecosystem. This is an independent implementation against Harness extension points and shares no code with it; it deliberately covers only the run-checkers-after-edit slice, not pi-lens's AST rules, dependency mapping, or triage system.