# dsh-openpencil

> A plugin for previewing, inspecting, and editing OpenPencil `.op` design files in DSH conversations: provides headless precise PNG rendering, read-only interactive canvas, and

## Metadata

- Author: [@ZSeven-W](https://github.com/ZSeven-W)
- Repo: <https://github.com/ZSeven-W/dsh-openpencil.git>
- GitHub: [ZSeven-W/dsh-openpencil](https://github.com/ZSeven-W/dsh-openpencil)
- Stars: 130
- Language: TypeScript
- License: [MIT](https://spdx.org/licenses/MIT.html)
- Homepage: <https://op.zseven.tech>
- Topics: `deepseek-harness`, `design`, `dsh`, `dsh-plugin`, `openpencil`, `ppt`, `ui`, `ui-design`
- Forks: 6
- Open Issues: 2
- Last push: 2026-08-20T13:01:52.000Z
- Added: 2026-08-13T00:00:00.000Z

## Install

```bash
dsh plugin --profile web add github:ZSeven-W/dsh-openpencil
```

## Wiki

## One-Line Pitch
dsh-openpencil turns the DSH conversation window into a workspace for previewing, inspecting, and real-time editing of OpenPencil `.op` design files: Agents can call five tools to render and send transactional design instructions to the canvas, while you directly see PNG thumbnails in chat, a pannable/zoomable read-only canvas, and a sidebar editor with save semantics.

## Core Capabilities
- **Headless Precise Rendering**: Through `openpencil_render`, calls OpenPencil's built-in headless exporter to generate fidelity-preserving PNGs for every top-level frame on the active page, outputting SHA-256 and dimension validation results
- **Read-Only Interactive Canvas**: Click "Open Interactive Canvas" to on-demand mount the OpenPencil Web SDK, supporting pan, zoom, fit-to-view, allowing inspection of any page or nested nodes without leaving the conversation
- **Hosted Editor**: When `editable: true`, the sidebar workspace launches a standalone op-host-web-server process, providing selection, layers, properties, drawing tools, undo/redo, and explicit save semantics
- **Agent-Native Design Tools**: Exposes five tools total — `openpencil_new` / `openpencil_create` / `openpencil_edit` / `openpencil_render` / `openpencil_selection` — enabling Agents to create and modify canvases using transactional `batch_design` programs
- **Signed Capability Credentials**: Both render outputs and editor entry points are delivered via HMAC-signed, content-addressed (filename + byte count + SHA-256) capability credentials, keeping host paths from leaking to browser or model context
- **Offline Draft Recovery**: When the plugin is uninstalled or the browser disconnects, unsaved canvases are left as opaque records locally for 7 days; reopening the same `.op` file asks whether to restore, never auto-overwriting source files

## Technical Implementation
- **Language**: TypeScript (Node-side + browser-side React)
- **Key Dependencies**: `@deepseek-ai/cordis` ^4.0.1, `@deepseek-ai/dsh-tools` ^0.1.0-rc.6, `@deepseek-ai/dsh-fs` ^0.1.0-rc.6, `react` ^18.2.0
- **Architecture Pattern**: Cordis plugin + Host/Client dual-end; `apply()` registers five tools and three same-origin HTTP routes (render, viewer assets, hosted editor) in the Host process; browser-side React components consume `presentationMeta.$dshOpenPencil` to render PNG cards, galleries, read-only canvas, and sidebar editor
- **Entry Files**: `src/index.ts` (Host-side Cordis service entry) + `src/client/index.tsx` (browser-side React entry)

## Use Cases
Designers, PMs, or frontend developers can directly use natural language in DSH to have an Agent generate an `.op` design file and verify the preview, modify nodes one by one in the same conversation window; OpenPencil users who want to have their `.op` files interpreted, modified, or cross-page inspected by an Agent; and any scenario requiring "real-time editable design mockups" embedded in AI conversation flows rather than relying on screenshot roundtrips.

## Prerequisites & Compatibility
| Dependency | Min Version | Description |
|---|---|---|
| DeepSeek Harness | >= 0.1.0-rc.6 | All `@deepseek-ai/dsh-*` packages in peerDependencies are `^0.1.0-rc.6`, also depends on `@deepseek-ai/cordis` `^4.0.1` |
| Node.js | >= 24.11.0 | Explicitly declared in `package.json#engines.node` |
| Operating System | macOS | Precise rendering defaults to searching `/Applications/OpenPencil.app` and `~/Applications/OpenPencil.app` (renderer.ts:520-521); Linux/Windows users need to provide OpenPencil binary via `DSH_OPENPENCIL_BINARY` / `PATH` |
| OpenPencil Binary | Undeclared (Optional) | Used for "precise" rendering; defaults to automatic fallback to Jian and marks `fidelity=runtime-preview` when missing |
| Jian Binary | Undeclared (Optional) | Only used as fallback renderer when OpenPencil binary is absent |
| op-host-web-server | Undeclared (Optional) | Launches hosted editor when `editable: true`; can be specified via `DSH_OPENPENCIL_EDITOR_BINARY` |
| Native Node Modules | None | Plugin only uses Node built-in modules and child processes, no node-gyp bindings |

## Installation
```bash
dsh plugin --profile web add github:ZSeven-W/dsh-openpencil
```

## Configuration
All runtime parameters of this plugin are overridden via environment variables as needed, not written to DSH configuration files:

| Environment Variable | Purpose | Default Behavior |
|---|---|---|
| `DSH_OPENPENCIL_BINARY` / `DSH_OPENPENCIL_DESKTOP` | Specifies OpenPencil binary path for precise rendering (mostly for Linux/Windows) | Auto-searches `/Applications/OpenPencil.app` and `~/Applications/OpenPencil.app`, then falls back to `openpencil-desktop` in `PATH` |
| `DSH_OPENPENCIL_JIAN` | Specifies Jian binary path for fallback rendering | Searches `~/workspace/jian/target/release/jian` and `PATH` |
| `DSH_OPENPENCIL_EDITOR_BINARY` | Specifies op-host-web-server path for hosted editor | Searches `target/{release,debug}/op-host-web-server` in OpenPencil source root, then `PATH` and macOS App in order |
| `DSH_OPENPENCIL_SOURCE_ROOT` / `OPENPENCIL_SOURCE_ROOT` | Specifies OpenPencil source root for resolving Web SDK and CanvasKit assets | Defaults to `~/workspace/openpencil` |
| `DSH_OPENPENCIL_VIEWER_ASSET_DIR` | Points to pre-built read-only canvas asset directory (`manifest.json` + `sdk.js` + WASM + CanvasKit) | Defaults to reading from built artifact `lib/viewer-assets`; canvas button won't show when missing |
| `DSH_HOME` | DSH user home directory, storage root for render outputs, signing keys, and recovery drafts | Defaults to `~/.dsh` |

## FAQ
**Q: What happens when I say "help me make an App homepage" in the conversation?**

A: The Agent will first call `openpencil_new` to atomically create a new `.op` file in the workspace; then use `openpencil_render` to render it as a PNG card displayed in the conversation, and finally attach `editable: true` + `autoOpen: true` to automatically expand the sidebar editor once. The entire process doesn't require you to manually select a filename or open the canvas first.

**Q: What to do if rendering fails or gets stuck?**

A: Precise rendering has a 60-second hard timeout (renderer.ts:49); the timeout will SIGKILL the child process and throw "OpenPencil render timed out"; PNG header, IHDR, dimensions and byte count are all validated (renderer.ts:863-877), and products exceeding 32 MB are rejected. Fallback rendering (runtime-preview) is only enabled when the OpenPencil binary is completely missing, and it doesn't take the blame for precise rendering failures.

**Q: Can I directly modify elements on the canvas in the conversation, or do I need to open the editor?**

A: The "read-only canvas" in the browser is read-only for inspection only; to actually modify the design, you must first use `openpencil_render` with `editable: true` to open the sidebar editor. The Agent applies changes to the real-time canvas via `openpencil_create` / `openpencil_edit`, but saving back to the `.op` file requires you to click Save in the editor.

**Q: Will uninstalling the plugin delete my design files?**

A: No. `.op` files in the workspace are managed by the DSH file system and are independent of the plugin lifecycle; if there are unsaved changes in the editor when uninstalling, the plugin will leave a 7-day local recovery draft on "plugin-dispose", which can be manually restored when reinstalling and opening the same `.op` file.

**Q: How are multi-frame document previews presented?**

A: Precise rendering outputs PNGs for all top-level frames on the active page; the `frames` field in results is ordered by node id/name/index; the browser card displays the first frame as a large image by default with a horizontal thumbnail bar below, supporting click-to-switch. Code Mode results with more than 128 frames only restore nested display metadata for the first 128 frames, with full data falling back to JSON.

**Q: Will switching light/dark mode or English/Chinese language interrupt editing?**

A: No. When host runtime changes (locale + light/dark theme), the tool cards and sidebar editor will refresh with the theme/language, but editing sessions and unsaved drafts are not lost (editor-panel.tsx listens to `editorLocaleFromDsh` / `EditorColorScheme`).

## Getting Started Difficulty
Intermediate — The plugin runs with default configuration, but to truly leverage its value, you need write access to the DSH workspace, the OpenPencil (or fallback Jian) binary on your machine, and a basic understanding of the `.op` document model; regular users only need to know how to trigger the Agent, while developers integrating custom design flows need to understand `batch_design` syntax and environment variable overrides.

## Known Issues & Limitations
- Precise rendering doesn't support manual width/height specification: passing `width` / `height` will directly error; only accepts `scale` (0 < scale ≤ 8, default 1), please use fallback rendering path for dimension-specific rendering (renderer.ts:687, tool.ts:166-168)
- Precise rendering has a hard 60-second timeout limit, and the child process will be killed via SIGKILL; oversized `.op` files (> 64 MB) or output PNGs (> 32 MB / total pixels > 128 million) will be rejected (renderer.ts:39-46, 863-877)
- The browser read-only canvas is lazily loaded on-demand as a lightweight Web SDK; the rendering-required SDK + WASM + CanvasKit assets must first be synced to `lib/viewer-assets` via `pnpm run sync:viewer-assets`; when assets are missing, the canvas button won't appear, but PNG preview still works normally (README.md:159-169, viewer-assets.ts:1-15)
- The sidebar editor depends on the op-host-web-server standalone process, which needs to be findable in `PATH` or the source root directory pointed to by environment variables; when not found, the edit button will be in an unavailable state
- Currently there's no product-level retention policy for render cache and document snapshots, still managed by the system (README.md:205)
- DSH 0.1.0-rc.6 doesn't persist nested browser display metadata under PTC / Code Mode; the plugin restores via same-origin session-bound endpoints; nested results > 128 frames only display metadata for the first 128 frames, with the rest falling back to JSON (README.md:196-198, presentation-hydration.ts:48)
- Editor capability credentials have TTL: launch credentials 2 hours, refresh credentials 24 hours; after timeout or external changes to the `.op` file, you must call `openpencil_render` again to get new credentials (editor-host.ts:34-36, 858-962)

---

This document is auto-generated by [deepseek-plugin.org](https://deepseek-plugin.org). HTML page: [dsh-openpencil](https://deepseek-plugin.org/plugins/ZSeven-W/dsh-openpencil)
Wiki generated by AI (model: `MiniMax-M2.5`)
