What it does
OpenWrite turns dsh into a long-form fiction studio. It is not a single tool: it installs an agent preset that merges planning and prose writing into one session, a bridge registering a large novel_* tool surface, a native writing workbench in the browser client, and a managed local Python backend that owns the domain logic. The README states the split plainly — dsh supplies the agent and interface, OpenWrite Core supplies the novel-domain behaviour, and the work itself stays in a local project directory you choose.
Three claims in the repository’s metadata are worth checking rather than repeating, and all three hold up: the 90 tools, the unified creation agent, and the review DAG.
The 90 tools are 90 distinct tools
This one survives counting. packages/openwrite-bridge/lib/tools.js in the published dsh-openwrite@0.2.10 tarball contains exactly 90 defineTool registrations, all names unique and all prefixed novel_. The bridge’s own policy test asserts it independently (“real dsh tool registry isolates 90 tools by preset and disposes them”) and passes on the published source.
Two qualifiers matter more than the number. The tools are scoped to a preset, not the harness: the same test asserts a normal session sees zero novel_* tools, they appear only once the OpenWrite creation preset is attached, and disposing the scope removes all 90. And they come from a per-preset row (dsh-openwrite/tools) rather than the host bundle; the preset composition states that mounting the bridge twice would register the process-level novelDomain service twice and make the preset unloadable.
What the review DAG actually is
The README’s “standard review DAG” is documented in docs/REVIEW_DAG_FRAMEWORK.md, more precisely than the phrase suggests. A chapter review is a fixed topology defined once by OpenWrite, which the dsh side only instantiates per chapter: 47 nodes, 46 containment edges and 14 execution dependencies, made of one root node for whole-chapter completion, one context node validating the prose revision and review baseline, six quality domains carrying 20 additive scoring criteria, 36 quality-check leaves, one hard gate (check 27) whose result is deliberately kept out of the quality score, and one aggregation node. Unrequested checks are written as inconclusive, so two chapters always produce comparable graph shapes. The blueprint runs under the openwrite.review-dag-framework.v1 contract with semantic versioning and a SHA-256 revision, and every review.json records frameworkId, frameworkVersion and frameworkRevision.
Per chapter the graph is written to data/novels/<novel_id>/data/dog/reviews/<chapter_id>/dog-graph.json, and the DoG verifier reads those records without calling a model again or recomputing scores. Extending it means using one of four declared points (context-evidence, domain-evaluator, gate-evaluator, post-review-policy), not editing one chapter’s graph. Treat “DAG” here as a persisted, inspectable artifact, not an engine that fans out live calls at review time.
The workbench is native dsh UI, not an embedded page
packages/studio-panel declares itself a dsh client plugin with dsh.client.platform: web, and its browser half registers into the harness’s own extension points: conversation.view for the three workbenches (创作 / 资料 / 任务), the session header, conversation.input.left, conversation.chat.turnTail, tool.call.toolview, and sidebar.footer.action for the launcher. There is no iframe anywhere in packages/studio-panel/src.
The changelog records the migration itself: the 2026-08-23 entry says the default workflow “彻底移除 iframe 与重复导航” and added a smoke gate asserting native routing and no iframe. The prose editor ships Vditor as a bundled runtime, and 55 of the 90 tools are mapped to eight native tool-call cards.
Requirements and install footprint
- Node
>=22.19.0(rootengines); the guide calls Node 24 the full acceptance baseline and Node 22.19 / 26 compatibility checks. Harness profileweb: the manifest declaresdsh.compatibility.profiles = ["web"]and pins@deepseek-ai/dsh0.1.2-rc.1as baseline, with the release map{"0.1.2-rc.1": "compatible", "0.1.3-alpha.1": "unknown", "0.1.3-alpha.2": "unknown", "0.1.5-alpha.1": "compatible"}. The manifest’sdsh.compatibility.dshdeclares"0.1.2-rc.1 || 0.1.5-alpha.1", which this listing records verbatim asdshTarget. - A managed local Python backend, not a hosted one. The first run downloads a pinned
uv0.11.19and Python3.12.13(URLs and SHA-256 inrelease/runtime-manifest.json) into$DSH_HOME/openwrite/, installs pinned dependencies fromrelease/requirements.lock, and ships anopenwrite-5.8.2-py3-none-any.whlCore. No pre-installed Python, no account, no cloud service — butdocs/DSH_STORE.mdrecords a first-run network need (GitHub and the Python package index). - The backend is loopback-only: the managed runtime builds its base URL as
http://127.0.0.1:${port}with an instance token, and the guide says authentication passes only between host and Core. An advancedmode: external/baseUrlconfiguration can point at an external Core you run yourself. - Model credentials are yours to configure. The README separates a dsh-host chat model from novel generation/review/test models configured under 任务 → 模型, states that install and health checks call no writing model, and notes that paid providers incur API costs. Data otherwise stays on your machine.
- Permissions are disclosed, not sandboxed.
docs/DSH_STORE.mdlists file read/write in the bound project directory, network access, subprocess spawning (the managed uv/Python) and the source-build path as real capabilities, and states the tool policy is not an OS sandbox. Preparation subprocesses use an allow-list environment and do not inherit unrelated API keys. No permission, telemetry or privacy statement beyond this appears in the README, and the repository has no telemetry client — undocumented is not the same as safe.
Install-time script disclosure
The root package.json has a prepare lifecycle script, node scripts/prepare.mjs, and prepare is an install-time hook — source installs execute repository code. It reads release/runtime-manifest.json, asserts the pinned Core wheel exists, then for each of packages/openwrite-bridge, packages/studio-panel and vendor/dsh-dog checks whether lib/index.js plus its second entry file exist; a missing build output triggers npm ci --ignore-scripts --no-audit --no-fund and npm run build inside that package directory, followed by scripts/release-provenance.mjs.
In the published 0.2.10 tarball all three lib/index.js files are present, so both the script’s header and docs/DSH_STORE.md describe prepare as source-install-only (“仅源码安装构建插件;预编译包已有运行资源”). For a git+/github: spec the harness CLI says pnpm blocks the build until you add the key it prints to allowBuilds in the profile’s pnpm-workspace.yaml, and the README tells the agent not to loosen that authorization.
Known limits
- The context-window cost of 90 tools is unmeasured in tokens.
docs/COST_MEASUREMENT.mdstates that UTF-8 declaration bytes are not tokenizer tokens and not billed cost, that no tokenizer is bundled, and that real provider tokens, cache hits and spend are recorded asnot-run. The bridge’s own policy test on 0.2.10 prints the two numbers it does measure:{"measurement":"native-tool-schema","tools":90,"utf8Bytes":63983,"tokenizer":"not-measured"}and, for PTC presentation,{"measurement":"ptc-presentation","schemaBytes":944,"sdkBytes":60560}. The tool row acceptspresentation: native(default),ptcorboth, but no measured token or dollar figure exists for either mode. - No measured model-billing results: the guide says verification used model doubles and ran no real-provider billing test.
- Platform coverage is narrower than “cross-platform”: macOS arm64/x64, Linux x64 and Windows x64, with minimum OS levels of macOS 14 (Apple Silicon) and macOS 13 (Intel).
- The npm and GitHub release artifacts are not verified identical here. Both are named
dsh-openwrite-0.2.10.tgz, the GitHub asset is listed at the npm tarball’s byte size (10,021,338 bytes), and the README asserts the same SHA-256 — but this listing did not finish a second download to confirm the checksum. - Mixed licensing inside the package. The repository is Apache-2.0 and
package.jsonagrees, so there is no README/manifest conflict; but the bundled Studio panel is MIT, vendoreddsh-dogis BSD-3-Clause, and Vditor, the preset skills and the rebuiltcryptography 50.0.1macOS x86_64 wheel carry their own terms. ReadTHIRD_PARTY_NOTICES.mdbefore redistributing. - Uninstalling is conservative by design: it stops the plugin’s services, UI and processes and preserves works, credentials, sessions and cache, with the cache a separate manual deletion.
When to use it — and when not to
Use it if you actually write long fiction in dsh and want one session to carry planning, drafting, review and revision with the manuscript on your own disk and no hosted writing service in the loop. The parts with no obvious substitute are the persisted review artifacts and the revision gate: outline, asset, focus, foreshadowing and writing-target changes go through a server-held preview token, a source-revision re-check on apply and a scoped undo token.
Do not install it because “a hundred tools sound useful”. This is a vertical suite with a managed Python runtime, a first-run network download and a lot of prompt surface committed to one domain. If your work is not novel-length fiction the 90 tools are cost with no return, and the preset’s persona is a long Chinese-language writing contract you would be fighting rather than using. If you need evidence that your harness version is supported, the manifest’s declared compatible set is exactly 0.1.2-rc.1 and 0.1.5-alpha.1 — for any other version this package gives you no such evidence.
FAQ
Is the “90 novel tools” claim real, or marketing?
Real and countable. packages/openwrite-bridge/lib/tools.js in the published 0.2.10 tarball has 90 defineTool registrations with 90 unique novel_* names, and the bridge’s tool-policy test asserts the same count against a live dsh tool registry. The count is scoped to the OpenWrite preset: a normal session sees zero.
What does the review DAG do?
It instantiates a fixed, versioned chapter-review blueprint: 47 nodes, 46 edges, 14 execution dependencies, one context node, six quality domains with 20 additive criteria, 36 quality-check leaves, one hard gate kept out of the quality score, and one aggregation node. The result lands per chapter as dog-graph.json and is read back by a verifier that calls no model and recomputes no scores.
Is the workbench native to dsh or an embedded web page?
Native. packages/studio-panel is a dsh client plugin with platform: web that registers React views into conversation.view, header, input and tool-call slots, and there is no iframe in its source; the changelog records removing the previous iframe on 2026-08-23.
Does it need an external OpenWrite service or account?
No. The domain backend is a local Python service the plugin downloads and manages itself on first use, listening on 127.0.0.1. The only external calls documented are the pinned runtime downloads, the Python package index, and your own model providers.
Does installing it execute code?
package.json declares a prepare lifecycle script, so source installs execute scripts/prepare.mjs: it verifies the pinned wheel, builds the three internal packages only when their lib output is absent, and regenerates release provenance. In the published tarball the prebuilt outputs are present, and the script’s header and docs/DSH_STORE.md both describe it as source-install-only. Installing and health-checking call no writing model.
Which dsh version should I run?
The manifest declares exactly two compatible releases, 0.1.2-rc.1 and 0.1.5-alpha.1, marking 0.1.3-alpha.1 and 0.1.3-alpha.2 as unknown, and its dsh.compatibility.dsh line reads "0.1.2-rc.1 || 0.1.5-alpha.1" — recorded verbatim as this listing’s dshTarget. Check dsh --version against that declaration and the Release notes first.