DSH plugin
Generative UI for DeepSeek Harness. The model answers with a live React interface instead of prose — and it streams, the component rendering while the model is still typing it.
dsh plugin --profile web add dsh-generative-uiWhere it shows up
````ui4a/tsxA fenced block in the reply
Renders in place, between the paragraphs. For a chart, a form, a set of options to click, a calculation the reader wants to change a number in — something that is part of reading the answer.
canvases/tarot.ui4a.tsxA file at .dsh/ui4a/canvases/
Opens in the panel beside the conversation and stays there across turns. For a tool the user comes back to — a tracker, a browser, an instrument. It is a file they own.
—Most of the time
Closures, CAP theorem, what day it is. An interface the reader has to decode is worse than a sentence, and the default is that prose is enough.
Live, not a screenshot
No schema, no component allowlist, no DSL. The model writes a component that export defaults — it can import anything on npm — and the runtime compiles it in the browser and mounts it.
-aarchive — recurse, and keep permissions, times, links-vverbose — print each file as it transfers-zcompress in transit (skip it on a fast LAN)--deletedelete anything on the server that is not hereThe trailing slash on ./dist/ decides whether the directory itself is copied. Both of these are controls, not decoration.
What a card can reach
A card imports the harness through the same capabilities the model has, under the same access mode the user can see and change in the composer. Read Only is Read Only for the card too.
$dsh/fsread and write files, under the session's own access mode$dsh/execrun a command where the host enables it, and check the exit code$dsh/aiask the model, on the app's default model, without seeing a key$dsh/websearch the web, and get sources back$dsh/chatsend text into the transcript as the user$dsh/stateusePersistedState — localStorage behind useStateHow the streaming works
The reply carries a four-backtick ui4a/tsx block. Four because generated TSX routinely contains triple backticks.
The client matches the rendered block against the conversation snapshot — never the language tag, which the host truncates and only emits once the fence closes.
partial-tsx + a wasm compiler run in the browser, on the growing text. Half-written JSX is normalized; frames that cannot compile are transient, not errors.
The component renders against the host's own React singleton, so hooks work and the card takes the app's colours, theme and container width.