aiterm-mcp 0.2.0 → 0.3.1
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/README.ja.md +78 -1
- package/README.md +78 -1
- package/dist/core.js +59 -2
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/README.ja.md
CHANGED
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
[](https://www.npmjs.com/package/aiterm-mcp)
|
|
9
9
|
[](https://nodejs.org)
|
|
10
10
|
[](LICENSE)
|
|
11
|
+
[](https://www.npmjs.com/package/aiterm-mcp)
|
|
12
|
+
[](https://packagephobia.com/result?p=aiterm-mcp)
|
|
11
13
|
|
|
12
14
|
> *(English: [README.md](README.md))*
|
|
13
15
|
|
|
@@ -15,6 +17,31 @@
|
|
|
15
17
|
|
|
16
18
|
`pty_open` / `pty_send` / `pty_read` / `pty_key` / `pty_close` / `pty_list` の 6 ツールだけ。バックエンドは tmux なので、MCP サーバや AI クライアントが再起動してもセッションは生き残る。
|
|
17
19
|
|
|
20
|
+
## クイックスタート(約60秒)
|
|
21
|
+
|
|
22
|
+
Claude Code なら 1 コマンドで登録 — clone もビルドも不要、`npx` が毎回取得して起動する:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
claude mcp add --scope user --transport stdio aiterm -- npx -y aiterm-mcp
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Claude Code を再起動して、接続を確認:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
/mcp # aiterm が connected・6 ツール公開、と出る
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
最初のセッション — 4 回の呼び出しで、1 個の永続端末:
|
|
35
|
+
|
|
36
|
+
```text
|
|
37
|
+
pty_open() → { session_id: "t1", attach: "tmux -S … attach -t t1" }
|
|
38
|
+
pty_send("t1", "echo hello") → PTY にコマンドを送る
|
|
39
|
+
pty_read("t1", { wait: true }) → "hello" (トークン削減・完了検出つき)
|
|
40
|
+
pty_close("t1") → 端末を解放
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
これだけ。`t1` の端末は本物で永続 — `ssh`・`docker exec`・REPL は、そこへ `pty_send` で打ち込む“ただのテキスト”([なぜ](#なぜ))。インストールも不要にしたいなら、どの MCP クライアントからでも stdio で `npx -y aiterm-mcp` を起動するだけ。
|
|
44
|
+
|
|
18
45
|
## インストール
|
|
19
46
|
|
|
20
47
|
npm に公開済み。clone もビルドも不要:
|
|
@@ -41,6 +68,43 @@ pty_send(id, "uname -a") → リモートで実行
|
|
|
41
68
|
pty_read(id, { wait: true }) → 削減済みの出力を読む
|
|
42
69
|
```
|
|
43
70
|
|
|
71
|
+
## デモ
|
|
72
|
+
|
|
73
|
+
<!-- demo gif: drop docs/demo.gif here (asciinema cast or animated GIF of the flow below) -->
|
|
74
|
+
|
|
75
|
+
決め手の流れ: PTY を 1 個開き、その**中で** SSH にネストし、リモートでコマンドを実行し、**すでにトークン削減された**出力を読む — コマンドごとの接続し直しは無い。
|
|
76
|
+
|
|
77
|
+
```text
|
|
78
|
+
# 1 — ローカル端末を 1 個握る(tmux 上・再起動を跨ぐ)
|
|
79
|
+
→ pty_open()
|
|
80
|
+
← { session_id: "t1", attach: "tmux -S /…/claude.sock attach -t t1" }
|
|
81
|
+
|
|
82
|
+
# 2 — その同じ端末の中で SSH にネスト(別ツールではない)
|
|
83
|
+
→ pty_send("t1", "ssh 192.168.1.2")
|
|
84
|
+
← sent
|
|
85
|
+
→ pty_read("t1", { until: "\\$ $" }) # リモートのプロンプト = 「シェルに戻った」
|
|
86
|
+
← user@remote:~$
|
|
87
|
+
|
|
88
|
+
# 3 — 同じ PTY のまま、リモートでコマンド実行(接続し直し無し)
|
|
89
|
+
→ pty_send("t1", "uname -a")
|
|
90
|
+
→ pty_read("t1", { until: "\\$ $" })
|
|
91
|
+
← Linux remote 6.1.0 #1 SMP x86_64 GNU/Linux
|
|
92
|
+
|
|
93
|
+
# 4 — ノイズの多いコマンドを、コマンド別 reducer で読む
|
|
94
|
+
→ pty_send("t1", "git status")
|
|
95
|
+
→ pty_read("t1", { until: "\\$ $", rtk: true }) # 自前実装・rtk バイナリ不要
|
|
96
|
+
← ## main…origin/main [ahead 1]
|
|
97
|
+
M src/core.ts
|
|
98
|
+
?? notes.txt
|
|
99
|
+
[reduced: 制御文字除去 · 重複圧縮 · git-status reducer]
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
この流れが「デモのための嘘」にならない理由:
|
|
103
|
+
|
|
104
|
+
- ステップ 2/3 が **`until`**(リモートのプロンプト)を使うのは、**ネスト中は quiescence が原理的に効かない**ため([完了検出](#完了検出4-層) / [既知の制約](#既知の制約バグではなく仕様))。ローカルシェルなら `{ wait: true }` だけで足りるが、ネスト中は `until`(または `mark: true`)が要る。
|
|
105
|
+
- 角括弧の `[reduced: …]` 行は `pty_read` が付けるメタ/復元ヒントの例示で、実際の文言は出力に応じて変わる。reducer は **自前実装**の `pty_read({ rtk: true })` 経路で、外部 `rtk` バイナリは不要。
|
|
106
|
+
- `t1` のソケットに人が `attach` すれば、同じ SSH セッションをライブで覗ける([人が覗く](#人が覗く))。
|
|
107
|
+
|
|
44
108
|
## 仕組み
|
|
45
109
|
|
|
46
110
|
```mermaid
|
|
@@ -67,7 +131,7 @@ flowchart LR
|
|
|
67
131
|
|
|
68
132
|
- **Node.js >= 18**
|
|
69
133
|
- **tmux**(実行時の前提。`tmux -V` で確認。未導入なら `apt install tmux` / `brew install tmux`)
|
|
70
|
-
- **macOS / Linux / WSL2** は tmux を直接使う。
|
|
134
|
+
- **macOS / Linux / WSL2** は tmux を直接使う。macOS は同梱されないので `brew install tmux` で導入する。MCP クライアントがターミナルでなく **GUI から起動**された場合、Homebrew の bin(Apple Silicon: `/opt/homebrew/bin`、Intel: `/usr/local/bin`)が `PATH` に入らないことがある。その場合 aiterm が自動で探索するか、**`AITERM_TMUX=/path/to/tmux`** で明示指定する。
|
|
71
135
|
- **Windows ネイティブ**には tmux が無いため、aiterm は裏で **WSL の中の tmux** を透過的に使う。[WSL](https://learn.microsoft.com/ja-jp/windows/wsl/) を導入・初期化し、**WSL のディストリ内に tmux を入れる**こと(`sudo apt install tmux`)。`wsl tmux -V` で確認できる。セッション・ソケット・人の `attach` はすべて WSL 側にあり、AI は Windows 側のコマンドから操作するだけ。(Windows のツールは SSH と同じく入れ子で握る: `pty_send "powershell.exe …"` で PowerShell に入る。)
|
|
72
136
|
- 任意: [`rtk`](https://github.com/rtk-ai/rtk) バイナリ(`pty_send` の `rtk: true` 委譲で使う。無くても動く)
|
|
73
137
|
|
|
@@ -138,6 +202,19 @@ npm link # ローカルで `aiterm-mcp` を PATH に
|
|
|
138
202
|
|
|
139
203
|
ロジックは `src/core.ts`(tmux 制御・削減・完了検出・安全)と `src/rtk.ts`(コマンド別 reducer)、公開は `src/index.ts`。設計の出発点と reducer の移植元(pytest reducer は本家 rtk 0.42.0 と出力が byte 一致するよう移植・回帰テストで固定)は `prototype/python/` を参照。
|
|
140
204
|
|
|
205
|
+
## 試す
|
|
206
|
+
|
|
207
|
+
1 コマンド、clone もビルドも不要:
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
claude mcp add --scope user --transport stdio aiterm -- npx -y aiterm-mcp
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
aiterm がトークンの往復を 1 回でも省けたなら、**[リポジトリに star](https://github.com/kitepon-rgb/aiterm-mcp)** を — 他の人に見つけてもらう一番安い方法です。
|
|
214
|
+
|
|
215
|
+
- **npm:** https://www.npmjs.com/package/aiterm-mcp
|
|
216
|
+
- **Issue / バグ報告:** https://github.com/kitepon-rgb/aiterm-mcp/issues
|
|
217
|
+
|
|
141
218
|
## ライセンス
|
|
142
219
|
|
|
143
220
|
MIT
|
package/README.md
CHANGED
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
[](https://www.npmjs.com/package/aiterm-mcp)
|
|
9
9
|
[](https://nodejs.org)
|
|
10
10
|
[](LICENSE)
|
|
11
|
+
[](https://www.npmjs.com/package/aiterm-mcp)
|
|
12
|
+
[](https://packagephobia.com/result?p=aiterm-mcp)
|
|
11
13
|
|
|
12
14
|
> *(日本語: [README.ja.md](README.ja.md))*
|
|
13
15
|
|
|
@@ -15,6 +17,31 @@
|
|
|
15
17
|
|
|
16
18
|
Just six tools — `pty_open` / `pty_send` / `pty_read` / `pty_key` / `pty_close` / `pty_list`. The backend is **tmux**, so sessions survive even if the MCP server or the AI client restarts.
|
|
17
19
|
|
|
20
|
+
## Quickstart (≈60 seconds)
|
|
21
|
+
|
|
22
|
+
One command registers it in Claude Code — no clone, no build, `npx` fetches it each run:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
claude mcp add --scope user --transport stdio aiterm -- npx -y aiterm-mcp
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Restart Claude Code, then verify the connection:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
/mcp # aiterm should show as connected, exposing 6 tools
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Your first session — four calls, one persistent terminal:
|
|
35
|
+
|
|
36
|
+
```text
|
|
37
|
+
pty_open() → { session_id: "t1", attach: "tmux -S … attach -t t1" }
|
|
38
|
+
pty_send("t1", "echo hello") → command sent into the PTY
|
|
39
|
+
pty_read("t1", { wait: true }) → "hello" (token-reduced, completion detected)
|
|
40
|
+
pty_close("t1") → terminal released
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
That's it. The terminal in `t1` is real and persistent — `ssh`, `docker exec`, a REPL are just text you `pty_send` into it (see [Why](#why)). Prefer no install? Any MCP client can launch `npx -y aiterm-mcp` over stdio directly.
|
|
44
|
+
|
|
18
45
|
## Install
|
|
19
46
|
|
|
20
47
|
It's on npm — no clone, no build:
|
|
@@ -41,6 +68,43 @@ pty_send(id, "uname -a") → run it on the remote
|
|
|
41
68
|
pty_read(id, { wait: true }) → read the reduced output
|
|
42
69
|
```
|
|
43
70
|
|
|
71
|
+
## Demo
|
|
72
|
+
|
|
73
|
+
<!-- demo gif: drop docs/demo.gif here (asciinema cast or animated GIF of the flow below) -->
|
|
74
|
+
|
|
75
|
+
The killer flow: open one PTY, nest into SSH *inside it*, run a command on the remote, and read back output that's already been token-reduced — no reconnect per command.
|
|
76
|
+
|
|
77
|
+
```text
|
|
78
|
+
# 1 — grab one local terminal (lives in tmux; survives restarts)
|
|
79
|
+
→ pty_open()
|
|
80
|
+
← { session_id: "t1", attach: "tmux -S /…/claude.sock attach -t t1" }
|
|
81
|
+
|
|
82
|
+
# 2 — nest SSH *inside* that same terminal (not a separate tool)
|
|
83
|
+
→ pty_send("t1", "ssh 192.168.1.2")
|
|
84
|
+
← sent
|
|
85
|
+
→ pty_read("t1", { until: "\\$ $" }) # remote prompt = "shell is back"
|
|
86
|
+
← user@remote:~$
|
|
87
|
+
|
|
88
|
+
# 3 — run a command on the remote, over the SAME PTY (no reconnect)
|
|
89
|
+
→ pty_send("t1", "uname -a")
|
|
90
|
+
→ pty_read("t1", { until: "\\$ $" })
|
|
91
|
+
← Linux remote 6.1.0 #1 SMP x86_64 GNU/Linux
|
|
92
|
+
|
|
93
|
+
# 4 — a noisy command, read with the per-command reducer
|
|
94
|
+
→ pty_send("t1", "git status")
|
|
95
|
+
→ pty_read("t1", { until: "\\$ $", rtk: true }) # self-contained, no rtk binary needed
|
|
96
|
+
← ## main…origin/main [ahead 1]
|
|
97
|
+
M src/core.ts
|
|
98
|
+
?? notes.txt
|
|
99
|
+
[reduced: control chars stripped · repeats collapsed · git-status reducer]
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Notes that make this accurate, not a demo lie:
|
|
103
|
+
|
|
104
|
+
- Step 2/3 use **`until`** with the remote prompt because **while nested, quiescence cannot fire by design** — see [Completion detection](#completion-detection-4-layers) and [Known constraints](#known-constraints-by-design-not-bugs). `{ wait: true }` alone works at the local shell; nested needs `until` (or `mark: true`).
|
|
105
|
+
- The bracketed `[reduced: …]` line is illustrative of the meta/restore hint `pty_read` appends; the exact text comes from your output. The reducer is the **self-contained** `pty_read({ rtk: true })` path — no external `rtk` binary required.
|
|
106
|
+
- A human can `attach` to the `t1` socket and watch the same SSH session live (see [A human can watch](#a-human-can-watch)).
|
|
107
|
+
|
|
44
108
|
## How it works
|
|
45
109
|
|
|
46
110
|
```mermaid
|
|
@@ -67,7 +131,7 @@ One PTY is the only primitive. Everything else — SSH, containers, REPLs — is
|
|
|
67
131
|
|
|
68
132
|
- **Node.js >= 18**
|
|
69
133
|
- **tmux** (runtime prerequisite; check with `tmux -V`. Install with `apt install tmux` / `brew install tmux`)
|
|
70
|
-
- **macOS / Linux / WSL2** run tmux directly.
|
|
134
|
+
- **macOS / Linux / WSL2** run tmux directly. On macOS install it with `brew install tmux` (stock macOS ships none). If your MCP client is launched from the **GUI** rather than a terminal, Homebrew's bin (`/opt/homebrew/bin` on Apple Silicon, `/usr/local/bin` on Intel) may be off its `PATH`; aiterm auto-searches those locations, or set **`AITERM_TMUX=/path/to/tmux`** to point at it explicitly.
|
|
71
135
|
- **Native Windows** has no tmux, so aiterm transparently runs tmux **inside WSL**. It needs [WSL](https://learn.microsoft.com/windows/wsl/) installed and initialized, with **tmux installed inside your WSL distro** (`sudo apt install tmux`); verify with `wsl tmux -V`. Sessions, the socket, and human `attach` all live on the WSL side — the AI just drives them from the Windows-side command. (You reach Windows tools the same way you reach SSH: `pty_send "powershell.exe …"` nests into PowerShell.)
|
|
72
136
|
- Optional: the [`rtk`](https://github.com/rtk-ai/rtk) binary (used by `pty_send`'s `rtk: true` delegation; works fine without it)
|
|
73
137
|
|
|
@@ -138,6 +202,19 @@ npm link # put `aiterm-mcp` on PATH locally
|
|
|
138
202
|
|
|
139
203
|
Logic lives in `src/core.ts` (tmux control, reduction, completion detection, safety) and `src/rtk.ts` (per-command reducers); `src/index.ts` is the MCP surface. The design origin and the reducer's porting source (the pytest reducer is ported to be byte-exact with upstream rtk 0.42.0, locked by regression tests) are in `prototype/python/`.
|
|
140
204
|
|
|
205
|
+
## Try it
|
|
206
|
+
|
|
207
|
+
One command, no clone, no build:
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
claude mcp add --scope user --transport stdio aiterm -- npx -y aiterm-mcp
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
If aiterm saved you a round-trip of tokens, **[star the repo](https://github.com/kitepon-rgb/aiterm-mcp)** — it's the cheapest way to help others find it.
|
|
214
|
+
|
|
215
|
+
- **npm:** https://www.npmjs.com/package/aiterm-mcp
|
|
216
|
+
- **Issues / bug reports:** https://github.com/kitepon-rgb/aiterm-mcp/issues
|
|
217
|
+
|
|
141
218
|
## License
|
|
142
219
|
|
|
143
220
|
MIT
|
package/dist/core.js
CHANGED
|
@@ -97,6 +97,50 @@ function ensureWinBridge() {
|
|
|
97
97
|
throw new AitermError("WSL 経由で tmux を起動できませんでした。WSL のディストリ未導入、または distro 内に tmux が無い可能性があります。`wsl tmux -V` が通るか確認してください(tmux 導入例: sudo apt install tmux)。", 2);
|
|
98
98
|
winBridgeOk = true;
|
|
99
99
|
}
|
|
100
|
+
// tmux が見つからないときの説明。macOS は tmux を同梱せず、Homebrew の bin は GUI 起動時の PATH に
|
|
101
|
+
// 入らないため、原因と対処(導入・自動探索・AITERM_TMUX 上書き)を正直に提示する。
|
|
102
|
+
function tmuxMissingMessage() {
|
|
103
|
+
const head = "tmux が見つかりません(PATH 上に存在しません)。aiterm は実行時に tmux を必要とします。";
|
|
104
|
+
const hint = process.platform === "darwin"
|
|
105
|
+
? "macOS では `brew install tmux` で導入してください。GUI から起動された場合、Homebrew の bin " +
|
|
106
|
+
"(Apple Silicon: /opt/homebrew/bin、Intel: /usr/local/bin)が PATH に含まれないことがあります" +
|
|
107
|
+
"(その場合 aiterm が自動で探索します)。"
|
|
108
|
+
: "(例: Debian/Ubuntu は `sudo apt install tmux`)。";
|
|
109
|
+
const override = "別の場所にある tmux を使うには AITERM_TMUX=/path/to/tmux を指定してください。";
|
|
110
|
+
return `${head}${hint}${override}`;
|
|
111
|
+
}
|
|
112
|
+
// POSIX(Linux/WSL2/macOS) 用の tmux バイナリ解決。Windows の ensureWinBridge() に対応する事前確認。
|
|
113
|
+
// 解決順: AITERM_TMUX(明示指定)→ PATH 上の tmux → Homebrew 既定パス。一度だけ実行しキャッシュする。
|
|
114
|
+
// 見つからなければ tmuxMissingMessage で投げる(黙ってフォールバックせず、原因が見えるようにする)。
|
|
115
|
+
let tmuxBin = null;
|
|
116
|
+
function resolveTmux() {
|
|
117
|
+
if (tmuxBin)
|
|
118
|
+
return tmuxBin;
|
|
119
|
+
const override = process.env.AITERM_TMUX;
|
|
120
|
+
if (override) {
|
|
121
|
+
const r = spawnSync(override, ["-V"], { encoding: "utf8", timeout: 5000 });
|
|
122
|
+
if (!r.error && r.status === 0)
|
|
123
|
+
return (tmuxBin = override);
|
|
124
|
+
throw new AitermError(`AITERM_TMUX に指定された tmux を起動できません: ${override}(\`${override} -V\` が通りません)`, 2);
|
|
125
|
+
}
|
|
126
|
+
// CLI/開発時は PATH 上の tmux をそのまま使う(最優先)。
|
|
127
|
+
const onPath = spawnSync("tmux", ["-V"], { encoding: "utf8", timeout: 5000 });
|
|
128
|
+
if (!onPath.error && onPath.status === 0)
|
|
129
|
+
return (tmuxBin = "tmux");
|
|
130
|
+
// GUI 起動などで PATH に Homebrew の bin が無い場合、既定の場所を探す。
|
|
131
|
+
// 使う場合は黙らず stderr へ告知する(stdout は JSON-RPC 専用=index.ts の制約)。
|
|
132
|
+
for (const cand of ["/opt/homebrew/bin/tmux", "/usr/local/bin/tmux"]) {
|
|
133
|
+
try {
|
|
134
|
+
fs.accessSync(cand, fs.constants.X_OK);
|
|
135
|
+
console.error(`aiterm: tmux が PATH 上に無いため ${cand} を使用します`);
|
|
136
|
+
return (tmuxBin = cand);
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
/* 次の候補へ */
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
throw new AitermError(tmuxMissingMessage(), 2);
|
|
143
|
+
}
|
|
100
144
|
function tmux(...args) {
|
|
101
145
|
// maxBuffer は既定 1MiB。capture-pane(大きなスクロールバック)や多セッションの list-sessions で
|
|
102
146
|
// 頭打ちになり stdout が切れる/空になる。Python の subprocess.run は無制限だったので 64MiB へ広げる。
|
|
@@ -107,13 +151,20 @@ function tmux(...args) {
|
|
|
107
151
|
r = spawnSync("wsl.exe", ["-e", "tmux", "-S", SOCK, ...args], { encoding: "utf8", maxBuffer: 64 * 1024 * 1024 });
|
|
108
152
|
}
|
|
109
153
|
else {
|
|
110
|
-
|
|
154
|
+
// resolveTmux() は tmux を解決できなければ明確な AitermError を投げる(POSIX 版の事前確認)。
|
|
155
|
+
r = spawnSync(resolveTmux(), ["-S", SOCK, ...args], { encoding: "utf8", maxBuffer: 64 * 1024 * 1024 });
|
|
111
156
|
}
|
|
112
157
|
// ENOBUFS(出力が 64MiB 超)を「code=1 の失敗」へ握り潰すと部分/空 stdout を正常扱いしてしまう。区別して投げる。
|
|
113
158
|
// EXPECTED-FAILURE: 外部システム境界(tmux 出力過大)
|
|
114
159
|
if (r.error && r.error.code === "ENOBUFS") {
|
|
115
160
|
throw new AitermError(`tmux 出力が 64MiB を超えました(${args[0]})。範囲を絞って読んでください。`, 2);
|
|
116
161
|
}
|
|
162
|
+
// 解決済み tmux が実行時に消えた(アンインストール等)場合の ENOENT を、空 stderr の code=1 へ握り潰さない。
|
|
163
|
+
// 通常は resolveTmux() が事前に弾くため発火しないが、mid-run 消滅に対する正直な防御。
|
|
164
|
+
if (!isWin && r.error && r.error.code === "ENOENT") {
|
|
165
|
+
tmuxBin = null; // 次回 resolveTmux で再解決を許す
|
|
166
|
+
throw new AitermError(tmuxMissingMessage(), 2);
|
|
167
|
+
}
|
|
117
168
|
return { code: r.status ?? 1, stdout: r.stdout ?? "", stderr: r.stderr ?? "" };
|
|
118
169
|
}
|
|
119
170
|
function sessionExists(name) {
|
|
@@ -347,7 +398,13 @@ export function openSession(name, shell = "bash") {
|
|
|
347
398
|
assertSessionName(nm);
|
|
348
399
|
if (sessionExists(nm))
|
|
349
400
|
throw new AitermError(`session '${nm}' は既に存在します(list で確認)`, 2);
|
|
350
|
-
|
|
401
|
+
// macOS の /bin/bash は 3.2 で、起動時に zsh 移行バナーを出して最初の read を汚す。darwin かつ bash の
|
|
402
|
+
// ときだけ -e で環境変数を渡して抑止する。-e は tmux>=3.2 が必要だが macOS の Homebrew tmux は常に該当。
|
|
403
|
+
// (古い tmux<3.2 が残る Linux/WSL で -e を渡すと new-session が落ちるため、darwin 限定にする。)
|
|
404
|
+
const banner = process.platform === "darwin" && path.basename(shell) === "bash"
|
|
405
|
+
? ["-e", "BASH_SILENCE_DEPRECATION_WARNING=1"]
|
|
406
|
+
: [];
|
|
407
|
+
const r = tmux("new-session", "-d", "-s", nm, ...banner, "-f", "/dev/null", shell);
|
|
351
408
|
if (r.code !== 0)
|
|
352
409
|
throw new AitermError("tmux new-session 失敗: " + r.stderr.trim(), 2);
|
|
353
410
|
fs.closeSync(fs.openSync(logpath(nm), "a")); // touch
|
package/dist/index.js
CHANGED
|
@@ -12,7 +12,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
12
12
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
13
13
|
import { z } from "zod";
|
|
14
14
|
import * as core from "./core.js";
|
|
15
|
-
const server = new McpServer({ name: "aiterm", version: "0.
|
|
15
|
+
const server = new McpServer({ name: "aiterm", version: "0.3.1" });
|
|
16
16
|
function ok(s) {
|
|
17
17
|
return { content: [{ type: "text", text: s }] };
|
|
18
18
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aiterm-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "AI-driven persistent terminal as a local stdio MCP server (tmux-backed). Holds one local PTY; SSH and containers are just commands you send into it. Token-reducing reads.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mcp",
|