Skip to content
dsh-market Browse plugins GitHub 中文

Finderchangchang/brewreel#deepseek-harness

Makes 1080x1920 vertical promo videos from a storyboard JSON with 7 tools (doctor, setup, catalog, guide, validate, render, verify), rendered locally with Remotion.

Stars ★ 113 Category Skills Listed 2026-10-01 npm dsh-brewreel

Install

Inside DeepSeek Harness, with dsh-market

dsh plugin --profile web add dshmarket

Or from the command line

dsh plugin --profile web add dsh-brewreel

Installing runs third-party code with your own permissions — it can read your files, use your credentials and reach the network. Review the source first, and pin a commit (github:owner/repo#sha) when you can.

README

中文 | English

Let a DeepSeek model write one storyboard JSON, then get a vertical promo video (1080x1920, 15–45 s) from a single tool call.

Author: 柳伟杰 / Liu Weijie (Finderchangchang) · License: Apache-2.0 · Main repository: https://github.com/Finderchangchang/brewreel

Package name dsh-brewreel. From 0.2.0 the plugin follows the project's new name (formerly dsh-distill-video; the project was formerly promo-video-skill / Distill Video). Upgrading from the old package: see "Upgrading from dsh-distill-video".

What it does and does not do

  • Does: the model only writes storyboard.json (pick shots, fill in text); ready-made Remotion shot components draw the frames; the validator blocks rule violations and Chinese advertising-law / industry compliance problems; one call runs validation → machine checks → music → render → layout checks → delivery manifest.
  • Does not: generate arbitrary video, or decide compliance grey areas for the user (human-review items are handed to the user as they are).
  • The plugin is "7 tools + one skill": the skill teaches the model how to write a storyboard; the tools validate, render and verify, and keep output paths, child processes and environment variables in check.

Examples

See the screenshots and sample videos in the main repository README. This README has no images; the skill snapshot inside the package carries the main repository's docs/images/ previews (about 3.5 MB), which the image links in the style docs point to.

Requirements

Item Requirement
Node.js 22.x from 22.19, or 24 and later (the same as dsh itself)
DeepSeek Harness @deepseek-ai/dsh 0.1.x from 0.1.7-rc.2 on (tested with 0.1.7-rc.2)
pnpm dsh plugin installs plugins through pnpm, so pnpm must be on PATH
Python (optional) 3.10+ with numpy and scipy; without them the music is silent, the video still renders
Disk about 1 GB (render dependencies + Chrome Headless Shell)
Network first-time setup downloads from npm and Google

Install

If dsh is not installed yet, install it together with pnpm (dsh plugin forwards its arguments to pnpm):

npm install -g @deepseek-ai/dsh@0.1.7-rc.2 pnpm

Keep the version: dsh's latest tag on npm still points to the older 0.1.5-rc.3, below the 0.1.7-rc.2 this plugin needs (newer builds are under the next tag). If dsh is already installed, check it with dsh --version.

The commands use the web profile; any profile name works. The first dsh plugin --profile web … creates the profile. Start it with dsh web afterwards; if the profile is already running, restart it (dsh applies bundle changes on the next boot).

A. Link a local clone (most reliable)

git clone https://github.com/Finderchangchang/brewreel.git
dsh plugin --profile web add ./brewreel/integrations/deepseek-harness

Run the second command from the folder that contains the clone (relative paths resolve against the current directory). The plugin uses the skill in that clone (checkout mode): render dependencies go into the clone's template/node_modules/, and while rendering make.mjs writes temporary assets and a render lock inside the clone's template/ (both ignored by the repository's .gitignore). Set stageCheckout: true to leave the clone untouched and run from a copy in the runtime folder instead.

B. GitHub Release asset (before the npm release)

Download dsh-brewreel-<version>.tgz from the Releases page, then:

dsh plugin --profile web add ./dsh-brewreel-0.3.0.tgz

C. npm (once the author publishes it)

dsh plugin --profile web add dsh-brewreel

D. Skill only, no plugin

Clone the repository into ~/.agents/skills/brewreel/ (or a project's .agents/skills/). dsh discovers the skill on its own and the model runs node scripts/… through its shell tool — no progress, no path guard, no structured errors. Fine for a quick try.

Uninstall: dsh plugin --profile web remove dsh-brewreel, then delete the runtime folder (default ~/.dsh/brewreel/, or ~/.dsh/distill-video/ when upgraded from 0.1.x; with option A and stageCheckout off, the dependencies live in the clone's template/node_modules/).

First-time setup

Ask the model to "check the video plugin environment"; it calls brewreel_doctor. If something is missing, the model asks you first and then calls brewreel_setup:

  1. stage: copy the skill into the runtime folder (needed for npm / tgz installs; no download);
  2. deps: npm ci in template/ (Remotion and friends, a few hundred MB);
  3. browser: download Chrome Headless Shell (about 110 MB).

Slow or blocked networks: set npmRegistry to a mirror. If the Chrome Headless Shell download fails, follow the manual steps in the main repository FAQ, place it under template/node_modules/.remotion/chrome-headless-shell/ inside the runtimeRoot that doctor reports, and run setup again (present files are skipped).

Python packages are detected, never installed; for music, run the python -m pip install numpy scipy command that doctor prints.

How to use it

Example conversation:

You: Make a ~20-second promo for my expense-tracking app. Selling points: snap a receipt to log it, a warning before you overspend at month end. The brief is at promo/ledger/brief.md.

Model: (calls brewreel_catalog) One clear benefit and a UI demo → the default cards style, software industry. (calls brewreel_guide for the cards recipes and the hook shot, writes promo/ledger/storyboard.json)

Model: (calls brewreel_validate) Shot 3's caption is too long; shortened to two lines as suggested… validated again, passed.

Model: (calls brewreel_render, background job brewreel-1; job_output shows "rendering 420/735 frames")

Model: Done. Video: …/promo/ledger/video.mp4 (24.5 s), contact sheet sheet.png. Please confirm these 2 human-review items before publishing: …

Output folder contents:

File Meaning
video.mp4 The video. Only the path in the tool result's video.path counts as delivered
sheet.png Contact sheet of the whole video
check/ Check frames
report.txt Full validation, machine-check and layout-check report
manifest.json Storyboard sha256, video sha256 / duration, every check's verdict

"Trust only the delivery line": video appears only when exit code 0, a final make.mjs line starting with the delivery marker, manifest status delivered and a matching file sha256 all hold. A leftover video.rejected.mp4 only shows what broke and must never be delivered. stills (single-frame previews) are never a video.

Tools

Tool Purpose Writes files Background
brewreel_doctor Environment check (Node, skill files, dependencies, Chrome, Python, output folder, render lock) no no
brewreel_setup One-time setup: stage / deps / browser runtime folder default yes
brewreel_catalog List styles, industries, color themes no no
brewreel_guide Read the skill, style recipes, industry recipes, shot notes, examples no no
brewreel_validate Validate a storyboard: errors / warnings / human items, each with a fix no no
brewreel_render Render (about 3–10 min, depending on the machine) with progress; stills renders single frames only output folder default yes
brewreel_verify Check that the video still matches the current storyboard no no

If the same validation error survives 3 rounds in a row, validate flags it in stuck and tells the model to stop and ask you — no endless loops with cheap models.

Configuration

Edit it in the Web UI plugin settings (the form comes from the config schema) or in your profile's cordis.patch.yml:

- id: brewreel
  config:
    outputRoot: promo
    npmRegistry: https://registry.npmmirror.com
    renderTimeoutMin: 40

Note: a patch replaces the row's whole config; restate every key you want to keep.

Key Default Meaning
skillRoot '' A BrewReel clone to use; empty = auto-detect (the clone two levels up → the bundled snapshot)
stageCheckout false Copy a clone into the runtime folder before running instead of rendering inside it
runtimeDir '' Empty = $DSH_HOME/brewreel (~/.dsh/brewreel); when only the ~/.dsh/distill-video left by 0.1.x exists, that one is reused
outputRoot promo Output root, relative to the session workspace
extraWriteRoots [] Extra absolute folders the tools may read from and write to
renderInBackground true Render as a background job by default
maxConcurrentRenders 1 Render processes this plugin runs at once (1–4)
renderTimeoutMin 30 Hard timeout per render (minutes); the whole process tree is terminated
queueTimeoutMin 20 Maximum wait for the render lock (minutes)
bgm true Generate music by default
autoSetup false Let a render run setup (downloads) when dependencies are missing. Off so you stay informed
npmRegistry '' npm registry used by setup; must be https
python / ffmpeg '' Python / ffmpeg executables
registerSkill true Register the skill instructions
skillLang zh Register the Chinese or English SKILL; also the language of tool results
maxResultChars 16000 Upper bound on text one tool result gives the model
envPassthrough [] Extra environment variable names for child processes; credential-looking names (KEY/TOKEN/SECRET/PASSWORD/AUTH/COOKIE) are rejected

To confirm every render yourself, set brewreel_render to "ask" with dsh's tool approval policy (tools/pre-execute).

Security

  • Writes: only the output folder in the session workspace (default promo/<name>/), extraWriteRoots, and the plugin's runtime folder. The output folder cannot be the workspace root, outputRoot itself, your home folder or a drive root; make.mjs clears fixed product file names when it starts (video.mp4, report.txt, layout.json, manifest.json, check/*.png and so on), so a folder holding someone else's storyboard.json, or any of those names without a manifest.json from make.mjs or the plugin's marker file .brewreel-out.json (or .distill-video-out.json written by 0.1.x), is refused. Paths are compared after resolving real paths, so symlinks and junctions cannot escape.
  • Reads: storyboards and briefs must be in the workspace; assets referenced by a storyboard cannot leave its folder or the workspace.
  • No arbitrary commands: the plugin only starts the current Node on fixed scripts inside the skill (validate.mjs, make.mjs, the Remotion CLI, npm), Python for a fixed detection command, and on Windows taskkill for its own process trees. make.mjs itself additionally runs Python to generate the music and, when configured, ffmpeg. Always shell: false with fixed argument arrays; model input reaches argv only as a verified absolute path or a verified number.
  • Environment whitelist: child processes get basic variables such as PATH, TEMP, HOME, LANG; the DeepSeek key and other credentials never reach the render process. The one exception is voice-over: the render process (make.mjs) also gets a fixed set of variables — MiniMax (MINIMAX_API_KEY, MINIMAX_GROUP_ID, MINIMAX_BASE_URL), Alibaba Cloud (DASHSCOPE_API_KEY, DASHSCOPE_WORKSPACE_ID, DASHSCOPE_REGION, DASHSCOPE_TTS_URL), Volcengine (VOLCENGINE_TTS_API_KEY, VOLCENGINE_TTS_APP_ID, VOLCENGINE_TTS_ACCESS_TOKEN, VOLCENGINE_TTS_BASE_URL) and BREWREEL_TTS_CACHE (the voice cache folder); validate, doctor and setup processes never see them, no other key is passed, and envPassthrough cannot add one. make.mjs only sends the key to the matching voice service in the request header; it never writes it to a file, log or manifest.json, and error messages leave it out. Storyboards without meta.voice never use it.
  • Plainly: render processes do not run inside dsh's shell sandbox; they run with your user's permissions and the plugin restrains itself with the rules above. Setup downloads Remotion and Chrome Headless Shell from npm and Google.

Troubleshooting

Symptom What to do
"Render dependencies are not installed" Call brewreel_doctor, then brewreel_setup once you agree
Exit 1 (invalid) Validation failed; fix validation.errors one by one
Exit 3 (rejected) A layout / blank-frame check failed: remove items or shorten text, validate, render again
Exit 4 (render-failed) Usually a missing Chrome Headless Shell or low memory; run doctor
Exit 5 (queue-timeout) Another render holds the lock; wait or raise queueTimeoutMin
Exit 6 (internal) Attach report.txt to an issue on the repository
killed Past renderTimeoutMin or cancelled; the process tree is gone and the next render reclaims the lock
Silent music Python lacks numpy / scipy; run the command doctor prints
Chrome download fails Set npmRegistry; place Chrome manually as the main FAQ describes
Windows paths with Chinese characters Supported, spaces too; save storyboards and briefs as UTF-8

Relation to the main repository, versions

  • The repository root is the only source. The skill/ folder inside npm / tgz packages is a snapshot generated at pack time by scripts/sync-skill.mjs; skill/.distill-source.json records the skill version, repository commit and file hash, and brewreel_doctor shows them.
  • The plugin has its own version. 0.1.0 (package dsh-distill-video) shipped with v0.3.0; from 0.2.0 the package is dsh-brewreel, shipped with v0.4.0; 0.3.0 ships with v0.5.x (the 0.3.0 on npm is a v0.5.1 snapshot) and passes the voice-over variables to the render process: keys and hosts for MiniMax, Alibaba Cloud and Volcengine, plus the voice cache folder (see "Security"). The exact skill version and commit inside a package's snapshot are whatever skill/.distill-source.json records (doctor shows them too).
  • Upgrading: reinstall and restart the profile; the new snapshot is staged in a new runtime subfolder, downloaded dependencies are reused when the dependencies in package-lock.json are unchanged (a new name or version of the template package does not count), and only the two latest copies are kept.

Upgrading from dsh-distill-video

From 0.2.0 the plugin follows the project's new name, 精酿 · BrewReel; the package, tool and skill names changed:

Item 0.1.x (old) 0.2.0 on
npm package dsh-distill-video dsh-brewreel
7 tools distill_video_doctor etc. brewreel_doctor etc.; suffixes unchanged (doctor / setup / catalog / guide / validate / render / verify)
Registered skill name promo-video-skill brewreel (the name in SKILL.md)
Plugin row in cordis.patch.yml id: distill-video id: brewreel
Default runtime folder ~/.dsh/distill-video/ ~/.dsh/brewreel/
Output folder marker .distill-video-out.json .brewreel-out.json
Env var to pack with uncommitted changes DISTILL_SYNC_ALLOW_DIRTY BREWREEL_SYNC_ALLOW_DIRTY

Steps: dsh plugin --profile web remove dsh-distill-video, install dsh-brewreel as in "Install" above, restart the profile.

  • What you change: the old tool names are no longer registered. Replace distill_video_* with brewreel_* in tool approval policies (tools/pre-execute), your own prompts and scripts; if your profile's cordis.patch.yml overrides the plugin row, change its id to brewreel (a row with the old id no longer matches this plugin).
  • What keeps working: output folders marked .distill-video-out.json are still recognised, so you can keep rendering into them; when only the old runtime folder ~/.dsh/distill-video/ exists it is reused, so dependencies and Chrome Headless Shell are not downloaded again; DISTILL_SYNC_ALLOW_DIRTY still works.
  • The GitHub repository moved to https://github.com/Finderchangchang/brewreel; the old address redirects. Point an existing clone at it with git remote set-url origin https://github.com/Finderchangchang/brewreel.git (pulling works without it too).

Developers

cd integrations/deepseek-harness
npm test                  # unit tests, no dependencies, no dsh needed
npm run smoke -- --runtime-dir <dir> --work <dir> --setup [--full]   # smoke test calling the tool functions directly
npm run sync              # build the skill/ snapshot (prepack runs it and refuses uncommitted changes; BREWREEL_SYNC_ALLOW_DIRTY=1 overrides)
dsh plugin --profile dev add .   # link for local debugging

Publishing (done by the author): check the npm name is free → npm pack --dry-run to review the file list → npm publish → add the dsh-plugin topic to the GitHub repository.

License and third parties

  • Plugin and skill: Apache-2.0, see LICENSE and NOTICE.
  • Remotion has its own license; companies may need a commercial license — see THIRD_PARTY_LICENSES.md in the main repository.
  • Font and other third-party licenses are listed in THIRD_PARTY_LICENSES.md as well.

Disclaimer

The validation rules summarize public regulations and platform rules for self-checking only; they are not legal advice. You confirm the pre-publish checklist yourself.

Content from the project README on GitHub ↗

Comments

Comments live in GitHub Discussions. Sign in with GitHub to post or react.