用图片设计并预览皮肤,确认后安全写入本机
29/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/9/17 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
自动兼容检查未通过:缺少 main/exports/bin 入口声明;仓库 package.json 标记 private,未发布到 npm,需从源码安装。以下命令仍可尝试,但可能失败。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add trrrrrryg/dsh-visual-skin该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:待复验
是什么
dsh 原生插件 · vision
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 65 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查需源码安装缺少 main/exports/bin 入口声明;仓库 package.json 标记 private,未发布到 npm,需从源码安装
展开查看检查明细 ↓
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✗npm 包deepseek-harness-skin-studio(未发布到 npm,仅可源码安装)
✓Node 引擎要求 >=22 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✗入口文件缺少入口声明
源码安装时若 pnpm 拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑。
验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/9/23 11:36:14
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 140 处,展示前 94 条)
- 写入本地文件apps/controller/src/assets.ts:65
await mkdir(dirname(target), { recursive: true }); - 读取本地文件apps/controller/src/assets.ts:66
try { await stat(target); } catch { - 写入本地文件apps/controller/src/assets.ts:68
await writeFile(temp, canonical, { flag: "wx" }); - 写入本地文件apps/controller/src/assets.ts:69
await rename(temp, target); - 读取本地文件apps/controller/src/assets.ts:81
const info = await stat(path); - 读取本地文件apps/controller/src/assets.ts:83
return { record, bytes: await readFile(path) }; - 读取本地文件apps/controller/src/dsh.ts:47
try { detectedVersion = (JSON.parse(await readFile(packageJson, "utf8")) as { version?: string }).version ?? null; } catch {} - 删除本地文件递归apps/controller/src/dsh.ts:103
await rm(stagePackage, { recursive: true, force: true }); - 写入本地文件apps/controller/src/dsh.ts:104
await mkdir(dirname(stagePackage), { recursive: true }); - 写入本地文件apps/controller/src/dsh.ts:106
if (snapshot.hadPlugin) { await rename(plan.packageRoot, rollbackPackage); movedOld = true; } - 写入本地文件apps/controller/src/dsh.ts:107
await rename(stagePackage, plan.packageRoot); movedStage = true; - 删除本地文件递归apps/controller/src/dsh.ts:114
if (movedOld) await rm(rollbackPackage, { recursive: true, force: true }); - 写入本地文件apps/controller/src/dsh.ts:121
try { if (movedStage) await rm(plan.packageRoot, { recursive: true, force: true }); if (movedOld) await rename(rollbackPackage, plan.packageRoot); com - 删除本地文件递归apps/controller/src/dsh.ts:121
try { if (movedStage) await rm(plan.packageRoot, { recursive: true, force: true }); if (movedOld) await rename(rollbackPackage, plan.packageRoot); com - 删除本地文件递归apps/controller/src/dsh.ts:128
} finally { await rm(stagePackage, { recursive: true, force: true }); } - 写入本地文件apps/controller/src/dsh.ts:152
if (await exists(packageRoot)) await rename(packageRoot, stagedRemoval); - 删除本地文件递归apps/controller/src/dsh.ts:158
await rm(stagedRemoval, { recursive: true, force: true }); - 写入本地文件apps/controller/src/dsh.ts:163
try { if (await exists(stagedRemoval)) await rename(stagedRemoval, packageRoot); } catch (rollback) { rollbackErrors.push(`plugin: ${String(rollback)} - 删除本地文件递归apps/controller/src/dsh.ts:207
try { if (moved) await rm(plan.packageRoot, { recursive: true, force: true }); } catch {} - 读取本地文件apps/controller/src/dsh.ts:236
async function readText(path: string, fallback: string): Promise<string> { try { return await readFile(path, "utf8"); } catch (error) { if ((error as - 读取本地文件apps/controller/src/dsh.ts:238
async function exists(path: string): Promise<boolean> { try { await stat(path); return true; } catch { return false; } } - 读取本地文件apps/controller/src/dsh.ts:244
if (!(await stat(source)).isDirectory()) continue; - 读取本地文件apps/controller/src/dsh.ts:245
const manifest = JSON.parse(await readFile(join(source, "package.json"), "utf8")) as { name?: string }; - 读取本地文件apps/controller/src/dsh.ts:247
if (!(await stat(join(source, "dist", "host", "index.js"))).isFile()) continue; - 删除本地文件递归apps/controller/src/gc.ts:118
await rm(core.store.path("isolated-preview-runtime", id), { recursive: true, force: true }); - 读取本地文件apps/controller/src/gc.ts:129
if (resolve(home).toLowerCase().startsWith(`${expected}${process.platform === "win32" ? "\\" : "/"}dsh-skin-isolated-`) && (await stat(home).catch(() - 删除本地文件递归apps/controller/src/gc.ts:130
await rm(home, { recursive: true, force: true }); - 读取本地文件apps/controller/src/gc.ts:155
try { size = (await stat(journal)).size; } catch { return; } - 写入本地文件apps/controller/src/gc.ts:158
await rename(journal, `${dirname(journal)}${process.platform === "win32" ? "\\" : "/"}journal-${stamp}.jsonl`); - 读取本地文件apps/controller/src/index.ts:471
try { if (!(await stat(file)).isFile()) throw new Error("not-file"); } - 读取本地文件apps/controller/src/index.ts:474
const content = await readFile(file); - 读取本地文件apps/controller/src/index.ts:536
async function managedPluginExists(target: DshTarget): Promise<boolean> { try { return (await stat(join(target.dshHome, "profiles", "node_modules", "@ - 执行外部命令来自配置/变量apps/controller/src/open.ts:11
const child = spawn(executable, [url], { detached: true, stdio: "ignore", shell: false, windowsHide: true }); - 读取本地文件apps/controller/src/open.ts:30
for (const path of paths) { try { await access(path); return path; } catch {} } - 写入本地文件apps/controller/src/preview-runtime.ts:193
await mkdir(target.dshHome, { recursive: true }); - 执行外部命令来自配置/变量apps/controller/src/preview-runtime.ts:200
const child = spawn(process.execPath, [runtime.bin, "web", "--host", "127.0.0.1", "--port", String(port)], { cwd: target.dshHome, shell: false, window - 发起网络请求apps/controller/src/preview-runtime.ts:221
const response = await fetch(`${url}/dsh-skin/health`, { signal: AbortSignal.timeout(750) }); - 删除本地文件递归apps/controller/src/preview-runtime.ts:396
async function removeTempHome(id: string): Promise<void> { const home = tempHome(id); const expected = resolve(tmpdir()).toLowerCase(); if (!resolve(h - 删除本地文件递归apps/controller/src/preview-runtime.ts:397
async function removeSessionRuntimeData(dataDir: string, id: string): Promise<void> { const root = resolve(dataDir, "isolated-preview-runtime"); const - 读取本地文件apps/controller/src/preview-runtime.ts:442
const patch = await readFile(join(meta.home, "profiles", "web", "cordis.patch.yml"), "utf8"); - 读取本地文件apps/controller/src/preview-runtime.ts:452
for (const candidate of candidates) try { if (!(await stat(candidate)).isFile()) continue; const packageRoot = resolve(candidate, "..", ".."); if (!aw - 写入本地文件apps/controller/src/preview-runtime.ts:459
await mkdir(targetScope, { recursive: true }); - 读取本地文件apps/controller/src/preview-runtime.ts:469
try { await stat(target); throw new AppError(ERROR_CODES.unavailable, `Temporary DSH package is incompatible: @deepseek-ai/${name}`, 503); } catch (er - 读取本地文件apps/controller/src/preview-runtime.ts:479
const addScope = async (candidate: string) => { try { if ((await stat(candidate)).isDirectory()) scopes.add(resolve(candidate)); } catch {} }; - 读取本地文件apps/controller/src/preview-runtime.ts:481
try { await addScope(resolve(await realpath(sourcePackageRoot), "..")); } catch {} - 读取本地文件apps/controller/src/preview-runtime.ts:488
const entries = await readdir(store, { withFileTypes: true }); - 发起网络请求apps/controller/src/runtime.ts:67
try { const response = await fetch(`${base}${path}`, { signal: AbortSignal.timeout(700) }); return response.ok; } catch { return false; } - 发起网络请求apps/controller/src/runtime.ts:71
const response = await fetch(`${base}/dsh-skin/health`, { signal: AbortSignal.timeout(700), headers: { accept: "application/json" } }); - 读取本地文件apps/controller/src/runtime.ts:87
async function exists(path: string): Promise<boolean> { try { await access(path); return true; } catch { return false; } } - 写入本地文件apps/controller/src/selfcheck.ts:21
await mkdir(join(dshHome, "profiles", "node_modules", "@deepseek-ai", "dsh"), { recursive: true }); - 写入本地文件apps/controller/src/selfcheck.ts:22
await mkdir(profileRoot, { recursive: true }); - 写入本地文件apps/controller/src/selfcheck.ts:23
await writeFile(join(dshHome, "profiles", "node_modules", "@deepseek-ai", "dsh", "package.json"), JSON.stringify({ name: "@deepseek-ai/dsh", version: - 写入本地文件apps/controller/src/selfcheck.ts:24
await writeFile(join(profileRoot, "package.json"), `${JSON.stringify({ name: "fixture-profile", dependencies: { keep: "1.0.0" } }, null, 2)}\n`); - 写入本地文件apps/controller/src/selfcheck.ts:25
await writeFile(join(profileRoot, "cordis.patch.yml"), "[]\n"); - 执行外部命令来自配置/变量apps/controller/src/selfcheck.ts:28
controller = spawn(process.execPath, [controllerEntry], { - 发起网络请求apps/controller/src/selfcheck.ts:39
const landing = await fetch(discovery.url); - 读取本地文件apps/controller/src/selfcheck.ts:59
const storedPreview = JSON.parse(await readFile(join(controllerData, "isolated-preview-sessions", `${preview.session.id}.json`), "utf8")) as Record<st - 删除本地文件递归apps/controller/src/selfcheck.ts:99
if (dirname(root) === tmpdir()) await rm(root, { recursive: true, force: true }); - 读取本地文件apps/controller/src/selfcheck.ts:105
try { return JSON.parse(await readFile(path, "utf8")) as T; } catch { await new Promise((resolveWait) => setTimeout(resolveWait, 80)); } - 发起网络请求apps/controller/src/selfcheck.ts:112
const response = await fetch(`${base}${path}`, init); - 发起网络请求apps/studio/src/api.ts:46
return this.request(`/api/v1/design/${encodeURIComponent(id)}`, { method: "DELETE", body: {} }); - 发起网络请求apps/studio/src/api.ts:50
return this.request("/api/v1/theme/validate", { method: "POST", body: { theme } }); - 发起网络请求apps/studio/src/api.ts:85
return this.request("/api/v1/theme/apply-plan", { method: "POST", body: { designId: design.id, revision: design.revision, target: { profile: "web" }, - 发起网络请求apps/studio/src/api.ts:89
return this.request("/api/v1/theme/restore-plan", { method: "POST", body: { designId: design.id, revision: design.revision, target: { profile: "web" } - 发起网络请求apps/studio/src/api.ts:93
return this.request("/api/v1/theme/confirm-and-apply", { - 发起网络请求apps/studio/src/api.ts:107
return this.request("/api/v1/theme/confirm-and-restore", { - 执行外部命令来自配置/变量packages/agent-cli/src/client.ts:55
const child = spawn(process.execPath, [controllerEntry], { detached: true, stdio: "ignore", shell: false, windowsHide: true, env: { ...process.env, .. - 读取本地文件packages/agent-cli/src/client.ts:71
const discovery = JSON.parse(await readFile(path, "utf8")) as Discovery; - 读取本地文件packages/agent-cli/src/client.ts:82
await access(entry); - 读取本地文件packages/agent-cli/src/client.ts:83
if (!(await stat(entry)).isFile() || !entry.toLowerCase().endsWith(".js")) throw new Error("DSH_SKIN_CONTROLLER_ENTRY must identify a JavaScript file" - 发起网络请求packages/agent-cli/src/index.ts:10
else if (group === "studio" && action === "start") { await client.ensureStarted(); result = await client.request("/api/v1/studio/start"); } - 发起网络请求packages/agent-cli/src/index.ts:11
else if (group === "studio" && action === "open") { await client.ensureStarted(); result = await client.request("/api/v1/studio/open"); } - 发起网络请求packages/agent-cli/src/index.ts:12
else if (group === "design" && action === "create") result = await client.request("/api/v1/session/design", "POST", parseJson(rest)); - 发起网络请求packages/agent-cli/src/index.ts:13
else if (group === "design" && action === "list") result = await client.request("/api/v1/designs", "GET"); - 发起网络请求packages/agent-cli/src/index.ts:14
else if (group === "design" && action === "get") result = await client.request(`/api/v1/design/${required(rest[0], "design id")}`, "GET"); - 发起网络请求packages/agent-cli/src/index.ts:15
else if (group === "design" && action === "patch") result = await client.request(`/api/v1/design/${required(rest[0], "design id")}`, "PATCH", parseJso - 读取本地文件packages/design-session-core/src/store.ts:14
return JSON.parse(await readFile(this.path(relative), "utf8")) as T; - 写入本地文件packages/design-session-core/src/store.ts:23
await mkdir(dirname(target), { recursive: true }); - 写入本地文件packages/design-session-core/src/store.ts:25
await writeFile(temp, `${JSON.stringify(value, null, 2)}\n`, { encoding: "utf8", flag: "wx" }); - 写入本地文件packages/design-session-core/src/store.ts:26
await rename(temp, target); - 写入本地文件packages/design-session-core/src/store.ts:31
await mkdir(dirname(target), { recursive: true }); - 写入本地文件packages/design-session-core/src/store.ts:32
await appendFile(target, `${JSON.stringify(value)}\n`, "utf8"); - 读取本地文件packages/design-session-core/src/store.ts:37
return (await readdir(this.path(relative))).filter((name) => name.endsWith(suffix)).sort(); - 删除本地文件packages/design-session-core/src/store.ts:45
try { await unlink(this.path(relative)); } catch (error) { if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error; } - 写入本地文件packages/design-session-core/src/store.ts:50
await mkdir(dirname(lock), { recursive: true }); - 删除本地文件packages/design-session-core/src/store.ts:60
try { await unlink(lock); } catch {} - 读取本地文件packages/design-session-core/src/store.ts:64
try { if (Date.now() - (await stat(lock)).mtimeMs > 30_000) { await unlink(lock); continue; } } catch {} - 删除本地文件packages/design-session-core/src/store.ts:64
try { if (Date.now() - (await stat(lock)).mtimeMs > 30_000) { await unlink(lock); continue; } } catch {} - 发起网络请求packages/mcp-server/src/index.ts:17
tool("studio_open", "Open the independent Studio web UI; returns a copyable URL if opening fails.", empty, async () => { await client.ensureStarted(); - 发起网络请求packages/mcp-server/src/index.ts:18
tool("design_create", "Create a shared revisioned design session.", { name: z.string().max(80).optional(), theme: z.unknown().optional() }, async (arg - 发起网络请求packages/mcp-server/src/index.ts:19
tool("design_list", "List shared design sessions.", empty, async () => client.request("/api/v1/designs", "GET")); - 发起网络请求packages/mcp-server/src/index.ts:20
tool("theme_get", "Read one shared design session.", { designId: z.string().uuid() }, async ({ designId }) => client.request(`/api/v1/design/${designI - 发起网络请求packages/mcp-server/src/index.ts:21
tool("theme_patch", "Patch a design with optimistic baseRevision conflict protection.", { designId: z.string().uuid(), baseRevision: z.number().int(). - 发起网络请求packages/mcp-server/src/index.ts:22
tool("design_duplicate", "Duplicate a shared design.", { designId: z.string().uuid(), name: z.string().max(80).optional(), actor, patchId: z.string().
扫描于 2026/11/3(1 天前) · 范围 全包扫描 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
依赖的 DSH / Cordis 模块
@deepseek-ai/dsh给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
功能亮点
- 图片设计皮肤
- 隔离预览
- 确认后写入本机
README
由 DeepSeek 最新模型翻译生成dsh-visual-skin
DeepSeek Harness 皮肤工作室
为 DeepSeek Harness(DSH)制作、预览并安全写入皮肤的本地可视化工作台。
Target DSH
Windows
Local first
License
点击演示图播放 MP4 · 查看动画源文件 · 查看分镜
先说结论
给一张图片,或直接在 Studio 里调色、调背景和区域效果;Skin Studio 会在隔离的临时 DSH中渲染结果。只有你在可见网页中审阅并确认后,主题才会写入本机 DSH。
| 你要做的事 | 得到什么 |
| 用图片做皮肤 | Agent Skill / MCP 自动创建设计、上传资产并打开预览 |
| 精细调整两块背景 | 侧边栏、主工作区、图片位置、遮罩和分隔线的即时预览 |
| 安全写入本机 DSH | 不可变计划、可见确认、可恢复的安装记录 |
10 秒看懂流程
flowchart LR
A[图片 / 你的描述] --> B[Skin Studio 设计]
B --> C[隔离 DSH 真实预览]
C --> D{你在 Studio 中确认}
D -- 确认 --> E[写入你的 DSH]
D -- 继续修改 --> B
Agent 和 MCP 可以帮你完成设计与预览;不能伪造最后的写入确认。
展开完整文档(README 剩余 1 节)
dsh-visual-skin
DeepSeek Harness 皮肤工作室
为 DeepSeek Harness(DSH)制作、预览并安全写入皮肤的本地可视化工作台。
Target DSH
Windows
Local first
License
点击演示图播放 MP4 · 查看动画源文件 · 查看分镜
先说结论
给一张图片,或直接在 Studio 里调色、调背景和区域效果;Skin Studio 会在隔离的临时 DSH中渲染结果。只有你在可见网页中审阅并确认后,主题才会写入本机 DSH。
| 你要做的事 | 得到什么 |
| 用图片做皮肤 | Agent Skill / MCP 自动创建设计、上传资产并打开预览 |
| 精细调整两块背景 | 侧边栏、主工作区、图片位置、遮罩和分隔线的即时预览 |
| 安全写入本机 DSH | 不可变计划、可见确认、可恢复的安装记录 |
10 秒看懂流程
flowchart LR
A[图片 / 你的描述] --> B[Skin Studio 设计]
B --> C[隔离 DSH 真实预览]
C --> D{你在 Studio 中确认}
D -- 确认 --> E[写入你的 DSH]
D -- 继续修改 --> B
Agent 和 MCP 可以帮你完成设计与预览;不能伪造最后的写入确认。
功能一览
| 模块 | 做什么 | 为什么有用 |
| Skin Studio | 图片、纯色、渐变;双区域背景;遮罩、玻璃拟态、token 调色与分隔线 | 所见即所得,不必手改配置文件 |
| 隔离预览 | 使用 Controller 管理的临时 DSH 实例,并复用 warm runner | 预览不触碰正在使用的 DSH,也减少重复启动负载 |
| DSH 插件 | 常驻背景层、对话蒙版、侧边栏分隔与「皮肤设置」入口 | 切换对话后仍保持皮肤,不需要重新注入页面 |
| Agent Skill | 理解「换个皮肤」「用这张图做背景」等请求并编排流程 | DSH、Codex 等 agent 都能接入同一套设计能力 |
| MCP Server | design_create、asset_upload、theme_patch、preview_start、theme_apply 等工具 | 让 agent 有结构化、可审计的操作接口 |
| 安全写入 | 隔离预览回执 + 不可变 apply 计划 + 人工确认 | 写入前知道会改什么,失败时可恢复 |
安装
| 前置条件 | 版本 / 说明 |
| Windows | 10 或 11 |
| Node.js | 22+ |
| pnpm | 11+;首次构建便携运行时时需要 |
| DeepSeek Harness | 0.1.0-rc.6;版本不匹配时插件会 fail-closed |
git clone https://github.com/trrrrrryg/dsh-visual-skin.git
cd dsh-visual-skin
powershell -NoProfile -ExecutionPolicy Bypass -File .\install.ps1
安装器会构建便携运行时、安装 Skill、注册 DSH 插件与 MCP,并启动 Studio。默认不重启 DSH,避免打断正在进行的会话;完成后请自行重启一次 DSH。
常用安装参数
| 参数 | 作用 |
| -DshHome | 指定 DSH 根目录,默认 %USERPROFILE%\.dsh |
| -ProfileName | 指定 profile,默认 web |
| -DataDir | Studio 数据目录 |
| -ControllerPort | Studio Controller 端口,默认 11862 |
| -SkipBuild | 复用已构建 runtime |
| -SkipSkill / -SkipStudio / -SkipCodexMcp | 跳过可选组件 |
| -RestartDsh | 安装后自动重启 DSH |
.\install.ps1 -DshHome C:\Users\me\.dsh -ProfileName web -ControllerPort 12000 -RestartDsh
使用
在 Studio 中手动设计
1. 打开 http://127.0.0.1:11862,或从 DSH 的「设置 → 插件 → 皮肤设置」打开 Studio。
2. 上传图片,或调整背景、区域和 token,等待隔离预览就绪。
3. 点击 写入我的 DSH,审阅计划并亲自勾选确认;随后重启 DSH。
- 勾选整合两区域:背景会是一张随窗口缩放保持连续的画面。
- 取消勾选:可分别编辑侧边栏与主工作区,使用不同的颜色、渐变或图片。
- 所有变更先进入实时隔离预览;正式 DSH 在确认前不会被改动。
直接对 agent 说
- 「给我换个皮肤」
- 「用这张图片做背景」
- 「把现在的皮肤背景换掉」
Agent 会调用 mcp__skin-studio__* 完成设计与隔离预览,并把最终确认留在 Studio 网页中。
验证安装
DSH 插件健康检查(DSH 默认端口为 10402) Invoke-RestMethod http://127.0.0.1:10402/dsh-skin/health
Studio Controller 状态 Invoke-RestMethod http://127.0.0.1:11862/api/v1/status
开发
pnpm install
pnpm build # 构建全部包
pnpm test # 回归测试;会启动真实 rc.6 隔离预览
pnpm controller # 本地启动 Controller
pnpm dev # Studio Vite 开发模式
目录说明
apps/controller/ # API、隔离预览、apply/restore、GC apps/studio/ # React + Vite Studio packages/dsh-plugin/ # DSH host 路由与 client 皮肤渲染 packages/theme-schema/ # ThemeSpec v2 数据契约 packages/mcp-server/ # MCP stdio 服务 agents/codex-skill/ # 可安装 Agent Skill 与脚本 tests/ # 含真实 rc.6 Chromium 隔离预览的回归测试 docs/demo/ # README 动画、分镜与导出脚本 docx/ # 实施计划、需求分析、架构文档
安全与兼容
- ThemeSpec 只接受受控的颜色、内容寻址图片(sha256)和 token;不接收任意 CSS、JS 或 URL。
- 预览只在 Controller 拥有的临时 DSH 里运行;浏览器、MCP 和 agent 都拿不到写入确认凭据。
- 当前目标版本是 0.1.0-rc.6;不兼容时拒绝加载,而不是猜测性修改 DSH。
卸载
1. 从 %DSH_HOME%\profiles\\cordis.patch.yml 移除 # >>> dsh-skin-studio 到 # <<< dsh-skin-studio 之间的托管条目;
2. 删除 %DSH_HOME%\profiles\node_modules\@dsh-skin 和 %DSH_HOME%\skills\deepseek-harness-skin-studio;
3. 重启 DSH;如需清理 Studio 数据,再删除 %LOCALAPPDATA%\DeepSeekHarnessSkinStudio。
文档
- 变更记录
- 发布清单
- 项目文档
- MIT License
MIT © 2026 trrrrrryg预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
trrrrrryg/dsh-visual-skin
用图片设计并预览皮肤,确认后安全写入本机
相关插件 · 视觉能力
智能体工作台Devin-AXIS/iPolloWork
企业级、本地优先的智能体工作台,面向个人和智能体团队——一个工作区,容纳多个智能体引擎;一套统一体系,管理插件和技能;支…
★ 7,364已汉化DSH
72
开源设计工作台nexu-io/open-design
OpenDesign:首个协作式 AI 设计智能体工作区
★ 105,709已汉化DSH
71.8
GPT 图像提示词库freestylefly/awesome-gpt-image-2
Prompt as Code | GPT Image 2 / 2.5 提示词与案例库,530+ 个案例、20+…
★ 34,534已汉化DSH
71.5
多智能体编码工作区spacering-net/codeg
多智能体协作的 AI 编程工作区:汇总 Claude Code、Codex、OpenCode、Pi、Grok Build 等来源的会话。支持桌面应用、自托管服务器或 Docker。
★ 4,319已汉化DSH
71.5
AI 用量桌面小部件Javis603/token-monitor
EN | 简 | 繁 | KO | JA | PT
★ 3,533已汉化DSH
71.1
架构图生成器tt-a1i/archify
把你想理解、规划或分享的事,变成可以互动的可视化作品。
★ 93,105已汉化DSH
71.1
这是你的仓库?认领条目