Detecting AI Agent Terminals in PowerShell
Introduction
If you’re working with Visual Studio 2026, VS Code with Copilot, or other AI-assisted development tools, you may have noticed that these tools spawn terminal sessions for executing commands. I’ve created a PowerShell profile configuration that automatically detects these AI agent terminals and adjusts the experience accordingly.
Why This Matters
When an AI agent (like GitHub Copilot) runs commands in a terminal, you typically don’t need the full interactive experience - Oh My Posh themes, PSReadLine predictions, and fancy prompts just add overhead. Conversely, when you’re using the terminal, you want the full experience.
This profile script:
- Detects AI agent terminals (VS Code Copilot, Visual Studio 2026 DevHub)
- Displays a clear visual banner showing whether you or an AI is in control
- Optimizes the environment based on the terminal type
- Supports Nerd Fonts with ASCII fallbacks
The Setup
Step 1: Locate Your Profile
Open PowerShell and run:
$PROFILE
This shows the path to your profile script (typically ~\Documents\PowerShell\Microsoft.PowerShell_profile.ps1).
Step 2: Create or Edit Your Profile
If the file doesn’t exist:
New-Item -Path $PROFILE -ItemType File -Force
notepad $PROFILE
Step 3: Add the Configuration
Here’s the complete script broken down by section:
Mode Detection
# Detect Copilot/AI agent terminals
$script:parentProcessName = try { (Get-Process -Id $PID).Parent.Name } catch { $null }
$script:isCopilot = ($env:VSC_COPILOT_TERMINAL -eq "1") -or
($env:VS_TERMINAL_AGENT -eq "1") -or
($script:parentProcessName -eq "DevHub")
# Detect non-interactive/background terminals
$isNonInteractive = ($env:VSCODE_RESOLVING_TERMINAL -eq "1") -or
(-not [Environment]::UserInteractive)
This checks for:
VSC_COPILOT_TERMINAL- Set by VS Code for Copilot terminalsVS_TERMINAL_AGENT- Set by Visual Studio for agent terminalsDevHubparent process - Visual Studio 2026’s Copilot service
Visual Banner
The script displays a header banner showing who’s in control:
- Blue “COPILOT AGENT” banner when an AI is running commands
- Purple username banner for interactive sessions
if ($hasValidWindow) {
$width = $Host.UI.RawUI.WindowSize.Width
$time = Get-Date -Format "HH:mm:ss"
$user = $env:USERNAME.ToUpper()
if ($supportsNerdFonts) {
$copilotIcon = [char]::ConvertFromUtf32(0xF166A) # nf-md-robot
$userIcon = [char]::ConvertFromUtf32(0xF489) # nf-oct-terminal
$clockIcon = [char]::ConvertFromUtf32(0xF1425) # nf-md-clock_outline
} else {
$copilotIcon = "[BOT]"
$userIcon = ">"
$clockIcon = "@"
}
if ($script:isCopilot) {
$leftLabel = " $copilotIcon COPILOT AGENT "
$modeColor = "38;5;39" # Blue
} else {
$leftLabel = " $userIcon $user "
$modeColor = "38;5;99" # Purple
}
$rightLabel = " $time $clockIcon "
$fillCount = $width - $leftLabel.Length - $rightLabel.Length
$fillLine = if ($fillCount -gt 0) { [string]::new([char]0x2501, $fillCount) } else { "" }
Write-Host ""
Write-Host "`e[1;$($modeColor)m$leftLabel`e[0m`e[38;5;236m$fillLine`e[0m`e[90m$rightLabel`e[0m"
Write-Host ""
}
If you have Nerd Fonts installed (Windows Terminal, VS Code), you’ll see nice icons; otherwise, ASCII fallbacks are used.
Conditional Setup
if ($script:isCopilot) {
# Minimal prompt for AI agents
function global:prompt {
$Host.UI.RawUI.WindowTitle = "VS 2026 | Copilot"
"PS $($PWD.Path)> "
}
} else {
# Full Oh My Posh experience for humans
if (Get-Command oh-my-posh -ErrorAction SilentlyContinue) {
$poshTheme = "$env:POSH_THEMES_PATH\marcduiker.omp.json"
if (Test-Path $poshTheme) {
oh-my-posh init pwsh --config $poshTheme | Invoke-Expression
}
}
}
The Complete Script
Here’s the full profile script you can copy:
# ============================================================================
# PowerShell Profile - AI Agent Detection
# ============================================================================
# ----------------------------------------------------------------------------
# 1. MODE DETECTION
# ----------------------------------------------------------------------------
$script:parentProcessName = try { (Get-Process -Id $PID).Parent.Name } catch { $null }
$script:isCopilot = ($env:VSC_COPILOT_TERMINAL -eq "1") -or
($env:VS_TERMINAL_AGENT -eq "1") -or
($script:parentProcessName -eq "DevHub")
$isNonInteractive = ($env:VSCODE_RESOLVING_TERMINAL -eq "1") -or
(-not [Environment]::UserInteractive)
$hasValidWindow = try { $Host.UI.RawUI.WindowSize.Width -gt 0 } catch { $false }
$supportsNerdFonts = ($env:WT_SESSION) -or
($env:TERM_PROGRAM -eq "vscode") -or
($env:VSAPPIDNAME -eq "devenv.exe") -or
($env:ConEmuANSI -eq "ON")
# ----------------------------------------------------------------------------
# 2. HEADER BANNER
# ----------------------------------------------------------------------------
if ($hasValidWindow) {
$width = $Host.UI.RawUI.WindowSize.Width
$time = Get-Date -Format "HH:mm:ss"
$user = $env:USERNAME.ToUpper()
if ($supportsNerdFonts) {
$copilotIcon = [char]::ConvertFromUtf32(0xF166A)
$userIcon = [char]::ConvertFromUtf32(0xF489)
$clockIcon = [char]::ConvertFromUtf32(0xF1425)
} else {
$copilotIcon = "[BOT]"
$userIcon = ">"
$clockIcon = "@"
}
if ($script:isCopilot) {
$leftLabel = " $copilotIcon COPILOT AGENT "
$modeColor = "38;5;39"
} else {
$leftLabel = " $userIcon $user "
$modeColor = "38;5;99"
}
$rightLabel = " $time $clockIcon "
$fillCount = $width - $leftLabel.Length - $rightLabel.Length
$fillLine = if ($fillCount -gt 0) { [string]::new([char]0x2501, $fillCount) } else { "" }
Write-Host ""
Write-Host "`e[1;$($modeColor)m$leftLabel`e[0m`e[38;5;236m$fillLine`e[0m`e[90m$rightLabel`e[0m"
Write-Host ""
}
# ----------------------------------------------------------------------------
# 3. EARLY EXIT FOR NON-INTERACTIVE TERMINALS
# ----------------------------------------------------------------------------
if ($isNonInteractive) { return }
# ----------------------------------------------------------------------------
# 4. INTERACTIVE UI SETUP
# ----------------------------------------------------------------------------
if ($script:isCopilot) {
function global:prompt {
$Host.UI.RawUI.WindowTitle = "VS 2026 | Copilot"
"PS $($PWD.Path)> "
}
} else {
if (Get-Module -ListAvailable -Name PSReadLine) {
Import-Module PSReadLine -ErrorAction SilentlyContinue
Set-PSReadLineOption -PredictionSource History -ErrorAction SilentlyContinue
Set-PSReadLineOption -PredictionViewStyle ListView -ErrorAction SilentlyContinue
}
if (Get-Command oh-my-posh -ErrorAction SilentlyContinue) {
$poshTheme = "$env:POSH_THEMES_PATH\marcduiker.omp.json"
if (Test-Path $poshTheme) {
oh-my-posh init pwsh --config $poshTheme | Invoke-Expression
}
}
}
# ----------------------------------------------------------------------------
# 5. ENCODING
# ----------------------------------------------------------------------------
$OutputEncoding = [Console]::OutputEncoding = [System.Text.UTF8Encoding]::new()
Prerequisites
For the full experience:
- Oh My Posh:
winget install JanDeDobbeleer.OhMyPosh - A Nerd Font: Download from nerdfonts.com and configure in your terminal
- Windows Terminal (recommended):
winget install Microsoft.WindowsTerminal
Customization Tips
- Change the theme to your preferred Oh My Posh theme
- Adjust the colors by modifying the ANSI codes (
38;5;39for blue,38;5;99for purple) - Add additional detection methods if you use other AI tools
What It Looks Like
When Copilot is active (with Nerd Fonts):
[robot-icon] COPILOT AGENT ━━━━━━━━━━━━━━━━━━━━━━━━━ 14:32:15 [clock-icon]
When you’re in control:
> YOURNAME ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 14:32:15 [clock-icon]
(The actual icons render beautifully with Nerd Fonts installed!)
Conclusion
This small addition to your PowerShell profile makes it immediately clear whether you’re looking at a terminal session you control or one being operated by an AI assistant. It’s a simple quality-of-life improvement that becomes invaluable when working with modern AI-assisted development tools.
Feel free to adapt this to your needs - and share your improvements in the comments!
This article is also published on my personal blog: Detecting AI Agent Terminals in PowerShell
No comments:
Post a Comment