Skip to content
dsh.fish
Bundle

@foxi-ai/dsh-command-vscode

DeepSeek Harness slash command: open the current workspace (or a given path) in Visual Studio Code

Source
foxi-ui
License
MIT
Updated
Updated 14 days ago

Readme

# @foxi-ai/dsh-command-vscode

> DeepSeek Harness 插件:一条斜杠命令,用 VS Code 快速打开当前工作区。

`/vscode` 让 DeepSeek Harness 把当前会话的工作区目录(会话的 `cwd`)在 Visual Studio Code 中打开,也可以打开任意指定路径。

## 功能

- `/vscode` —— 打开当前会话工作区
- `/vscode <path>` —— 打开指定目录(空格安全,可加引号)
- 自动探测 VS Code CLI:环境变量 → `PATH` → 常见安装路径
- macOS 上回退到 `open -a "Visual Studio Code"`
- **零运行时依赖**:仅用 Node 内置 `child_process.execFile`,无 shell,自动透传中止信号
- 跨平台:macOS / Windows / Linux

## 安装

> 前置:`dsh plugin` 通过 pnpm 工作,请先确保已安装 pnpm(`corepack enable pnpm` 或 `npm i -g pnpm`)。

### 从 npm 安装(推荐)

```bash
dsh plugin --profile web add @foxi-ai/dsh-command-vscode
```

本包声明了 `dsh.bundle`,`dsh plugin` 安装后会自动把它加入 `dsh.profile.bundles` 并激活。重启 dsh 后即可使用。

### 从 tarball 安装(无需 npm 账号)

在本包目录内打包,再安装:

```bash
npm pack                                            # 生成 foxi-ai-dsh-command-vscode-0.1.0.tgz
dsh plugin --profile web add ./foxi-ai-dsh-command-vscode-0.1.0.tgz
```

### 从 GitHub 安装

```bash
dsh plugin --profile web add github:you/dsh-command-vscode#<commit>
```

本插件是纯 JS(`lib/index.js` 直接提交,无构建步骤),git 安装开箱即用。若你改造后引入 TypeScript,需按[官方文档](https://github.com/deepseek-ai/DeepSeek-Harness/blob/HEAD/docs/user/develop/basic/publish.zh.md)配置 `prepare` 脚本,并在 profile 的 `pnpm-workspace.yaml` 里 `allowBuilds` 授权。

### 本地开发安装(symlink + 热重载)

```bash
./install.sh
```

该脚本把本包软链接进 profile 的 `node_modules`,并把插件行写入 profile 的 `cordis.patch.yml`(受 HMR 监听,保存即热加载,无需重启)。

## 命令说明

### `/vscode`

打开当前会话的工作区目录。

```text
/vscode
```

- 工作区目录取自该会话的 `session.header.cwd`(即启动 dsh 时所在的目录)。
- 会话没有 `cwd` 时返回错误:
  `No workspace directory is associated with this session. Usage: /vscode [path]`。

### `/vscode <path>`

打开指定目录。

```text
/vscode /path/to/project
/vscode "/path/with spaces"
```

- `<path>` 为相对或绝对路径,原样传给 VS Code CLI(不经 shell,所以空格安全)。
- 若整体用成对引号 `"…"` 或 `'…'` 包裹,会去掉外层引号。

### 参数

| 参数 | 必填 | 说明 |
| --- | --- | --- |
| `path` | 否 | 要打开的目录;省略时打开当前会话工作区 |

### 环境变量

| 变量 | 说明 |
| --- | --- |
| `VSCODE_CLI` | 自定义 VS Code 可执行文件路径,优先级最高。例如 `export VSCODE_CLI=/path/to/code` |

### CLI 探测顺序

1. `$VSCODE_CLI`(若设置)
2. `code`(`PATH`)
3. macOS:`/usr/local/bin/code` → `/opt/homebrew/bin/code` → VS Code.app 内置 CLI
4. Windows:`code.cmd` → `code`
5. Linux:`/usr/local/bin/code` → `/usr/bin/code`
6. macOS 兜底:`open -a "Visual Studio Code"`(随后尝试 Insiders)

### 输出

| 情形 | 输出 |
| --- | --- |
| 成功 | `Opened <path> in VS Code` |
| 未找到 CLI / 打开失败 | `Could not open VS Code: <原因>` |
| 请求被中止 | `Opening VS Code was cancelled.` |

## 工作原理

插件把 `/vscode` 注册到 Harness 的命令注册表(`ctx.commands`)。命令处理器读取 `invocation.agent.session.header.cwd` 作为默认目录,再用无 shell 的 `execFile` 调用 VS Code CLI,并把 AbortSignal 透传给孩子进程。

## 目录结构

```
.
├── package.json        # 包元数据 + dsh.bundle 声明
├── cordis.patch.yml    # bundle patch:向 profile 插入插件行
├── lib/index.js        # 插件实现(name / inject / apply)
├── install.sh          # 本地开发安装(symlink + cordis.patch.yml)
├── test/smoke.mjs      # 冒烟测试
├── LICENSE             # MIT
└── README.md
```

## 发布到 npm

使用「细粒度令牌 + 绕过 2FA」发布(无需全局登录,token 不落盘):

1. 在 npmjs.com 生成 **Granular Access Token**,勾选 **Bypass two-factor authentication (2FA)**,权限给 `@foxi-ai/dsh-command-vscode` 的 *Read and write*。
2. 把令牌写入本地 `.env.local`(该文件已被 `.gitignore` / `.npmignore` 忽略,切勿提交或公开):

   ```bash
   cp .env.example .env.local   # 然后编辑 .env.local,填入 NPM_TOKEN=npm_xxx
   ```

3. 发布:

   ```bash
   ./publish.sh            # 或 ./publish.sh --dry-run 预演
   ```

发布前请确认:

- `package.json` 的 `name` 为 `@foxi-ai/dsh-command-vscode`(作用域包,需 `publishConfig.access` 为 `public`,已配置);
- `repository` 指向正确的源码仓库;
- `cordis.patch.yml` 里的插件行 `name` 与包名一致。

发布后即可用 `dsh plugin --profile web add @foxi-ai/dsh-command-vscode` 安装。

## 开发与测试

```bash
node test/smoke.mjs
```

## License

[MIT](./LICENSE)

Install

dsh plugin --profile web add github:foxi-ui/dsh-command-vscode

Profile: web

  • This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.
Source