- Startseite
- Plugins
- UI-Erweiterungen
- dsh-virtuoso
dsh-virtuoso
deanyou/dsh-virtuoso
Cadence Virtuoso integration for the DeepSeek Harness — bundles the virtuoso-cli agent skills, manages the daemon / tunnel / sessions from the settings panel. · DSH 的 Virtuoso 集成插件,把 virtuoso-cli 的 agent skills 与 daemon / tunnel / session 管理一并打包到 DSH 设置面板
Installation
dsh plugin --profile web add github:deanyou/dsh-virtuosoREADME
dsh-virtuoso
dsh-virtuosoships the Cadence Virtuoso EDA integration for the DeepSeek Harness: thevirtuoso-cliagent skills are bundled so the model can drive SKILL, Maestro, Spectre, schematics, Verilog-A and the SSH tunnel directly from a DSH session; the settings panel exposesvclihealth, tunnel control, and thevcliconfiguration the daemons read.The plugin is the DSH-shaped bridge over virtuoso-cli. All execution paths run the
vcli(or legacyvirtuoso) binary the agent calls viaBash; the host half adds nothing to the trust surface — no extra remote, no extra daemon, no extra process — it only readsVB_*env vars and reports them.
What's in 0.1.0
This is the first npm release of dsh-virtuoso. Highlights:
- Local-mode
tunnel/startshort-circuit —vcli tunnel startno longer fails withssh "Could not resolve hostname"whenVB_REMOTE_HOSTis unset. The route now probesvcli session listdirectly in local mode and returns the parsed session array as proof of liveness. - Connected Virtuoso panel section —
GET /dsh-virtuoso/sessionsshows every active Virtuoso instance (id, port, host, user, started).GET /dsh-virtuoso/session-currenthighlights which instance auto-routing will pick for the nextvcli skill exec(a● activemarker on the matching row). - Auto-refresh toggle — opt-in 30s polling for the status tab when you leave the panel open. Off by default; the panel is conservative.
- Path-redacted stderr — for shared-kiosk displays,
CallResultscrubs/foo/bar/...-shaped strings before showing stderr. The raw stderr is still on the wire for curl/devtools. - Bundled-skill trust gate —
sync-skills.mjsnow inserts anallowed-tools: Bash(*/vcli *) Bash(*/virtuoso *) Read Write Editgate on every skill that ships without one. Five previously-ungated skills were patched in place. - Tests — 95 unit tests across 7 files (config, vcli, http, routes,
skills, redact-paths, user-skill).
npm testruns them in ~750 ms. - Published on npm —
dsh plugin --profile web add dsh-virtuosoinstalls from the registry; no build step, noprepareauthorization. - Add user-level skill —
POST /dsh-virtuoso/skills/addwrites a SKILL.md into$DSH_HOME/skills/<id>/from the panel. The skill is auto-discovered on the next dsh restart (or via the inotify watcher). Defaults to the standard vcliallowed-tools:gate; the file is yours, not the plugin's. (Disabling a bundled skill is not exposed by the panel — DSH'sSkillRegistryhas no public unregister-by-name API. Workaround: edit the SKILL.md to adddisable-model-invocation: true.)
Install
Pick one of the four install paths below.
A. From the npm registry (recommended for users)
dsh plugin --profile web add dsh-virtuoso
npm publish ships the pre-built lib/ and client/; the user does not
need a build step, nor do they have to authorize any prepare script.
The trade-off vs tarball/Git-install: the published artifact is bound
to a specific dsh-virtuoso version; bug fixes require bumping the
version and re-publishing.
B. From this checkout, via the helper (recommended for development)
npm install
npm run install:local # = node scripts/install-locally.mjs
# (pass --profile <name> to install into a non-web profile;
# pass --pack-only to produce the tarball without installing —
# useful when running inside a sandbox that blocks writes to
# ~/.dsh/profiles/<name>/)
install:local does the two-step dance that dsh plugin add does NOT do
for you: it npm packs the repo into dsh-virtuoso-<version>.tgz, then
calls dsh plugin --profile web add <that tgz>. Without the pack step
pnpm sees ./dsh-virtuoso-0.1.0.tgz as a missing file and aborts with
ENOENT (issue #1).
If npm pack succeeds but dsh plugin add fails with EACCES on the
profile dir, you are running inside a sandbox where ~/.dsh/profiles/<name>/
is read-only. Use --pack-only and run dsh plugin add from a normal shell.
C. From this checkout, by hand (equivalent to B, two steps)
npm install
npm run build
npm pack # produces dsh-virtuoso-0.1.0.tgz
dsh plugin --profile web add ./dsh-virtuoso-0.1.0.tgz
D. From a GitHub commit (no local checkout needed)
# `dsh plugin add` accepts git+https specifiers directly, but only as a
# real tarball URL — `github:owner/repo` shorthand depends on the dsh
# version. Substitute the commit/tag you want:
DSH_VIRTUOSO_REF="$(git -C /home/user1/git/dsh-virtuoso rev-parse HEAD)"
dsh plugin --profile web add "https://codeload.github.com/deanyou/dsh-virtuoso/tar.gz/${DSH_VIRTUOSO_REF}"
Whichever path you took:
dsh web # restart to load the new bundle
…then open Settings → Virtuoso.
Requires dsh web 0.1.0-rc.7 or newer. On an older host the plugin disables its UI entry cleanly rather than rendering against primitives that aren't there: if the Settings → Virtuoso entry never appears, that is usually why.
What you get
- Bundled agent skills — every skill in virtuoso-cli
is shipped inside the plugin at
bundled-skill/<id>/SKILL.mdand auto-discovered by DSH'sdsh-skill-filesystem. Eighteen skills today, covering SKILL execution, Maestro, simulation setup/run/sweep/measure, schematic generation, Verilog-A design, gm/Id methodology, amplifier copilot, circuit optimization, ocean netlist regen, two "gotchas" skills (SKILL shell + Spectre netlist), the spec-driven design flow, and the tunnel-connect bootstrap. New skills show up aftersync-skillsfrom a newer virtuoso-cli release. Every bundled skill carries anallowed-tools:gate limiting it tovcli(or the legacyvirtuosoalias) plus Read/Write/Edit — the agent cannot pivot through these skills to invoke arbitrary tools. - Settings status panel — the
vclibinary presence, host/port/session bridge state, remote host / jump host / timeout / cache / log directories DSH reads out of yourVB_*environment. The header note reminds you thatVB_*values are read from the dsh-web process env and need a restart to take effect. - Connected Virtuoso — a dedicated panel section lists every active
Virtuoso instance with id/port/host/user/started. The session the
auto-routing layer would pick (
vcli session current) gets a● activemarker. No more guessing which instance the nextvcli skill execwill land on. - Tunnel control —
Start tunnel,Stop tunnel, andPing daemonbuttons in the panel each call out tovcli tunnel start|stopandvcli session listrespectively (round-1 fix:session showrequires a session ID and would crash on local mode). In local mode the tunnel buttons are disabled with a hint explaining why; thePing daemonbutton stays enabled and probes the daemon viasession list. - Auto-refresh — an opt-in 30 s polling toggle (
⏱ off/⏱ 30s) re-fetches status, sessions, and session-current in parallel. Off by default so the panel doesn't surprise anyone; flip it on when you leave the panel open while waiting for a daemon restart. - Skill listing — a third tab in the panel mirrors
bundled-skill/to the user with description preview and size, so the model selection screen and the agent'sBash-allowed skill set stay auditable in one place. - Add user-level skill — same tab has an Add user-level skill form that
writes a SKILL.md into
$DSH_HOME/skills/<id>/. The DSHskill-filesystemprovider auto-discovers it on the next reload (or via the inotify watcher). Defaults to the standard vcliallowed-tools:gate. Survives plugin uninstall — your skill, your filesystem. (Disabling a bundled skill is not exposed by the panel: DSH'sSkillRegistryhas no public unregister-by-name API. If you need to suppress a bundled skill, editbundled-skill/<id>/SKILL.mdto setdisable-model-invocation: true.) - Install commands — a fourth tab pastes the
cargo install virtuoso-clicommands and the SKILL bridgeload(...)line into your clipboard, with the exact wording virtuoso-cli'sramic_bridge.ilaccepts. - Settings card — on dsh 0.1.0-rc.7 and newer the plugin manages itself
from Settings → Plugins → Plugin configuration: see the running version,
whether
vcliwas detected, and the bundled-skill count. Toggle Allow tunnel start off when the deployment is air-gapped, toggle Allow restart off under systemd/launchd supervision.
How it works
┌──────────────────────────────────────────────────────────────────────┐
│ DSH session │
│ │
│ ┌──────────────────────┐ Bash(*/vcli *) ┌────────┐ │
│ │ agent (skill: │ ───────────────────────────▶│ vcli │ │
│ │ skill-exec, │ └────────┘ │
│ │ sim-run, ...) │ │ │
│ │ bundled-skill/) │ ▼ │
│ └──────────────────────┘ ┌────────────┐ │
│ │ vcli │ │
│ ┌──────────────────────┐ /dsh-virtuoso/{status, │ daemon │ │
│ │ browser settings │ sessions, session-current, │ (separate │ │
│ │ panel (client.js) │ ping, tunnel/*, skills, │ process) │ │
│ │ │ loader} │ │ │
│ └──────────────────────┘◀─────────────→ host half └────────────┘ │
│ (this plugin, browser) (this plugin, node) │
└──────────────────────────────────────────────────────────────────────┘
- DSH auto-discovers
bundled-skill/through itsdsh-skill-filesystemprovider. The skill descriptions end up in the model's context window just like every other skill; the skill body instructs the agent to runvcli .... - The agent invokes
vcli skill exec 'let(...)'etc. via theBashtool.vcliis a separate Rust process; the plugin does not fork anything itself. - The browser settings panel calls:
GET /dsh-virtuoso/status— version, profile, fullVB_*config dumpGET /dsh-virtuoso/sessions— parsedvcli session listJSONGET /dsh-virtuoso/session-current— parsedvcli session currentJSONPOST /dsh-virtuoso/ping— same asvcli session list(proves liveness)POST /dsh-virtuoso/tunnel/start— callsvcli tunnel start, or short-circuits to avcli session listprobe in local modePOST /dsh-virtuoso/tunnel/stop— callsvcli tunnel stop, or no-ops in local modeGET /dsh-virtuoso/skills— bundled-skill metadataPOST /dsh-virtuoso/skills/add— write a SKILL.md to$DSH_HOME/skills/<id>/GET /dsh-virtuoso/loader— the DSH plugin stack The host half shells out tovclionce per click and returns the discriminated{ ok, stdout, stderr, code, reason, durationMs, mode?, note? }payload.
- The plugin reads
VB_HOST,VB_PORT,VB_SESSION,VB_REMOTE_HOST,VB_JUMP_HOST,VB_TIMEOUTand so on straight out ofprocess.env. The settings panel renders those exactly asvcliitself reads them — there is no second source of truth.
Security
- The plugin spawns
vcliwith array-formspawn(no shell). The SKILL body arguments the agent types stay arguments, not shell strings. - Every bundled skill carries an
allowed-tools: Bash(*/vcli *) Bash(*/virtuoso *) Read Write Editgate.scripts/sync-skills.mjsenforces the gate on every sync; the agent cannot pivot through bundled skills to invoke arbitrary tools. - All POST routes accept same-origin only — previewing the panel from a
malicious origin can read the rendered environment but cannot run a command.
The
sameOrigingate ignores scheme (HTTPS vs HTTP) intentionally: the browser blocks mixed-content requests at the network layer, so a scheme-mismatch check is not a real attack vector and would only reject legitimate dev-mode traffic. - The host half never reads
~/.cache/virtuoso_bridgedirectly. The tunnel / session files arevcli's concern; surfacing them belongs in vcli itself (issue tracker upstream). - The settings panel does not import clipboard contents and does not upload any
state anywhere. The "copy" buttons use
navigator.clipboard.writeTextwith nothing more than the literalvclicommand the agent would type. - The
CallResultcomponent scrubs/foo/bar/...-shaped strings fromstderrbefore display, so a shared-kiosk panel doesn't leak the operator's home directory path. The raw stderr is on the wire for curl/devtools; only the panel rendering is sanitized. - Listing the bundled skills ≠ endorsing the upstream. The skills live inside
the package and ship with it; review them in
bundled-skill/<id>/SKILL.mdbefore updating.
Sync with upstream
node scripts/sync-skills.mjs ../virtuoso-cli
scripts/sync-skills.mjs is the only entry point that touches bundled-skill/.
It wipes the directory and copies the upstream tree verbatim, rewriting the
allowed-tools: frontmatter line so the bundled skills work through the
vcli binary path (and accept virtuoso as a legacy alias). The script
inserts the line if missing — the previous version only rewrote an
existing line, which left five skills ungated. It is idempotent: running it
twice with the same source produces byte-identical bundled-skill/.
The floor is 14 skills — if upstream's tree collapses below that, the script
aborts.
Develop
npm install
npm run typecheck # tsc for host (tsconfig.json) + client (tsconfig.client.json)
npm run build # tsc → lib/, tsdown → client/client.js, banner preflight
npm test # vitest run (72 tests, ~750 ms)
npm run check # all of the above + scripts/validate-skills.mjs + check-inject-boundary.mjs
The host half runs in the dsh-cordis-host-runner sandbox (Node, vm-isolated).
The client half runs in the dsh web bundle loader (browser, closure-factory).
Both halves type-check against the runtime types DSH ships under
@deepseek-ai/cordis, @deepseek-ai/dsh-settings, and
@deepseek-ai/dsh-client-ui-primitives.
Tests
npm test runs 95 unit tests across 7 files:
tests/config.test.ts(22) —isRemotederivation, numeric coercion, binary-path cachetests/vcli.test.ts(9) —callVclibranches (missing/timeout/exit/spawn-error) and array-form spawntests/http.test.ts(15) —sameOrigin,sendJson,readJsonBodytests/routes.test.ts(6) — the local-mode tunnel/start short-circuit (regression test for the empty-hostname SSH error)tests/skills.test.ts(5) — bundled-skill listing invariantstests/redact-paths.test.ts(15) — path-redaction helpertests/user-skill.test.ts(23) —validateUserSkillDraft,buildSkillMarkdown,resolveDshSkillsRoot/resolveUserSkillPath
Watch mode: npm run test:watch.
Publish to npm
# Dry-run (preflight + check + dry-run only):
npm run publish:dry-run
# Real publish (requires a granular access token with "Bypass 2FA" in .npmrc):
npm run publish:npm
scripts/publish-npm.mjs wraps npm publish with:
- A
npm run checkpreflight - A
--dry-runfirst - A clear hint if the token lacks the 2FA-bypass grant (npm returns403 in that case)
.npmrc holds the token and is gitignored. Generate a fresh token at
https://www.npmjs.com/settings/tokens, choose Granular Access Token, and
check Bypass 2FA.
License
MIT · this plugin is a thin translation layer over the upstream virtuoso-cli, which itself is MIT-licensed by deanyou.
Ähnliche Plugins
dsh-web-ui (dsh-web-ui-all)
zhu1090093659/dsh-web-ui
DSH-better-sidebar
omdsh-dev/dsh-better-sidebar
dsh-TUI
ccch1mneyyy/dsh-tui
dsh-at-file
fsmargoo/dsh-at-file