sessioncast-cli 2.1.0 → 2.2.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.
@@ -184,7 +184,7 @@ class AgentRunner {
184
184
  const handler = new session_handler_1.TmuxSessionHandler({
185
185
  config: this.config,
186
186
  tmuxSession,
187
- onCreateSession: (name) => this.createTmuxSession(name)
187
+ onCreateSession: (name, workingDir) => this.createTmuxSession(name, workingDir)
188
188
  });
189
189
  this.handlers.set(tmuxSession, handler);
190
190
  handler.start();
@@ -199,7 +199,7 @@ class AgentRunner {
199
199
  console.log(`Stopped handler for session: ${this.config.machineId}/${tmuxSession}`);
200
200
  }
201
201
  }
202
- createTmuxSession(sessionName) {
202
+ createTmuxSession(sessionName, workingDir) {
203
203
  // Sanitize session name
204
204
  const sanitized = sessionName.replace(/[^a-zA-Z0-9_-]/g, '_');
205
205
  if (!sanitized) {
@@ -210,8 +210,8 @@ class AgentRunner {
210
210
  console.warn(`Session already exists: ${sanitized}`);
211
211
  return;
212
212
  }
213
- console.log(`Creating new tmux session: ${sanitized}`);
214
- if (tmux.createSession(sanitized)) {
213
+ console.log(`Creating new tmux session: ${sanitized}${workingDir ? ` (cwd: ${workingDir})` : ''}`);
214
+ if (tmux.createSession(sanitized, workingDir)) {
215
215
  console.log(`Successfully created tmux session: ${sanitized}`);
216
216
  // Force immediate scan
217
217
  this.scanAndUpdateSessions();
@@ -2,7 +2,7 @@ import { AgentConfig } from './types';
2
2
  interface SessionHandlerOptions {
3
3
  config: AgentConfig;
4
4
  tmuxSession: string;
5
- onCreateSession?: (name: string) => void;
5
+ onCreateSession?: (name: string, workingDir?: string) => void;
6
6
  }
7
7
  export declare class TmuxSessionHandler {
8
8
  private config;
@@ -52,6 +52,7 @@ export declare class TmuxSessionHandler {
52
52
  * Get content type from file extension
53
53
  */
54
54
  private getContentType;
55
+ private handleCreateWorktree;
55
56
  private startMetaTracking;
56
57
  private stopMetaTracking;
57
58
  private checkAndSendMeta;
@@ -38,6 +38,7 @@ const websocket_1 = require("./websocket");
38
38
  const tmux = __importStar(require("./tmux"));
39
39
  const fs = __importStar(require("fs"));
40
40
  const path = __importStar(require("path"));
41
+ const child_process_1 = require("child_process");
41
42
  const sentry_1 = require("../sentry");
42
43
  const debug_1 = require("./debug");
43
44
  // Capture intervals
@@ -133,6 +134,9 @@ class TmuxSessionHandler {
133
134
  this.wsClient.on('uploadFile', (chunk) => {
134
135
  this.handleUploadChunk(chunk);
135
136
  });
137
+ this.wsClient.on('createWorktree', (branch) => {
138
+ this.handleCreateWorktree(branch);
139
+ });
136
140
  this.wsClient.on('error', (error) => {
137
141
  (0, sentry_1.captureException)(error);
138
142
  console.error(`[${this.tmuxSession}] WebSocket error:`, error.message);
@@ -300,6 +304,41 @@ class TmuxSessionHandler {
300
304
  };
301
305
  return types[ext] || 'application/octet-stream';
302
306
  }
307
+ handleCreateWorktree(branch) {
308
+ try {
309
+ const cwd = tmux.getPaneCwd(this.tmuxSession);
310
+ if (!cwd) {
311
+ console.error(`[${this.tmuxSession}] Cannot create worktree: no cwd`);
312
+ return;
313
+ }
314
+ // Check if it's a git repo
315
+ try {
316
+ (0, child_process_1.execSync)('git rev-parse --is-inside-work-tree', { cwd, stdio: 'pipe', timeout: 5000 });
317
+ }
318
+ catch {
319
+ console.error(`[${this.tmuxSession}] Cannot create worktree: not a git repo`);
320
+ return;
321
+ }
322
+ // Sanitize branch name
323
+ const safeBranch = branch.replace(/[^a-zA-Z0-9_\-/.]/g, '-');
324
+ const worktreeDir = path.join(cwd, '.worktrees', safeBranch.replace(/\//g, '-'));
325
+ console.log(`[${this.tmuxSession}] Creating worktree: branch=${safeBranch}, dir=${worktreeDir}`);
326
+ // git worktree add
327
+ (0, child_process_1.execSync)(`git worktree add -b "${safeBranch}" "${worktreeDir}"`, {
328
+ cwd, stdio: 'pipe', timeout: 10000
329
+ });
330
+ // Create new tmux session at worktree path
331
+ const sessionName = safeBranch.replace(/\//g, '-');
332
+ if (this.onCreateSession) {
333
+ this.onCreateSession(sessionName, worktreeDir);
334
+ }
335
+ console.log(`[${this.tmuxSession}] Worktree created: ${worktreeDir}`);
336
+ (0, debug_1.debugLog)(this.tmuxSession, 'Worktree created', { branch: safeBranch, dir: worktreeDir, session: sessionName });
337
+ }
338
+ catch (error) {
339
+ console.error(`[${this.tmuxSession}] Worktree creation failed:`, error.message);
340
+ }
341
+ }
303
342
  startMetaTracking() {
304
343
  this.checkAndSendMeta();
305
344
  this.metaCheckTimer = setInterval(() => this.checkAndSendMeta(), META_CHECK_INTERVAL_MS);
@@ -143,6 +143,11 @@ class RelayWebSocketClient extends events_1.EventEmitter {
143
143
  this.emit('killSession');
144
144
  }
145
145
  break;
146
+ case 'createWorktree':
147
+ if (message.session === this.sessionId && message.meta?.branch) {
148
+ this.emit('createWorktree', message.meta.branch);
149
+ }
150
+ break;
146
151
  case 'requestFileView':
147
152
  if (message.session === this.sessionId && message.meta?.filePath) {
148
153
  this.emit('requestFileView', message.meta.filePath);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sessioncast-cli",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "description": "SessionCast CLI - Control your agents from anywhere",
5
5
  "main": "dist/index.js",
6
6
  "bin": {