opencode-diff-viewer 1.0.7 → 1.0.8

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.
Files changed (3) hide show
  1. package/README.md +44 -57
  2. package/dist/index.js +72 -31
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -3,44 +3,38 @@
3
3
  [![npm version](https://img.shields.io/npm/v/opencode-diff-viewer.svg)](https://www.npmjs.com/package/opencode-diff-viewer)
4
4
  [![npm downloads](https://img.shields.io/npm/dm/opencode-diff-viewer.svg)](https://www.npmjs.com/package/opencode-diff-viewer)
5
5
 
6
- 一个 OpenCode 插件,使用 [lumen](https://github.com/jnsahaj/lumen) 提供美观的 TUI diff 查看功能。
6
+ 一个 OpenCode 插件,使用 [lumen](https://github.com/jnsahaj/lumen) + [tmux](https://github.com/tmux/tmux) 提供美观的 TUI diff 查看功能。
7
7
 
8
8
  ## 功能特性
9
9
 
10
- - ✨ **自动安装 lumen** - 插件会自动检测并安装 lumen 依赖
10
+ - ✨ **自动安装 tmux 和 lumen** - 插件会自动检测并安装依赖
11
11
  - 🚀 **一键查看 diff** - 使用 `/diff` 命令快速查看代码变更
12
- - 🔧 **智能终端适配** - 自动检测操作系统,打开新终端窗口展示 diff
12
+ - 🔧 **tmux 集成** - 在后台 tmux 会话中运行 lumen
13
13
  - 🤖 **LLM 工具集成** - LLM 可自动调用 `view_diff` 工具
14
14
 
15
15
  ## 前置条件
16
16
 
17
- ### 1. 安装 lumen
17
+ ### 自动安装
18
18
 
19
- 插件会自动尝试安装 lumen,如果自动安装失败,需要手动安装:
19
+ 插件会在启动时自动检查并安装以下依赖:
20
20
 
21
- **macOS / Linux (Homebrew)**:
22
- ```bash
23
- brew install jnsahaj/lumen/lumen
24
- ```
21
+ 1. **tmux** - 终端复用器
22
+ 2. **lumen** - TUI diff 查看器
25
23
 
26
- **Bun**:
27
- ```bash
28
- bun install jnsahaj/lumen/lumen
29
- ```
24
+ ### 手动安装(如果自动安装失败)
30
25
 
31
- **Cargo (Rust)**:
26
+ **tmux**:
32
27
  ```bash
33
- cargo install lumen
28
+ brew install tmux
29
+ # or
30
+ apt install tmux
34
31
  ```
35
32
 
36
- **Windows**:
37
- 下载 [lumen releases](https://github.com/jnsahaj/lumen/releases) 并添加到 PATH
38
-
39
- ### 2. Git 仓库
40
-
41
- 确保项目是 git 仓库,并且有修改的文件:
33
+ **lumen**:
42
34
  ```bash
43
- git status # 查看修改的文件
35
+ brew install jnsahaj/lumen/lumen
36
+ # or
37
+ cargo install lumen
44
38
  ```
45
39
 
46
40
  ## 安装(全局配置)
@@ -68,7 +62,7 @@ cat > ~/.config/opencode/opencode.json << 'EOF'
68
62
  {
69
63
  "command": {
70
64
  "diff": {
71
- "template": "View git diff using lumen TUI.",
65
+ "template": "View git diff using lumen in tmux.",
72
66
  "description": "View diff of modified files using lumen TUI"
73
67
  }
74
68
  },
@@ -96,10 +90,19 @@ EOF
96
90
 
97
91
  LLM 可以自动调用 `view_diff` 工具来展示代码变更。无需手动操作,LLM 会根据对话上下文智能判断何时需要展示 diff。
98
92
 
99
- ## lumen 快捷键
93
+ ### 查看 lumen
94
+
95
+ 执行 `/diff` 后,lumen 会在 tmux 会话中运行。要查看 lumen:
96
+
97
+ ```bash
98
+ tmux attach -t opencode-diff-viewer
99
+ ```
100
100
 
101
- lumen diff 查看器中:
101
+ **tmux 快捷键**:
102
+ - `Ctrl+B` 然后 `D` - 分离会话(回到 OpenCode)
103
+ - `Ctrl+B` 然后 `?` - 查看所有快捷键
102
104
 
105
+ **lumen 快捷键**:
103
106
  | 快捷键 | 功能 |
104
107
  |--------|------|
105
108
  | `j` / `k` 或 `↑` / `↓` | 上/下移动 |
@@ -110,15 +113,23 @@ LLM 可以自动调用 `view_diff` 工具来展示代码变更。无需手动操
110
113
 
111
114
  ## 故障排除
112
115
 
113
- ### 1. lumen 未安装
116
+ ### 1. tmux 未安装
117
+
118
+ ```
119
+ ❌ tmux is not installed
120
+ ```
121
+
122
+ **解决方案**: 手动安装 tmux(见上方手动安装)
123
+
124
+ ### 2. lumen 未安装
114
125
 
115
126
  ```
116
127
  ❌ lumen is not installed
117
128
  ```
118
129
 
119
- **解决方案**: 手动安装 lumen(见上方前置条件)
130
+ **解决方案**: 手动安装 lumen(见上方手动安装)
120
131
 
121
- ### 2. 没有修改的文件
132
+ ### 3. 没有修改的文件
122
133
 
123
134
  ```
124
135
  📝 No modified files
@@ -129,12 +140,6 @@ LLM 可以自动调用 `view_diff` 工具来展示代码变更。无需手动操
129
140
  git add .
130
141
  ```
131
142
 
132
- ### 3. 新终端未打开
133
-
134
- 检查终端模拟器是否支持:
135
- - macOS: Terminal.app
136
- - Linux: gnome-terminal 或 xterm
137
-
138
143
  ### 4. 插件未加载
139
144
 
140
145
  检查全局配置文件是否正确:
@@ -142,24 +147,12 @@ git add .
142
147
  cat ~/.config/opencode/opencode.json
143
148
  ```
144
149
 
145
- 确保配置正确:
146
- ```json
147
- {
148
- "command": {
149
- "diff": {
150
- "template": "View git diff using lumen TUI.",
151
- "description": "View diff of modified files using lumen TUI"
152
- }
153
- },
154
- "plugin": ["opencode-diff-viewer"]
155
- }
156
- ```
157
-
158
150
  ## 工作原理
159
151
 
160
- 1. **检测修改文件** - 插件使用 `git diff` 获取已暂存和未暂存的修改
161
- 2. **启动 lumen** - 在新终端窗口中运行 `lumen diff --file <files>`
162
- 3. **自动安装** - 插件启动时检查 lumen,未安装则自动安装
152
+ 1. **检测依赖** - 插件启动时检查 tmux lumen
153
+ 2. **自动安装** - 如果未安装,自动通过 brew cargo 安装
154
+ 3. **创建 tmux 会话** - 执行 `/diff` 时创建后台 tmux 会话
155
+ 4. **运行 lumen** - 在 tmux 会话中运行 lumen diff
163
156
 
164
157
  ## 项目结构
165
158
 
@@ -184,18 +177,11 @@ cd opencode-diff-viewer
184
177
 
185
178
  # 安装依赖
186
179
  npm install
187
- # 或
188
- pnpm install
189
- # 或
190
- bun install
191
180
 
192
181
  # 构建
193
182
  npm run build
194
183
 
195
184
  # 链接本地包
196
- npm link
197
-
198
- # 在全局使用
199
185
  npm link -g opencode-diff-viewer
200
186
  ```
201
187
 
@@ -213,6 +199,7 @@ npm publish
213
199
 
214
200
  ## 依赖
215
201
 
202
+ - [tmux](https://github.com/tmux/tmux) - 终端复用器
216
203
  - [lumen](https://github.com/jnsahaj/lumen) - TUI Diff 查看器
217
204
  - [@opencode-ai/plugin](https://www.npmjs.com/package/@opencode-ai/plugin) - OpenCode 插件 SDK
218
205
 
package/dist/index.js CHANGED
@@ -9,6 +9,15 @@ export const DiffViewerPlugin = async ({ project, client, $, directory, worktree
9
9
  return false;
10
10
  }
11
11
  };
12
+ const isTmuxInstalled = async () => {
13
+ try {
14
+ await $ `which tmux`;
15
+ return true;
16
+ }
17
+ catch {
18
+ return false;
19
+ }
20
+ };
12
21
  const isBrewInstalled = async () => {
13
22
  try {
14
23
  await $ `which brew`;
@@ -51,6 +60,21 @@ export const DiffViewerPlugin = async ({ project, client, $, directory, worktree
51
60
  error: "Neither brew nor cargo available. Please install lumen manually:\n brew install jnsahaj/lumen/lumen\n # or\n cargo install lumen"
52
61
  };
53
62
  };
63
+ const installTmux = async () => {
64
+ if (await isBrewInstalled()) {
65
+ try {
66
+ await $ `brew install tmux`;
67
+ return { success: true, method: "brew" };
68
+ }
69
+ catch (e) {
70
+ console.warn(`brew install tmux failed: ${e}`);
71
+ }
72
+ }
73
+ return {
74
+ success: false,
75
+ error: "Please install tmux manually:\n brew install tmux\n # or\n apt install tmux"
76
+ };
77
+ };
54
78
  const ensureLumenInstalled = async () => {
55
79
  if (await isLumenInstalled()) {
56
80
  return { installed: true };
@@ -61,7 +85,25 @@ export const DiffViewerPlugin = async ({ project, client, $, directory, worktree
61
85
  }
62
86
  return { installed: false, message: `❌ ${result.error}` };
63
87
  };
64
- await ensureLumenInstalled();
88
+ const ensureTmuxInstalled = async () => {
89
+ if (await isTmuxInstalled()) {
90
+ return { installed: true };
91
+ }
92
+ const result = await installTmux();
93
+ if (result.success) {
94
+ return { installed: true, message: `✅ tmux installed via ${result.method}` };
95
+ }
96
+ return { installed: false, message: `❌ ${result.error}` };
97
+ };
98
+ // Check and install dependencies on startup
99
+ const tmuxCheck = await ensureTmuxInstalled();
100
+ if (!tmuxCheck.installed) {
101
+ console.warn(tmuxCheck.message);
102
+ }
103
+ const lumenCheck = await ensureLumenInstalled();
104
+ if (!lumenCheck.installed) {
105
+ console.warn(lumenCheck.message);
106
+ }
65
107
  const getModifiedFiles = async () => {
66
108
  try {
67
109
  const unstaged = await $ `git diff --name-only`.text();
@@ -77,6 +119,18 @@ export const DiffViewerPlugin = async ({ project, client, $, directory, worktree
77
119
  }
78
120
  };
79
121
  const launchDiffViewer = async (files) => {
122
+ // Check tmux
123
+ if (!await isTmuxInstalled()) {
124
+ return `❌ tmux is not installed.
125
+
126
+ To install:
127
+ brew install tmux
128
+ # or
129
+ apt install tmux
130
+
131
+ Then restart OpenCode.`;
132
+ }
133
+ // Check lumen
80
134
  if (!await isLumenInstalled()) {
81
135
  return `❌ lumen is not installed.
82
136
 
@@ -93,40 +147,27 @@ Then restart OpenCode.`;
93
147
  }
94
148
  const fileList = modifiedFiles.map(f => ` • ${f}`).join('\n');
95
149
  const fileArgs = modifiedFiles.map(f => `"${f}"`).join(' ');
150
+ const sessionName = "opencode-diff-viewer";
96
151
  const cmd = `cd "${directory}" && lumen diff ${fileArgs}`;
97
- const platform = process.platform;
98
- // Try to launch in new terminal
99
- let launched = false;
100
- let errorMsg = "";
101
152
  try {
102
- if (platform === 'darwin') {
103
- await $ `osascript -e 'tell application "Terminal" to do script "${cmd}; exit"'`;
104
- launched = true;
105
- }
106
- else if (platform === 'linux') {
107
- try {
108
- await $ `which gnome-terminal && gnome-terminal -- bash -c "${cmd}; read -p 'Press Enter to close...'" `;
109
- launched = true;
110
- }
111
- catch {
112
- try {
113
- await $ `which xterm && xterm -e "bash -c '${cmd}; read -p Press Enter to close...'" `;
114
- launched = true;
115
- }
116
- catch (e) {
117
- errorMsg = "No terminal emulator found (gnome-terminal/xterm)";
118
- }
119
- }
120
- }
153
+ // Kill existing session if it exists
154
+ await $ `tmux kill-session -t "${sessionName}" 2>/dev/null || true`;
155
+ // Create new tmux session
156
+ await $ `tmux new-session -d -s "${sessionName}" "${cmd}"`;
157
+ return `✅ Opened lumen in tmux session "${sessionName}":\n${fileList}\n\nTo use lumen:
158
+ 1. Run: tmux attach -t "${sessionName}"
159
+ 2. Navigate: j/k or arrows, {/} for hunks
160
+ 3. Detach: Ctrl+B then D
161
+
162
+ Keybindings:
163
+ j/k or ↑/↓: Navigate {/}: Jump hunks
164
+ tab: Sidebar e: Edit file
165
+ q: Quit`;
121
166
  }
122
167
  catch (e) {
123
- errorMsg = e.message || "Unknown error";
124
- }
125
- if (launched) {
126
- return `✅ Opened lumen diff viewer:\n${fileList}\n\nKeybindings:\n j/k: Navigate {/}: Jump hunks tab: Sidebar e: Edit q: Quit`;
168
+ return `❌ Failed to launch tmux session: ${e.message || e}\n\nTry manually:
169
+ tmux new-session -s "${sessionName}" "${cmd}"`;
127
170
  }
128
- // If we couldn't launch, show manual instructions
129
- return `📺 Could not open terminal automatically.\n\nTo view diffs in lumen:\n1. Open a new terminal\n2. Run:\n ${cmd}\n\nModified files:\n${fileList}`;
130
171
  };
131
172
  return {
132
173
  "tui.command.execute": async (input, output) => {
@@ -141,7 +182,7 @@ Then restart OpenCode.`;
141
182
  },
142
183
  tool: {
143
184
  view_diff: tool({
144
- description: "Open the lumen diff viewer to show git diff for modified files.",
185
+ description: "Open the lumen diff viewer in a tmux session.",
145
186
  args: {
146
187
  file: tool.schema.string().optional().describe("Optional: specific file path"),
147
188
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-diff-viewer",
3
- "version": "1.0.7",
3
+ "version": "1.0.8",
4
4
  "description": "OpenCode plugin for viewing git diffs using lumen TUI",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",