bashterm-mcp-server 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/CLAUDE.md +61 -36
- package/README.md +122 -312
- package/README.zh-CN.md +72 -186
- package/dist/extension.js +165 -9
- package/package.json +15 -3
- package/server.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.2.2] - 2026-06-04
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- 扩展激活时自动配置 Claude Code hook,禁止内置 Bash 工具,引导使用 BashTerm MCP 工具
|
|
9
|
+
- `restoreClaudeCodeDefaultBash` 命令,允许用户一键恢复 Claude Code 默认 Bash 工具
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
- 修复 `shell` 参数无效导致终端使用默认 shell 而非指定 shell 的问题
|
|
13
|
+
- 修复 Windows 中文输出乱码问题
|
|
14
|
+
- 修复 Claude Code hook 自动配置 JSON 格式错误
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
- `autoConfigureClaudeCode` 改为写入用户目录 `~/.claude/settings.json` 而非项目级别配置
|
|
18
|
+
- README 安装指南简化为仅安装 VSCode 扩展即可,零手动配置
|
|
19
|
+
- README 完善 Claude Code Bash 回归与恢复说明
|
|
20
|
+
|
|
21
|
+
## [0.2.1] - 2026-06-04
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
- 全面重命名为 BashTerm MCP:统一所有文档和代码中的项目名称引用
|
|
25
|
+
- 修复 v0.2.0 标签指向错误的 commit
|
|
26
|
+
|
|
5
27
|
## [0.2.0] - 2026-06-04
|
|
6
28
|
|
|
7
29
|
### Added
|
package/CLAUDE.md
CHANGED
|
@@ -1,66 +1,100 @@
|
|
|
1
|
-
# Project:
|
|
1
|
+
# Project: BashTerm MCP
|
|
2
2
|
|
|
3
3
|
MCP server that runs commands in visible VSCode terminal tabs.
|
|
4
4
|
|
|
5
|
+
---
|
|
6
|
+
|
|
5
7
|
## Release Process
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
以下以发布 v0.2.1 为例,一步一步执行。
|
|
8
10
|
|
|
9
|
-
### 1.
|
|
11
|
+
### 1. 更新版本号(2 个文件,3 处)
|
|
10
12
|
|
|
11
13
|
```bash
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
+
# package.json "version": "0.2.0" → "0.2.1"
|
|
15
|
+
# server.json 顶层 "version": "0.2.0" → "0.2.1"
|
|
16
|
+
# server.json packages[0].version: "0.2.0" → "0.2.1"
|
|
14
17
|
```
|
|
15
18
|
|
|
16
|
-
### 2.
|
|
19
|
+
### 2. 更新 CHANGELOG.md
|
|
17
20
|
|
|
18
|
-
|
|
21
|
+
在文件顶部新增条目:
|
|
19
22
|
|
|
20
23
|
```markdown
|
|
21
|
-
## [0.1
|
|
24
|
+
## [0.2.1] - YYYY-MM-DD
|
|
22
25
|
|
|
23
26
|
### Added
|
|
24
|
-
-
|
|
27
|
+
- 新功能...
|
|
25
28
|
|
|
26
29
|
### Fixed
|
|
27
|
-
-
|
|
30
|
+
- 修复...
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
- 变更...
|
|
28
34
|
```
|
|
29
35
|
|
|
30
|
-
### 3.
|
|
36
|
+
### 3. 更新 README.md 和 README.zh-CN.md
|
|
37
|
+
|
|
38
|
+
替换 **Latest Changes** 节为新版本改动,只列核心条目,完整历史指向 CHANGELOG.md。
|
|
31
39
|
|
|
32
|
-
|
|
40
|
+
> ⚠️ **不要用 `replace_all` 做模糊全局替换!** `bashterm-` 会匹配并误伤 `bashterm-mcp` 等 URL。只精确替换目标字符串。
|
|
33
41
|
|
|
34
|
-
### 4.
|
|
42
|
+
### 4. 构建和测试
|
|
35
43
|
|
|
36
44
|
```bash
|
|
37
|
-
#
|
|
38
|
-
npm
|
|
45
|
+
npm run build # esbuild 双产物:dist/extension.js + dist/mcp-entry.js
|
|
46
|
+
npm test # 45 tests must pass
|
|
47
|
+
```
|
|
39
48
|
|
|
40
|
-
|
|
41
|
-
npm publish --access public
|
|
49
|
+
### 5. 打包 VSIX
|
|
42
50
|
|
|
43
|
-
|
|
51
|
+
```bash
|
|
44
52
|
npx vsce package --allow-missing-repository
|
|
53
|
+
# 生成 bashterm-mcp-server-0.2.1.vsix
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### 6. 发布 npm
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npm whoami # 确认已登录
|
|
60
|
+
npm publish --access public
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### 7. 创建 GitHub Release
|
|
45
64
|
|
|
46
|
-
|
|
47
|
-
|
|
65
|
+
```bash
|
|
66
|
+
gh release create v0.2.1 \
|
|
67
|
+
--title "v0.2.1 — BashTerm MCP" \
|
|
68
|
+
--notes "从 CHANGELOG.md 复制改动内容" \
|
|
69
|
+
bashterm-mcp-server-0.2.1.vsix
|
|
48
70
|
```
|
|
49
71
|
|
|
50
|
-
###
|
|
72
|
+
### 8. 上传 VSCode Marketplace
|
|
73
|
+
|
|
74
|
+
1. 打开 https://marketplace.visualstudio.com/manage/publishers/hcdb
|
|
75
|
+
2. 找到 BashTerm MCP → `...` → **Update**
|
|
76
|
+
3. 上传 `.vsix`
|
|
51
77
|
|
|
52
|
-
|
|
53
|
-
2. Click "..." next to BashTerm MCP → "Update"
|
|
54
|
-
3. Upload the `.vsix` file
|
|
78
|
+
> 备选:配置 Azure DevOps PAT 后可用 `npx vsce publish` 一键发布。
|
|
55
79
|
|
|
56
|
-
###
|
|
80
|
+
### 9. 提交和推送
|
|
57
81
|
|
|
58
82
|
```bash
|
|
59
83
|
git add -A
|
|
60
|
-
git commit -m "v0.1
|
|
84
|
+
git commit -m "v0.2.1:<变更摘要>"
|
|
61
85
|
git push
|
|
62
86
|
```
|
|
63
87
|
|
|
88
|
+
### 10. 验证
|
|
89
|
+
|
|
90
|
+
- [ ] `npx bashterm-mcp-server@latest` 正常启动
|
|
91
|
+
- [ ] VSCode 扩展商店搜索 "BashTerm MCP" 显示新版本
|
|
92
|
+
- [ ] https://www.npmjs.com/package/bashterm-mcp-server 显示新版本
|
|
93
|
+
- [ ] GitHub Release 徽章显示新版本号
|
|
94
|
+
- [ ] README.md 和 README.zh-CN.md 的徽章链接全部正常
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
64
98
|
## Extension Cache Workaround
|
|
65
99
|
|
|
66
100
|
VSCode aggressively caches extensions. When developing locally:
|
|
@@ -68,17 +102,8 @@ VSCode aggressively caches extensions. When developing locally:
|
|
|
68
102
|
```bash
|
|
69
103
|
# Quick update (after modifying source)
|
|
70
104
|
npm run build
|
|
71
|
-
cp dist/extension.js ~/.vscode/extensions/hcdb.bashterm-<version>/dist/extension.js
|
|
105
|
+
cp dist/extension.js ~/.vscode/extensions/hcdb.bashterm-mcp-server-<version>/dist/extension.js
|
|
72
106
|
# Then "Developer: Reload Window"
|
|
73
107
|
|
|
74
108
|
# If reload doesn't pick up changes, close and reopen VSCode completely
|
|
75
109
|
```
|
|
76
|
-
|
|
77
|
-
## Terminal Execution
|
|
78
|
-
|
|
79
|
-
Prefer the BashTerm MCP tools (`run`, `exec`, `read`, etc.) over the built-in Bash tool for executing commands. BashTerm runs commands in visible VSCode terminal tabs where the user can see output in real time.
|
|
80
|
-
|
|
81
|
-
For commands that may take longer than 30 seconds or produce large output, use pull mode:
|
|
82
|
-
1. Call `run` with `waitForCompletion: false`
|
|
83
|
-
2. Call `read` with `offset: -10` to check progress
|
|
84
|
-
3. Repeat until done
|
package/README.md
CHANGED
|
@@ -1,312 +1,122 @@
|
|
|
1
|
-
# BashTerm
|
|
2
|
-
|
|
3
|
-
[](README.zh-CN.md) [![
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
- **
|
|
12
|
-
- **
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
### Simple Command
|
|
125
|
-
|
|
126
|
-
The `run` tool handles everything — creates a terminal if needed, executes, and returns clean output:
|
|
127
|
-
|
|
128
|
-
```
|
|
129
|
-
> Run npm test
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
```
|
|
133
|
-
$ npm test
|
|
134
|
-
PASS src/utils.test.ts (3 tests)
|
|
135
|
-
PASS src/index.test.ts (5 tests)
|
|
136
|
-
|
|
137
|
-
[exit: 0 | 1243ms | session-abc123]
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
### Long-Running Process
|
|
141
|
-
|
|
142
|
-
For builds, deployments, or any command that takes a while:
|
|
143
|
-
|
|
144
|
-
```
|
|
145
|
-
> Start `npm run build` without waiting, then check progress
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
The agent will:
|
|
149
|
-
1. Call `run` with `waitForCompletion: false` — returns immediately
|
|
150
|
-
2. Call `read` with `offset: -10` to check the last 10 lines
|
|
151
|
-
3. Repeat until the process completes
|
|
152
|
-
|
|
153
|
-
### Interactive Commands
|
|
154
|
-
|
|
155
|
-
For commands that need user input:
|
|
156
|
-
|
|
157
|
-
```
|
|
158
|
-
> Run npm init and answer the prompts
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
The agent will:
|
|
162
|
-
1. Call `run` with `npm init`
|
|
163
|
-
2. Call `read` to see the prompt
|
|
164
|
-
3. Call `input` to send the answer
|
|
165
|
-
|
|
166
|
-
### Parallel Agents
|
|
167
|
-
|
|
168
|
-
Subagents can work in isolated terminals using `agentId`:
|
|
169
|
-
|
|
170
|
-
```
|
|
171
|
-
> Have one agent run tests while another runs the linter
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
Each subagent gets its own terminal tagged with its `agentId`, preventing output from mixing.
|
|
175
|
-
|
|
176
|
-
## Configuration
|
|
177
|
-
|
|
178
|
-
The extension reads configuration from VSCode settings under `bashterm-mcp-server-mcp-server.*`:
|
|
179
|
-
|
|
180
|
-
| Setting | Type | Default | Description |
|
|
181
|
-
|---------|------|---------|-------------|
|
|
182
|
-
| `bashterm-mcp-server-mcp-server.maxSessions` | number | 10 | Maximum concurrent terminal sessions |
|
|
183
|
-
| `bashterm-mcp-server-mcp-server.commandTimeout` | number | 30000 | Default command timeout in ms |
|
|
184
|
-
| `bashterm-mcp-server-mcp-server.maxOutputLines` | number | 5000 | Max lines kept in output buffer per session |
|
|
185
|
-
| `bashterm-mcp-server-mcp-server.idleTimeout` | number | 1800000 | Close idle sessions after this many ms (0 = disabled) |
|
|
186
|
-
| `bashterm-mcp-server-mcp-server.blockedCommands` | string[] | `["rm -rf /"]` | Commands that will be rejected |
|
|
187
|
-
|
|
188
|
-
## Recommended: Set as Preferred Tool
|
|
189
|
-
|
|
190
|
-
LLM agents like Claude Code have a built-in `Bash` tool that executes commands inline within the chat. The output is embedded in the conversation and hard to read, especially for commands with verbose output. **We recommend telling the agent to prefer this MCP over its built-in Bash tool.**
|
|
191
|
-
|
|
192
|
-
Add the following to your project's `CLAUDE.md` (or equivalent instructions file):
|
|
193
|
-
|
|
194
|
-
```markdown
|
|
195
|
-
## Terminal Execution
|
|
196
|
-
|
|
197
|
-
Prefer the BashTerm MCP tools (`run`, `exec`, `read`, etc.) over the built-in Bash tool for executing commands.
|
|
198
|
-
BashTerm runs commands in visible VSCode terminal tabs where the user can see output in real time.
|
|
199
|
-
Only fall back to the built-in Bash tool for simple, non-interactive operations like reading environment variables.
|
|
200
|
-
|
|
201
|
-
For commands that may take longer than 30 seconds or produce large amounts of output (builds, test suites,
|
|
202
|
-
deployments, installs), use the pull mode pattern:
|
|
203
|
-
1. Call `run` with `waitForCompletion: false` to launch the command without blocking.
|
|
204
|
-
2. Call `read` with `offset: -10` to check the last 10 lines of output.
|
|
205
|
-
3. Repeat step 2 until you see the command has finished (look for exit messages, prompts, or "Done").
|
|
206
|
-
4. Report the final result to the user.
|
|
207
|
-
|
|
208
|
-
This prevents conversation timeouts and lets the user watch progress in the terminal in real time.
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
**Why this matters:**
|
|
212
|
-
|
|
213
|
-
| | Built-in Bash | BashTerm MCP |
|
|
214
|
-
|---|---|---|
|
|
215
|
-
| Output visibility | Embedded in chat, hard to scroll | Visible in VSCode terminal tab |
|
|
216
|
-
| Real-time feedback | User sees nothing until command finishes | User watches output live |
|
|
217
|
-
| Long-running commands | Blocks the conversation until timeout | Fire-and-forget + polling |
|
|
218
|
-
| Session state | Each command is isolated | Persistent sessions with history |
|
|
219
|
-
| Interactive commands | Not supported | Send input to prompts/REPLs |
|
|
220
|
-
|
|
221
|
-
## Development: Updating the Extension
|
|
222
|
-
|
|
223
|
-
VSCode aggressively caches extensions in memory. When developing locally, `code --install-extension` and even "Developer: Reload Window" may **not** reload your changes. Use this workflow:
|
|
224
|
-
|
|
225
|
-
### Quick update (no restart needed)
|
|
226
|
-
|
|
227
|
-
After modifying source files, build and copy directly into the installed extension directory:
|
|
228
|
-
|
|
229
|
-
```bash
|
|
230
|
-
cd /path/to/bashterm-mcp-server-mcp
|
|
231
|
-
npm run build
|
|
232
|
-
cp dist/extension.js ~/.vscode/extensions/hcdb.bashterm-mcp-server-<version>/dist/extension.js
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
Then run **"Developer: Reload Window"** (`Ctrl+Shift+P`).
|
|
236
|
-
|
|
237
|
-
### Full reinstall (when quick update doesn't work)
|
|
238
|
-
|
|
239
|
-
If VSCode still uses old code:
|
|
240
|
-
|
|
241
|
-
```bash
|
|
242
|
-
# 1. Uninstall and remove all copies
|
|
243
|
-
code --uninstall-extension hcdb.bashterm
|
|
244
|
-
rm -rf ~/.vscode/extensions/hcdb.bashterm-mcp-server-*
|
|
245
|
-
|
|
246
|
-
# 2. Check for ghost entries with old publisher names
|
|
247
|
-
# Look in ~/.vscode/extensions/extensions.json for stale entries
|
|
248
|
-
# Remove any entries with old publisher IDs
|
|
249
|
-
|
|
250
|
-
# 3. Close VSCode completely (not just reload)
|
|
251
|
-
|
|
252
|
-
# 4. Rebuild and install
|
|
253
|
-
npm run build
|
|
254
|
-
npx vsce package --allow-missing-repository
|
|
255
|
-
code --install-extension bashterm-mcp-server-<version>.vsix --force
|
|
256
|
-
|
|
257
|
-
# 5. Open VSCode
|
|
258
|
-
```
|
|
259
|
-
|
|
260
|
-
### Verify the correct version is loaded
|
|
261
|
-
|
|
262
|
-
```bash
|
|
263
|
-
# Check which extension directories exist
|
|
264
|
-
ls ~/.vscode/extensions/ | grep terminal
|
|
265
|
-
|
|
266
|
-
# Verify your changes are in the installed extension
|
|
267
|
-
grep "YOUR_UNIQUE_STRING" ~/.vscode/extensions/hcdb.bashterm-mcp-server-*/dist/extension.js
|
|
268
|
-
|
|
269
|
-
# Compare checksums
|
|
270
|
-
md5sum dist/extension.js ~/.vscode/extensions/hcdb.bashterm-mcp-server-*/dist/extension.js
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
## Large Output Handling
|
|
274
|
-
|
|
275
|
-
When `read` returns output that exceeds the MCP client's token limit, the system automatically saves the full output to a temporary JSON file and returns the file path in the error message.
|
|
276
|
-
|
|
277
|
-
To extract the relevant content:
|
|
278
|
-
|
|
279
|
-
```bash
|
|
280
|
-
# Get the last 50 lines (most relevant for status)
|
|
281
|
-
tail -50 /path/to/saved/file.txt
|
|
282
|
-
|
|
283
|
-
# Or parse the JSON to extract the text content
|
|
284
|
-
python3 -c "import json; data=json.load(open('/path/to/file.txt')); print(data[0]['text'][-2000:])"
|
|
285
|
-
```
|
|
286
|
-
|
|
287
|
-
The file format is JSON: `[{"type": "text", "text": "..."}]`
|
|
288
|
-
|
|
289
|
-
This commonly happens with commands that produce heavy TUI output (progress bars, ANSI escape codes). Use smaller `offset` values (e.g., `offset: -20` instead of `offset: -100`) to reduce the captured output size.
|
|
290
|
-
|
|
291
|
-
## How It Works
|
|
292
|
-
|
|
293
|
-
1. The **VSCode extension** activates and starts an IPC server (Named Pipe on Windows, Unix socket on macOS/Linux)
|
|
294
|
-
2. The **MCP entry point** (`mcp-entry.js`) is spawned by the MCP client and bridges JSON-RPC stdio with the IPC socket
|
|
295
|
-
3. Commands execute via `child_process.exec()` for reliable cross-platform output capture and exit code detection
|
|
296
|
-
4. Output is stored in circular buffers with pagination support for efficient reading
|
|
297
|
-
|
|
298
|
-
## Latest Changes (0.2.0)
|
|
299
|
-
|
|
300
|
-
- **Command allowlist**: New `allowedCommands` config to restrict which commands can run
|
|
301
|
-
- **Session idle reaper**: Auto-close inactive terminals after 5 minutes (configurable, disable with `0`)
|
|
302
|
-
- **Bug fixes**: Fixed duplicate output from Shell Integration + exec, negative buffer index, notification memory leak
|
|
303
|
-
- **Performance**: Batch buffer eviction replaces per-line shift (O(n×m) → O(n+m))
|
|
304
|
-
- **Better session reuse**: Now matches `env` and `shell` config when reusing terminals
|
|
305
|
-
- **Shell-ready detection**: Replaces hardcoded 500ms delay with proper detection + 2s fallback
|
|
306
|
-
- **Code cleanup**: Enabled CommandGuard, extracted shared formatting, dynamic version reading from package.json
|
|
307
|
-
|
|
308
|
-
See [CHANGELOG.md](CHANGELOG.md) for full history.
|
|
309
|
-
|
|
310
|
-
## License
|
|
311
|
-
|
|
312
|
-
MIT
|
|
1
|
+
# BashTerm MCP
|
|
2
|
+
|
|
3
|
+
[](README.zh-CN.md) [](https://github.com/1170953489/bashterm-mcp/releases) [](https://www.npmjs.com/package/bashterm-mcp-server)
|
|
4
|
+
|
|
5
|
+
Run AI-generated shell commands in **real, visible VSCode terminals**.
|
|
6
|
+
|
|
7
|
+
BashTerm MCP turns Claude Code command execution into something you can see, inspect, interrupt, and continue. Instead of hidden shell calls, commands open in normal VSCode terminal tabs with live output, scrollback, interactive input, reusable sessions, and safety controls.
|
|
8
|
+
|
|
9
|
+
## Why BashTerm MCP
|
|
10
|
+
|
|
11
|
+
- **Visible by default**: Every command runs in a real VSCode terminal tab, so you can watch builds, tests, logs, and failures as they happen.
|
|
12
|
+
- **Claude Code ready**: The extension registers its MCP server automatically and can guide Claude Code away from the hidden built-in `Bash` tool.
|
|
13
|
+
- **Long-task friendly**: Start commands without blocking the agent, then read output incrementally while the process keeps running.
|
|
14
|
+
- **Interactive when needed**: Answer prompts, drive REPLs, confirm commands, or send Ctrl+C-style input through the same terminal session.
|
|
15
|
+
- **Session reuse**: Keep context in a terminal instead of creating a fresh process for every command.
|
|
16
|
+
- **Parallel-agent isolation**: Use `agentId` to keep multiple AI workers in separate, readable terminals.
|
|
17
|
+
- **Practical guardrails**: Block dangerous command prefixes, restrict working directories, cap output buffers, and auto-close idle sessions.
|
|
18
|
+
- **Safe rollback**: Disable the Claude Code auto-hook or run a restore command to return to Claude Code's default Bash behavior.
|
|
19
|
+
|
|
20
|
+
## Install
|
|
21
|
+
|
|
22
|
+
1. Install **BashTerm MCP** from the [VSCode Marketplace](https://marketplace.visualstudio.com/items?itemName=hcdb.bashterm-mcp-server).
|
|
23
|
+
2. Open VSCode.
|
|
24
|
+
3. Use Claude Code normally.
|
|
25
|
+
|
|
26
|
+
The extension automatically registers the MCP server through `contributes.mcpServers`, so tools such as `run`, `exec`, `read`, and `input` are available without manual MCP JSON setup.
|
|
27
|
+
|
|
28
|
+
## Claude Code Integration
|
|
29
|
+
|
|
30
|
+
BashTerm MCP can write a user-level PreToolUse hook to `~/.claude/settings.json`. That hook blocks Claude Code's built-in hidden `Bash` tool and tells Claude Code to use BashTerm MCP tools instead, keeping command execution visible inside VSCode.
|
|
31
|
+
|
|
32
|
+
You stay in control:
|
|
33
|
+
|
|
34
|
+
- Turn it off with `bashterm-mcp-server.autoConfigureClaudeCode`.
|
|
35
|
+
- Restore default Bash with `BashTerm MCP: Restore Claude Code Default Bash` from the Command Palette.
|
|
36
|
+
- Disable or uninstall the extension safely: it removes its own Claude Code hook during deactivation.
|
|
37
|
+
|
|
38
|
+
## Screenshots
|
|
39
|
+
|
|
40
|
+

|
|
41
|
+

|
|
42
|
+

|
|
43
|
+
|
|
44
|
+
## Common Workflows
|
|
45
|
+
|
|
46
|
+
### Run a Command
|
|
47
|
+
|
|
48
|
+
Ask Claude Code:
|
|
49
|
+
|
|
50
|
+
```text
|
|
51
|
+
Run npm test
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
BashTerm MCP creates or reuses a visible terminal, runs the command, and returns clean output with the exit code.
|
|
55
|
+
|
|
56
|
+
### Watch a Long Build
|
|
57
|
+
|
|
58
|
+
```text
|
|
59
|
+
Start npm run build without waiting, then monitor progress
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The agent can launch the command with `waitForCompletion: false`, then poll output with `read` while you watch the same terminal live in VSCode.
|
|
63
|
+
|
|
64
|
+
### Handle Interactive Prompts
|
|
65
|
+
|
|
66
|
+
```text
|
|
67
|
+
Run npm init and answer the prompts
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
The agent can start the process, read the prompt, send input, and continue step by step in the visible terminal.
|
|
71
|
+
|
|
72
|
+
### Separate Parallel Agents
|
|
73
|
+
|
|
74
|
+
```text
|
|
75
|
+
Have one agent run tests while another runs the linter
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Each agent can receive its own `agentId`, keeping terminal sessions and output streams separate.
|
|
79
|
+
|
|
80
|
+
## Tools
|
|
81
|
+
|
|
82
|
+
| Tool | What it does |
|
|
83
|
+
|------|--------------|
|
|
84
|
+
| `run` | Create or reuse a terminal and run a command in one step. |
|
|
85
|
+
| `create` | Open a visible terminal tab and return a `sessionId`. |
|
|
86
|
+
| `exec` | Run a command in an existing session and capture output. |
|
|
87
|
+
| `read` | Read session output with offset-based pagination or tail mode. |
|
|
88
|
+
| `input` | Send text to an interactive process. |
|
|
89
|
+
| `list` | List active sessions, optionally filtered by `agentId`. |
|
|
90
|
+
| `close` | Close a session and its terminal tab. |
|
|
91
|
+
|
|
92
|
+
## Configuration
|
|
93
|
+
|
|
94
|
+
Configure BashTerm MCP from VSCode settings under `bashterm-mcp-server.*`.
|
|
95
|
+
|
|
96
|
+
| Setting | Type | Default | Description |
|
|
97
|
+
|---------|------|---------|-------------|
|
|
98
|
+
| `bashterm-mcp-server.autoConfigureClaudeCode` | boolean | `true` | Automatically configure Claude Code to prefer BashTerm MCP over the built-in `Bash` tool. |
|
|
99
|
+
| `bashterm-mcp-server.blockedCommands` | string[] | `["rm -rf /", "mkfs", "dd if=", ":(){ :|:& };:"]` | Command prefixes that are always rejected. |
|
|
100
|
+
| `bashterm-mcp-server.allowedDirectories` | string[] | `[]` | Allowed working directories. Empty means unrestricted. |
|
|
101
|
+
| `bashterm-mcp-server.defaultTimeoutMs` | number | `30000` | Default command timeout in milliseconds. |
|
|
102
|
+
| `bashterm-mcp-server.maxConcurrentSessions` | number | `10` | Maximum number of concurrent terminal sessions. |
|
|
103
|
+
| `bashterm-mcp-server.maxOutputLines` | number | `10000` | Maximum output lines buffered per session. |
|
|
104
|
+
| `bashterm-mcp-server.idleTimeoutMs` | number | `300000` | Auto-close idle sessions after this many milliseconds. `0` disables it. |
|
|
105
|
+
|
|
106
|
+
## Requirements
|
|
107
|
+
|
|
108
|
+
- VSCode 1.99+
|
|
109
|
+
- Node.js 20+
|
|
110
|
+
- Claude Code or another MCP-capable client
|
|
111
|
+
|
|
112
|
+
## When It Helps Most
|
|
113
|
+
|
|
114
|
+
BashTerm MCP is especially useful when the agent needs to run commands you care about observing: tests, package installs, dev servers, migrations, scaffolding tools, deploy scripts, and any command that might ask for input or run longer than a few seconds.
|
|
115
|
+
|
|
116
|
+
## Changelog
|
|
117
|
+
|
|
118
|
+
See [CHANGELOG.md](CHANGELOG.md) for release history.
|
|
119
|
+
|
|
120
|
+
## License
|
|
121
|
+
|
|
122
|
+
MIT
|
package/README.zh-CN.md
CHANGED
|
@@ -1,235 +1,121 @@
|
|
|
1
|
-
# BashTerm
|
|
1
|
+
# BashTerm MCP
|
|
2
2
|
|
|
3
|
-
[](README.md) [](README.md) [](https://github.com/1170953489/bashterm-mcp/releases) [](https://www.npmjs.com/package/bashterm-mcp-server)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
让 AI 生成的 shell 命令在 **真实可见的 VSCode 终端**里运行。
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
BashTerm MCP 把 Claude Code 的命令执行变成你能看见、能检查、能中断、能继续交互的过程。不再是隐藏的后台 Bash 调用,而是普通 VSCode 终端标签页:实时输出、历史滚动、交互输入、会话复用和安全控制都在你眼前。
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## 为什么选择 BashTerm MCP
|
|
10
10
|
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
11
|
+
- **默认可见**:每条命令都在真实 VSCode 终端标签页中运行,测试、构建、日志和报错都能实时看到。
|
|
12
|
+
- **开箱支持 Claude Code**:扩展会自动注册 MCP server,并可引导 Claude Code 使用 BashTerm MCP 替代隐藏的内置 `Bash`。
|
|
13
|
+
- **适合长任务**:命令可以非阻塞启动,进程持续运行时再增量读取输出。
|
|
14
|
+
- **支持交互命令**:可以回答提示、驱动 REPL、确认操作,或向同一个终端会话继续发送输入。
|
|
15
|
+
- **会话复用**:复用已有终端上下文,减少每条命令都新开进程带来的割裂感。
|
|
16
|
+
- **并行代理隔离**:通过 `agentId` 让多个 AI worker 使用不同终端,输出清晰不串台。
|
|
17
|
+
- **实用安全边界**:支持危险命令前缀拦截、工作目录限制、输出缓冲上限和空闲会话自动关闭。
|
|
18
|
+
- **可安全回退**:可关闭 Claude Code 自动 hook,或一键恢复 Claude Code 默认 Bash 行为。
|
|
16
19
|
|
|
17
|
-
##
|
|
20
|
+
## 安装
|
|
18
21
|
|
|
19
|
-
-
|
|
20
|
-
|
|
22
|
+
1. 从 [VSCode Marketplace](https://marketplace.visualstudio.com/items?itemName=hcdb.bashterm-mcp-server) 安装 **BashTerm MCP**。
|
|
23
|
+
2. 打开 VSCode。
|
|
24
|
+
3. 正常使用 Claude Code。
|
|
21
25
|
|
|
22
|
-
|
|
26
|
+
扩展会通过 `contributes.mcpServers` 自动注册 MCP server,`run`、`exec`、`read`、`input` 等工具无需手写 MCP JSON 配置即可使用。
|
|
23
27
|
|
|
24
|
-
|
|
28
|
+
## Claude Code 集成
|
|
25
29
|
|
|
26
|
-
|
|
27
|
-
claude mcp add BashTerm -- npx bashterm-mcp-server@latest
|
|
28
|
-
```
|
|
30
|
+
BashTerm MCP 可以向用户级 `~/.claude/settings.json` 写入 PreToolUse hook。这个 hook 会拦截 Claude Code 隐藏的内置 `Bash` 工具,并提示 Claude Code 改用 BashTerm MCP 工具,让命令执行保持在 VSCode 可见终端中。
|
|
29
31
|
|
|
30
|
-
|
|
32
|
+
控制权始终在用户手里:
|
|
31
33
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
code --install-extension bashterm-0.1.8.vsix
|
|
34
|
+
- 关闭 `bashterm-mcp-server.autoConfigureClaudeCode` 即可停用自动 hook。
|
|
35
|
+
- 在命令面板执行 `BashTerm MCP: Restore Claude Code Default Bash` 可恢复默认 Bash。
|
|
36
|
+
- 直接禁用或卸载扩展也安全:扩展停用时会移除自己写入的 Claude Code hook。
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
claude mcp add BashTerm -- node "C:\Users\<用户名>\.vscode\extensions\hcdb.bashterm-0.1.8\dist\mcp-entry.js"
|
|
39
|
-
```
|
|
38
|
+
## 截图
|
|
40
39
|
|
|
41
|
-
|
|
40
|
+

|
|
41
|
+

|
|
42
|
+

|
|
42
43
|
|
|
43
|
-
|
|
44
|
+
## 常见使用场景
|
|
44
45
|
|
|
45
|
-
|
|
46
|
-
{
|
|
47
|
-
"servers": {
|
|
48
|
-
"BashTerm": {
|
|
49
|
-
"type": "stdio",
|
|
50
|
-
"command": "npx",
|
|
51
|
-
"args": ["bashterm-mcp-server@latest"]
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
<details>
|
|
58
|
-
<summary>Cursor</summary>
|
|
46
|
+
### 运行普通命令
|
|
59
47
|
|
|
60
|
-
|
|
48
|
+
告诉 Claude Code:
|
|
61
49
|
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
"mcpServers": {
|
|
65
|
-
"BashTerm": {
|
|
66
|
-
"command": "npx",
|
|
67
|
-
"args": ["-y", "bashterm-mcp-server@latest"]
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
50
|
+
```text
|
|
51
|
+
运行 npm test
|
|
71
52
|
```
|
|
72
53
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
<details>
|
|
76
|
-
<summary>Claude Desktop</summary>
|
|
77
|
-
|
|
78
|
-
在 `claude_desktop_config.json` 中添加:
|
|
79
|
-
|
|
80
|
-
```json
|
|
81
|
-
{
|
|
82
|
-
"mcpServers": {
|
|
83
|
-
"BashTerm": {
|
|
84
|
-
"command": "npx",
|
|
85
|
-
"args": ["-y", "bashterm-mcp-server@latest"]
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
</details>
|
|
92
|
-
|
|
93
|
-
### 你的第一个提示
|
|
94
|
-
|
|
95
|
-
安装完成后,试试问:
|
|
96
|
-
|
|
97
|
-
> 在终端中运行 `ls -la`
|
|
98
|
-
|
|
99
|
-
你应该能在 VSCode 中看到一个新的终端标签页打开,并显示命令输出。
|
|
100
|
-
|
|
101
|
-
## 工具
|
|
102
|
-
|
|
103
|
-
### 快速执行
|
|
104
|
-
|
|
105
|
-
| 工具 | 说明 |
|
|
106
|
-
|------|------|
|
|
107
|
-
| `run` | 一步创建(或复用)终端并执行命令,返回清洁输出和退出码。 |
|
|
108
|
-
|
|
109
|
-
### 会话管理
|
|
110
|
-
|
|
111
|
-
| 工具 | 说明 |
|
|
112
|
-
|------|------|
|
|
113
|
-
| `create` | 创建新的可见终端会话,返回 `sessionId`。 |
|
|
114
|
-
| `exec` | 在已有会话中执行命令并捕获输出。 |
|
|
115
|
-
| `read` | 分页读取会话输出,支持增量读取和 tail 模式(`offset: -N`)。 |
|
|
116
|
-
| `input` | 向交互式终端发送文本(用于提示、REPL、确认等)。 |
|
|
117
|
-
| `list` | 列出活动会话,可选按 `agentId` 过滤。 |
|
|
118
|
-
| `close` | 关闭终端会话及其 VSCode 标签页。 |
|
|
119
|
-
|
|
120
|
-
## 使用模式
|
|
121
|
-
|
|
122
|
-
### 简单命令
|
|
54
|
+
BashTerm MCP 会创建或复用一个可见终端,执行命令,并返回清洁输出和退出码。
|
|
123
55
|
|
|
124
|
-
|
|
56
|
+
### 观察长时间构建
|
|
125
57
|
|
|
58
|
+
```text
|
|
59
|
+
启动 npm run build,不要等待结束,然后持续查看进度
|
|
126
60
|
```
|
|
127
|
-
> 运行 npm test
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
```
|
|
131
|
-
$ npm test
|
|
132
|
-
PASS src/utils.test.ts (3 tests)
|
|
133
|
-
PASS src/index.test.ts (5 tests)
|
|
134
61
|
|
|
135
|
-
|
|
136
|
-
```
|
|
62
|
+
代理可以用 `waitForCompletion: false` 启动命令,再通过 `read` 轮询输出;同时你也能在 VSCode 终端里实时观察同一个进程。
|
|
137
63
|
|
|
138
|
-
###
|
|
64
|
+
### 处理交互式提示
|
|
139
65
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
```
|
|
143
|
-
> 启动 npm run build 不等待,然后检查进度
|
|
66
|
+
```text
|
|
67
|
+
运行 npm init 并回答提示
|
|
144
68
|
```
|
|
145
69
|
|
|
146
|
-
|
|
147
|
-
1. 调用 `run` 设置 `waitForCompletion: false` —— 立即返回
|
|
148
|
-
2. 调用 `read` 设置 `offset: -10` 查看最后 10 行
|
|
149
|
-
3. 重复直到进程完成
|
|
150
|
-
|
|
151
|
-
### 交互式命令
|
|
70
|
+
代理可以启动进程、读取提示、发送输入,然后一步步驱动交互式命令。
|
|
152
71
|
|
|
153
|
-
|
|
72
|
+
### 隔离并行代理
|
|
154
73
|
|
|
74
|
+
```text
|
|
75
|
+
让一个代理跑测试,另一个代理跑 lint
|
|
155
76
|
```
|
|
156
|
-
> 运行 npm init 并回答提示
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
代理会:
|
|
160
|
-
1. 调用 `run` 执行 `npm init`
|
|
161
|
-
2. 调用 `read` 查看提示
|
|
162
|
-
3. 调用 `input` 发送答案
|
|
163
|
-
|
|
164
|
-
### 并行代理
|
|
165
77
|
|
|
166
|
-
|
|
78
|
+
每个代理都可以带上自己的 `agentId`,终端会话和输出流彼此分离。
|
|
167
79
|
|
|
168
|
-
|
|
169
|
-
> 让一个代理运行测试,另一个运行代码检查
|
|
170
|
-
```
|
|
80
|
+
## 工具列表
|
|
171
81
|
|
|
172
|
-
|
|
82
|
+
| 工具 | 功能 |
|
|
83
|
+
|------|------|
|
|
84
|
+
| `run` | 创建或复用终端,并一步执行命令。 |
|
|
85
|
+
| `create` | 打开可见终端标签页并返回 `sessionId`。 |
|
|
86
|
+
| `exec` | 在已有会话中执行命令并捕获输出。 |
|
|
87
|
+
| `read` | 按偏移量分页读取输出,或进入 tail 模式。 |
|
|
88
|
+
| `input` | 向交互式进程发送文本。 |
|
|
89
|
+
| `list` | 列出活动会话,可按 `agentId` 过滤。 |
|
|
90
|
+
| `close` | 关闭会话及其终端标签页。 |
|
|
173
91
|
|
|
174
92
|
## 配置
|
|
175
93
|
|
|
176
|
-
|
|
94
|
+
可在 VSCode 设置中配置 `bashterm-mcp-server.*`。
|
|
177
95
|
|
|
178
96
|
| 设置项 | 类型 | 默认值 | 说明 |
|
|
179
97
|
|--------|------|--------|------|
|
|
180
|
-
| `bashterm-mcp-server.
|
|
181
|
-
| `bashterm-mcp-server.
|
|
182
|
-
| `bashterm-mcp-server.
|
|
183
|
-
| `bashterm-mcp-server.
|
|
184
|
-
| `bashterm-mcp-server.
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
像 Claude Code 这样的 LLM 代理内置了 `Bash` 工具,会在聊天中内联执行命令。输出嵌入在对话中,难以阅读,尤其是输出冗长的命令。**建议告诉代理优先使用本 MCP 工具,而非内置 Bash 工具。**
|
|
189
|
-
|
|
190
|
-
将以下内容添加到项目的 `CLAUDE.md`(或等效指令文件)中:
|
|
191
|
-
|
|
192
|
-
```markdown
|
|
193
|
-
## 终端执行
|
|
194
|
-
|
|
195
|
-
优先使用 BashTerm MCP 工具(`run`、`exec`、`read` 等)来执行命令,而不是使用内置的 Bash 工具。
|
|
196
|
-
BashTerm 在可见的 VSCode 终端标签页中运行命令,用户可以实时查看输出。
|
|
197
|
-
仅在简单、非交互式操作(如读取环境变量)时回退到内置 Bash 工具。
|
|
98
|
+
| `bashterm-mcp-server.autoConfigureClaudeCode` | boolean | `true` | 自动配置 Claude Code,使其优先使用 BashTerm MCP 而不是内置 `Bash`。 |
|
|
99
|
+
| `bashterm-mcp-server.blockedCommands` | string[] | `["rm -rf /", "mkfs", "dd if=", ":(){ :|:& };:"]` | 始终拒绝执行的命令前缀。 |
|
|
100
|
+
| `bashterm-mcp-server.allowedDirectories` | string[] | `[]` | 允许的工作目录。为空表示不限制。 |
|
|
101
|
+
| `bashterm-mcp-server.defaultTimeoutMs` | number | `30000` | 默认命令超时时间,单位毫秒。 |
|
|
102
|
+
| `bashterm-mcp-server.maxConcurrentSessions` | number | `10` | 最大并发终端会话数。 |
|
|
103
|
+
| `bashterm-mcp-server.maxOutputLines` | number | `10000` | 每个会话最多缓冲的输出行数。 |
|
|
104
|
+
| `bashterm-mcp-server.idleTimeoutMs` | number | `300000` | 空闲会话自动关闭时间,单位毫秒。`0` 表示禁用。 |
|
|
198
105
|
|
|
199
|
-
|
|
200
|
-
1. 调用 `run` 设置 `waitForCompletion: false` 启动命令但不阻塞。
|
|
201
|
-
2. 调用 `read` 设置 `offset: -10` 查看最后 10 行输出。
|
|
202
|
-
3. 重复步骤 2 直到看到命令完成(查找退出消息、提示或 "Done")。
|
|
203
|
-
4. 向用户报告最终结果。
|
|
204
|
-
|
|
205
|
-
这样可以防止对话超时,并让用户实时观察终端进度。
|
|
206
|
-
```
|
|
207
|
-
|
|
208
|
-
**为什么重要:**
|
|
209
|
-
|
|
210
|
-
| | 内置 Bash | BashTerm MCP |
|
|
211
|
-
|---|---|---|
|
|
212
|
-
| 输出可见性 | 嵌入聊天,难以滚动 | 在 VSCode 终端标签页中可见 |
|
|
213
|
-
| 实时反馈 | 用户看不到任何输出直到命令完成 | 用户实时观看输出 |
|
|
214
|
-
| 长时间命令 | 阻塞对话直到超时 | 发射后不管 + 轮询 |
|
|
215
|
-
| 会话状态 | 每个命令隔离 | 持久化会话,带历史 |
|
|
216
|
-
| 交互式命令 | 不支持 | 可向提示/REPL 发送输入 |
|
|
106
|
+
## 环境要求
|
|
217
107
|
|
|
218
|
-
|
|
108
|
+
- VSCode 1.99+
|
|
109
|
+
- Node.js 20+
|
|
110
|
+
- Claude Code 或其它支持 MCP 的客户端
|
|
219
111
|
|
|
220
|
-
|
|
221
|
-
2. **MCP 入口**(`mcp-entry.js`)由 MCP 客户端启动,在 JSON-RPC stdio 和 IPC socket 之间建立桥接
|
|
222
|
-
3. 命令通过 `child_process.exec()` 执行,输出直接捕获,不再依赖 Shell Integration API
|
|
223
|
-
4. 输出存储在循环缓冲区中,支持分页高效读取
|
|
112
|
+
## 适合什么场景
|
|
224
113
|
|
|
225
|
-
|
|
114
|
+
BashTerm MCP 特别适合那些你希望亲眼观察的命令:测试、包安装、开发服务器、数据库迁移、脚手架工具、部署脚本,以及任何可能需要输入或运行时间较长的命令。
|
|
226
115
|
|
|
227
|
-
|
|
228
|
-
- **修复 bin 路径**:更正 npm 二进制入口路径
|
|
229
|
-
- **动态版本图标**:badge 徽章现在反映实际版本号
|
|
230
|
-
- 中文 README 补充版本徽章
|
|
116
|
+
## 更新日志
|
|
231
117
|
|
|
232
|
-
|
|
118
|
+
完整历史见 [CHANGELOG.md](CHANGELOG.md)。
|
|
233
119
|
|
|
234
120
|
## 许可证
|
|
235
121
|
|
package/dist/extension.js
CHANGED
|
@@ -5389,7 +5389,7 @@ var zodToJsonSchema = (schema, options) => {
|
|
|
5389
5389
|
};
|
|
5390
5390
|
|
|
5391
5391
|
// package.json
|
|
5392
|
-
var version = "0.2.
|
|
5392
|
+
var version = "0.2.2";
|
|
5393
5393
|
|
|
5394
5394
|
// src/mcp/tools/schemas.ts
|
|
5395
5395
|
var coerceBoolean = external_exports.preprocess(
|
|
@@ -5980,6 +5980,29 @@ function generateCommandId() {
|
|
|
5980
5980
|
return `cmd-${v4_default().slice(0, 8)}`;
|
|
5981
5981
|
}
|
|
5982
5982
|
|
|
5983
|
+
// src/utils/exec-options.ts
|
|
5984
|
+
function buildExecOptions(params) {
|
|
5985
|
+
return {
|
|
5986
|
+
cwd: params.cwd,
|
|
5987
|
+
timeout: params.timeoutMs,
|
|
5988
|
+
windowsHide: true,
|
|
5989
|
+
encoding: params.isWin ? null : "utf8",
|
|
5990
|
+
shell: params.shell
|
|
5991
|
+
};
|
|
5992
|
+
}
|
|
5993
|
+
function detectShellEncoding(isWin, shell) {
|
|
5994
|
+
if (!isWin) return "utf-8";
|
|
5995
|
+
if (!shell) return "gbk";
|
|
5996
|
+
const lower = shell.toLowerCase();
|
|
5997
|
+
if (/(^|[\/\\])(ba|z|fi|da|k)?sh(\.exe)?$/i.test(lower) || lower.includes("wsl")) {
|
|
5998
|
+
return "utf-8";
|
|
5999
|
+
}
|
|
6000
|
+
if (lower.includes("pwsh")) {
|
|
6001
|
+
return "utf-8";
|
|
6002
|
+
}
|
|
6003
|
+
return "gbk";
|
|
6004
|
+
}
|
|
6005
|
+
|
|
5983
6006
|
// src/terminal/session.ts
|
|
5984
6007
|
var TerminalSession = class {
|
|
5985
6008
|
sessionId;
|
|
@@ -6094,12 +6117,12 @@ var TerminalSession = class {
|
|
|
6094
6117
|
return new Promise((resolve2) => {
|
|
6095
6118
|
let resolved = false;
|
|
6096
6119
|
const isWin = process.platform === "win32";
|
|
6097
|
-
const options = {
|
|
6120
|
+
const options = buildExecOptions({
|
|
6098
6121
|
cwd: this.cwd,
|
|
6099
|
-
|
|
6100
|
-
|
|
6101
|
-
|
|
6102
|
-
};
|
|
6122
|
+
timeoutMs,
|
|
6123
|
+
shell: this.shell,
|
|
6124
|
+
isWin
|
|
6125
|
+
});
|
|
6103
6126
|
const child = cp.exec(command, options, (error, stdout, stderr) => {
|
|
6104
6127
|
if (resolved) return;
|
|
6105
6128
|
resolved = true;
|
|
@@ -6107,7 +6130,8 @@ var TerminalSession = class {
|
|
|
6107
6130
|
let outStr;
|
|
6108
6131
|
let errStr;
|
|
6109
6132
|
if (isWin) {
|
|
6110
|
-
const
|
|
6133
|
+
const textEncoding = detectShellEncoding(isWin, this.shell);
|
|
6134
|
+
const td = new import_util4.TextDecoder(textEncoding);
|
|
6111
6135
|
outStr = stdout ? td.decode(stdout) : "";
|
|
6112
6136
|
errStr = stderr ? td.decode(stderr) : "";
|
|
6113
6137
|
} else {
|
|
@@ -6431,6 +6455,7 @@ var SessionManager = class {
|
|
|
6431
6455
|
var ipcServer;
|
|
6432
6456
|
var sessionManager;
|
|
6433
6457
|
var statusBarItem;
|
|
6458
|
+
var CLAUDE_CODE_BASH_BLOCK_MESSAGE = "Please use BashTerm MCP tools (run / exec / read) instead of the built-in Bash tool. These commands execute visibly in VSCode terminal tabs.";
|
|
6434
6459
|
function getSocketPath() {
|
|
6435
6460
|
const tmpDir = os.tmpdir();
|
|
6436
6461
|
const crypto3 = require("crypto");
|
|
@@ -6438,12 +6463,14 @@ function getSocketPath() {
|
|
|
6438
6463
|
const hash = crypto3.createHash("md5").update(workspace4).digest("hex").slice(0, 8);
|
|
6439
6464
|
const isWin = process.platform === "win32";
|
|
6440
6465
|
const socketPath = isWin ? path2.join("\\\\?\\pipe", `bashterm-mcp-${hash}`) : path2.join(tmpDir, `bashterm-mcp-${hash}.sock`);
|
|
6441
|
-
|
|
6466
|
+
return socketPath;
|
|
6467
|
+
}
|
|
6468
|
+
function publishSocketPath(socketPath) {
|
|
6469
|
+
const discoveryPath = path2.join(os.tmpdir(), "bashterm-mcp.discovery");
|
|
6442
6470
|
try {
|
|
6443
6471
|
fs.writeFileSync(discoveryPath, socketPath);
|
|
6444
6472
|
} catch {
|
|
6445
6473
|
}
|
|
6446
|
-
return socketPath;
|
|
6447
6474
|
}
|
|
6448
6475
|
function cleanupSocket(socketPath) {
|
|
6449
6476
|
if (process.platform === "win32") return;
|
|
@@ -6454,9 +6481,136 @@ function cleanupSocket(socketPath) {
|
|
|
6454
6481
|
} catch {
|
|
6455
6482
|
}
|
|
6456
6483
|
}
|
|
6484
|
+
function getClaudeCodeSettingsPath() {
|
|
6485
|
+
const claudeDir = path2.join(os.homedir(), ".claude");
|
|
6486
|
+
return {
|
|
6487
|
+
claudeDir,
|
|
6488
|
+
settingsPath: path2.join(claudeDir, "settings.json")
|
|
6489
|
+
};
|
|
6490
|
+
}
|
|
6491
|
+
function isRecord(value) {
|
|
6492
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
6493
|
+
}
|
|
6494
|
+
function isLegacyBashTermClaudeCodeHook(value) {
|
|
6495
|
+
if (!isRecord(value) || value.matcher !== "Bash") return false;
|
|
6496
|
+
const legacyMessage = value.message;
|
|
6497
|
+
return value.action === "block" && typeof legacyMessage === "string" && legacyMessage.includes("BashTerm MCP");
|
|
6498
|
+
}
|
|
6499
|
+
function isCurrentBashTermClaudeCodeHook(value) {
|
|
6500
|
+
if (!isRecord(value) || value.matcher !== "Bash") return false;
|
|
6501
|
+
if (!Array.isArray(value.hooks)) return false;
|
|
6502
|
+
return value.hooks.some(
|
|
6503
|
+
(handler) => isRecord(handler) && handler.type === "command" && typeof handler.command === "string" && handler.command.includes("BashTerm MCP")
|
|
6504
|
+
);
|
|
6505
|
+
}
|
|
6506
|
+
function isBashTermClaudeCodeHook(value) {
|
|
6507
|
+
return isLegacyBashTermClaudeCodeHook(value) || isCurrentBashTermClaudeCodeHook(value);
|
|
6508
|
+
}
|
|
6509
|
+
function readClaudeCodeSettings(settingsPath) {
|
|
6510
|
+
if (!fs.existsSync(settingsPath)) return {};
|
|
6511
|
+
try {
|
|
6512
|
+
const raw = fs.readFileSync(settingsPath, "utf-8");
|
|
6513
|
+
return JSON.parse(raw);
|
|
6514
|
+
} catch {
|
|
6515
|
+
log("Failed to parse .claude/settings.json");
|
|
6516
|
+
return {};
|
|
6517
|
+
}
|
|
6518
|
+
}
|
|
6519
|
+
function writeClaudeCodeSettings(claudeDir, settingsPath, settings) {
|
|
6520
|
+
if (!fs.existsSync(claudeDir)) {
|
|
6521
|
+
fs.mkdirSync(claudeDir, { recursive: true });
|
|
6522
|
+
}
|
|
6523
|
+
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
6524
|
+
}
|
|
6525
|
+
function createClaudeCodeBashBlockHook() {
|
|
6526
|
+
const blockCommand = process.platform === "win32" ? `powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "[Console]::Error.WriteLine('${CLAUDE_CODE_BASH_BLOCK_MESSAGE}'); exit 2"` : `sh -c 'printf "%s\\n" "${CLAUDE_CODE_BASH_BLOCK_MESSAGE}" >&2; exit 2'`;
|
|
6527
|
+
return {
|
|
6528
|
+
matcher: "Bash",
|
|
6529
|
+
hooks: [
|
|
6530
|
+
{
|
|
6531
|
+
type: "command",
|
|
6532
|
+
command: blockCommand
|
|
6533
|
+
}
|
|
6534
|
+
]
|
|
6535
|
+
};
|
|
6536
|
+
}
|
|
6537
|
+
function autoConfigureClaudeCode() {
|
|
6538
|
+
const { claudeDir, settingsPath } = getClaudeCodeSettingsPath();
|
|
6539
|
+
const settings = readClaudeCodeSettings(settingsPath);
|
|
6540
|
+
const hooks = isRecord(settings.hooks) ? settings.hooks : {};
|
|
6541
|
+
const existingPreToolUse = Array.isArray(hooks.PreToolUse) ? hooks.PreToolUse : [];
|
|
6542
|
+
const preToolUse = existingPreToolUse.filter(
|
|
6543
|
+
(h) => isRecord(h) && !isLegacyBashTermClaudeCodeHook(h)
|
|
6544
|
+
);
|
|
6545
|
+
const alreadyConfigured = preToolUse.some(isCurrentBashTermClaudeCodeHook);
|
|
6546
|
+
const needsCleanup = preToolUse.length !== existingPreToolUse.length;
|
|
6547
|
+
if (alreadyConfigured && !needsCleanup) return;
|
|
6548
|
+
if (!alreadyConfigured) {
|
|
6549
|
+
preToolUse.push(createClaudeCodeBashBlockHook());
|
|
6550
|
+
}
|
|
6551
|
+
hooks.PreToolUse = preToolUse;
|
|
6552
|
+
settings.hooks = hooks;
|
|
6553
|
+
try {
|
|
6554
|
+
writeClaudeCodeSettings(claudeDir, settingsPath, settings);
|
|
6555
|
+
log("Auto-configured .claude/settings.json: Bash tool blocked, BashTerm MCP preferred");
|
|
6556
|
+
} catch (err) {
|
|
6557
|
+
logError("Failed to auto-configure .claude/settings.json", err);
|
|
6558
|
+
}
|
|
6559
|
+
}
|
|
6560
|
+
function restoreClaudeCodeDefaultBash() {
|
|
6561
|
+
const { claudeDir, settingsPath } = getClaudeCodeSettingsPath();
|
|
6562
|
+
if (!fs.existsSync(settingsPath)) return false;
|
|
6563
|
+
const settings = readClaudeCodeSettings(settingsPath);
|
|
6564
|
+
if (!isRecord(settings.hooks)) return false;
|
|
6565
|
+
const hooks = settings.hooks;
|
|
6566
|
+
const existingPreToolUse = Array.isArray(hooks.PreToolUse) ? hooks.PreToolUse : [];
|
|
6567
|
+
const preToolUse = existingPreToolUse.filter((hook) => !isBashTermClaudeCodeHook(hook));
|
|
6568
|
+
if (preToolUse.length === existingPreToolUse.length) return false;
|
|
6569
|
+
if (preToolUse.length > 0) {
|
|
6570
|
+
hooks.PreToolUse = preToolUse;
|
|
6571
|
+
} else {
|
|
6572
|
+
delete hooks.PreToolUse;
|
|
6573
|
+
}
|
|
6574
|
+
if (Object.keys(hooks).length > 0) {
|
|
6575
|
+
settings.hooks = hooks;
|
|
6576
|
+
} else {
|
|
6577
|
+
delete settings.hooks;
|
|
6578
|
+
}
|
|
6579
|
+
try {
|
|
6580
|
+
writeClaudeCodeSettings(claudeDir, settingsPath, settings);
|
|
6581
|
+
log("Restored Claude Code default Bash by removing BashTerm MCP hook");
|
|
6582
|
+
return true;
|
|
6583
|
+
} catch (err) {
|
|
6584
|
+
logError("Failed to restore Claude Code default Bash", err);
|
|
6585
|
+
return false;
|
|
6586
|
+
}
|
|
6587
|
+
}
|
|
6457
6588
|
function activate(context) {
|
|
6458
6589
|
const outputChannel2 = initLogger();
|
|
6459
6590
|
log("BashTerm MCP extension activating...");
|
|
6591
|
+
const applyClaudeCodePreference = () => {
|
|
6592
|
+
const autoConfigureClaude = vscode4.workspace.getConfiguration("bashterm-mcp-server").get("autoConfigureClaudeCode", true);
|
|
6593
|
+
if (autoConfigureClaude) {
|
|
6594
|
+
autoConfigureClaudeCode();
|
|
6595
|
+
} else {
|
|
6596
|
+
restoreClaudeCodeDefaultBash();
|
|
6597
|
+
}
|
|
6598
|
+
};
|
|
6599
|
+
applyClaudeCodePreference();
|
|
6600
|
+
context.subscriptions.push(
|
|
6601
|
+
vscode4.workspace.onDidChangeConfiguration((event) => {
|
|
6602
|
+
if (event.affectsConfiguration("bashterm-mcp-server.autoConfigureClaudeCode")) {
|
|
6603
|
+
applyClaudeCodePreference();
|
|
6604
|
+
}
|
|
6605
|
+
})
|
|
6606
|
+
);
|
|
6607
|
+
context.subscriptions.push(
|
|
6608
|
+
vscode4.commands.registerCommand("bashterm-mcp-server.restoreClaudeCodeDefaultBash", () => {
|
|
6609
|
+
const restored = restoreClaudeCodeDefaultBash();
|
|
6610
|
+
const message = restored ? "Claude Code default Bash restored. Restart Claude Code to apply the change." : "No BashTerm MCP Claude Code hook was found.";
|
|
6611
|
+
void vscode4.window.showInformationMessage(message);
|
|
6612
|
+
})
|
|
6613
|
+
);
|
|
6460
6614
|
sessionManager = new SessionManager();
|
|
6461
6615
|
statusBarItem = vscode4.window.createStatusBarItem(
|
|
6462
6616
|
vscode4.StatusBarAlignment.Left,
|
|
@@ -6474,6 +6628,7 @@ function activate(context) {
|
|
|
6474
6628
|
});
|
|
6475
6629
|
const handleMcpRequest = createMcpRequestHandler(sessionManager);
|
|
6476
6630
|
const socketPath = getSocketPath();
|
|
6631
|
+
publishSocketPath(socketPath);
|
|
6477
6632
|
cleanupSocket(socketPath);
|
|
6478
6633
|
ipcServer = net.createServer((connection) => {
|
|
6479
6634
|
log("IPC client connected");
|
|
@@ -6543,6 +6698,7 @@ async function handleIpcRequest(request, connection, handleMcpRequest) {
|
|
|
6543
6698
|
}
|
|
6544
6699
|
function deactivate() {
|
|
6545
6700
|
log("BashTerm MCP extension deactivating...");
|
|
6701
|
+
restoreClaudeCodeDefaultBash();
|
|
6546
6702
|
if (ipcServer) {
|
|
6547
6703
|
ipcServer.close();
|
|
6548
6704
|
ipcServer = void 0;
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "bashterm-mcp-server",
|
|
3
3
|
"displayName": "BashTerm MCP",
|
|
4
4
|
"description": "MCP server that executes commands in visible VSCode terminal tabs. Supports Windows, macOS and Linux.",
|
|
5
|
-
"version": "0.2.
|
|
5
|
+
"version": "0.2.2",
|
|
6
6
|
"publisher": "hcdb",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"author": "hcdb",
|
|
@@ -32,13 +32,20 @@
|
|
|
32
32
|
"Other"
|
|
33
33
|
],
|
|
34
34
|
"activationEvents": [
|
|
35
|
-
"onStartupFinished"
|
|
35
|
+
"onStartupFinished",
|
|
36
|
+
"onCommand:bashterm-mcp-server.restoreClaudeCodeDefaultBash"
|
|
36
37
|
],
|
|
37
38
|
"main": "./dist/extension.js",
|
|
38
39
|
"bin": {
|
|
39
40
|
"bashterm-mcp-server": "dist/mcp-entry.js"
|
|
40
41
|
},
|
|
41
42
|
"contributes": {
|
|
43
|
+
"commands": [
|
|
44
|
+
{
|
|
45
|
+
"command": "bashterm-mcp-server.restoreClaudeCodeDefaultBash",
|
|
46
|
+
"title": "BashTerm MCP: Restore Claude Code Default Bash"
|
|
47
|
+
}
|
|
48
|
+
],
|
|
42
49
|
"mcpServers": {
|
|
43
50
|
"bashterm-mcp-server": {
|
|
44
51
|
"type": "stdio",
|
|
@@ -51,6 +58,11 @@
|
|
|
51
58
|
"configuration": {
|
|
52
59
|
"title": "BashTerm MCP",
|
|
53
60
|
"properties": {
|
|
61
|
+
"bashterm-mcp-server.autoConfigureClaudeCode": {
|
|
62
|
+
"type": "boolean",
|
|
63
|
+
"default": true,
|
|
64
|
+
"description": "Automatically configure Claude Code to block the built-in Bash tool and prefer BashTerm MCP tools"
|
|
65
|
+
},
|
|
54
66
|
"bashterm-mcp-server.blockedCommands": {
|
|
55
67
|
"type": "array",
|
|
56
68
|
"items": {
|
|
@@ -122,6 +134,6 @@
|
|
|
122
134
|
"eslint": "^8.57.0",
|
|
123
135
|
"prettier": "^3.2.0",
|
|
124
136
|
"typescript": "^5.4.0",
|
|
125
|
-
"vitest": "^
|
|
137
|
+
"vitest": "^3.2.6"
|
|
126
138
|
}
|
|
127
139
|
}
|
package/server.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
|
3
3
|
"name": "io.github.hcdb/bashterm-mcp-server",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.2",
|
|
5
5
|
"description": "BashTerm MCP — execute commands in visible VSCode terminal tabs with output capture and session reuse.",
|
|
6
6
|
"author": "hcdb",
|
|
7
7
|
"license": "MIT",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
{
|
|
15
15
|
"registryType": "npm",
|
|
16
16
|
"identifier": "bashterm-mcp-server",
|
|
17
|
-
"version": "0.2.
|
|
17
|
+
"version": "0.2.2",
|
|
18
18
|
"transport": {
|
|
19
19
|
"type": "stdio"
|
|
20
20
|
}
|