bashterm-mcp-server 0.2.1 → 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 CHANGED
@@ -2,6 +2,22 @@
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
+
5
21
  ## [0.2.1] - 2026-06-04
6
22
 
7
23
  ### Changed
package/CLAUDE.md CHANGED
@@ -2,15 +2,6 @@
2
2
 
3
3
  MCP server that runs commands in visible VSCode terminal tabs.
4
4
 
5
- ## Terminal Execution
6
-
7
- 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.
8
-
9
- For commands that may take longer than 30 seconds or produce large output, use pull mode:
10
- 1. Call `run` with `waitForCompletion: false`
11
- 2. Call `read` with `offset: -10` to check progress
12
- 3. Repeat until done
13
-
14
5
  ---
15
6
 
16
7
  ## Release Process
package/README.md CHANGED
@@ -1,184 +1,122 @@
1
- # BashTerm
2
-
3
- [![中文文档](https://img.shields.io/badge/README-中文-red)](README.zh-CN.md) [![release](https://img.shields.io/npm/v/bashterm-mcp-server?label=release)](https://github.com/1170953489/bashterm-mcp/releases) [![npm version](https://img.shields.io/npm/v/bashterm-mcp-server)](https://www.npmjs.com/package/bashterm-mcp-server)
4
-
5
- MCP server that runs shell commands in **visible VSCode terminal tabs** — watch output live, scroll history, interact when needed.
6
-
7
- ## Key Features
8
-
9
- - **Visible Terminals**: Commands run in real VSCode terminal tabs — watch output live, scroll history, interact when needed.
10
- - **Session Reuse**: `run` automatically reuses idle sessions, creating new terminals only when necessary.
11
- - **Non-Blocking Execution**: Fire-and-forget with `waitForCompletion: false`, then poll with `read`.
12
- - **Subagent Isolation**: Tag sessions with `agentId` to keep parallel agent workloads in separate terminals.
13
-
14
- ## Requirements
15
-
16
- - VS Code 1.93+
17
- - Node.js 20+
18
-
19
- ## Getting Started
20
-
21
- ### Claude Code
22
-
23
- ```bash
24
- claude mcp add BashTerm -- npx bashterm-mcp-server@latest
25
- ```
26
-
27
- ### VS Code / Copilot
28
-
29
- Add to your `.vscode/mcp.json`:
30
-
31
- ```json
32
- {
33
- "servers": {
34
- "BashTerm": {
35
- "type": "stdio",
36
- "command": "npx",
37
- "args": ["bashterm-mcp-server@latest"]
38
- }
39
- }
40
- }
41
- ```
42
-
43
- <details>
44
- <summary>Cursor</summary>
45
-
46
- Add to your `.cursor/mcp.json`:
47
-
48
- ```json
49
- {
50
- "mcpServers": {
51
- "BashTerm": {
52
- "command": "npx",
53
- "args": ["-y", "bashterm-mcp-server@latest"]
54
- }
55
- }
56
- }
57
- ```
58
-
59
- </details>
60
-
61
- <details>
62
- <summary>Claude Desktop</summary>
63
-
64
- Add to your `claude_desktop_config.json`:
65
-
66
- ```json
67
- {
68
- "mcpServers": {
69
- "BashTerm": {
70
- "command": "npx",
71
- "args": ["-y", "bashterm-mcp-server@latest"]
72
- }
73
- }
74
- }
75
- ```
76
-
77
- </details>
78
-
79
- ## Screenshots
80
-
81
- ![Run command output](docs/images/run_finished.png)
82
- ![Exec permission dialog](docs/images/ask_exec_permission.png)
83
- ![Exec finished](docs/images/exec_finished.png)
84
-
85
- ## Tools
86
-
87
- ### Quick Execution
88
-
89
- | Tool | Description |
90
- |------|-------------|
91
- | `run` | Create (or reuse) a terminal and execute a command in one step. Returns clean output with exit code. |
92
-
93
- ### Session Management
94
-
95
- | Tool | Description |
96
- |------|-------------|
97
- | `create` | Open a new visible terminal tab and return a `sessionId`. |
98
- | `exec` | Run a command in an existing session and capture its output. |
99
- | `read` | Read session output with offset-based pagination. Use `offset: -N` for tail mode. |
100
- | `input` | Send text to an interactive process (answer prompts, drive REPLs, confirm actions). |
101
- | `list` | List active sessions, optionally filtered by `agentId`. |
102
- | `close` | Close a session and its terminal tab. |
103
-
104
- ## Usage Patterns
105
-
106
- ### Simple Command
107
-
108
- The `run` tool handles everything — creates a terminal if needed, executes, and returns clean output:
109
-
110
- ```
111
- > Run npm test
112
- ```
113
-
114
- ```
115
- $ npm test
116
- PASS src/utils.test.ts (3 tests)
117
- PASS src/index.test.ts (5 tests)
118
-
119
- [exit: 0 | 1243ms | session-abc123]
120
- ```
121
-
122
- ### Long-Running Process
123
-
124
- For builds, deployments, or any command that takes a while:
125
-
126
- ```
127
- > Start `npm run build` without waiting, then check progress
128
- ```
129
-
130
- The agent launches the command with `waitForCompletion: false` (returns immediately), then polls with `read` (`offset: -10`) until the process finishes.
131
-
132
- ### Interactive Commands
133
-
134
- For commands that need user input:
135
-
136
- ```
137
- > Run npm init and answer the prompts
138
- ```
139
-
140
- The agent uses `run` to start the command, `read` to check the prompt, and `input` to send responses — driving the interactive process step by step.
141
-
142
- ### Parallel Agents
143
-
144
- Subagents can work in isolated terminals using `agentId`:
145
-
146
- ```
147
- > Have one agent run tests while another runs the linter
148
- ```
149
-
150
- Each subagent gets its own terminal tagged with its `agentId`, keeping output separate and readable.
151
-
152
- ## Configuration
153
-
154
- The extension reads configuration from VSCode settings under `bashterm-mcp-server.*`:
155
-
156
- | Setting | Type | Default | Description |
157
- |---------|------|---------|-------------|
158
- | `bashterm-mcp-server.maxSessions` | number | 10 | Maximum concurrent terminal sessions |
159
- | `bashterm-mcp-server.commandTimeout` | number | 30000 | Default command timeout in ms |
160
- | `bashterm-mcp-server.maxOutputLines` | number | 5000 | Max lines kept in output buffer per session |
161
- | `bashterm-mcp-server.idleTimeout` | number | 1800000 | Close idle sessions after this many ms (0 = disabled) |
162
- | `bashterm-mcp-server.blockedCommands` | string[] | `["rm -rf /"]` | Commands that will be rejected |
163
-
164
- ## Recommended
165
-
166
- LLM agents include a built-in `Bash` tool that runs commands inline, embedding output in the conversation. Prefer BashTerm MCP for visible, scrollable terminal output. Add this to your project's `CLAUDE.md`:
167
-
168
- ```markdown
169
- ## Terminal Execution
170
- Prefer the BashTerm MCP tools (`run`, `exec`, `read`, etc.) over the built-in Bash tool.
171
- BashTerm runs commands in visible VSCode terminal tabs where you can see output in real time.
172
- For commands over 30 seconds, use pull mode: `run` with `waitForCompletion: false`, then poll with `read` (`offset: -10`).
173
- ```
174
-
175
- ## Latest Changes (0.2.1)
176
-
177
- - **Rename cleanup**: Unified all code, docs, and config references to BashTerm MCP — no more legacy names
178
- - **Tag fix**: Corrected v0.2.0 tag to point to the proper release commit
179
-
180
- See [CHANGELOG.md](CHANGELOG.md) for full history.
181
-
182
- ## License
183
-
184
- MIT
1
+ # BashTerm MCP
2
+
3
+ [![中文文档](https://img.shields.io/badge/README-中文-red)](README.zh-CN.md) [![release](https://img.shields.io/npm/v/bashterm-mcp-server?label=release)](https://github.com/1170953489/bashterm-mcp/releases) [![npm version](https://img.shields.io/npm/v/bashterm-mcp-server)](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
+ ![Run command output](docs/images/run_finished.png)
41
+ ![Exec permission dialog](docs/images/ask_exec_permission.png)
42
+ ![Exec finished](docs/images/exec_finished.png)
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,183 +1,122 @@
1
- # BashTerm
2
-
3
- [![English](https://img.shields.io/badge/README-English-blue)](README.md) [![release](https://img.shields.io/npm/v/bashterm-mcp-server?label=release)](https://github.com/1170953489/bashterm-mcp/releases) [![npm version](https://img.shields.io/npm/v/bashterm-mcp-server)](https://www.npmjs.com/package/bashterm-mcp-server)
4
-
5
- **VSCode 可见的终端标签页**中执行命令的 MCP 服务器——实时观看输出、滚动历史、按需交互。
6
-
7
- ## 核心功能
8
-
9
- - **可见终端**:命令在真实的 VSCode 终端标签页中运行——实时观看输出、滚动历史、按需交互。
10
- - **会话复用**:`run` 自动复用空闲会话,仅在必要时创建新终端。
11
- - **非阻塞执行**:`waitForCompletion: false` 发射后不管,随后用 `read` 轮询。
12
- - **子代理隔离**:通过 `agentId` 标记会话,将并行代理的工作负载隔离在独立终端中。
13
-
14
- ## 环境要求
15
-
16
- - VS Code 1.93+
17
- - Node.js 20+
18
-
19
- ## 快速开始
20
-
21
- ### Claude Code
22
-
23
- ```bash
24
- claude mcp add BashTerm -- npx bashterm-mcp-server@latest
25
- ```
26
-
27
- ### VS Code / Copilot
28
-
29
- 在 `.vscode/mcp.json` 中添加:
30
-
31
- ```json
32
- {
33
- "servers": {
34
- "BashTerm": {
35
- "type": "stdio",
36
- "command": "npx",
37
- "args": ["bashterm-mcp-server@latest"]
38
- }
39
- }
40
- }
41
- ```
42
-
43
- <details>
44
- <summary>Cursor</summary>
45
-
46
- `.cursor/mcp.json` 中添加:
47
-
48
- ```json
49
- {
50
- "mcpServers": {
51
- "BashTerm": {
52
- "command": "npx",
53
- "args": ["-y", "bashterm-mcp-server@latest"]
54
- }
55
- }
56
- }
57
- ```
58
-
59
- </details>
60
-
61
- <details>
62
- <summary>Claude Desktop</summary>
63
-
64
- `claude_desktop_config.json` 中添加:
65
-
66
- ```json
67
- {
68
- "mcpServers": {
69
- "BashTerm": {
70
- "command": "npx",
71
- "args": ["-y", "bashterm-mcp-server@latest"]
72
- }
73
- }
74
- }
75
- ```
76
-
77
- </details>
78
-
79
- ## 截图
80
-
81
- ![Run command output](docs/images/run_finished.png)
82
- ![Exec permission dialog](docs/images/ask_exec_permission.png)
83
- ![Exec finished](docs/images/exec_finished.png)
84
-
85
- ## 工具
86
-
87
- ### 快速执行
88
-
89
- | 工具 | 说明 |
90
- |------|------|
91
- | `run` | 一步创建(或复用)终端并执行命令,返回清洁输出和退出码。 |
92
-
93
- ### 会话管理
94
-
95
- | 工具 | 说明 |
96
- |------|------|
97
- | `create` | 打开新的可见终端标签页,返回 `sessionId`。 |
98
- | `exec` | 在已有会话中执行命令并捕获输出。 |
99
- | `read` | 基于偏移量分页读取会话输出。使用 `offset: -N` 进入 tail 模式。 |
100
- | `input` | 向交互式进程发送文本(回答提示、驱动 REPL、确认操作)。 |
101
- | `list` | 列出活动会话,可按 `agentId` 过滤。 |
102
- | `close` | 关闭会话及其终端标签页。 |
103
-
104
- ## 使用模式
105
-
106
- ### 简单命令
107
-
108
- `run` 工具处理一切——按需创建终端、执行命令、返回清洁输出:
109
-
110
- ```
111
- > 运行 npm test
112
- ```
113
-
114
- ```
115
- $ npm test
116
- PASS src/utils.test.ts (3 tests)
117
- PASS src/index.test.ts (5 tests)
118
-
119
- [exit: 0 | 1243ms | session-abc123]
120
- ```
121
-
122
- ### 长时间运行
123
-
124
- 对于构建、部署或其他耗时命令:
125
-
126
- ```
127
- > 启动 npm run build 不等待,然后检查进度
128
- ```
129
-
130
- 代理使用 `waitForCompletion: false` 启动命令(立即返回),然后通过 `read`(`offset: -10`)轮询直到进程完成。
131
-
132
- ### 交互式命令
133
-
134
- 对于需要用户输入的命令:
135
-
136
- ```
137
- > 运行 npm init 并回答提示
138
- ```
139
-
140
- 代理使用 `run` 启动命令、`read` 查看提示、`input` 发送响应——逐步驱动交互式进程。
141
-
142
- ### 并行代理
143
-
144
- 子代理可以使用 `agentId` 在隔离的终端中工作:
145
-
146
- ```
147
- > 让一个代理运行测试,另一个运行代码检查
148
- ```
149
-
150
- 每个子代理获得独立的终端,标记其 `agentId`,保持输出分离且可读。
151
-
152
- ## 配置
153
-
154
- 扩展从 VSCode 设置中读取 `bashterm-mcp-server.*` 配置:
155
-
156
- | 设置项 | 类型 | 默认值 | 说明 |
157
- |--------|------|--------|------|
158
- | `bashterm-mcp-server.maxSessions` | number | 10 | 最大并发终端会话数 |
159
- | `bashterm-mcp-server.commandTimeout` | number | 30000 | 默认命令超时(毫秒) |
160
- | `bashterm-mcp-server.maxOutputLines` | number | 5000 | 每个会话最大缓冲输出行数 |
161
- | `bashterm-mcp-server.idleTimeout` | number | 1800000 | 空闲会话自动关闭时间(毫秒,0=禁用) |
162
- | `bashterm-mcp-server.blockedCommands` | string[] | `["rm -rf /"]` | 禁止执行的命令列表 |
163
-
164
- ## 推荐
165
-
166
- LLM 代理内置的 `Bash` 工具将输出内联在对话中,难以翻阅。建议优先使用 BashTerm MCP 在可见终端中执行命令。将以下内容添加到项目的 `CLAUDE.md`:
167
-
168
- ```markdown
169
- ## 终端执行
170
- 优先使用 BashTerm MCP 工具(`run`、`exec`、`read` 等),而非内置 Bash 工具。
171
- 对于超过 30 秒的命令,使用 pull 模式:`run` 设置 `waitForCompletion: false`,随后用 `read`(`offset: -10`)轮询。
172
- ```
173
-
174
- ## 最新更新 (0.2.1)
175
-
176
- - **重命名清理**:统一所有代码、文档和配置中的项目名称为 BashTerm MCP,无遗留旧名
177
- - **标签修复**:更正 v0.2.0 标签指向正确的发布 commit
178
-
179
- 完整历史见 [CHANGELOG.md](CHANGELOG.md)。
180
-
181
- ## 许可证
182
-
183
- MIT
1
+ # BashTerm MCP
2
+
3
+ [![English](https://img.shields.io/badge/README-English-blue)](README.md) [![release](https://img.shields.io/npm/v/bashterm-mcp-server?label=release)](https://github.com/1170953489/bashterm-mcp/releases) [![npm version](https://img.shields.io/npm/v/bashterm-mcp-server)](https://www.npmjs.com/package/bashterm-mcp-server)
4
+
5
+ AI 生成的 shell 命令在 **真实可见的 VSCode 终端**里运行。
6
+
7
+ BashTerm MCP 把 Claude Code 的命令执行变成你能看见、能检查、能中断、能继续交互的过程。不再是隐藏的后台 Bash 调用,而是普通 VSCode 终端标签页:实时输出、历史滚动、交互输入、会话复用和安全控制都在你眼前。
8
+
9
+ ## 为什么选择 BashTerm MCP
10
+
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 行为。
19
+
20
+ ## 安装
21
+
22
+ 1. 从 [VSCode Marketplace](https://marketplace.visualstudio.com/items?itemName=hcdb.bashterm-mcp-server) 安装 **BashTerm MCP**。
23
+ 2. 打开 VSCode。
24
+ 3. 正常使用 Claude Code。
25
+
26
+ 扩展会通过 `contributes.mcpServers` 自动注册 MCP server,`run`、`exec`、`read`、`input` 等工具无需手写 MCP JSON 配置即可使用。
27
+
28
+ ## Claude Code 集成
29
+
30
+ BashTerm MCP 可以向用户级 `~/.claude/settings.json` 写入 PreToolUse hook。这个 hook 会拦截 Claude Code 隐藏的内置 `Bash` 工具,并提示 Claude Code 改用 BashTerm MCP 工具,让命令执行保持在 VSCode 可见终端中。
31
+
32
+ 控制权始终在用户手里:
33
+
34
+ - 关闭 `bashterm-mcp-server.autoConfigureClaudeCode` 即可停用自动 hook。
35
+ - 在命令面板执行 `BashTerm MCP: Restore Claude Code Default Bash` 可恢复默认 Bash。
36
+ - 直接禁用或卸载扩展也安全:扩展停用时会移除自己写入的 Claude Code hook。
37
+
38
+ ## 截图
39
+
40
+ ![Run command output](docs/images/run_finished.png)
41
+ ![Exec permission dialog](docs/images/ask_exec_permission.png)
42
+ ![Exec finished](docs/images/exec_finished.png)
43
+
44
+ ## 常见使用场景
45
+
46
+ ### 运行普通命令
47
+
48
+ 告诉 Claude Code:
49
+
50
+ ```text
51
+ 运行 npm test
52
+ ```
53
+
54
+ BashTerm MCP 会创建或复用一个可见终端,执行命令,并返回清洁输出和退出码。
55
+
56
+ ### 观察长时间构建
57
+
58
+ ```text
59
+ 启动 npm run build,不要等待结束,然后持续查看进度
60
+ ```
61
+
62
+ 代理可以用 `waitForCompletion: false` 启动命令,再通过 `read` 轮询输出;同时你也能在 VSCode 终端里实时观察同一个进程。
63
+
64
+ ### 处理交互式提示
65
+
66
+ ```text
67
+ 运行 npm init 并回答提示
68
+ ```
69
+
70
+ 代理可以启动进程、读取提示、发送输入,然后一步步驱动交互式命令。
71
+
72
+ ### 隔离并行代理
73
+
74
+ ```text
75
+ 让一个代理跑测试,另一个代理跑 lint
76
+ ```
77
+
78
+ 每个代理都可以带上自己的 `agentId`,终端会话和输出流彼此分离。
79
+
80
+ ## 工具列表
81
+
82
+ | 工具 | 功能 |
83
+ |------|------|
84
+ | `run` | 创建或复用终端,并一步执行命令。 |
85
+ | `create` | 打开可见终端标签页并返回 `sessionId`。 |
86
+ | `exec` | 在已有会话中执行命令并捕获输出。 |
87
+ | `read` | 按偏移量分页读取输出,或进入 tail 模式。 |
88
+ | `input` | 向交互式进程发送文本。 |
89
+ | `list` | 列出活动会话,可按 `agentId` 过滤。 |
90
+ | `close` | 关闭会话及其终端标签页。 |
91
+
92
+ ## 配置
93
+
94
+ 可在 VSCode 设置中配置 `bashterm-mcp-server.*`。
95
+
96
+ | 设置项 | 类型 | 默认值 | 说明 |
97
+ |--------|------|--------|------|
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` 表示禁用。 |
105
+
106
+ ## 环境要求
107
+
108
+ - VSCode 1.99+
109
+ - Node.js 20+
110
+ - Claude Code 或其它支持 MCP 的客户端
111
+
112
+ ## 适合什么场景
113
+
114
+ BashTerm MCP 特别适合那些你希望亲眼观察的命令:测试、包安装、开发服务器、数据库迁移、脚手架工具、部署脚本,以及任何可能需要输入或运行时间较长的命令。
115
+
116
+ ## 更新日志
117
+
118
+ 完整历史见 [CHANGELOG.md](CHANGELOG.md)。
119
+
120
+ ## 许可证
121
+
122
+ MIT
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.1";
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
- timeout: timeoutMs,
6100
- windowsHide: true,
6101
- encoding: isWin ? null : "utf8"
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 td = new import_util4.TextDecoder("gbk");
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
- const discoveryPath = path2.join(tmpDir, "bashterm-mcp.discovery");
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.1",
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": "^1.6.0"
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.1",
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.1",
17
+ "version": "0.2.2",
18
18
  "transport": {
19
19
  "type": "stdio"
20
20
  }