mirror of
https://github.com/samsonjs/vibetunnel.git
synced 2026-03-25 09:25:50 +00:00
Add new vt binary that supports both rust and go
This commit is contained in:
parent
ae270d66f8
commit
943410fc1c
7 changed files with 346 additions and 190 deletions
6
.gitignore
vendored
6
.gitignore
vendored
|
|
@ -105,3 +105,9 @@ Workspace.xcworkspace/
|
|||
|
||||
# Sparkle private keys - NEVER commit these
|
||||
private/
|
||||
|
||||
# Built binaries (should be built during build process)
|
||||
linux/vibetunnel
|
||||
linux/vt
|
||||
VibeTunnel/Resources/vt
|
||||
VibeTunnel/Resources/vibetunnel
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@
|
|||
B2C3D4E5F6A7B8C9D0E1F234 /* Build Web Frontend */,
|
||||
A189466CB0AD49BEBE16B954 /* Build tty-fwd Universal Binary */,
|
||||
C2D3E4F5A6B7C8D9E0F1A234 /* Build Go vibetunnel Universal Binary */,
|
||||
D3E4F5A6B7C8D9E0F1A2B345 /* Build VT Universal Binary */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
|
|
@ -283,6 +284,29 @@
|
|||
shellPath = /bin/sh;
|
||||
shellScript = "# Build Go vibetunnel universal binary\necho \"Building Go vibetunnel universal binary...\"\n\n# Get the project directory\nPROJECT_DIR=\"${SRCROOT}\"\nLINUX_DIR=\"${PROJECT_DIR}/linux\"\nBUILD_SCRIPT=\"${LINUX_DIR}/build-universal.sh\"\n\n# Source Go environment\n[ -f \"$HOME/.profile\" ] && . \"$HOME/.profile\"\n[ -f \"$HOME/.zprofile\" ] && . \"$HOME/.zprofile\"\n\n# Check if go is available\nif ! command -v go &> /dev/null; then\n echo \"warning: go could not be found in PATH. Skipping Go binary build.\"\n echo \"PATH is: $PATH\"\n echo \"To enable Go server support, please install Go and ensure it's in your PATH\"\n # Create a dummy file so the build doesn't fail\n mkdir -p \"${BUILT_PRODUCTS_DIR}/${CONTENTS_FOLDER_PATH}/Resources\"\n touch \"${BUILT_PRODUCTS_DIR}/${CONTENTS_FOLDER_PATH}/Resources/vibetunnel.disabled\"\n exit 0\nfi\n\nSOURCE_BINARY=\"${LINUX_DIR}/build/vibetunnel-universal\"\nDEST_BINARY=\"${BUILT_PRODUCTS_DIR}/${CONTENTS_FOLDER_PATH}/Resources/vibetunnel\"\n\n# Check if build script exists\nif [ ! -f \"${BUILD_SCRIPT}\" ]; then\n echo \"error: Build script not found at ${BUILD_SCRIPT}\"\n exit 1\nfi\n\n# Make build script executable\nchmod +x \"${BUILD_SCRIPT}\"\n\n# Change to linux directory and run build\ncd \"${LINUX_DIR}\"\n./build-universal.sh\n\n# Check if build succeeded\nif [ ! -f \"${SOURCE_BINARY}\" ]; then\n echo \"error: Universal binary not found at ${SOURCE_BINARY}\"\n exit 1\nfi\n\n# Create Resources directory if it doesn't exist\nmkdir -p \"${BUILT_PRODUCTS_DIR}/${CONTENTS_FOLDER_PATH}/Resources\"\n\n# Copy the binary\ncp \"${SOURCE_BINARY}\" \"${DEST_BINARY}\"\nchmod +x \"${DEST_BINARY}\"\n\n# Sign the binary\necho \"Signing Go vibetunnel binary...\"\ncodesign --force --sign - \"${DEST_BINARY}\"\n\necho \"Go vibetunnel universal binary copied and signed to ${DEST_BINARY}\"\n";
|
||||
};
|
||||
D3E4F5A6B7C8D9E0F1A2B345 /* Build VT Universal Binary */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"$(SRCROOT)/linux/cmd/vt/main.go",
|
||||
"$(SRCROOT)/linux/go.mod",
|
||||
"$(SRCROOT)/linux/build-vt-universal.sh",
|
||||
);
|
||||
name = "Build VT Universal Binary";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(BUILT_PRODUCTS_DIR)/$(CONTENTS_FOLDER_PATH)/Resources/vt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "#!/bin/bash\nset -e\n\necho \"Building VT universal binary...\"\n\n# Get the project directory\nPROJECT_DIR=\"${SRCROOT}\"\nLINUX_DIR=\"${PROJECT_DIR}/linux\"\n\n# Source Go environment\n[ -f \"$HOME/.profile\" ] && . \"$HOME/.profile\"\n[ -f \"$HOME/.zprofile\" ] && . \"$HOME/.zprofile\"\n\n# Check if go is available\nif ! command -v go &> /dev/null; then\n echo \"warning: go could not be found in PATH. Skipping VT binary build.\"\n echo \"PATH is: $PATH\"\n echo \"To enable VT CLI support, please install Go and ensure it's in your PATH\"\n # Don't fail the build, just skip VT\n exit 0\nfi\n\n# Build the VT binary\ncd \"$LINUX_DIR\"\n./build-vt-universal.sh \"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/Resources/vt\"\n\n# Sign the binary\nif [ -f \"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/Resources/vt\" ]; then\n echo \"Signing VT binary...\"\n codesign --force --sign - \"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/Resources/vt\"\n echo \"VT binary built and signed successfully\"\nelse\n echo \"error: VT binary was not created\"\n exit 1\nfi\n";
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
|
|
|
|||
|
|
@ -1,190 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# vt - VibeTunnel TTY Forward Wrapper
|
||||
# This script wraps tty-fwd to enable VibeTunnel to see command output
|
||||
|
||||
# Function to find Claude executable in common locations
|
||||
find_claude() {
|
||||
local claude_paths=(
|
||||
"$HOME/.claude/local/claude"
|
||||
"$HOME/.claude/local/node_modules/.bin/claude"
|
||||
"/opt/homebrew/bin/claude"
|
||||
"/usr/local/bin/claude"
|
||||
"/usr/bin/claude"
|
||||
"$(which claude 2>/dev/null)"
|
||||
)
|
||||
|
||||
for path in "${claude_paths[@]}"; do
|
||||
if [[ -n "$path" && -x "$path" ]]; then
|
||||
echo "$path"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Error: Claude executable not found in any of the following locations:" >&2
|
||||
printf " %s\n" "${claude_paths[@]}" >&2
|
||||
echo "Please ensure Claude is installed or specify the full path manually." >&2
|
||||
return 1
|
||||
}
|
||||
|
||||
# Get the real path of this script, resolving any symlinks
|
||||
SCRIPT_REAL_PATH="$(readlink -f "${BASH_SOURCE[0]}" 2>/dev/null || greadlink -f "${BASH_SOURCE[0]}" 2>/dev/null || realpath "${BASH_SOURCE[0]}" 2>/dev/null)"
|
||||
if [[ -z "$SCRIPT_REAL_PATH" ]]; then
|
||||
# Fallback for systems without readlink -f, greadlink, or realpath
|
||||
SCRIPT_REAL_PATH="${BASH_SOURCE[0]}"
|
||||
while [[ -L "$SCRIPT_REAL_PATH" ]]; do
|
||||
SCRIPT_REAL_PATH="$(readlink "$SCRIPT_REAL_PATH")"
|
||||
done
|
||||
fi
|
||||
|
||||
# Get the directory where this script is actually located (Resources folder)
|
||||
SCRIPT_DIR="$(cd "$(dirname "$SCRIPT_REAL_PATH")" && pwd)"
|
||||
|
||||
# Path to tty-fwd executable in the same Resources directory
|
||||
TTY_FWD="$SCRIPT_DIR/tty-fwd"
|
||||
|
||||
# Check if tty-fwd exists there, otherwise use the one from ../tty-fwd/target/debug/tty-fwd
|
||||
if [[ ! -x "$TTY_FWD" ]]; then
|
||||
TTY_FWD="$SCRIPT_DIR/../tty-fwd/target/debug/tty-fwd"
|
||||
if [[ ! -x "$TTY_FWD" ]]; then
|
||||
echo "Error: tty-fwd executable not found at $TTY_FWD" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Handle --claude option
|
||||
if [[ "$1" == "--claude" ]]; then
|
||||
shift
|
||||
claude_path="$(find_claude)"
|
||||
if [[ $? -ne 0 ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Re-execute vt with claude and remaining arguments
|
||||
exec "$0" "$claude_path" "$@"
|
||||
fi
|
||||
|
||||
# Handle --claude-yolo option
|
||||
if [[ "$1" == "--claude-yolo" ]]; then
|
||||
shift
|
||||
claude_path="$(find_claude)"
|
||||
if [[ $? -ne 0 ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Re-execute vt with claude --dangerously-skip-permissions and remaining arguments
|
||||
exec "$0" "$claude_path" --dangerously-skip-permissions "$@"
|
||||
fi
|
||||
|
||||
# Handle --show-session-info option
|
||||
if [[ "$1" == "--show-session-info" ]]; then
|
||||
shift
|
||||
exec "$TTY_FWD" --show-session-info "$@"
|
||||
fi
|
||||
|
||||
# Handle --show-session-id option
|
||||
if [[ "$1" == "--show-session-id" ]]; then
|
||||
shift
|
||||
exec "$TTY_FWD" --show-session-id "$@"
|
||||
fi
|
||||
|
||||
# Handle --shell or -i option (launch current shell)
|
||||
if [[ "$1" == "--shell" || "$1" == "-i" ]]; then
|
||||
shift
|
||||
# Execute current shell through tty-fwd
|
||||
exec "$0" "${SHELL:-/bin/bash}" "$@"
|
||||
fi
|
||||
|
||||
# Handle --no-shell-wrap or -S option
|
||||
NO_SHELL_WRAP=false
|
||||
if [[ "$1" == "--no-shell-wrap" || "$1" == "-S" ]]; then
|
||||
NO_SHELL_WRAP=true
|
||||
shift
|
||||
fi
|
||||
|
||||
if [[ $# -eq 0 || "$1" == "--help" || "$1" == "-h" ]]; then
|
||||
cat << 'EOF'
|
||||
vt - VibeTunnel TTY Forward Wrapper
|
||||
|
||||
USAGE:
|
||||
vt [command] [args...]
|
||||
vt --claude [args...]
|
||||
vt --claude-yolo [args...]
|
||||
vt --shell [args...]
|
||||
vt -i [args...]
|
||||
vt --no-shell-wrap [command] [args...]
|
||||
vt --show-session-info
|
||||
vt --show-session-id
|
||||
vt -S [command] [args...]
|
||||
vt --help
|
||||
|
||||
DESCRIPTION:
|
||||
This wrapper script allows VibeTunnel to see the output of commands by
|
||||
forwarding TTY data through the tty-fwd utility. When you run commands
|
||||
through 'vt', VibeTunnel can monitor and display the command's output
|
||||
in real-time.
|
||||
|
||||
By default, commands are executed through your shell to resolve aliases,
|
||||
functions, and builtins. Use --no-shell-wrap to execute commands directly.
|
||||
|
||||
EXAMPLES:
|
||||
vt top # Watch top with VibeTunnel monitoring
|
||||
vt python script.py # Run Python script with output forwarding
|
||||
vt npm test # Run tests with VibeTunnel visibility
|
||||
vt --claude # Auto-locate and run Claude
|
||||
vt --claude --help # Run Claude with --help option
|
||||
vt --claude-yolo # Run Claude with --dangerously-skip-permissions
|
||||
vt --shell # Launch current shell (equivalent to vt $SHELL)
|
||||
vt -i # Launch current shell (short form)
|
||||
vt -S ls -la # List files without shell alias resolution
|
||||
|
||||
OPTIONS:
|
||||
--claude Auto-locate Claude executable and run it
|
||||
--claude-yolo Auto-locate Claude and run with --dangerously-skip-permissions
|
||||
--shell, -i Launch current shell (equivalent to vt $SHELL)
|
||||
--no-shell-wrap, -S Execute command directly without shell wrapper
|
||||
--help, -h Show this help message and exit
|
||||
--show-session-info Show current session info
|
||||
--show-session-id Show current session ID only
|
||||
|
||||
NOTE:
|
||||
This script automatically uses the tty-fwd executable bundled with
|
||||
VibeTunnel from the Resources folder.
|
||||
EOF
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Function to resolve command through user's shell
|
||||
resolve_command() {
|
||||
local user_shell="${SHELL:-/bin/bash}"
|
||||
local cmd="$1"
|
||||
shift
|
||||
|
||||
local shell_name=$(basename "$user_shell")
|
||||
|
||||
# Always try through shell first to handle aliases, functions, and builtins
|
||||
# The shell will fall back to PATH lookup if no alias/function exists
|
||||
case "$shell_name" in
|
||||
zsh)
|
||||
# For zsh, we need interactive mode to get aliases
|
||||
exec "$TTY_FWD" -- "$user_shell" -i -c "$(printf '%q ' "$cmd" "$@")"
|
||||
;;
|
||||
bash)
|
||||
# For bash, expand aliases in non-interactive mode
|
||||
exec "$TTY_FWD" -- "$user_shell" -c "shopt -s expand_aliases; source ~/.bashrc 2>/dev/null || source ~/.bash_profile 2>/dev/null || true; $(printf '%q ' "$cmd" "$@")"
|
||||
;;
|
||||
*)
|
||||
# Generic shell handling
|
||||
exec "$TTY_FWD" -- "$user_shell" -c "$(printf '%q ' "$cmd" "$@")"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Resolve and execute the command
|
||||
if [[ "$NO_SHELL_WRAP" == "true" ]]; then
|
||||
# Execute directly without shell wrapper
|
||||
exec "$TTY_FWD" -- "$@"
|
||||
else
|
||||
# Use shell wrapper to resolve aliases/functions/builtins
|
||||
resolve_command "$@"
|
||||
fi
|
||||
36
linux/build-vt-universal.sh
Executable file
36
linux/build-vt-universal.sh
Executable file
|
|
@ -0,0 +1,36 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Build universal vt binary for macOS
|
||||
|
||||
echo "Building vt universal binary..."
|
||||
|
||||
# Get the directory where this script is located
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
cd "$SCRIPT_DIR"
|
||||
|
||||
# Build for x86_64
|
||||
echo "Building vt for x86_64..."
|
||||
GOOS=darwin GOARCH=amd64 go build -o vt-x86_64 ./cmd/vt
|
||||
|
||||
# Build for arm64
|
||||
echo "Building vt for arm64..."
|
||||
GOOS=darwin GOARCH=arm64 go build -o vt-arm64 ./cmd/vt
|
||||
|
||||
# Create universal binary
|
||||
echo "Creating universal binary..."
|
||||
lipo -create -output vt vt-x86_64 vt-arm64
|
||||
|
||||
# Clean up architecture-specific binaries
|
||||
rm vt-x86_64 vt-arm64
|
||||
|
||||
# Make it executable
|
||||
chmod +x vt
|
||||
|
||||
echo "vt universal binary built successfully at: $SCRIPT_DIR/vt"
|
||||
|
||||
# Copy to target location if provided
|
||||
if [ -n "$1" ]; then
|
||||
echo "Copying vt to $1"
|
||||
cp vt "$1"
|
||||
fi
|
||||
1
linux/claude
Executable file
1
linux/claude
Executable file
|
|
@ -0,0 +1 @@
|
|||
echo "Claude called with args: $@"
|
||||
277
linux/cmd/vt/main.go
Normal file
277
linux/cmd/vt/main.go
Normal file
|
|
@ -0,0 +1,277 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
const Version = "1.0.0"
|
||||
|
||||
type Config struct {
|
||||
Server string `json:"server,omitempty"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Debug incoming args
|
||||
if os.Getenv("VT_DEBUG") != "" {
|
||||
fmt.Fprintf(os.Stderr, "VT Debug: args = %v\n", os.Args)
|
||||
}
|
||||
|
||||
// Handle version flag only if it's the only argument
|
||||
if len(os.Args) == 2 && (os.Args[1] == "--version" || os.Args[1] == "-v") {
|
||||
fmt.Printf("vt version %s\n", Version)
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
// Get preferred server
|
||||
server := getPreferredServer()
|
||||
|
||||
// Forward to appropriate server
|
||||
var err error
|
||||
switch server {
|
||||
case "rust":
|
||||
err = forwardToRustServer(os.Args[1:])
|
||||
case "go":
|
||||
err = forwardToGoServer(os.Args[1:])
|
||||
default:
|
||||
err = forwardToGoServer(os.Args[1:])
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
// If the command exited with a specific code, preserve it
|
||||
if exitErr, ok := err.(*exec.ExitError); ok {
|
||||
if status, ok := exitErr.Sys().(syscall.WaitStatus); ok {
|
||||
os.Exit(status.ExitStatus())
|
||||
}
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "vt: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func getPreferredServer() string {
|
||||
// Check environment variable first
|
||||
if server := os.Getenv("VT_SERVER"); server != "" {
|
||||
if server == "rust" || server == "go" {
|
||||
return server
|
||||
}
|
||||
}
|
||||
|
||||
// Read from config file
|
||||
configPath := filepath.Join(os.Getenv("HOME"), ".vibetunnel", "config.json")
|
||||
data, err := os.ReadFile(configPath)
|
||||
if err != nil {
|
||||
return "go" // default
|
||||
}
|
||||
|
||||
var config Config
|
||||
if err := json.Unmarshal(data, &config); err != nil {
|
||||
return "go" // default on parse error
|
||||
}
|
||||
|
||||
if config.Server == "rust" || config.Server == "go" {
|
||||
return config.Server
|
||||
}
|
||||
return "go" // default for invalid values
|
||||
}
|
||||
|
||||
func forwardToGoServer(args []string) error {
|
||||
// Find vibetunnel binary
|
||||
vibetunnelPath := findVibetunnelBinary()
|
||||
if vibetunnelPath == "" {
|
||||
return fmt.Errorf("vibetunnel binary not found")
|
||||
}
|
||||
|
||||
// Check if this is a special VT command
|
||||
var finalArgs []string
|
||||
if len(args) > 0 && isVTSpecialCommand(args[0]) {
|
||||
// Translate special VT commands
|
||||
finalArgs = translateVTToGoArgs(args)
|
||||
} else {
|
||||
// For regular commands, just prepend -- to tell vibetunnel to stop parsing
|
||||
finalArgs = append([]string{"--"}, args...)
|
||||
}
|
||||
|
||||
// Debug: print what we're executing
|
||||
if os.Getenv("VT_DEBUG") != "" {
|
||||
fmt.Fprintf(os.Stderr, "VT Debug: executing %s with args: %v\n", vibetunnelPath, finalArgs)
|
||||
}
|
||||
|
||||
// Create command
|
||||
cmd := exec.Command(vibetunnelPath, finalArgs...)
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
|
||||
// Run and return
|
||||
return cmd.Run()
|
||||
}
|
||||
|
||||
func isVTSpecialCommand(arg string) bool {
|
||||
switch arg {
|
||||
case "--claude", "--claude-yolo", "--shell", "-i",
|
||||
"--no-shell-wrap", "-S", "--show-session-info", "--show-session-id":
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func forwardToRustServer(args []string) error {
|
||||
// Find tty-fwd binary
|
||||
ttyFwdPath := findTtyFwdBinary()
|
||||
if ttyFwdPath == "" {
|
||||
return fmt.Errorf("tty-fwd binary not found")
|
||||
}
|
||||
|
||||
// Create command with original args (tty-fwd already understands vt args)
|
||||
cmd := exec.Command(ttyFwdPath, args...)
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
|
||||
// Run and return
|
||||
return cmd.Run()
|
||||
}
|
||||
|
||||
func translateVTToGoArgs(args []string) []string {
|
||||
if len(args) == 0 {
|
||||
return args
|
||||
}
|
||||
|
||||
// Check for special vt-only flags
|
||||
switch args[0] {
|
||||
case "--claude":
|
||||
// Find Claude and run it with any additional arguments
|
||||
claudePath := findClaude()
|
||||
if claudePath != "" {
|
||||
// Pass all remaining args to claude
|
||||
result := []string{"--", claudePath}
|
||||
if len(args) > 1 {
|
||||
result = append(result, args[1:]...)
|
||||
}
|
||||
return result
|
||||
}
|
||||
// Fallback
|
||||
result := []string{"--", "claude"}
|
||||
if len(args) > 1 {
|
||||
result = append(result, args[1:]...)
|
||||
}
|
||||
return result
|
||||
|
||||
case "--claude-yolo":
|
||||
// Find Claude and run with permissions skip
|
||||
claudePath := findClaude()
|
||||
if claudePath != "" {
|
||||
return []string{"--", claudePath, "--dangerously-skip-permissions"}
|
||||
}
|
||||
return []string{"--", "claude", "--dangerously-skip-permissions"}
|
||||
|
||||
case "--shell", "-i":
|
||||
// Launch interactive shell
|
||||
shell := os.Getenv("SHELL")
|
||||
if shell == "" {
|
||||
shell = "/bin/bash"
|
||||
}
|
||||
return []string{"--", shell, "-i"}
|
||||
|
||||
case "--no-shell-wrap", "-S":
|
||||
// Direct execution without shell - skip the flag and pass rest
|
||||
if len(args) > 1 {
|
||||
return append([]string{"--"}, args[1:]...)
|
||||
}
|
||||
return []string{}
|
||||
|
||||
case "--show-session-info":
|
||||
return []string{"--list-sessions"}
|
||||
|
||||
case "--show-session-id":
|
||||
// This needs special handling - just pass through for now
|
||||
return args
|
||||
|
||||
default:
|
||||
// This shouldn't happen since we check isVTSpecialCommand first
|
||||
return args
|
||||
}
|
||||
}
|
||||
|
||||
func findVibetunnelBinary() string {
|
||||
// Check common locations
|
||||
paths := []string{
|
||||
// App bundle location
|
||||
"/Applications/VibeTunnel.app/Contents/Resources/vibetunnel",
|
||||
// Development locations
|
||||
"./vibetunnel",
|
||||
"../vibetunnel",
|
||||
"../../linux/vibetunnel",
|
||||
// Installed location
|
||||
"/usr/local/bin/vibetunnel",
|
||||
}
|
||||
|
||||
for _, path := range paths {
|
||||
if _, err := os.Stat(path); err == nil {
|
||||
return path
|
||||
}
|
||||
}
|
||||
|
||||
// Try to find in PATH
|
||||
if path, err := exec.LookPath("vibetunnel"); err == nil {
|
||||
return path
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func findTtyFwdBinary() string {
|
||||
// Check common locations
|
||||
paths := []string{
|
||||
// App bundle location
|
||||
"/Applications/VibeTunnel.app/Contents/Resources/tty-fwd",
|
||||
// Development locations
|
||||
"./tty-fwd",
|
||||
"../tty-fwd",
|
||||
"../../tty-fwd/target/release/tty-fwd",
|
||||
// Installed location
|
||||
"/usr/local/bin/tty-fwd",
|
||||
}
|
||||
|
||||
for _, path := range paths {
|
||||
if _, err := os.Stat(path); err == nil {
|
||||
return path
|
||||
}
|
||||
}
|
||||
|
||||
// Try to find in PATH
|
||||
if path, err := exec.LookPath("tty-fwd"); err == nil {
|
||||
return path
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func findClaude() string {
|
||||
// Check common Claude installation paths
|
||||
claudePaths := []string{
|
||||
filepath.Join(os.Getenv("HOME"), ".claude", "local", "claude"),
|
||||
"/opt/homebrew/bin/claude",
|
||||
"/usr/local/bin/claude",
|
||||
"/usr/bin/claude",
|
||||
}
|
||||
|
||||
for _, path := range claudePaths {
|
||||
if _, err := os.Stat(path); err == nil {
|
||||
return path
|
||||
}
|
||||
}
|
||||
|
||||
// Try PATH
|
||||
if path, err := exec.LookPath("claude"); err == nil {
|
||||
return path
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
2
linux/test-vt.sh
Executable file
2
linux/test-vt.sh
Executable file
|
|
@ -0,0 +1,2 @@
|
|||
#!/bin/bash
|
||||
VT_DEBUG=1 ./vt claude --dangerously-skip-permissions
|
||||
Loading…
Reference in a new issue