From 19652c49c9e48ec96d84b40739b275831b8c8b90 Mon Sep 17 00:00:00 2001 From: Reinier Criel Date: Mon, 12 Jan 2026 14:53:23 -0800 Subject: [PATCH 1/3] Attempted fix for powershell swallowing '--' --- .../startup-scripts/init-pwsh.ps1 | 66 ++++++++++++++----- 1 file changed, 50 insertions(+), 16 deletions(-) diff --git a/packages/safe-chain/src/shell-integration/startup-scripts/init-pwsh.ps1 b/packages/safe-chain/src/shell-integration/startup-scripts/init-pwsh.ps1 index 7fabcad..f02b900 100644 --- a/packages/safe-chain/src/shell-integration/startup-scripts/init-pwsh.ps1 +++ b/packages/safe-chain/src/shell-integration/startup-scripts/init-pwsh.ps1 @@ -6,27 +6,27 @@ $safeChainBin = Join-Path (Join-Path $HOME '.safe-chain') 'bin' $env:PATH = "$env:PATH$pathSeparator$safeChainBin" function npx { - Invoke-WrappedCommand "npx" $args + Invoke-WrappedCommand "npx" $args $MyInvocation.Line $MyInvocation.OffsetInLine } function yarn { - Invoke-WrappedCommand "yarn" $args + Invoke-WrappedCommand "yarn" $args $MyInvocation.Line $MyInvocation.OffsetInLine } function pnpm { - Invoke-WrappedCommand "pnpm" $args + Invoke-WrappedCommand "pnpm" $args $MyInvocation.Line $MyInvocation.OffsetInLine } function pnpx { - Invoke-WrappedCommand "pnpx" $args + Invoke-WrappedCommand "pnpx" $args $MyInvocation.Line $MyInvocation.OffsetInLine } function bun { - Invoke-WrappedCommand "bun" $args + Invoke-WrappedCommand "bun" $args $MyInvocation.Line $MyInvocation.OffsetInLine } function bunx { - Invoke-WrappedCommand "bunx" $args + Invoke-WrappedCommand "bunx" $args $MyInvocation.Line $MyInvocation.OffsetInLine } function npm { @@ -37,37 +37,37 @@ function npm { return } - Invoke-WrappedCommand "npm" $args + Invoke-WrappedCommand "npm" $args $MyInvocation.Line $MyInvocation.OffsetInLine } function pip { - Invoke-WrappedCommand "pip" $args + Invoke-WrappedCommand "pip" $args $MyInvocation.Line $MyInvocation.OffsetInLine } function pip3 { - Invoke-WrappedCommand "pip3" $args + Invoke-WrappedCommand "pip3" $args $MyInvocation.Line $MyInvocation.OffsetInLine } function uv { - Invoke-WrappedCommand "uv" $args + Invoke-WrappedCommand "uv" $args $MyInvocation.Line $MyInvocation.OffsetInLine } function poetry { - Invoke-WrappedCommand "poetry" $args + Invoke-WrappedCommand "poetry" $args $MyInvocation.Line $MyInvocation.OffsetInLine } # `python -m pip`, `python -m pip3`. function python { - Invoke-WrappedCommand 'python' $args + Invoke-WrappedCommand 'python' $args $MyInvocation.Line $MyInvocation.OffsetInLine } # `python3 -m pip`, `python3 -m pip3'. function python3 { - Invoke-WrappedCommand 'python3' $args + Invoke-WrappedCommand 'python3' $args $MyInvocation.Line $MyInvocation.OffsetInLine } function pipx { - Invoke-WrappedCommand "pipx" $args + Invoke-WrappedCommand "pipx" $args $MyInvocation.Line $MyInvocation.OffsetInLine } function Write-SafeChainWarning { @@ -111,10 +111,44 @@ function Invoke-RealCommand { function Invoke-WrappedCommand { param( [string]$OriginalCmd, - [string[]]$Arguments + [string[]]$Arguments, + [string]$RawLine = $null, + [int]$RawOffset = 0 ) - if (Test-CommandAvailable "safe-chain") { + # Use raw line parsing to recover arguments like '--' that PowerShell consumes + if ($RawLine) { + $tokens = [System.Management.Automation.PSParser]::Tokenize($RawLine, [ref]$null) + $newArgs = @() + $foundCommand = $false + $canUseRaw = $true + + foreach ($t in $tokens) { + # Find the command token based on offset + if (-not $foundCommand) { + if ($t.Start -eq ($RawOffset - 1)) { $foundCommand = $true } + continue + } + # Stop at command separators + if ($t.Type -eq 'Operator' -and $t.Content -match '[|;&]') { break } + # Stop if complex variable expansion is used + if ($t.Type -eq 'Variable' -or $t.Type -eq 'Group' -or $t.Type -eq 'SubExpression') { + $canUseRaw = $false + break + } + $newArgs += $t.Content + } + + if ($foundCommand -and $canUseRaw) { + $Arguments = $newArgs + Write-Host "Safe-chain Powershell Wrapper: Reconstructed args: $($Arguments -join ' ')" + } + } + + if ($isWindowsPlatform -and (Test-CommandAvailable "safe-chain.cmd")) { + & safe-chain.cmd $OriginalCmd @Arguments + } + elseif (Test-CommandAvailable "safe-chain") { & safe-chain $OriginalCmd @Arguments } else { From 9a902af917fce9920a71a34235cd8fc5ec39977c Mon Sep 17 00:00:00 2001 From: Reinier Criel Date: Mon, 12 Jan 2026 15:12:19 -0800 Subject: [PATCH 2/3] Fix some logic --- .../startup-scripts/init-pwsh.ps1 | 60 ++++++++++++------- 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/packages/safe-chain/src/shell-integration/startup-scripts/init-pwsh.ps1 b/packages/safe-chain/src/shell-integration/startup-scripts/init-pwsh.ps1 index f02b900..e1ed660 100644 --- a/packages/safe-chain/src/shell-integration/startup-scripts/init-pwsh.ps1 +++ b/packages/safe-chain/src/shell-integration/startup-scripts/init-pwsh.ps1 @@ -108,6 +108,40 @@ function Invoke-RealCommand { } } +function Get-ReconstructedArguments { + param( + [string]$RawLine, + [int]$RawOffset + ) + + if (-not $RawLine) { return $null } + + $tokens = [System.Management.Automation.PSParser]::Tokenize($RawLine, [ref]$null) + $newArgs = @() + $foundCommand = $false + + foreach ($t in $tokens) { + if (-not $foundCommand) { + if ($t.Start -eq ($RawOffset - 1)) { $foundCommand = $true } + continue + } + + if ($t.Type -eq 'Operator' -and $t.Content -match '[|;&]') { break } + + # Stop if complex variable expansion is used + if ($t.Type -eq 'Variable' -or $t.Type -eq 'Group' -or $t.Type -eq 'SubExpression') { + return $null + } + + $newArgs += $t.Content + } + + if ($foundCommand) { + return ,$newArgs + } + return $null +} + function Invoke-WrappedCommand { param( [string]$OriginalCmd, @@ -118,29 +152,9 @@ function Invoke-WrappedCommand { # Use raw line parsing to recover arguments like '--' that PowerShell consumes if ($RawLine) { - $tokens = [System.Management.Automation.PSParser]::Tokenize($RawLine, [ref]$null) - $newArgs = @() - $foundCommand = $false - $canUseRaw = $true - - foreach ($t in $tokens) { - # Find the command token based on offset - if (-not $foundCommand) { - if ($t.Start -eq ($RawOffset - 1)) { $foundCommand = $true } - continue - } - # Stop at command separators - if ($t.Type -eq 'Operator' -and $t.Content -match '[|;&]') { break } - # Stop if complex variable expansion is used - if ($t.Type -eq 'Variable' -or $t.Type -eq 'Group' -or $t.Type -eq 'SubExpression') { - $canUseRaw = $false - break - } - $newArgs += $t.Content - } - - if ($foundCommand -and $canUseRaw) { - $Arguments = $newArgs + $reconstructedArgs = Get-ReconstructedArguments $RawLine $RawOffset + if ($null -ne $reconstructedArgs) { + $Arguments = $reconstructedArgs Write-Host "Safe-chain Powershell Wrapper: Reconstructed args: $($Arguments -join ' ')" } } From 340e9a90a5f47c6725852c4b61e057ccb017cf97 Mon Sep 17 00:00:00 2001 From: Reinier Criel Date: Mon, 12 Jan 2026 15:13:34 -0800 Subject: [PATCH 3/3] Remove comment --- .../src/shell-integration/startup-scripts/init-pwsh.ps1 | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/safe-chain/src/shell-integration/startup-scripts/init-pwsh.ps1 b/packages/safe-chain/src/shell-integration/startup-scripts/init-pwsh.ps1 index e1ed660..f82d0fc 100644 --- a/packages/safe-chain/src/shell-integration/startup-scripts/init-pwsh.ps1 +++ b/packages/safe-chain/src/shell-integration/startup-scripts/init-pwsh.ps1 @@ -155,7 +155,6 @@ function Invoke-WrappedCommand { $reconstructedArgs = Get-ReconstructedArguments $RawLine $RawOffset if ($null -ne $reconstructedArgs) { $Arguments = $reconstructedArgs - Write-Host "Safe-chain Powershell Wrapper: Reconstructed args: $($Arguments -join ' ')" } }