Add VIBETUNNEL_PREFER_DERIVED_DATA support and version tracking

- Add VIBETUNNEL_PREFER_DERIVED_DATA environment variable to vt script
  - When set, prefers VibeTunnel builds from Xcode's DerivedData
  - Logs binary location, version, and build timestamp
  - Falls back to /Applications if no DerivedData build found
- Add version and buildDate to StatusResponse interface
- Include version info in api-socket-server status responses
- Add comprehensive documentation in README.md
- Version info already stored in session.json (was pre-existing)

This helps developers easily test changes without installing to /Applications
This commit is contained in:
Peter Steinberger 2025-07-28 02:05:39 +02:00
parent 60e33948b2
commit cd6cbd8d6e
4 changed files with 86 additions and 16 deletions

View file

@ -862,6 +862,35 @@ VIBETUNNEL_DEBUG=1 vt your-command
Debug logs are written to `~/.vibetunnel/log.txt`.
### Using Development Builds with vt
When developing VibeTunnel, you can use the `VIBETUNNEL_PREFER_DERIVED_DATA` environment variable to make the `vt` command prefer development builds from Xcode's DerivedData folder:
```bash
# Enable DerivedData preference
export VIBETUNNEL_PREFER_DERIVED_DATA=1
# vt will now search for and use the latest VibeTunnel build from DerivedData
vt your-command
```
When this environment variable is set, `vt` will:
1. First search for VibeTunnel builds in `~/Library/Developer/Xcode/DerivedData`
2. Use the most recently modified build found there
3. Fall back to `/Applications/VibeTunnel.app` if no DerivedData build exists
4. Log the exact binary location, version, and build timestamp being used
This is particularly useful for:
- Testing changes without installing to `/Applications`
- Working with multiple VibeTunnel builds simultaneously
- Quickly switching between development and production versions
- Debugging which version of VibeTunnel is being used
The version information is also:
- Stored in `session.json` for each session
- Displayed in `vt status` output
- Shown in the initial log output when `VIBETUNNEL_PREFER_DERIVED_DATA` is set
### Verbosity Control
Control the amount of output from VibeTunnel commands:

View file

@ -20,28 +20,47 @@ if [[ "$OSTYPE" == "darwin"* ]]; then
# Get the real path of this script to avoid infinite recursion
SCRIPT_REAL_PATH="$(resolve_symlink_macos "${BASH_SOURCE[0]}")"
# Comprehensive Mac app search - try standard locations first, then development locations
# Comprehensive Mac app search - order depends on VIBETUNNEL_PREFER_DERIVED_DATA
APP_PATH=""
# First try standard locations with valid binary check
for TRY_PATH in "/Applications/VibeTunnel.app" "$HOME/Applications/VibeTunnel.app"; do
if [ -d "$TRY_PATH" ] && [ -f "$TRY_PATH/Contents/Resources/vibetunnel" ]; then
VT_SCRIPT="$TRY_PATH/Contents/Resources/vt"
if [ -f "$VT_SCRIPT" ] && [ -x "$VT_SCRIPT" ]; then
# Avoid infinite recursion by checking if this is the same script
VT_REAL_PATH="$(resolve_symlink_macos "$VT_SCRIPT")"
if [ "$SCRIPT_REAL_PATH" != "$VT_REAL_PATH" ]; then
exec "$VT_SCRIPT" "$@"
if [ -n "$VIBETUNNEL_PREFER_DERIVED_DATA" ]; then
# When preference is set, try DerivedData first
for CANDIDATE in $(find ~/Library/Developer/Xcode/DerivedData -name "VibeTunnel.app" -type d 2>/dev/null | grep -v "\.dSYM" | grep -v "Index\.noindex" | sort -r); do
if [ -f "$CANDIDATE/Contents/Resources/vibetunnel" ]; then
VT_SCRIPT="$CANDIDATE/Contents/Resources/vt"
if [ -f "$VT_SCRIPT" ] && [ -x "$VT_SCRIPT" ]; then
VT_REAL_PATH="$(resolve_symlink_macos "$VT_SCRIPT")"
if [ "$SCRIPT_REAL_PATH" != "$VT_REAL_PATH" ]; then
exec "$VT_SCRIPT" "$@"
fi
fi
APP_PATH="$CANDIDATE"
break
fi
APP_PATH="$TRY_PATH"
break
fi
done
done
fi
# If not found in standard locations, search for development builds
# If not found yet, try standard locations
if [ -z "$APP_PATH" ]; then
# First try DerivedData (for development)
for TRY_PATH in "/Applications/VibeTunnel.app" "$HOME/Applications/VibeTunnel.app"; do
if [ -d "$TRY_PATH" ] && [ -f "$TRY_PATH/Contents/Resources/vibetunnel" ]; then
VT_SCRIPT="$TRY_PATH/Contents/Resources/vt"
if [ -f "$VT_SCRIPT" ] && [ -x "$VT_SCRIPT" ]; then
# Avoid infinite recursion by checking if this is the same script
VT_REAL_PATH="$(resolve_symlink_macos "$VT_SCRIPT")"
if [ "$SCRIPT_REAL_PATH" != "$VT_REAL_PATH" ]; then
exec "$VT_SCRIPT" "$@"
fi
fi
APP_PATH="$TRY_PATH"
break
fi
done
fi
# If not found in standard locations and VIBETUNNEL_PREFER_DERIVED_DATA wasn't set, search development builds
if [ -z "$APP_PATH" ] && [ -z "$VIBETUNNEL_PREFER_DERIVED_DATA" ]; then
# Try DerivedData (for development)
for CANDIDATE in $(find ~/Library/Developer/Xcode/DerivedData -name "VibeTunnel.app" -type d 2>/dev/null | grep -v "\.dSYM" | grep -v "Index\.noindex"); do
if [ -f "$CANDIDATE/Contents/Resources/vibetunnel" ]; then
VT_SCRIPT="$CANDIDATE/Contents/Resources/vt"
@ -105,6 +124,23 @@ if [ -z "$VIBETUNNEL_BIN" ]; then
fi
fi
# Log VibeTunnel binary info when VIBETUNNEL_PREFER_DERIVED_DATA is set
if [ -n "$VIBETUNNEL_PREFER_DERIVED_DATA" ] && [ -n "$VIBETUNNEL_BIN" ]; then
# Get version and build info
VERSION_OUTPUT=$("$VIBETUNNEL_BIN" --version 2>&1)
VERSION_LINE=$(echo "$VERSION_OUTPUT" | grep "^VibeTunnel Server" | head -n 1)
BUILD_LINE=$(echo "$VERSION_OUTPUT" | grep "^Built:" | head -n 1)
# Always log this info regardless of verbosity level
echo "[VibeTunnel] Using binary: $VIBETUNNEL_BIN"
if [ -n "$VERSION_LINE" ]; then
echo "[VibeTunnel] Version: ${VERSION_LINE#VibeTunnel Server }"
fi
if [ -n "$BUILD_LINE" ]; then
echo "[VibeTunnel] ${BUILD_LINE}"
fi
fi
# Check if we're already inside a VibeTunnel session
if [ -n "$VIBETUNNEL_SESSION_ID" ]; then
# Special case: handle 'vt title' command inside a session

View file

@ -23,6 +23,7 @@ import { createGitError } from './utils/git-error.js';
import { areHooksInstalled, installGitHooks, uninstallGitHooks } from './utils/git-hooks.js';
import { createLogger } from './utils/logger.js';
import { prettifyPath } from './utils/path-prettify.js';
import { BUILD_DATE, VERSION } from './version.js';
import { createControlEvent } from './websocket/control-protocol.js';
import { controlUnixHandler } from './websocket/control-unix-handler.js';
@ -255,6 +256,8 @@ export class ApiSocketServer {
running: true,
port: this.serverPort,
url: this.serverUrl,
version: VERSION,
buildDate: BUILD_DATE,
followMode,
};

View file

@ -90,6 +90,8 @@ export interface StatusResponse {
running: boolean;
port?: number;
url?: string;
version?: string;
buildDate?: string;
followMode?: {
enabled: boolean;
branch?: string;