# 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
}