Improve UI session names to use human-readable format

Replace ugly timestamp-based session names (session_1703123456789)
with human-readable format like "claude (~/Dev/vibetunnel/web)".

- Extract session naming logic into shared utility
- Update UI session creation to use same naming as CLI
- Consolidate abbreviatePath and generateSessionName functions
- Both CLI and UI sessions now use consistent readable names

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Armin Ronacher 2025-06-23 09:52:47 +02:00
parent 3c7b2855d3
commit cb9e7c640c
3 changed files with 56 additions and 5 deletions

View file

@ -17,6 +17,7 @@ import chalk from 'chalk';
import { PtyManager } from './pty/index.js';
import { VERSION, BUILD_DATE, GIT_COMMIT } from './version.js';
import { createLogger, closeLogger } from './utils/logger.js';
import { generateSessionName } from './utils/session-naming.js';
const logger = createLogger('fwd');
@ -79,8 +80,8 @@ export async function startVibeTunnelForward(args: string[]) {
const ptyManager = new PtyManager(controlPath);
try {
// Create the session
const sessionName = `fwd_${command[0]}_${Date.now()}`;
// Create a human-readable session name
const sessionName = generateSessionName(command, cwd);
// Pre-generate session ID if not provided
const finalSessionId = sessionId || `fwd_${Date.now()}`;

View file

@ -7,6 +7,7 @@ import { RemoteRegistry } from '../services/remote-registry.js';
import { ActivityMonitor } from '../services/activity-monitor.js';
import { cellsToText } from '../../shared/terminal-text-formatter.js';
import { createLogger } from '../utils/logger.js';
import { generateSessionName } from '../utils/session-naming.js';
import chalk from 'chalk';
import * as fs from 'fs';
import * as path from 'path';
@ -186,7 +187,8 @@ export function createSessionRoutes(config: SessionRoutesConfig): Router {
try {
// Generate session ID
const sessionId = generateSessionId();
const sessionName = name || `session_${Date.now()}`;
const sessionName =
name || generateSessionName(command, resolvePath(workingDir, process.cwd()));
// Request Mac app to spawn terminal
logger.log(
@ -227,9 +229,8 @@ export function createSessionRoutes(config: SessionRoutesConfig): Router {
}
// Create local session
const sessionName =
name || `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
const cwd = resolvePath(workingDir, process.cwd());
const sessionName = name || generateSessionName(command, cwd);
logger.log(chalk.blue(`creating session: ${command.join(' ')} in ${cwd}`));

View file

@ -0,0 +1,49 @@
import * as path from 'path';
import * as os from 'os';
/**
* Abbreviate a file path to make it more readable
* Examples:
* /Users/john/Projects/myproject -> ~/Projects/myproject
* /Users/john/Development/vibetunnel/web -> ~/Dev/vibetunnel/web
* /very/long/path/to/some/directory -> /some/directory
*/
export function abbreviatePath(fullPath: string): string {
if (!fullPath) return '';
const homedir = os.homedir();
let abbreviated = fullPath;
// Replace home directory with ~
if (fullPath.startsWith(homedir)) {
abbreviated = '~' + fullPath.slice(homedir.length);
}
// Common abbreviations
abbreviated = abbreviated
.replace('/Development/', '/Dev/')
.replace('/Documents/', '/Docs/')
.replace('/Applications/', '/Apps/');
// If still long, show only last 2 path components
const parts = abbreviated.split('/').filter((p) => p);
if (parts.length > 3) {
return '…/' + parts.slice(-2).join('/');
}
return abbreviated;
}
/**
* Generate a human-readable session name
* Format: commandName (abbreviatedPath)
* Examples:
* claude (~/Dev/vibetunnel/web)
* bash (~/Projects/myapp)
* python3 (~)
*/
export function generateSessionName(command: string[], workingDir: string): string {
const commandName = path.basename(command[0]);
const abbrevCwd = abbreviatePath(workingDir);
return abbrevCwd ? `${commandName} (${abbrevCwd})` : commandName;
}