dmux 0.0.1 → 1.0.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/LICENSE +21 -0
- package/README.md +235 -16
- package/dist/DmuxApp.d.ts +10 -0
- package/dist/DmuxApp.d.ts.map +1 -0
- package/dist/DmuxApp.js +503 -0
- package/dist/DmuxApp.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +67 -0
- package/dist/index.js.map +1 -0
- package/dmux +2 -0
- package/package.json +62 -9
- package/index.js +0 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Justin Schroeder
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,29 +1,248 @@
|
|
|
1
|
-
#
|
|
1
|
+
# cmux - AI-Powered tmux Development Sessions
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
cmux is a powerful tmux pane manager that creates parallel development environments with Claude Code AI assistance. Each pane gets its own git worktree and branch, enabling seamless parallel development workflows.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Features
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
- **🚀 Parallel Development**: Work on multiple features simultaneously in separate panes
|
|
8
|
+
- **🌳 Git Worktree Integration**: Each pane operates in its own isolated git worktree
|
|
9
|
+
- **🤖 AI-Powered**: Automatic branch naming and commit message generation
|
|
10
|
+
- **🎯 Claude Code Integration**: Launch Claude with prompts and auto-accept edits
|
|
11
|
+
- **📦 Project Isolation**: Each project gets its own tmux session
|
|
12
|
+
- **🔄 Smart Merging**: One-command merge workflow with automatic cleanup
|
|
8
13
|
|
|
9
|
-
|
|
14
|
+
## Prerequisites
|
|
10
15
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
- **
|
|
14
|
-
- **
|
|
15
|
-
- **
|
|
16
|
-
- **Intelligent merge workflows**: Auto-commits, generates commit messages, and merges worktrees
|
|
17
|
-
- **React-based TUI**: Interactive terminal UI for managing panes
|
|
16
|
+
- **tmux** 3.0 or higher
|
|
17
|
+
- **Node.js** 18 or higher
|
|
18
|
+
- **Git** 2.20 or higher (with worktree support)
|
|
19
|
+
- **Claude Code CLI** (`claude` command must be available)
|
|
20
|
+
- **OpenRouter API Key** (optional but recommended for AI features)
|
|
18
21
|
|
|
19
22
|
## Installation
|
|
20
23
|
|
|
21
|
-
|
|
24
|
+
### 1. Clone and Build
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# Clone the repository
|
|
28
|
+
git clone <repository-url> ~/cmux
|
|
29
|
+
cd ~/cmux
|
|
30
|
+
|
|
31
|
+
# Install dependencies
|
|
32
|
+
npm install
|
|
33
|
+
|
|
34
|
+
# Build the project
|
|
35
|
+
npm run build
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### 2. Global Installation
|
|
39
|
+
|
|
40
|
+
Choose one of these methods:
|
|
41
|
+
|
|
42
|
+
#### Option A: Symlink (Recommended)
|
|
43
|
+
```bash
|
|
44
|
+
# Make the script executable
|
|
45
|
+
chmod +x ~/cmux/cmux
|
|
46
|
+
|
|
47
|
+
# Create symlink in a directory that's in your PATH
|
|
48
|
+
sudo ln -s ~/cmux/cmux /usr/local/bin/cmux
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
#### Option B: Add to PATH
|
|
52
|
+
```bash
|
|
53
|
+
# Add this line to your ~/.bashrc or ~/.zshrc
|
|
54
|
+
export PATH="$PATH:$HOME/cmux"
|
|
55
|
+
|
|
56
|
+
# Reload your shell configuration
|
|
57
|
+
source ~/.bashrc # or ~/.zshrc
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
#### Option C: NPM Global Link
|
|
61
|
+
```bash
|
|
62
|
+
# From the cmux directory
|
|
63
|
+
npm link
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 3. Configure AI Features (Optional)
|
|
67
|
+
|
|
68
|
+
For AI-powered branch naming and commit messages:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
# Add to your ~/.bashrc or ~/.zshrc
|
|
72
|
+
export OPENROUTER_API_KEY="your-api-key-here"
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Get your API key from [OpenRouter](https://openrouter.ai/).
|
|
76
|
+
|
|
77
|
+
## Quick Start
|
|
78
|
+
|
|
79
|
+
### Basic Usage
|
|
80
|
+
|
|
81
|
+
1. **Start cmux in your project**
|
|
82
|
+
```bash
|
|
83
|
+
cd /path/to/your/project
|
|
84
|
+
cmux
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
2. **Create a new development pane**
|
|
88
|
+
- Press `n` or select "+ New cmux pane"
|
|
89
|
+
- Enter an optional prompt like "fix authentication bug"
|
|
90
|
+
- Claude launches in a new pane with your prompt
|
|
91
|
+
|
|
92
|
+
3. **Navigate between panes**
|
|
93
|
+
- Use `↑/↓` arrows to select panes
|
|
94
|
+
- Press `j` or `Enter` to jump to a pane
|
|
95
|
+
|
|
96
|
+
4. **Merge your work**
|
|
97
|
+
- Select the pane you want to merge
|
|
98
|
+
- Press `m` to merge into main branch
|
|
99
|
+
- Confirm to close the pane
|
|
100
|
+
|
|
101
|
+
## Keyboard Shortcuts
|
|
102
|
+
|
|
103
|
+
| Key | Action |
|
|
104
|
+
|-----|--------|
|
|
105
|
+
| `↑/↓` | Navigate pane list |
|
|
106
|
+
| `Enter` or `j` | Jump to selected pane |
|
|
107
|
+
| `n` | Create new cmux pane |
|
|
108
|
+
| `m` | Merge worktree to main |
|
|
109
|
+
| `x` | Close selected pane |
|
|
110
|
+
| `q` | Quit cmux interface |
|
|
111
|
+
| `ESC` | Cancel current dialog |
|
|
112
|
+
|
|
113
|
+
## Example Workflow
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
# Start cmux in your project
|
|
117
|
+
cd ~/projects/my-app
|
|
118
|
+
cmux
|
|
119
|
+
|
|
120
|
+
# Create a pane for a new feature
|
|
121
|
+
# Press 'n', enter: "add user dashboard"
|
|
122
|
+
# Claude opens with your prompt
|
|
123
|
+
|
|
124
|
+
# Create another pane for a bug fix
|
|
125
|
+
# Press 'n', enter: "fix memory leak"
|
|
126
|
+
# Work on both simultaneously
|
|
127
|
+
|
|
128
|
+
# When feature is complete
|
|
129
|
+
# Select the pane, press 'm' to merge
|
|
130
|
+
|
|
131
|
+
# Jump between panes as needed
|
|
132
|
+
# Press 'j' on any pane to switch focus
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## How It Works
|
|
136
|
+
|
|
137
|
+
1. **Session Management**: Each project gets its own tmux session (`cmux-projectname`)
|
|
138
|
+
2. **Worktree Creation**: New panes create git worktrees in sibling directories
|
|
139
|
+
3. **Branch Management**: Automatic branch creation with AI-generated names
|
|
140
|
+
4. **Claude Integration**: Launches Claude with `--accept-edits` for immediate coding
|
|
141
|
+
5. **Smart Merging**: Auto-commits, generates messages, and cleans up worktrees
|
|
142
|
+
|
|
143
|
+
## Project Structure
|
|
144
|
+
|
|
145
|
+
When you create panes, cmux organizes your work like this:
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
my-project/ # Your main repository
|
|
149
|
+
├── .git/
|
|
150
|
+
└── src/
|
|
151
|
+
|
|
152
|
+
my-project-fix-auth/ # Worktree for "fix authentication"
|
|
153
|
+
├── .git # Worktree reference
|
|
154
|
+
└── src/ # Independent working copy
|
|
155
|
+
|
|
156
|
+
my-project-add-feature/ # Worktree for "add new feature"
|
|
157
|
+
├── .git
|
|
158
|
+
└── src/
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Troubleshooting
|
|
162
|
+
|
|
163
|
+
### Claude command not found
|
|
164
|
+
Install Claude Code CLI from [Claude Code documentation](https://claude.ai/code).
|
|
165
|
+
|
|
166
|
+
### API features not working
|
|
167
|
+
```bash
|
|
168
|
+
# Check your API key
|
|
169
|
+
echo $OPENROUTER_API_KEY
|
|
170
|
+
|
|
171
|
+
# If missing, add to your shell config
|
|
172
|
+
export OPENROUTER_API_KEY="your-key"
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Panes not appearing
|
|
176
|
+
- Ensure tmux version 3.0+: `tmux -V`
|
|
177
|
+
- Check git version 2.20+: `git --version`
|
|
178
|
+
- Verify write permissions in parent directory
|
|
179
|
+
|
|
180
|
+
### Screen artifacts
|
|
181
|
+
Press `Ctrl+L` in the affected pane to clear the screen.
|
|
182
|
+
|
|
183
|
+
## Tips
|
|
184
|
+
|
|
185
|
+
- **Use descriptive prompts** for better AI-generated branch names
|
|
186
|
+
- **Merge frequently** to keep your main branch updated
|
|
187
|
+
- **One feature per pane** for clean separation of work
|
|
188
|
+
- **Close unused panes** with `x` to keep the interface clean
|
|
189
|
+
|
|
190
|
+
## tmux Configuration for Beginners
|
|
191
|
+
|
|
192
|
+
While cmux handles most tmux operations automatically, having a good tmux configuration can enhance your experience. This isn't the place to learn tmux comprehensively, but here's a helpful configuration to get you started.
|
|
193
|
+
|
|
194
|
+
### Recommended tmux Configuration
|
|
195
|
+
|
|
196
|
+
Add this to your `~/.tmux.conf` file:
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
# Visual distinction between active and inactive panes
|
|
200
|
+
set -g window-style 'fg=colour247,bg=colour236'
|
|
201
|
+
set -g window-active-style 'fg=default,bg=colour234'
|
|
202
|
+
|
|
203
|
+
# Pane borders
|
|
204
|
+
set -g pane-border-style "fg=colour238 bg=default"
|
|
205
|
+
set -g pane-active-border-style "fg=blue bg=default"
|
|
206
|
+
|
|
207
|
+
# Status bar styling
|
|
208
|
+
set -g status-style 'bg=colour236'
|
|
209
|
+
|
|
210
|
+
# Keyboard shortcuts for pane navigation
|
|
211
|
+
# Hold Ctrl+Shift and use arrow keys to move between panes
|
|
212
|
+
bind -n C-S-Left select-pane -L
|
|
213
|
+
bind -n C-S-Right select-pane -R
|
|
214
|
+
bind -n C-S-Up select-pane -U
|
|
215
|
+
bind -n C-S-Down select-pane -D
|
|
216
|
+
|
|
217
|
+
# Enable mouse support (click panes, resize with mouse)
|
|
218
|
+
set -g mouse on
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Key Features of This Configuration
|
|
222
|
+
|
|
223
|
+
- **Visual Feedback**: Active panes have a darker background and blue border
|
|
224
|
+
- **Easy Navigation**: Hold `Ctrl+Shift` and use arrow keys to switch between panes instantly
|
|
225
|
+
- **Mouse Support**: Click on panes to focus them, drag borders to resize
|
|
226
|
+
|
|
227
|
+
After adding this configuration, reload tmux:
|
|
228
|
+
```bash
|
|
229
|
+
tmux source-file ~/.tmux.conf
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Or start a new tmux session for the changes to take effect.
|
|
233
|
+
|
|
234
|
+
## Requirements Summary
|
|
235
|
+
|
|
236
|
+
- tmux ≥ 3.0
|
|
237
|
+
- Node.js ≥ 18
|
|
238
|
+
- Git ≥ 2.20
|
|
239
|
+
- Claude Code CLI
|
|
240
|
+
- OpenRouter API key (optional)
|
|
22
241
|
|
|
23
|
-
##
|
|
242
|
+
## Support
|
|
24
243
|
|
|
25
|
-
|
|
244
|
+
For issues or questions, please check the [full documentation](CLAUDE.md) or open an issue on GitHub.
|
|
26
245
|
|
|
27
246
|
## License
|
|
28
247
|
|
|
29
|
-
|
|
248
|
+
[Your License Here]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DmuxApp.d.ts","sourceRoot":"","sources":["../src/DmuxApp.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAgBnD,UAAU,YAAY;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,QAAA,MAAM,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CAinBnC,CAAC;AAEF,eAAe,OAAO,CAAC"}
|
package/dist/DmuxApp.js
ADDED
|
@@ -0,0 +1,503 @@
|
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
2
|
+
import { Box, Text, useInput, useApp } from 'ink';
|
|
3
|
+
import TextInput from 'ink-text-input';
|
|
4
|
+
import { execSync } from 'child_process';
|
|
5
|
+
import fs from 'fs/promises';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
const DmuxApp = ({ dmuxDir, panesFile, projectName, sessionName }) => {
|
|
8
|
+
const [panes, setPanes] = useState([]);
|
|
9
|
+
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
10
|
+
const [showNewPaneDialog, setShowNewPaneDialog] = useState(false);
|
|
11
|
+
const [newPanePrompt, setNewPanePrompt] = useState('');
|
|
12
|
+
const [statusMessage, setStatusMessage] = useState('');
|
|
13
|
+
const [showMergeConfirmation, setShowMergeConfirmation] = useState(false);
|
|
14
|
+
const [mergedPane, setMergedPane] = useState(null);
|
|
15
|
+
const [showCloseOptions, setShowCloseOptions] = useState(false);
|
|
16
|
+
const [selectedCloseOption, setSelectedCloseOption] = useState(0);
|
|
17
|
+
const [closingPane, setClosingPane] = useState(null);
|
|
18
|
+
const [isCreatingPane, setIsCreatingPane] = useState(false);
|
|
19
|
+
const { exit } = useApp();
|
|
20
|
+
// Load panes on mount and refresh periodically
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
loadPanes();
|
|
23
|
+
const interval = setInterval(loadPanes, 2000);
|
|
24
|
+
return () => clearInterval(interval);
|
|
25
|
+
}, []);
|
|
26
|
+
const loadPanes = async () => {
|
|
27
|
+
try {
|
|
28
|
+
const content = await fs.readFile(panesFile, 'utf-8');
|
|
29
|
+
const loadedPanes = JSON.parse(content);
|
|
30
|
+
// Filter out dead panes
|
|
31
|
+
const activePanes = loadedPanes.filter(pane => {
|
|
32
|
+
try {
|
|
33
|
+
execSync(`tmux list-panes -F '#{pane_id}' | grep -q '${pane.paneId}'`, {
|
|
34
|
+
stdio: 'pipe'
|
|
35
|
+
});
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
setPanes(activePanes);
|
|
43
|
+
// Save cleaned list
|
|
44
|
+
if (activePanes.length !== loadedPanes.length) {
|
|
45
|
+
await fs.writeFile(panesFile, JSON.stringify(activePanes, null, 2));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
setPanes([]);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
const savePanes = async (newPanes) => {
|
|
53
|
+
await fs.writeFile(panesFile, JSON.stringify(newPanes, null, 2));
|
|
54
|
+
setPanes(newPanes);
|
|
55
|
+
};
|
|
56
|
+
const generateSlug = async (prompt) => {
|
|
57
|
+
const apiKey = process.env.OPENROUTER_API_KEY;
|
|
58
|
+
if (!apiKey || !prompt) {
|
|
59
|
+
return `dmux-${Date.now()}`;
|
|
60
|
+
}
|
|
61
|
+
try {
|
|
62
|
+
const response = await fetch('https://openrouter.ai/api/v1/chat/completions', {
|
|
63
|
+
method: 'POST',
|
|
64
|
+
headers: {
|
|
65
|
+
'Content-Type': 'application/json',
|
|
66
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
67
|
+
},
|
|
68
|
+
body: JSON.stringify({
|
|
69
|
+
model: 'openai/gpt-4o-mini',
|
|
70
|
+
messages: [
|
|
71
|
+
{
|
|
72
|
+
role: 'user',
|
|
73
|
+
content: `Generate a 1-2 word kebab-case slug for this prompt. Only respond with the slug, nothing else: "${prompt}"`
|
|
74
|
+
}
|
|
75
|
+
],
|
|
76
|
+
max_tokens: 10,
|
|
77
|
+
temperature: 0.3
|
|
78
|
+
})
|
|
79
|
+
});
|
|
80
|
+
if (!response.ok) {
|
|
81
|
+
throw new Error(`OpenRouter API error: ${response.status}`);
|
|
82
|
+
}
|
|
83
|
+
const data = await response.json();
|
|
84
|
+
const slug = data.choices[0].message.content.trim().toLowerCase().replace(/[^a-z0-9-]/g, '');
|
|
85
|
+
return slug || `dmux-${Date.now()}`;
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return `dmux-${Date.now()}`;
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
const createNewPane = async (prompt) => {
|
|
92
|
+
setIsCreatingPane(true);
|
|
93
|
+
setStatusMessage('Generating slug...');
|
|
94
|
+
const slug = await generateSlug(prompt);
|
|
95
|
+
setStatusMessage('Creating new pane...');
|
|
96
|
+
// Get current directory
|
|
97
|
+
const currentDir = process.cwd();
|
|
98
|
+
// Create worktree path
|
|
99
|
+
const worktreePath = path.join(currentDir, '..', `${path.basename(currentDir)}-${slug}`);
|
|
100
|
+
// Get the original pane ID (where dmux is running) before clearing
|
|
101
|
+
const originalPaneId = execSync('tmux display-message -p "#{pane_id}"', { encoding: 'utf-8' }).trim();
|
|
102
|
+
// Multiple clearing strategies to prevent artifacts
|
|
103
|
+
// 1. Clear screen with ANSI codes
|
|
104
|
+
process.stdout.write('\x1b[2J\x1b[H');
|
|
105
|
+
// 2. Fill with blank lines to push content off screen
|
|
106
|
+
process.stdout.write('\n'.repeat(100));
|
|
107
|
+
// 3. Clear tmux history and send clear command
|
|
108
|
+
try {
|
|
109
|
+
execSync('tmux clear-history', { stdio: 'pipe' });
|
|
110
|
+
execSync('tmux send-keys C-l', { stdio: 'pipe' });
|
|
111
|
+
}
|
|
112
|
+
catch { }
|
|
113
|
+
// Exit Ink app cleanly before creating tmux pane
|
|
114
|
+
exit();
|
|
115
|
+
// Wait for exit to complete
|
|
116
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
117
|
+
// 4. Force tmux to refresh the display
|
|
118
|
+
try {
|
|
119
|
+
execSync('tmux refresh-client', { stdio: 'pipe' });
|
|
120
|
+
}
|
|
121
|
+
catch { }
|
|
122
|
+
// Create new pane
|
|
123
|
+
const paneInfo = execSync(`tmux split-window -h -P -F '#{pane_id}'`, { encoding: 'utf-8' }).trim();
|
|
124
|
+
// Wait for pane creation to settle
|
|
125
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
126
|
+
// Resize panes evenly
|
|
127
|
+
execSync('tmux select-layout even-horizontal', { stdio: 'pipe' });
|
|
128
|
+
// Create git worktree and cd into it
|
|
129
|
+
try {
|
|
130
|
+
execSync(`tmux send-keys -t '${paneInfo}' 'git worktree add "${worktreePath}" -b ${slug}' Enter`, { stdio: 'pipe' });
|
|
131
|
+
execSync(`tmux send-keys -t '${paneInfo}' 'cd "${worktreePath}"' Enter`, { stdio: 'pipe' });
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
// Continue in current directory if worktree fails
|
|
135
|
+
}
|
|
136
|
+
// Prepare the Claude command
|
|
137
|
+
let claudeCmd;
|
|
138
|
+
if (prompt && prompt.trim()) {
|
|
139
|
+
const escapedPrompt = prompt
|
|
140
|
+
.replace(/\\/g, '\\\\')
|
|
141
|
+
.replace(/"/g, '\\"')
|
|
142
|
+
.replace(/`/g, '\\`')
|
|
143
|
+
.replace(/\$/g, '\\$');
|
|
144
|
+
claudeCmd = `claude "${escapedPrompt}" --permission-mode=acceptEdits`;
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
claudeCmd = `claude --permission-mode=acceptEdits`;
|
|
148
|
+
}
|
|
149
|
+
// Send command to new pane
|
|
150
|
+
const escapedCmd = claudeCmd.replace(/'/g, "'\\''");
|
|
151
|
+
execSync(`tmux send-keys -t '${paneInfo}' '${escapedCmd}'`, { stdio: 'pipe' });
|
|
152
|
+
execSync(`tmux send-keys -t '${paneInfo}' Enter`, { stdio: 'pipe' });
|
|
153
|
+
// Keep focus on the new pane
|
|
154
|
+
execSync(`tmux select-pane -t '${paneInfo}'`, { stdio: 'pipe' });
|
|
155
|
+
// Save pane info
|
|
156
|
+
const newPane = {
|
|
157
|
+
id: `dmux-${Date.now()}`,
|
|
158
|
+
slug,
|
|
159
|
+
prompt: prompt ? (prompt.substring(0, 50) + (prompt.length > 50 ? '...' : '')) : 'No initial prompt',
|
|
160
|
+
paneId: paneInfo,
|
|
161
|
+
worktreePath
|
|
162
|
+
};
|
|
163
|
+
const updatedPanes = [...panes, newPane];
|
|
164
|
+
await fs.writeFile(panesFile, JSON.stringify(updatedPanes, null, 2));
|
|
165
|
+
// Switch back to the original pane (where cmux was running)
|
|
166
|
+
execSync(`tmux select-pane -t '${originalPaneId}'`, { stdio: 'pipe' });
|
|
167
|
+
// Re-launch dmux in the original pane
|
|
168
|
+
execSync(`tmux send-keys -t '${originalPaneId}' 'dmux' Enter`, { stdio: 'pipe' });
|
|
169
|
+
};
|
|
170
|
+
const jumpToPane = (paneId) => {
|
|
171
|
+
try {
|
|
172
|
+
execSync(`tmux select-pane -t '${paneId}'`, { stdio: 'pipe' });
|
|
173
|
+
setStatusMessage('Jumped to pane');
|
|
174
|
+
setTimeout(() => setStatusMessage(''), 2000);
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
setStatusMessage('Failed to jump - pane may be closed');
|
|
178
|
+
setTimeout(() => setStatusMessage(''), 2000);
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
const closePane = async (pane) => {
|
|
182
|
+
try {
|
|
183
|
+
// Kill the tmux pane
|
|
184
|
+
execSync(`tmux kill-pane -t '${pane.paneId}'`, { stdio: 'pipe' });
|
|
185
|
+
// Remove from list
|
|
186
|
+
const updatedPanes = panes.filter(p => p.id !== pane.id);
|
|
187
|
+
await savePanes(updatedPanes);
|
|
188
|
+
setStatusMessage(`Closed pane: ${pane.slug}`);
|
|
189
|
+
setTimeout(() => setStatusMessage(''), 3000);
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
setStatusMessage('Failed to close pane');
|
|
193
|
+
setTimeout(() => setStatusMessage(''), 2000);
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
const mergeAndPrune = async (pane) => {
|
|
197
|
+
if (!pane.worktreePath) {
|
|
198
|
+
setStatusMessage('No worktree to merge');
|
|
199
|
+
setTimeout(() => setStatusMessage(''), 2000);
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
try {
|
|
203
|
+
setStatusMessage('Checking worktree status...');
|
|
204
|
+
// Get current branch
|
|
205
|
+
const mainBranch = execSync('git branch --show-current', { encoding: 'utf-8' }).trim();
|
|
206
|
+
// Check for uncommitted changes in the worktree
|
|
207
|
+
const statusOutput = execSync(`git -C "${pane.worktreePath}" status --porcelain`, { encoding: 'utf-8' });
|
|
208
|
+
if (statusOutput.trim()) {
|
|
209
|
+
setStatusMessage('Generating commit message...');
|
|
210
|
+
// Get the diff for uncommitted changes
|
|
211
|
+
const diffOutput = execSync(`git -C "${pane.worktreePath}" diff HEAD`, { encoding: 'utf-8' });
|
|
212
|
+
const statusDetails = execSync(`git -C "${pane.worktreePath}" status`, { encoding: 'utf-8' });
|
|
213
|
+
// Generate commit message using LLM
|
|
214
|
+
const commitMessage = await generateCommitMessage(`${statusDetails}\n\n${diffOutput}`);
|
|
215
|
+
setStatusMessage('Committing changes...');
|
|
216
|
+
// Stage all changes and commit with generated message
|
|
217
|
+
execSync(`git -C "${pane.worktreePath}" add -A`, { stdio: 'pipe' });
|
|
218
|
+
// Escape the commit message for shell
|
|
219
|
+
const escapedMessage = commitMessage.replace(/'/g, "'\\''");
|
|
220
|
+
execSync(`git -C "${pane.worktreePath}" commit -m '${escapedMessage}'`, { stdio: 'pipe' });
|
|
221
|
+
}
|
|
222
|
+
setStatusMessage('Merging into main...');
|
|
223
|
+
// Merge the worktree branch
|
|
224
|
+
execSync(`git merge ${pane.slug}`, { stdio: 'pipe' });
|
|
225
|
+
// Remove worktree
|
|
226
|
+
execSync(`git worktree remove "${pane.worktreePath}"`, { stdio: 'pipe' });
|
|
227
|
+
// Delete branch
|
|
228
|
+
execSync(`git branch -d ${pane.slug}`, { stdio: 'pipe' });
|
|
229
|
+
// Close the pane
|
|
230
|
+
await closePane(pane);
|
|
231
|
+
setStatusMessage(`Merged ${pane.slug} into ${mainBranch} and closed pane`);
|
|
232
|
+
setTimeout(() => setStatusMessage(''), 3000);
|
|
233
|
+
}
|
|
234
|
+
catch (error) {
|
|
235
|
+
setStatusMessage('Failed to merge - check git status');
|
|
236
|
+
setTimeout(() => setStatusMessage(''), 3000);
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
const deleteUnsavedChanges = async (pane) => {
|
|
240
|
+
if (!pane.worktreePath) {
|
|
241
|
+
// No worktree, just close the pane
|
|
242
|
+
await closePane(pane);
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
try {
|
|
246
|
+
setStatusMessage('Removing worktree with unsaved changes...');
|
|
247
|
+
// Force remove worktree (discards uncommitted changes)
|
|
248
|
+
execSync(`git worktree remove --force "${pane.worktreePath}"`, { stdio: 'pipe' });
|
|
249
|
+
// Delete branch
|
|
250
|
+
try {
|
|
251
|
+
execSync(`git branch -D ${pane.slug}`, { stdio: 'pipe' });
|
|
252
|
+
}
|
|
253
|
+
catch {
|
|
254
|
+
// Branch might not exist or have commits, that's ok
|
|
255
|
+
}
|
|
256
|
+
// Close the pane
|
|
257
|
+
await closePane(pane);
|
|
258
|
+
setStatusMessage(`Deleted worktree ${pane.slug} and closed pane`);
|
|
259
|
+
setTimeout(() => setStatusMessage(''), 3000);
|
|
260
|
+
}
|
|
261
|
+
catch (error) {
|
|
262
|
+
setStatusMessage('Failed to delete worktree');
|
|
263
|
+
setTimeout(() => setStatusMessage(''), 3000);
|
|
264
|
+
}
|
|
265
|
+
};
|
|
266
|
+
const handleCloseOption = async (option, pane) => {
|
|
267
|
+
setShowCloseOptions(false);
|
|
268
|
+
setClosingPane(null);
|
|
269
|
+
setSelectedCloseOption(0);
|
|
270
|
+
switch (option) {
|
|
271
|
+
case 0: // Merge & Prune
|
|
272
|
+
await mergeAndPrune(pane);
|
|
273
|
+
break;
|
|
274
|
+
case 1: // Merge Only
|
|
275
|
+
await mergeWorktree(pane);
|
|
276
|
+
break;
|
|
277
|
+
case 2: // Delete Unsaved Changes
|
|
278
|
+
await deleteUnsavedChanges(pane);
|
|
279
|
+
break;
|
|
280
|
+
case 3: // Just Close
|
|
281
|
+
await closePane(pane);
|
|
282
|
+
break;
|
|
283
|
+
}
|
|
284
|
+
};
|
|
285
|
+
const generateCommitMessage = async (changes) => {
|
|
286
|
+
const apiKey = process.env.OPENROUTER_API_KEY;
|
|
287
|
+
if (!apiKey) {
|
|
288
|
+
return 'chore: merge worktree changes';
|
|
289
|
+
}
|
|
290
|
+
try {
|
|
291
|
+
const response = await fetch('https://openrouter.ai/api/v1/chat/completions', {
|
|
292
|
+
method: 'POST',
|
|
293
|
+
headers: {
|
|
294
|
+
'Content-Type': 'application/json',
|
|
295
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
296
|
+
},
|
|
297
|
+
body: JSON.stringify({
|
|
298
|
+
model: 'openai/gpt-4o-mini',
|
|
299
|
+
messages: [
|
|
300
|
+
{
|
|
301
|
+
role: 'system',
|
|
302
|
+
content: 'You are a git commit message generator. Generate semantic commit messages following conventional commits format (feat:, fix:, docs:, style:, refactor:, test:, chore:). Be concise and specific.'
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
role: 'user',
|
|
306
|
+
content: `Generate a semantic commit message for these changes:\n\n${changes.substring(0, 3000)}`
|
|
307
|
+
}
|
|
308
|
+
],
|
|
309
|
+
max_tokens: 100,
|
|
310
|
+
temperature: 0.3
|
|
311
|
+
})
|
|
312
|
+
});
|
|
313
|
+
if (!response.ok) {
|
|
314
|
+
throw new Error(`OpenRouter API error: ${response.status}`);
|
|
315
|
+
}
|
|
316
|
+
const data = await response.json();
|
|
317
|
+
const message = data.choices[0].message.content.trim();
|
|
318
|
+
return message || 'chore: merge worktree changes';
|
|
319
|
+
}
|
|
320
|
+
catch {
|
|
321
|
+
return 'chore: merge worktree changes';
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
const mergeWorktree = async (pane) => {
|
|
325
|
+
if (!pane.worktreePath) {
|
|
326
|
+
setStatusMessage('No worktree to merge');
|
|
327
|
+
setTimeout(() => setStatusMessage(''), 2000);
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
try {
|
|
331
|
+
setStatusMessage('Checking worktree status...');
|
|
332
|
+
// Get current branch
|
|
333
|
+
const mainBranch = execSync('git branch --show-current', { encoding: 'utf-8' }).trim();
|
|
334
|
+
// Check for uncommitted changes in the worktree
|
|
335
|
+
const statusOutput = execSync(`git -C "${pane.worktreePath}" status --porcelain`, { encoding: 'utf-8' });
|
|
336
|
+
if (statusOutput.trim()) {
|
|
337
|
+
setStatusMessage('Staging changes...');
|
|
338
|
+
// Stage all changes first (including untracked files)
|
|
339
|
+
execSync(`git -C "${pane.worktreePath}" add -A`, { stdio: 'pipe' });
|
|
340
|
+
setStatusMessage('Generating commit message...');
|
|
341
|
+
// Get the diff of staged changes (after adding files)
|
|
342
|
+
const diffOutput = execSync(`git -C "${pane.worktreePath}" diff --cached`, { encoding: 'utf-8' });
|
|
343
|
+
const statusDetails = execSync(`git -C "${pane.worktreePath}" status`, { encoding: 'utf-8' });
|
|
344
|
+
// Generate commit message using LLM
|
|
345
|
+
const commitMessage = await generateCommitMessage(`${statusDetails}\n\n${diffOutput}`);
|
|
346
|
+
setStatusMessage('Committing changes...');
|
|
347
|
+
// Escape the commit message for shell
|
|
348
|
+
const escapedMessage = commitMessage.replace(/'/g, "'\\''");
|
|
349
|
+
execSync(`git -C "${pane.worktreePath}" commit -m '${escapedMessage}'`, { stdio: 'pipe' });
|
|
350
|
+
}
|
|
351
|
+
setStatusMessage('Merging into main...');
|
|
352
|
+
// Merge the worktree branch
|
|
353
|
+
execSync(`git merge ${pane.slug}`, { stdio: 'pipe' });
|
|
354
|
+
// Remove worktree
|
|
355
|
+
execSync(`git worktree remove "${pane.worktreePath}"`, { stdio: 'pipe' });
|
|
356
|
+
// Delete branch
|
|
357
|
+
execSync(`git branch -d ${pane.slug}`, { stdio: 'pipe' });
|
|
358
|
+
setStatusMessage(`Merged ${pane.slug} into ${mainBranch}`);
|
|
359
|
+
setTimeout(() => setStatusMessage(''), 3000);
|
|
360
|
+
// Show confirmation dialog to close the pane
|
|
361
|
+
setMergedPane(pane);
|
|
362
|
+
setShowMergeConfirmation(true);
|
|
363
|
+
}
|
|
364
|
+
catch (error) {
|
|
365
|
+
setStatusMessage('Failed to merge - check git status');
|
|
366
|
+
setTimeout(() => setStatusMessage(''), 3000);
|
|
367
|
+
}
|
|
368
|
+
};
|
|
369
|
+
useInput((input, key) => {
|
|
370
|
+
if (isCreatingPane) {
|
|
371
|
+
// Disable input while creating pane
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
if (showNewPaneDialog) {
|
|
375
|
+
if (key.escape) {
|
|
376
|
+
setShowNewPaneDialog(false);
|
|
377
|
+
setNewPanePrompt('');
|
|
378
|
+
}
|
|
379
|
+
else if (key.return) {
|
|
380
|
+
createNewPane(newPanePrompt);
|
|
381
|
+
setShowNewPaneDialog(false);
|
|
382
|
+
setNewPanePrompt('');
|
|
383
|
+
}
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
if (showMergeConfirmation) {
|
|
387
|
+
if (input === 'y' || input === 'Y') {
|
|
388
|
+
if (mergedPane) {
|
|
389
|
+
closePane(mergedPane);
|
|
390
|
+
}
|
|
391
|
+
setShowMergeConfirmation(false);
|
|
392
|
+
setMergedPane(null);
|
|
393
|
+
}
|
|
394
|
+
else if (input === 'n' || input === 'N' || key.escape) {
|
|
395
|
+
setShowMergeConfirmation(false);
|
|
396
|
+
setMergedPane(null);
|
|
397
|
+
}
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
if (showCloseOptions) {
|
|
401
|
+
if (key.escape) {
|
|
402
|
+
setShowCloseOptions(false);
|
|
403
|
+
setClosingPane(null);
|
|
404
|
+
setSelectedCloseOption(0);
|
|
405
|
+
}
|
|
406
|
+
else if (key.upArrow) {
|
|
407
|
+
setSelectedCloseOption(Math.max(0, selectedCloseOption - 1));
|
|
408
|
+
}
|
|
409
|
+
else if (key.downArrow) {
|
|
410
|
+
setSelectedCloseOption(Math.min(3, selectedCloseOption + 1));
|
|
411
|
+
}
|
|
412
|
+
else if (key.return && closingPane) {
|
|
413
|
+
handleCloseOption(selectedCloseOption, closingPane);
|
|
414
|
+
}
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
if (key.upArrow) {
|
|
418
|
+
setSelectedIndex(Math.max(0, selectedIndex - 1));
|
|
419
|
+
}
|
|
420
|
+
else if (key.downArrow) {
|
|
421
|
+
setSelectedIndex(Math.min(panes.length, selectedIndex + 1));
|
|
422
|
+
}
|
|
423
|
+
else if (input === 'q') {
|
|
424
|
+
exit();
|
|
425
|
+
}
|
|
426
|
+
else if (input === 'n' || (key.return && selectedIndex === panes.length)) {
|
|
427
|
+
setShowNewPaneDialog(true);
|
|
428
|
+
}
|
|
429
|
+
else if (input === 'j' && selectedIndex < panes.length) {
|
|
430
|
+
jumpToPane(panes[selectedIndex].paneId);
|
|
431
|
+
}
|
|
432
|
+
else if (input === 'x' && selectedIndex < panes.length) {
|
|
433
|
+
setClosingPane(panes[selectedIndex]);
|
|
434
|
+
setShowCloseOptions(true);
|
|
435
|
+
setSelectedCloseOption(0);
|
|
436
|
+
}
|
|
437
|
+
else if (input === 'm' && selectedIndex < panes.length) {
|
|
438
|
+
mergeWorktree(panes[selectedIndex]);
|
|
439
|
+
}
|
|
440
|
+
else if (key.return && selectedIndex < panes.length) {
|
|
441
|
+
jumpToPane(panes[selectedIndex].paneId);
|
|
442
|
+
}
|
|
443
|
+
});
|
|
444
|
+
return (React.createElement(Box, { flexDirection: "column" },
|
|
445
|
+
React.createElement(Box, { marginBottom: 1 },
|
|
446
|
+
React.createElement(Text, { bold: true, color: "cyan" },
|
|
447
|
+
"dmux - ",
|
|
448
|
+
projectName)),
|
|
449
|
+
panes.map((pane, index) => (React.createElement(Box, { key: pane.id, paddingX: 1, borderStyle: "single", borderColor: selectedIndex === index ? 'cyan' : 'gray', marginBottom: 1 },
|
|
450
|
+
React.createElement(Box, { flexDirection: "column" },
|
|
451
|
+
React.createElement(Box, null,
|
|
452
|
+
React.createElement(Text, { color: selectedIndex === index ? 'cyan' : 'white', bold: true }, pane.slug),
|
|
453
|
+
pane.worktreePath && (React.createElement(Text, { color: "gray" }, " (worktree)"))),
|
|
454
|
+
React.createElement(Text, { color: "gray", dimColor: true }, pane.prompt))))),
|
|
455
|
+
React.createElement(Box, { paddingX: 1, borderStyle: "single", borderColor: selectedIndex === panes.length ? 'green' : 'gray', marginBottom: 1 },
|
|
456
|
+
React.createElement(Text, { color: selectedIndex === panes.length ? 'green' : 'white' }, "+ New dmux pane")),
|
|
457
|
+
showNewPaneDialog && (React.createElement(Box, { borderStyle: "double", borderColor: "cyan", paddingX: 1 },
|
|
458
|
+
React.createElement(Box, { flexDirection: "column" },
|
|
459
|
+
React.createElement(Text, null, "Enter initial Claude prompt (ESC to cancel):"),
|
|
460
|
+
React.createElement(TextInput, { value: newPanePrompt, onChange: setNewPanePrompt, placeholder: "Optional prompt..." })))),
|
|
461
|
+
isCreatingPane && (React.createElement(Box, { borderStyle: "single", borderColor: "yellow", paddingX: 1, marginTop: 1 },
|
|
462
|
+
React.createElement(Text, { color: "yellow" },
|
|
463
|
+
React.createElement(Text, { bold: true }, "\u23F3 Creating new pane... "),
|
|
464
|
+
statusMessage))),
|
|
465
|
+
showMergeConfirmation && mergedPane && (React.createElement(Box, { borderStyle: "double", borderColor: "yellow", paddingX: 1, marginTop: 1 },
|
|
466
|
+
React.createElement(Box, { flexDirection: "column" },
|
|
467
|
+
React.createElement(Text, { color: "yellow", bold: true }, "Worktree merged successfully!"),
|
|
468
|
+
React.createElement(Text, null,
|
|
469
|
+
"Close the pane \"",
|
|
470
|
+
mergedPane.slug,
|
|
471
|
+
"\"? (y/n)")))),
|
|
472
|
+
showCloseOptions && closingPane && (React.createElement(Box, { borderStyle: "double", borderColor: "red", paddingX: 1, marginTop: 1 },
|
|
473
|
+
React.createElement(Box, { flexDirection: "column" },
|
|
474
|
+
React.createElement(Text, { color: "red", bold: true },
|
|
475
|
+
"Close pane \"",
|
|
476
|
+
closingPane.slug,
|
|
477
|
+
"\"?"),
|
|
478
|
+
React.createElement(Text, { dimColor: true }, "Select an option (ESC to cancel):"),
|
|
479
|
+
React.createElement(Box, { flexDirection: "column", marginTop: 1 },
|
|
480
|
+
React.createElement(Box, null,
|
|
481
|
+
React.createElement(Text, { color: selectedCloseOption === 0 ? 'cyan' : 'white' },
|
|
482
|
+
selectedCloseOption === 0 ? '▶ ' : ' ',
|
|
483
|
+
"Merge & Prune - Merge worktree to main and close")),
|
|
484
|
+
React.createElement(Box, null,
|
|
485
|
+
React.createElement(Text, { color: selectedCloseOption === 1 ? 'cyan' : 'white' },
|
|
486
|
+
selectedCloseOption === 1 ? '▶ ' : ' ',
|
|
487
|
+
"Merge Only - Merge worktree but keep pane open")),
|
|
488
|
+
React.createElement(Box, null,
|
|
489
|
+
React.createElement(Text, { color: selectedCloseOption === 2 ? 'cyan' : 'white' },
|
|
490
|
+
selectedCloseOption === 2 ? '▶ ' : ' ',
|
|
491
|
+
"Delete Unsaved - Remove worktree (discard changes)")),
|
|
492
|
+
React.createElement(Box, null,
|
|
493
|
+
React.createElement(Text, { color: selectedCloseOption === 3 ? 'cyan' : 'white' },
|
|
494
|
+
selectedCloseOption === 3 ? '▶ ' : ' ',
|
|
495
|
+
"Just Close - Close pane only")))))),
|
|
496
|
+
statusMessage && (React.createElement(Box, { marginTop: 1 },
|
|
497
|
+
React.createElement(Text, { color: "green" }, statusMessage))),
|
|
498
|
+
React.createElement(Box, { marginTop: 1, flexDirection: "column" },
|
|
499
|
+
React.createElement(Text, { dimColor: true }, "Commands: [j]ump to pane \u2022 [x] close \u2022 [m]erge worktree \u2022 [n]ew pane \u2022 [q]uit"),
|
|
500
|
+
React.createElement(Text, { dimColor: true }, "Use \u2191\u2193 arrows to navigate, Enter to select"))));
|
|
501
|
+
};
|
|
502
|
+
export default DmuxApp;
|
|
503
|
+
//# sourceMappingURL=DmuxApp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DmuxApp.js","sourceRoot":"","sources":["../src/DmuxApp.tsx"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { execSync } from 'child_process';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import fs from 'fs/promises';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
7
|
+
import { render } from 'ink';
|
|
8
|
+
import React from 'react';
|
|
9
|
+
import DmuxApp from './DmuxApp.js';
|
|
10
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
11
|
+
class Dmux {
|
|
12
|
+
dmuxDir;
|
|
13
|
+
panesFile;
|
|
14
|
+
projectName;
|
|
15
|
+
sessionName;
|
|
16
|
+
constructor() {
|
|
17
|
+
this.dmuxDir = path.join(process.env.HOME, '.dmux');
|
|
18
|
+
// Get project name from current directory
|
|
19
|
+
this.projectName = path.basename(process.cwd());
|
|
20
|
+
// Create unique session name for this project
|
|
21
|
+
this.sessionName = `dmux-${this.projectName}`;
|
|
22
|
+
// Store panes per project
|
|
23
|
+
this.panesFile = path.join(this.dmuxDir, `${this.projectName}-panes.json`);
|
|
24
|
+
}
|
|
25
|
+
async init() {
|
|
26
|
+
await fs.mkdir(this.dmuxDir, { recursive: true });
|
|
27
|
+
if (!await this.fileExists(this.panesFile)) {
|
|
28
|
+
await fs.writeFile(this.panesFile, '[]');
|
|
29
|
+
}
|
|
30
|
+
const inTmux = process.env.TMUX !== undefined;
|
|
31
|
+
if (!inTmux) {
|
|
32
|
+
// Check if project-specific session already exists
|
|
33
|
+
try {
|
|
34
|
+
execSync(`tmux has-session -t ${this.sessionName} 2>/dev/null`, { stdio: 'pipe' });
|
|
35
|
+
console.log(chalk.yellow(`Attaching to existing ${this.sessionName} session...`));
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
console.log(chalk.yellow(`Creating new tmux session for project: ${this.projectName}...`));
|
|
39
|
+
// Create new session first
|
|
40
|
+
execSync(`tmux new-session -d -s ${this.sessionName}`, { stdio: 'inherit' });
|
|
41
|
+
// Send dmux command to the new session
|
|
42
|
+
execSync(`tmux send-keys -t ${this.sessionName} "dmux" Enter`, { stdio: 'inherit' });
|
|
43
|
+
}
|
|
44
|
+
execSync(`tmux attach-session -t ${this.sessionName}`, { stdio: 'inherit' });
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
// Launch the Ink app
|
|
48
|
+
render(React.createElement(DmuxApp, {
|
|
49
|
+
dmuxDir: this.dmuxDir,
|
|
50
|
+
panesFile: this.panesFile,
|
|
51
|
+
projectName: this.projectName,
|
|
52
|
+
sessionName: this.sessionName
|
|
53
|
+
}));
|
|
54
|
+
}
|
|
55
|
+
async fileExists(path) {
|
|
56
|
+
try {
|
|
57
|
+
await fs.access(path);
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const dmux = new Dmux();
|
|
66
|
+
dmux.init().catch(console.error);
|
|
67
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dmux
ADDED
package/package.json
CHANGED
|
@@ -1,18 +1,71 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dmux",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"keywords": ["tmux", "pane", "manager", "ai", "development"],
|
|
8
|
-
"author": "",
|
|
3
|
+
"version": "1.0.2",
|
|
4
|
+
"description": "Tmux pane manager with AI agent integration for parallel development workflows",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"author": "Justin Schroeder",
|
|
9
7
|
"license": "MIT",
|
|
8
|
+
"homepage": "https://github.com/justinschroeder/dmux#readme",
|
|
10
9
|
"repository": {
|
|
11
10
|
"type": "git",
|
|
12
|
-
"url": "https://github.com/
|
|
11
|
+
"url": "git+https://github.com/justinschroeder/dmux.git"
|
|
13
12
|
},
|
|
14
13
|
"bugs": {
|
|
15
|
-
"url": "https://github.com/
|
|
14
|
+
"url": "https://github.com/justinschroeder/dmux/issues"
|
|
16
15
|
},
|
|
17
|
-
"
|
|
16
|
+
"keywords": [
|
|
17
|
+
"tmux",
|
|
18
|
+
"claude",
|
|
19
|
+
"ai",
|
|
20
|
+
"development",
|
|
21
|
+
"worktree",
|
|
22
|
+
"git",
|
|
23
|
+
"terminal",
|
|
24
|
+
"cli"
|
|
25
|
+
],
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=18.0.0"
|
|
28
|
+
},
|
|
29
|
+
"main": "./dist/index.js",
|
|
30
|
+
"exports": {
|
|
31
|
+
".": {
|
|
32
|
+
"import": "./dist/index.js",
|
|
33
|
+
"types": "./dist/index.d.ts"
|
|
34
|
+
},
|
|
35
|
+
"./package.json": "./package.json"
|
|
36
|
+
},
|
|
37
|
+
"files": [
|
|
38
|
+
"dist",
|
|
39
|
+
"dmux",
|
|
40
|
+
"README.md",
|
|
41
|
+
"LICENSE"
|
|
42
|
+
],
|
|
43
|
+
"bin": {
|
|
44
|
+
"dmux": "./dmux"
|
|
45
|
+
},
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"chalk": "^5.3.0",
|
|
48
|
+
"ink": "^5.0.1",
|
|
49
|
+
"ink-text-input": "^6.0.0",
|
|
50
|
+
"react": "^18.2.0"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@types/node": "^20.10.5",
|
|
54
|
+
"@types/react": "^18.2.45",
|
|
55
|
+
"bumpp": "^10.2.3",
|
|
56
|
+
"npm-run-all2": "^8.0.4",
|
|
57
|
+
"tsx": "^4.7.0",
|
|
58
|
+
"typescript": "^5.3.3"
|
|
59
|
+
},
|
|
60
|
+
"scripts": {
|
|
61
|
+
"build": "tsc",
|
|
62
|
+
"clean": "rm -rf dist",
|
|
63
|
+
"dev": "tsx src/index.ts",
|
|
64
|
+
"start": "node dist/index.js",
|
|
65
|
+
"typecheck": "tsc --noEmit",
|
|
66
|
+
"prerelease": "run-s clean typecheck build",
|
|
67
|
+
"release": "bumpp --commit --push --tag && pnpm publish",
|
|
68
|
+
"release:minor": "bumpp minor --commit --push --tag && pnpm publish",
|
|
69
|
+
"release:major": "bumpp major --commit --push --tag && pnpm publish"
|
|
70
|
+
}
|
|
18
71
|
}
|
package/index.js
DELETED