DeepSeek Harness Plugin Hub

Publish and manage complete Harness Profiles. Discover Plugins for your next setup.

Explore

PluginsPresetsDocsNews

Community

Publish a pluginContactReport an issue

Resources

Plugin Hub on GitHubDeepSeek HarnessSystem statusPrivacy notice
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

Independent and unofficial. Not affiliated with, authorized by, or endorsed by DeepSeek.

Image — DSH Plugin for DeepSeek Harness
← Plugins
I

@local/dsh-image

Image

Image generation for DeepSeek Harness through an OpenAI-compatible relay, exposed as both a slash command and an agent tool.

The plugin will be installed here. Keep web if you are unsure.

npx -y @deepseek-ai/dsh plugin --profile web add github:merlotqi/dsh-image#68e1df7f68ef26a63a94c28b365ef66da927bc4c
READMECompatibilityVersions

Compatibility and provenance

Image is published as @local/dsh-image and currently resolves to version 0.2.0. The Hub verifies its manifest and preserves the exact installation source for reproducible installs.

DSH compatibility
*
Runtime surfaces
web
Release source
github
Registry updated
10/16/2026

Versions

0.2.0stable
10/16/2026

Related plugins

Loading related plugins…

Latest
0.2.0
DSH
*
HMR
Process restart
Tree shaking
Safe tree shaking not declared
Unpacked size
Unavailable
Files
Unavailable
Surface
web
License
MIT
Source
github
GitHub
★ 0
Weekly downloads
0
Last push
10/16/2026
View source ↗
README badge

Click the badge to copy Markdown for your README.

Do you maintain this Plugin?Claim benefit · Priority security scan

Verify the GitHub repository declared in package.json to manage this listing. After you claim it, Hub will prioritize a security scan of the current version and publish the result when it passes.

Claim this Plugin →
Report an issue
DeepSeek Harness Plugin Hub
ProfilesPluginsCategoriesNewsDocsSign inManage Profiles
ProfilesPluginsCategoriesNewsDocsSign in

Related plugins

More verified plugins in vision-media.

Experimental Voice Input Bundle@deepseek-ai/dsh-experimental-voice-input-bundleExperimental voice input with local SenseVoice; downloads its runtime on first useAb Ocrdsh-ab-ocr--- description: "The out-of-tree ocr tool: recognizes a scanned PDF or image page by page, merges the pages in order only after the last one, and saves one Markdown document with the heading levels the model decided." kind: "package-reference" ---Modlens@liustack/modlensPlug-in vision for text-only LLMs, powered by the free Antigravity CLITool Describe Image@linxin666/dsh-tool-describe-imageModel-facing describe_image tool for the dsh web GUI: gives a text-only model image understanding by asking a vision-language model at an OpenAI-compatible endpoint to describe one image (local path, http(s) URL, or attachment reference). Hot-pluggable —

README

dsh-image

Image generation for DeepSeek Harness through an OpenAI-compatible relay (configured for api.ykh.ai / gpt-image-2).

No dependencies, no build step.

What it registers

SurfaceNameStarted by
Slash command/image <prompt>you
Agent toolgenerate_imagethe model

Both call one shared operation (lib/generate.js), per DSH's guidance for user actions and agent tools: "Do not maintain separate operation logic in the UI and tool paths."

The command's result is UI-side and never enters model history, so /image costs no tokens. The tool's result does enter the conversation, which is what lets the model show the picture and keep working.

Install

Install with file:, not link:. This is the one thing that will silently break the plugin.

dsh plugin --profile <profile> add file:C:/abs/path/to/dsh-image

Restart DSH once. Then / lists image, and the next agent gets generate_image.

Why file: and not link:

A link:ed package resolves its own imports from the link target's real path. When that path is outside the profile — a workspace, say — the host's installation-scope resolver does not cover it, so every bare @deepseek-ai/* import fails and the entry is dropped with:

dsh: warning: 1 entry did not activate
dsh-image (@local/dsh-image): failed to import

That message is a bare literal the loader emits when no fiber could be created, and nothing else reports it: --dump-config only composes (it never imports), and the plugin market reads composition state, not load outcomes. So the failure is completely silent in the UI.

file: installs a real copy inside the profile, where those packages resolve. (The zero-dependency plugins that get away with link: do so by importing nothing but node:* builtins.)

After editing

file: is a copy, so the installed plugin does not follow your edits:

dsh plugin --profile <profile> remove @local/dsh-image
dsh plugin --profile <profile> add file:C:/abs/path/to/dsh-image

Re-running only add may be reported as "Already up to date" and skip the copy, so remove first.

The API key

The config holds only the name of a credential reference. The value is resolved per operation through DSH's credential service, so rotating the key never needs a restart. Resolution order (fixed by DSH, highest wins):

  1. the environment DSH was launched with
  2. ~/.dsh/.credentials.yaml
  3. <project>/.env, then $DSH_HOME/.env

To set it persistently, add it to ~/.dsh/.credentials.yaml — the store reloads on change:

version: 1
refs:
  YKH_API_KEY: <your key>

Two things that quietly produce "no key":

  • an empty value (YKH_API_KEY: with nothing after it) — DSH treats a blank as absent, and also lists empty values among the things it refuses;
  • a missing space after the colon (YKH_API_KEY:sk-… is parsed as one plain string, not a mapping).

The key is never written into this plugin's config, never logged, and never sent anywhere except the configured relay.

Caveat, from DSH's own documentation: the shipped credential provider is file-backed, and file permissions cannot keep a key away from the agent — the agent's tool processes run as your OS user. A keyring or KMS provider exists only as an unimplemented seam. If that matters, do not put the key in the credential file.

Configuration

Change these in the profile patch, not in code — the user's patch layer survives upgrades:

- id: dsh-image
  name: '@local/dsh-image'
  config:
    baseUrl: https://api.ykh.ai/v1
    model: gpt-image-2
    apiKeyRef: YKH_API_KEY
    defaultSize: 1024x1024
    requestTimeoutMs: 180000
    outputDir: images

baseUrl is everything up to but not including /images/generations, so switching relays is a config edit.

Response shapes

The relay's response format is not assumed. The client branches on the content-type and handles all three shapes seen in the wild:

ShapeHandling
raw bytes, image/*written straight to disk
JSON data[0].b64_jsonbase64-decoded (OpenAI's own behaviour for gpt-image)
JSON data[0].urldownloaded, then written

The shape actually used is reported in the tool result, the log line and the command summary, so a first run resolves the question instead of us guessing. test/relay.test.mjs covers all three plus the failure modes.

Output

Images are written to <session workspace>/<outputDir>/<timestamp>-<slug>.<ext>.

Two paths are reported:

  • path — absolute, for tools that need a real filesystem path
  • relPath — workspace-relative with forward slashes, for markdown ![description](relPath)

An absolute Windows path in a markdown image reference is both an escape hazard and unresolvable by the transcript's loader, which resolves against the session workspace.

Development

index.js            wiring: identity, config schema, caller registration
client.js           browser half: the command row's label/description/icon
lib/generate.js     the one operation both callers use
lib/command.js      /image adapter
lib/tool.js         generate_image adapter
lib/relay.js        HTTP client (three response shapes)
lib/credentials.js  API-key resolution
lib/config.js       defaults + the config merge
lib/context.js      service lookup helper
lib/errors.js       error type + logging
test/relay.test.mjs relay tests (stubbed fetch; no host, no network, no key)

Run the tests:

npm test              # node --test test/
node test/relay.test.mjs   # same tests, in-process

Deliberately not included

  • No client bundle. The / entry works from the host-side registration alone (input.hint makes it a leadingInput command). client.js is plain hand-written JS in the shape DSH's module loader expects — there is no rolldown/tsdown build step.
  • No size/quality popup — that would be the first thing to need a real client contribution.
  • No cost guard. DSH can await confirmation from a tools/pre-execute listener returning ask; that belongs on model-initiated calls.
  • No batch / multi-image — data[0] only.