claude-code-plus-plus 0.1.0
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 +74 -0
- package/assets/screenshot.png +0 -0
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +2 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/worktree-manager.d.ts +26 -0
- package/dist/core/worktree-manager.d.ts.map +1 -0
- package/dist/core/worktree-manager.js +177 -0
- package/dist/core/worktree-manager.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +208 -0
- package/dist/index.js.map +1 -0
- package/dist/sidebar.d.ts +13 -0
- package/dist/sidebar.d.ts.map +1 -0
- package/dist/sidebar.js +1535 -0
- package/dist/sidebar.js.map +1 -0
- package/dist/state.d.ts +53 -0
- package/dist/state.d.ts.map +1 -0
- package/dist/state.js +101 -0
- package/dist/state.js.map +1 -0
- package/dist/terminal-manager.d.ts +16 -0
- package/dist/terminal-manager.d.ts.map +1 -0
- package/dist/terminal-manager.js +364 -0
- package/dist/terminal-manager.js.map +1 -0
- package/dist/tmux.d.ts +163 -0
- package/dist/tmux.d.ts.map +1 -0
- package/dist/tmux.js +360 -0
- package/dist/tmux.js.map +1 -0
- package/dist/types.d.ts +13 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/package.json +57 -0
package/dist/tmux.js
ADDED
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tmux control utilities
|
|
3
|
+
*/
|
|
4
|
+
import { execSync, spawnSync } from 'child_process';
|
|
5
|
+
import { writeFileSync, chmodSync } from 'fs';
|
|
6
|
+
export class Tmux {
|
|
7
|
+
sessionName;
|
|
8
|
+
constructor(sessionName = 'claude-pp') {
|
|
9
|
+
this.sessionName = sessionName;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Check if tmux is installed
|
|
13
|
+
*/
|
|
14
|
+
static isAvailable() {
|
|
15
|
+
try {
|
|
16
|
+
execSync('which tmux', { stdio: 'ignore' });
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Check if our session already exists
|
|
25
|
+
*/
|
|
26
|
+
sessionExists() {
|
|
27
|
+
try {
|
|
28
|
+
execSync(`tmux has-session -t ${this.sessionName} 2>/dev/null`, { stdio: 'ignore' });
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Kill existing session if it exists
|
|
37
|
+
*/
|
|
38
|
+
killSession() {
|
|
39
|
+
try {
|
|
40
|
+
execSync(`tmux kill-session -t ${this.sessionName} 2>/dev/null`, { stdio: 'ignore' });
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
// Session didn't exist, that's fine
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Create a new tmux session (detached)
|
|
48
|
+
* Returns the initial window/pane ID
|
|
49
|
+
*/
|
|
50
|
+
createSession(startDir) {
|
|
51
|
+
// Kill any existing session first
|
|
52
|
+
this.killSession();
|
|
53
|
+
// Create new detached session
|
|
54
|
+
execSync(`tmux new-session -d -s ${this.sessionName} -c "${startDir}"`, { stdio: 'ignore' });
|
|
55
|
+
// Get the pane ID
|
|
56
|
+
const paneId = execSync(`tmux display-message -p -t ${this.sessionName} '#{pane_id}'`)
|
|
57
|
+
.toString()
|
|
58
|
+
.trim();
|
|
59
|
+
return paneId;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Split pane horizontally (left/right)
|
|
63
|
+
* Returns the new pane ID (right pane)
|
|
64
|
+
*/
|
|
65
|
+
splitHorizontal(percentage = 50, startDir) {
|
|
66
|
+
const dirArg = startDir ? `-c "${startDir}"` : '';
|
|
67
|
+
execSync(`tmux split-window -h -t ${this.sessionName} -p ${percentage} ${dirArg}`, { stdio: 'ignore' });
|
|
68
|
+
// Get the new pane ID
|
|
69
|
+
const paneId = execSync(`tmux display-message -p -t ${this.sessionName} '#{pane_id}'`)
|
|
70
|
+
.toString()
|
|
71
|
+
.trim();
|
|
72
|
+
return paneId;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Split pane vertically (top/bottom)
|
|
76
|
+
* Returns the new pane ID (bottom pane)
|
|
77
|
+
*/
|
|
78
|
+
splitVertical(percentage = 50, startDir) {
|
|
79
|
+
const dirArg = startDir ? `-c "${startDir}"` : '';
|
|
80
|
+
execSync(`tmux split-window -v -t ${this.sessionName} -p ${percentage} ${dirArg}`, { stdio: 'ignore' });
|
|
81
|
+
const paneId = execSync(`tmux display-message -p -t ${this.sessionName} '#{pane_id}'`)
|
|
82
|
+
.toString()
|
|
83
|
+
.trim();
|
|
84
|
+
return paneId;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Send keys to a specific pane
|
|
88
|
+
*/
|
|
89
|
+
/**
|
|
90
|
+
* Send literal text to a pane (spaces and special chars preserved)
|
|
91
|
+
*/
|
|
92
|
+
sendKeys(paneId, keys, enter = true) {
|
|
93
|
+
// Use -l for literal string to avoid interpretation issues
|
|
94
|
+
// Escape single quotes in the keys
|
|
95
|
+
const escaped = keys.replace(/'/g, "'\\''");
|
|
96
|
+
execSync(`tmux send-keys -t ${paneId} -l '${escaped}'`, { stdio: 'ignore' });
|
|
97
|
+
if (enter) {
|
|
98
|
+
execSync(`tmux send-keys -t ${paneId} Enter`, { stdio: 'ignore' });
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Send control/special keys (e.g., C-c for Ctrl+C, Enter, Escape)
|
|
103
|
+
*/
|
|
104
|
+
sendControlKey(paneId, key) {
|
|
105
|
+
execSync(`tmux send-keys -t ${paneId} ${key}`, { stdio: 'ignore' });
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Run a command in a specific pane
|
|
109
|
+
*/
|
|
110
|
+
runInPane(paneId, command) {
|
|
111
|
+
this.sendKeys(paneId, command, true);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Select (focus) a specific pane
|
|
115
|
+
*/
|
|
116
|
+
selectPane(paneId) {
|
|
117
|
+
execSync(`tmux select-pane -t ${paneId}`, { stdio: 'ignore' });
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Resize a pane
|
|
121
|
+
*/
|
|
122
|
+
resizePane(paneId, width, height) {
|
|
123
|
+
if (width !== undefined) {
|
|
124
|
+
execSync(`tmux resize-pane -t ${paneId} -x ${width}`, { stdio: 'ignore' });
|
|
125
|
+
}
|
|
126
|
+
if (height !== undefined) {
|
|
127
|
+
execSync(`tmux resize-pane -t ${paneId} -y ${height}`, { stdio: 'ignore' });
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Break a pane out to its own window (keeps it running in background)
|
|
132
|
+
* Returns the new window ID
|
|
133
|
+
*/
|
|
134
|
+
breakPane(paneId, windowName) {
|
|
135
|
+
const nameArg = windowName ? `-n "${windowName}"` : '';
|
|
136
|
+
execSync(`tmux break-pane -d -s ${paneId} ${nameArg}`, { stdio: 'ignore' });
|
|
137
|
+
// Get the window ID of the broken-out pane
|
|
138
|
+
const windowId = execSync(`tmux display-message -p -t ${paneId} '#{window_id}'`)
|
|
139
|
+
.toString()
|
|
140
|
+
.trim();
|
|
141
|
+
return windowId;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Join a pane from another window into the current window
|
|
145
|
+
* Returns the new pane ID
|
|
146
|
+
*/
|
|
147
|
+
joinPane(sourcePaneId, targetPaneId, horizontal = true) {
|
|
148
|
+
const direction = horizontal ? '-h' : '-v';
|
|
149
|
+
execSync(`tmux join-pane ${direction} -s ${sourcePaneId} -t ${targetPaneId}`, { stdio: 'ignore' });
|
|
150
|
+
// Return the source pane ID (it keeps its ID after joining)
|
|
151
|
+
return sourcePaneId;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Swap two panes
|
|
155
|
+
*/
|
|
156
|
+
swapPane(paneId1, paneId2) {
|
|
157
|
+
execSync(`tmux swap-pane -s ${paneId1} -t ${paneId2}`, { stdio: 'ignore' });
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Create a new pane by splitting, run a command, then break it to background
|
|
161
|
+
* Returns the pane ID (which persists even after breaking to background window)
|
|
162
|
+
*/
|
|
163
|
+
createBackgroundPane(startDir, command) {
|
|
164
|
+
// Split to create new pane
|
|
165
|
+
const paneId = this.splitHorizontal(50, startDir);
|
|
166
|
+
// Run command if provided
|
|
167
|
+
if (command) {
|
|
168
|
+
this.runInPane(paneId, command);
|
|
169
|
+
}
|
|
170
|
+
// Break it to background window (keeps it running)
|
|
171
|
+
this.breakPane(paneId);
|
|
172
|
+
return paneId;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Bring a background pane to the foreground (swap with current right pane)
|
|
176
|
+
*/
|
|
177
|
+
showPane(paneId, targetPaneId) {
|
|
178
|
+
this.swapPane(paneId, targetPaneId);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Create a new window (like a tab)
|
|
182
|
+
*/
|
|
183
|
+
createWindow(name, startDir) {
|
|
184
|
+
const dirArg = startDir ? `-c "${startDir}"` : '';
|
|
185
|
+
execSync(`tmux new-window -t ${this.sessionName} -n "${name}" ${dirArg}`, { stdio: 'ignore' });
|
|
186
|
+
const windowId = execSync(`tmux display-message -p -t ${this.sessionName} '#{window_id}'`)
|
|
187
|
+
.toString()
|
|
188
|
+
.trim();
|
|
189
|
+
return windowId;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Select a window by index or ID
|
|
193
|
+
*/
|
|
194
|
+
selectWindow(windowId) {
|
|
195
|
+
execSync(`tmux select-window -t ${windowId}`, { stdio: 'ignore' });
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Rename a window
|
|
199
|
+
*/
|
|
200
|
+
renameWindow(windowId, name) {
|
|
201
|
+
execSync(`tmux rename-window -t ${windowId} "${name}"`, { stdio: 'ignore' });
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Kill a pane
|
|
205
|
+
*/
|
|
206
|
+
killPane(paneId) {
|
|
207
|
+
try {
|
|
208
|
+
execSync(`tmux kill-pane -t ${paneId}`, { stdio: 'ignore' });
|
|
209
|
+
}
|
|
210
|
+
catch {
|
|
211
|
+
// Pane might already be dead
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Kill a window
|
|
216
|
+
*/
|
|
217
|
+
killWindow(windowId) {
|
|
218
|
+
try {
|
|
219
|
+
execSync(`tmux kill-window -t ${windowId}`, { stdio: 'ignore' });
|
|
220
|
+
}
|
|
221
|
+
catch {
|
|
222
|
+
// Window might already be dead
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Detach the current client from the session
|
|
227
|
+
*/
|
|
228
|
+
detachClient() {
|
|
229
|
+
try {
|
|
230
|
+
execSync(`tmux detach-client -s ${this.sessionName}`, { stdio: 'ignore' });
|
|
231
|
+
}
|
|
232
|
+
catch {
|
|
233
|
+
// Client might already be detached
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Attach to the session (takes over the terminal)
|
|
238
|
+
* This is blocking - returns only after detach/exit
|
|
239
|
+
*/
|
|
240
|
+
attach() {
|
|
241
|
+
// Use spawnSync to block until tmux attach exits (user detaches or session ends)
|
|
242
|
+
const result = spawnSync('tmux', ['attach-session', '-t', this.sessionName], {
|
|
243
|
+
stdio: 'inherit',
|
|
244
|
+
});
|
|
245
|
+
return result.status || 0;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Get list of panes in current window
|
|
249
|
+
*/
|
|
250
|
+
listPanes() {
|
|
251
|
+
const output = execSync(`tmux list-panes -t ${this.sessionName} -F '#{pane_id},#{pane_width},#{pane_height},#{pane_active}'`).toString();
|
|
252
|
+
return output
|
|
253
|
+
.trim()
|
|
254
|
+
.split('\n')
|
|
255
|
+
.filter(Boolean)
|
|
256
|
+
.map((line) => {
|
|
257
|
+
const [id, width, height, active] = line.split(',');
|
|
258
|
+
return {
|
|
259
|
+
id,
|
|
260
|
+
width: parseInt(width, 10),
|
|
261
|
+
height: parseInt(height, 10),
|
|
262
|
+
active: active === '1',
|
|
263
|
+
};
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Get list of windows
|
|
268
|
+
*/
|
|
269
|
+
listWindows() {
|
|
270
|
+
const output = execSync(`tmux list-windows -t ${this.sessionName} -F '#{window_id},#{window_name},#{window_active}'`).toString();
|
|
271
|
+
return output
|
|
272
|
+
.trim()
|
|
273
|
+
.split('\n')
|
|
274
|
+
.filter(Boolean)
|
|
275
|
+
.map((line) => {
|
|
276
|
+
const [id, name, active] = line.split(',');
|
|
277
|
+
return {
|
|
278
|
+
id,
|
|
279
|
+
name,
|
|
280
|
+
active: active === '1',
|
|
281
|
+
panes: [], // Could populate with listPanes for each window if needed
|
|
282
|
+
};
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Set a tmux option
|
|
287
|
+
*/
|
|
288
|
+
setOption(option, value, global = false) {
|
|
289
|
+
const flag = global ? '-g' : '';
|
|
290
|
+
execSync(`tmux set-option ${flag} ${option} ${value}`, { stdio: 'ignore' });
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Set a pane-specific option
|
|
294
|
+
*/
|
|
295
|
+
setPaneOption(paneId, option, value) {
|
|
296
|
+
execSync(`tmux set-option -p -t ${paneId} ${option} ${value}`, { stdio: 'ignore' });
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Bind a key
|
|
300
|
+
*/
|
|
301
|
+
bindKey(key, command) {
|
|
302
|
+
execSync(`tmux bind-key ${key} ${command}`, { stdio: 'ignore' });
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Unbind a key
|
|
306
|
+
*/
|
|
307
|
+
unbindKey(table, key) {
|
|
308
|
+
try {
|
|
309
|
+
execSync(`tmux unbind-key -T ${table} ${key}`, { stdio: 'ignore' });
|
|
310
|
+
}
|
|
311
|
+
catch {
|
|
312
|
+
// Key might not be bound
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Bind a conditional key (does different things based on pane)
|
|
317
|
+
*/
|
|
318
|
+
bindConditionalKey(table, key, condition, ifTrue, ifFalse) {
|
|
319
|
+
const cmd = ifTrue || '""';
|
|
320
|
+
const elseCmd = ifFalse || '""';
|
|
321
|
+
execSync(`tmux bind-key -T ${table} ${key} if-shell -F "${condition}" ${cmd} ${elseCmd}`, { stdio: 'ignore' });
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Set up a key binding to toggle sidebar width
|
|
325
|
+
* Binds to Ctrl+G (no prefix needed, works from any pane)
|
|
326
|
+
*/
|
|
327
|
+
bindSidebarToggle(sidebarPaneId, expandedWidth, collapsedWidth) {
|
|
328
|
+
// Write a toggle script using Node.js (avoids shell escaping issues)
|
|
329
|
+
const scriptPath = `/tmp/claude-pp-toggle-${this.sessionName}.sh`;
|
|
330
|
+
const script = `#!/bin/bash
|
|
331
|
+
width=$(tmux display-message -t '${sidebarPaneId}' -p '#{pane_width}')
|
|
332
|
+
if [ "$width" -gt ${collapsedWidth} ]; then
|
|
333
|
+
tmux resize-pane -t '${sidebarPaneId}' -x ${collapsedWidth}
|
|
334
|
+
else
|
|
335
|
+
tmux resize-pane -t '${sidebarPaneId}' -x ${expandedWidth}
|
|
336
|
+
fi
|
|
337
|
+
`;
|
|
338
|
+
writeFileSync(scriptPath, script);
|
|
339
|
+
chmodSync(scriptPath, 0o755);
|
|
340
|
+
// Bind to Ctrl+G in root table
|
|
341
|
+
execSync(`tmux bind-key -T root C-g run-shell -b '${scriptPath}'`, { stdio: 'ignore' });
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Disable scroll wheel for a specific pane, keep it for others
|
|
345
|
+
*/
|
|
346
|
+
disableScrollForPane(paneId) {
|
|
347
|
+
// Bind wheel events to do nothing if in sidebar pane, otherwise normal behavior
|
|
348
|
+
const condition = `#{==:#{pane_id},${paneId}}`;
|
|
349
|
+
// For WheelUpPane: if sidebar, do nothing; else enter copy-mode and scroll
|
|
350
|
+
execSync(`tmux bind-key -T root WheelUpPane if-shell -F "${condition}" "" "copy-mode -e; send-keys -M"`, { stdio: 'ignore' });
|
|
351
|
+
execSync(`tmux bind-key -T root WheelDownPane if-shell -F "${condition}" "" "copy-mode -e; send-keys -M"`, { stdio: 'ignore' });
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Get session name
|
|
355
|
+
*/
|
|
356
|
+
getSessionName() {
|
|
357
|
+
return this.sessionName;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
//# sourceMappingURL=tmux.js.map
|
package/dist/tmux.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tmux.js","sourceRoot":"","sources":["../src/tmux.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface Worktree {
|
|
2
|
+
id: string;
|
|
3
|
+
path: string;
|
|
4
|
+
branch: string;
|
|
5
|
+
isMain: boolean;
|
|
6
|
+
sessions: string[];
|
|
7
|
+
}
|
|
8
|
+
export interface AppConfig {
|
|
9
|
+
claudeCodeCommand: string;
|
|
10
|
+
dangerouslySkipPermissions: boolean;
|
|
11
|
+
}
|
|
12
|
+
export declare const DEFAULT_CONFIG: AppConfig;
|
|
13
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,SAAS;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,0BAA0B,EAAE,OAAO,CAAC;CACrC;AAED,eAAO,MAAM,cAAc,EAAE,SAG5B,CAAC"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAaA,MAAM,CAAC,MAAM,cAAc,GAAc;IACvC,iBAAiB,EAAE,QAAQ;IAC3B,0BAA0B,EAAE,IAAI;CACjC,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "claude-code-plus-plus",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Multi-pane terminal interface for parallel Claude Code agents with git worktree isolation",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"claude++": "./dist/index.js",
|
|
9
|
+
"ccp": "./dist/index.js"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"dev": "tsx src/index.ts",
|
|
13
|
+
"build": "tsc",
|
|
14
|
+
"start": "node dist/index.js",
|
|
15
|
+
"typecheck": "tsc --noEmit",
|
|
16
|
+
"prepublishOnly": "npm run build"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist/**/*",
|
|
20
|
+
"assets/**/*",
|
|
21
|
+
"README.md",
|
|
22
|
+
"LICENSE"
|
|
23
|
+
],
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "git+https://github.com/anthropics/claude-code-plus-plus.git"
|
|
27
|
+
},
|
|
28
|
+
"homepage": "https://github.com/anthropics/claude-code-plus-plus#readme",
|
|
29
|
+
"bugs": {
|
|
30
|
+
"url": "https://github.com/anthropics/claude-code-plus-plus/issues"
|
|
31
|
+
},
|
|
32
|
+
"author": "blitzjb",
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"simple-git": "^3.27.0"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/node": "^22.10.0",
|
|
38
|
+
"typescript": "^5.6.0",
|
|
39
|
+
"tsx": "^4.19.0"
|
|
40
|
+
},
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": ">=18.0.0"
|
|
43
|
+
},
|
|
44
|
+
"keywords": [
|
|
45
|
+
"claude",
|
|
46
|
+
"claude-code",
|
|
47
|
+
"ai",
|
|
48
|
+
"terminal",
|
|
49
|
+
"tui",
|
|
50
|
+
"tmux",
|
|
51
|
+
"git-worktree",
|
|
52
|
+
"multi-agent",
|
|
53
|
+
"parallel",
|
|
54
|
+
"coding-assistant"
|
|
55
|
+
],
|
|
56
|
+
"license": "MIT"
|
|
57
|
+
}
|