tempo-cli 0.4.0

Automatic project time tracking CLI tool with beautiful terminal interface
Documentation
# Tempo shell hook for PowerShell
# Add this to your PowerShell profile

# Configuration
$env:TEMPO_BIN = if ($env:TEMPO_BIN) { $env:TEMPO_BIN } else { "tempo" }
$env:TEMPO_DEBUG = if ($env:TEMPO_DEBUG) { $env:TEMPO_DEBUG } else { "0" }
$env:TEMPO_HOOK_ENABLED = if ($env:TEMPO_HOOK_ENABLED) { $env:TEMPO_HOOK_ENABLED } else { "1" }

# Internal variables
$Global:_TEMPO_LAST_DIR = ""

# Debug logging function
function Write-TempoDebug {
    param([string]$Message)
    if ($env:TEMPO_DEBUG -eq "1") {
        Write-Host "[TEMPO DEBUG] $Message" -ForegroundColor Gray
    }
}

# Function to detect if a directory is a project
function Test-TempoProject {
    param([string]$Dir)
    
    # Check for git repository
    if (Test-Path (Join-Path $Dir ".git")) {
        return $true
    }
    
    # Check for .tempo marker
    if (Test-Path (Join-Path $Dir ".tempo")) {
        return $true
    }
    
    # Check for common project files
    $projectFiles = @(
        "package.json", "Cargo.toml", "pyproject.toml", "pom.xml", 
        "Makefile", "CMakeLists.txt", "go.mod", "composer.json",
        "*.sln", "*.csproj", "*.vbproj", "*.fsproj"
    )
    
    foreach ($file in $projectFiles) {
        if (Get-ChildItem -Path $Dir -Filter $file -ErrorAction SilentlyContinue) {
            return $true
        }
    }
    
    return $false
}

# Function to find the project root
function Find-TempoProjectRoot {
    param([string]$Dir)
    
    $originalDir = $Dir
    $currentDir = $Dir
    
    # Walk up the directory tree
    while ($currentDir -and $currentDir -ne [System.IO.Path]::GetPathRoot($currentDir)) {
        if (Test-TempoProject $currentDir) {
            return $currentDir
        }
        $currentDir = Split-Path $currentDir -Parent
    }
    
    # If no project found, return the original directory if it's reasonable
    $systemPaths = @("C:\Windows", "C:\Program Files", "C:\Program Files (x86)")
    $isSystemPath = $systemPaths | Where-Object { $originalDir.StartsWith($_, [StringComparison]::OrdinalIgnoreCase) }
    
    if (-not $isSystemPath -and (Test-Path $originalDir -PathType Container)) {
        return $originalDir
    }
    
    return $null
}

# Function to send IPC message to tempo daemon
function Send-TempoIpc {
    param([string[]]$Arguments)
    
    # Check if tempo is available
    try {
        $tempoCmd = Get-Command $env:TEMPO_BIN -ErrorAction Stop
    }
    catch {
        Write-TempoDebug "tempo binary not found"
        return $false
    }
    
    try {
        & $tempoCmd @Arguments 2>$null
        return $true
    }
    catch {
        Write-TempoDebug "Failed to execute tempo command: $($_.Exception.Message)"
        return $false
    }
}

# Function to handle directory change
function Invoke-TempoDirectoryChange {
    if ($env:TEMPO_HOOK_ENABLED -ne "1") {
        return
    }
    
    $currentDir = $PWD.Path
    
    # Skip if we're in the same directory
    if ($currentDir -eq $Global:_TEMPO_LAST_DIR) {
        return
    }
    
    Write-TempoDebug "Directory changed from '$Global:_TEMPO_LAST_DIR' to '$currentDir'"
    
    # Find project root
    $projectRoot = Find-TempoProjectRoot $currentDir
    if ($projectRoot) {
        Write-TempoDebug "Found project at: $projectRoot"
        
        # Send project entered signal via CLI
        Send-TempoIpc @("session", "start", "--project", $projectRoot, "--context", "terminal")
        
        # Export for other tools
        $env:TEMPO_CURRENT_PROJECT = $projectRoot
    }
    else {
        Write-TempoDebug "No project found for: $currentDir"
        Remove-Item Env:TEMPO_CURRENT_PROJECT -ErrorAction SilentlyContinue
    }
    
    $Global:_TEMPO_LAST_DIR = $currentDir
}

# Override Set-Location to hook directory changes
$Global:OriginalSetLocation = Get-Command Set-Location
function Set-Location {
    param(
        [Parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
        [string]$Path,
        [switch]$PassThru,
        [string]$StackName
    )
    
    # Call original Set-Location
    if ($StackName) {
        & $Global:OriginalSetLocation -Path $Path -StackName $StackName -PassThru:$PassThru
    }
    elseif ($Path) {
        & $Global:OriginalSetLocation -Path $Path -PassThru:$PassThru
    }
    else {
        & $Global:OriginalSetLocation -PassThru:$PassThru
    }
    
    # Trigger tempo directory change handler
    Invoke-TempoDirectoryChange
}

# Set up prompt hook
$Global:OriginalPrompt = Get-Command prompt -ErrorAction SilentlyContinue
if ($Global:OriginalPrompt) {
    function prompt {
        Invoke-TempoDirectoryChange
        & $Global:OriginalPrompt
    }
}
else {
    function prompt {
        Invoke-TempoDirectoryChange
        "PS $($PWD.Path)> "
    }
}

# Initialize for current directory
Invoke-TempoDirectoryChange

# Utility functions for manual control
function Enable-TempoTracking {
    $env:TEMPO_HOOK_ENABLED = "1"
    Write-Host "βœ… Tempo automatic tracking enabled" -ForegroundColor Green
    Invoke-TempoDirectoryChange
}

function Disable-TempoTracking {
    $env:TEMPO_HOOK_ENABLED = "0"
    Write-Host "⏸️ Tempo automatic tracking disabled" -ForegroundColor Yellow
}

function Show-TempoStatus {
    if ($env:TEMPO_HOOK_ENABLED -eq "1") {
        Write-Host "βœ… Tempo automatic tracking is enabled" -ForegroundColor Green
        if ($env:TEMPO_CURRENT_PROJECT) {
            Write-Host "   πŸ“‚ Current project: $env:TEMPO_CURRENT_PROJECT" -ForegroundColor Cyan
        }
        else {
            Write-Host "   πŸ’€ No active project" -ForegroundColor Gray
        }
    }
    else {
        Write-Host "⏸️ Tempo automatic tracking is disabled" -ForegroundColor Yellow
    }
    
    # Show daemon status
    if (Get-Command $env:TEMPO_BIN -ErrorAction SilentlyContinue) {
        Write-Host ""
        & $env:TEMPO_BIN status
    }
}

function Toggle-TempoDebug {
    if ($env:TEMPO_DEBUG -eq "1") {
        $env:TEMPO_DEBUG = "0"
        Write-Host "πŸ”‡ Tempo debug logging disabled" -ForegroundColor Gray
    }
    else {
        $env:TEMPO_DEBUG = "1"
        Write-Host "πŸ”Š Tempo debug logging enabled" -ForegroundColor Yellow
    }
}

# Set up aliases
Set-Alias -Name tempo-enable -Value Enable-TempoTracking
Set-Alias -Name tempo-disable -Value Disable-TempoTracking  
Set-Alias -Name tempo-status -Value Show-TempoStatus
Set-Alias -Name tempo-debug -Value Toggle-TempoDebug

# Print installation message
if ($env:TEMPO_DEBUG -eq "1") {
    Write-Host "πŸ”„ Tempo shell hook loaded for PowerShell (debug mode)" -ForegroundColor Green
}