Skip to content

Instantly share code, notes, and snippets.

@kjanat
Last active November 5, 2025 22:53
Show Gist options
  • Select an option

  • Save kjanat/935aa383eafaf6510b2920c19d734dab to your computer and use it in GitHub Desktop.

Select an option

Save kjanat/935aa383eafaf6510b2920c19d734dab to your computer and use it in GitHub Desktop.
PowerShell argument completer for Bun's command-line interface.
<#
.SYNOPSIS
PowerShell argument completer for the Bun command-line interface.
.DESCRIPTION
This script provides tab completion for Bun commands in PowerShell.
- Completes top-level commands (e.g., 'bun add', 'bun run').
- Completes script names from 'package.json' when using 'bun run'.
.NOTES
Author: Kaj Kowalski
Version: 1.0
Date: 2025-11-05
Bun version: 1.3.1
.EXAMPLE
# You could run this script directly in your PowerShell session:
# irm https://gist.githubusercontent.com/kjanat/935aa383eafaf6510b2920c19d734dab/raw/bun_completions.ps1 | iex
#
# Note: This is not safe!!! You could introduce RCE vulnerabilities!!!
# Make sure that if you do this, you pin the commit hash to a specific version:
#
# irm https://gist.githubusercontent.com/kjanat/935aa383eafaf6510b2920c19d734dab/raw/f9540f04212a2ec320cc81da9768029d51ffc81a/bun_completions.ps1 | iex
.EXAMPLE
# To use this completer, add the following line to your PowerShell profile:
# . C:\path\to\your\bun_completions.ps1
.LINK
https://gist.github.com/kjanat/935aa383eafaf6510b2920c19d734dab
#>
# Register argument completer for the 'bun' command
Register-ArgumentCompleter -Native -CommandName bun -ScriptBlock {
param($wordToComplete, $commandAst, $cursorPosition)
try {
# Parse the command to determine context
$commandLine = $commandAst.ToString()
$words = $commandLine -split '\s+' | Where-Object { $_ }
# Determine the subcommand (if any)
$subCommand = if ($words.Count -ge 2) { $words[1] } else { $null }
# If we're completing after 'bun run', show package.json scripts
if ($subCommand -eq 'run') {
$packageJsonPath = Join-Path $PWD 'package.json'
if (Test-Path $packageJsonPath) {
$packageJson = Get-Content $packageJsonPath -Raw | ConvertFrom-Json
if ($packageJson.scripts) {
$packageJson.scripts.PSObject.Properties.Name | Where-Object {
if ($wordToComplete) {
$_ -like "$wordToComplete*"
} else {
$true
}
} | ForEach-Object {
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
}
}
}
}
# If we're completing the first argument after 'bun', show all commands
else {
# Try to get completions from bun, fallback to hardcoded list if it fails
$completions = $null
try {
$completions = & bun getcompletes 2>$null | Where-Object { $_ -and $_ -match '\S' }
} catch {}
# Fallback to common bun commands if getcompletes fails
if (-not $completions) {
$completions = @('add', 'build', 'create', 'install', 'link', 'pm', 'remove',
'run', 'test', 'unlink', 'update', 'upgrade', 'x', 'init',
'dev', 'bun', 'repl')
}
# Filter completions based on what's being typed
$completions | Where-Object {
if ($wordToComplete) {
$_ -like "$wordToComplete*"
} else {
$true
}
} | ForEach-Object {
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
}
}
} catch {
# Silent fail if bun getcompletes errors or package.json parsing fails
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment