@seflless/ghosttown 1.4.1 → 1.5.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/cli.js +44 -32
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seflless/ghosttown",
3
- "version": "1.4.1",
3
+ "version": "1.5.0",
4
4
  "description": "Web-based terminal emulator using Ghostty's VT100 parser via WebAssembly",
5
5
  "type": "module",
6
6
  "main": "./dist/ghostty-web.umd.cjs",
package/src/cli.js CHANGED
@@ -100,16 +100,16 @@ function getCurrentTmuxSessionName() {
100
100
  }
101
101
 
102
102
  /**
103
- * Check if currently inside a ghosttown session (named ghosttown-<N>)
103
+ * Check if currently inside a ghosttown session (named gt-<N>)
104
104
  */
105
105
  function isInsideGhosttownSession() {
106
106
  const sessionName = getCurrentTmuxSessionName();
107
- return sessionName && sessionName.startsWith('ghosttown-');
107
+ return sessionName && sessionName.startsWith('gt-');
108
108
  }
109
109
 
110
110
  /**
111
111
  * Get the next available ghosttown session ID
112
- * Scans existing tmux sessions named ghosttown-<N> and returns max(N) + 1
112
+ * Scans existing tmux sessions named gt-<N> and returns max(N) + 1
113
113
  */
114
114
  function getNextSessionId() {
115
115
  try {
@@ -119,12 +119,12 @@ function getNextSessionId() {
119
119
  stdio: ['pipe', 'pipe', 'pipe'],
120
120
  });
121
121
 
122
- // Find all ghosttown-<N> sessions and extract IDs
122
+ // Find all gt-<N> sessions and extract IDs
123
123
  const sessionIds = output
124
124
  .split('\n')
125
- .filter((name) => name.startsWith('ghosttown-'))
125
+ .filter((name) => name.startsWith('gt-'))
126
126
  .map((name) => {
127
- const id = Number.parseInt(name.replace('ghosttown-', ''), 10);
127
+ const id = Number.parseInt(name.replace('gt-', ''), 10);
128
128
  return Number.isNaN(id) ? 0 : id;
129
129
  });
130
130
 
@@ -150,9 +150,9 @@ function listSessions() {
150
150
  const BEIGE = '\x1b[38;2;255;220;150m';
151
151
 
152
152
  try {
153
- // Get detailed session information
153
+ // Get detailed session information including last activity time
154
154
  const output = execSync(
155
- 'tmux list-sessions -F "#{session_name}|#{session_created}|#{session_attached}|#{session_windows}"',
155
+ 'tmux list-sessions -F "#{session_name}|#{session_activity}|#{session_attached}|#{session_windows}"',
156
156
  {
157
157
  encoding: 'utf8',
158
158
  stdio: ['pipe', 'pipe', 'pipe'],
@@ -161,12 +161,15 @@ function listSessions() {
161
161
 
162
162
  const sessions = output
163
163
  .split('\n')
164
- .filter((line) => line.startsWith('ghosttown-'))
164
+ .filter((line) => line.startsWith('gt-'))
165
165
  .map((line) => {
166
- const [name, created, attached, windows] = line.split('|');
166
+ const [name, activity, attached, windows] = line.split('|');
167
+ // Extract just the number from gt-<N>
168
+ const id = name.replace('gt-', '');
167
169
  return {
170
+ id,
168
171
  name,
169
- created: new Date(Number.parseInt(created, 10) * 1000),
172
+ activity: new Date(Number.parseInt(activity, 10) * 1000),
170
173
  attached: attached === '1',
171
174
  windows: Number.parseInt(windows, 10),
172
175
  };
@@ -179,21 +182,24 @@ function listSessions() {
179
182
  process.exit(0);
180
183
  }
181
184
 
185
+ // Sort by last activity (most recent first)
186
+ sessions.sort((a, b) => b.activity.getTime() - a.activity.getTime());
187
+
182
188
  // Print header
183
189
  console.log('\n\x1b[1mGhosttown Sessions\x1b[0m\n');
184
190
  console.log(
185
- `${CYAN}${'Name'.padEnd(15)} ${'Created'.padEnd(22)} ${'Status'.padEnd(10)} Windows${RESET}`
191
+ `${CYAN}${'ID'.padEnd(6)} ${'Last Activity'.padEnd(22)} ${'Status'.padEnd(10)} Windows${RESET}`
186
192
  );
187
193
 
188
194
  // Print sessions
189
195
  for (const session of sessions) {
190
- const createdStr = session.created.toLocaleString();
196
+ const activityStr = session.activity.toLocaleString();
191
197
  // Status has ANSI codes so we need to pad the visible text differently
192
198
  const statusPadded = session.attached
193
199
  ? `\x1b[32m${'attached'.padEnd(10)}${RESET}`
194
200
  : `\x1b[33m${'detached'.padEnd(10)}${RESET}`;
195
201
  console.log(
196
- `${session.name.padEnd(15)} ${createdStr.padEnd(22)} ${statusPadded} ${session.windows}`
202
+ `${session.id.padEnd(6)} ${activityStr.padEnd(22)} ${statusPadded} ${session.windows}`
197
203
  );
198
204
  }
199
205
 
@@ -221,7 +227,7 @@ function createTmuxSession(command) {
221
227
  }
222
228
 
223
229
  const sessionId = getNextSessionId();
224
- const sessionName = `ghosttown-${sessionId}`;
230
+ const sessionName = `gt-${sessionId}`;
225
231
 
226
232
  try {
227
233
  // Create tmux session and attach directly (not detached)
@@ -268,14 +274,17 @@ function printDetachMessage(sessionName) {
268
274
  const formatHint = (label, command) =>
269
275
  ` ${CYAN}${label.padStart(labelWidth)}${RESET} ${BEIGE}${command}${RESET}`;
270
276
 
277
+ // Extract just the ID from gt-<N>
278
+ const sessionId = sessionName.replace('gt-', '');
279
+
271
280
  return [
272
281
  '',
273
282
  ` ${BOLD_YELLOW}You've detached from your ghosttown session.${RESET}`,
274
283
  ` ${DIM}It's now running in the background.${RESET}`,
275
284
  '',
276
- formatHint('To reattach:', `ghosttown attach ${sessionName}`),
285
+ formatHint('To reattach:', `gt attach ${sessionId}`),
277
286
  '',
278
- formatHint('To list all sessions:', 'ghosttown list'),
287
+ formatHint('To list all sessions:', 'gt list'),
279
288
  '',
280
289
  '',
281
290
  ].join('\n');
@@ -369,9 +378,9 @@ function attachToSession(sessionName) {
369
378
  const RED = '\x1b[31m';
370
379
  const BEIGE = '\x1b[38;2;255;220;150m';
371
380
 
372
- // Add ghosttown- prefix if not present
373
- if (!sessionName.startsWith('ghosttown-')) {
374
- sessionName = `ghosttown-${sessionName}`;
381
+ // Add gt- prefix if not present
382
+ if (!sessionName.startsWith('gt-')) {
383
+ sessionName = `gt-${sessionName}`;
375
384
  }
376
385
 
377
386
  // Check if session exists
@@ -521,9 +530,9 @@ function killSession(sessionName) {
521
530
  sessionName = getCurrentTmuxSessionName();
522
531
  }
523
532
 
524
- // Add ghosttown- prefix if not present
525
- if (!sessionName.startsWith('ghosttown-')) {
526
- sessionName = `ghosttown-${sessionName}`;
533
+ // Add gt- prefix if not present
534
+ if (!sessionName.startsWith('gt-')) {
535
+ sessionName = `gt-${sessionName}`;
527
536
  }
528
537
 
529
538
  // Check if session exists
@@ -557,10 +566,13 @@ function killSession(sessionName) {
557
566
  stdio: 'pipe',
558
567
  });
559
568
 
569
+ // Extract just the ID from gt-<N>
570
+ const sessionId = sessionName.replace('gt-', '');
571
+
560
572
  console.log('');
561
- console.log(` ${BOLD_YELLOW}Session '${sessionName}' has been killed.${RESET}`);
573
+ console.log(` ${BOLD_YELLOW}Session ${sessionId} has been killed.${RESET}`);
562
574
  console.log('');
563
- console.log(` ${CYAN}To list remaining:${RESET} ${BEIGE}ghosttown list${RESET}`);
575
+ console.log(` ${CYAN}To list remaining:${RESET} ${BEIGE}gt list${RESET}`);
564
576
  console.log('');
565
577
  process.exit(0);
566
578
  } catch (err) {
@@ -590,26 +602,26 @@ Usage: ghosttown [options] [command]
590
602
 
591
603
  Options:
592
604
  -p, --port <port> Port to listen on (default: 8080, or PORT env var)
593
- -k, --kill [session] Kill a session (current if inside one, or specify)
605
+ -k, --kill [session] Kill a session (current if inside one, or specify by ID)
594
606
  -v, --version Show version number
595
607
  -h, --help Show this help message
596
608
 
597
609
  Commands:
598
610
  list List all ghosttown tmux sessions
599
- attach <session> Attach to a ghosttown session
611
+ attach <id> Attach to a ghosttown session by ID (e.g., 'gt attach 1')
600
612
  detach Detach from current ghosttown session
601
613
  update Update ghosttown to the latest version
602
- <command> Run command in a new tmux session (ghosttown-<id>)
614
+ <command> Run command in a new tmux session (gt-<id>)
603
615
 
604
616
  Examples:
605
617
  ghosttown Start the web terminal server
606
618
  ghosttown -p 3000 Start the server on port 3000
607
619
  ghosttown list List all ghosttown sessions
608
- ghosttown attach ghosttown-1 Attach to session ghosttown-1
620
+ ghosttown attach 1 Attach to session gt-1
609
621
  ghosttown detach Detach from current session
610
622
  ghosttown update Update to the latest version
611
623
  ghosttown -k Kill current session (when inside one)
612
- ghosttown -k ghosttown-1 Kill a specific session
624
+ ghosttown -k 1 Kill session gt-1
613
625
  ghosttown vim Run vim in a new tmux session
614
626
  ghosttown "npm run dev" Run npm in a new tmux session
615
627
 
@@ -652,8 +664,8 @@ Aliases:
652
664
  else if (arg === 'attach') {
653
665
  const sessionArg = args[i + 1];
654
666
  if (!sessionArg) {
655
- console.error('Error: attach requires a session name');
656
- console.error('Usage: ghosttown attach <session>');
667
+ console.error('Error: attach requires a session ID');
668
+ console.error('Usage: gt attach <id>');
657
669
  handled = true;
658
670
  break;
659
671
  }