Wednesday, 17 December 2025

Detecting AI Agent Terminals in PowerShell

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 terminals
  • VS_TERMINAL_AGENT - Set by Visual Studio for agent terminals
  • DevHub parent 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:

  1. Oh My Posh: winget install JanDeDobbeleer.OhMyPosh
  2. A Nerd Font: Download from nerdfonts.com and configure in your terminal
  3. 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;39 for blue, 38;5;99 for 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!


:memo: This article is also published on my personal blog: Detecting AI Agent Terminals in PowerShell

📝 Originally posted at: https://community.panoramicdata.com/t/detecting-ai-agent-terminals-in-powershell/116

Tuesday, 9 December 2025

BBC Website Dark Mode HOWTO

It's December 2025 and the BBC website at https://www.bbc.co.uk/ still doesn't have automatic dark mode detection. In an era where virtually every major website respects the prefers-color-scheme media query, the BBC continues to blast users with a bright white interface regardless of their OS settings.

The frustrating part? It would be trivially easy for them to add. The CSS @media (prefers-color-scheme: dark) query has been widely supported since 2019. Six years later, we're still waiting.

The DIY Fix: Stylus Browser Extension

Until the BBC catches up with the rest of the internet, you can fix it yourself using the Stylus browser extension. Here's how:

Step 1: Install Stylus

Install the Stylus extension for your browser:

Step 2: Create a New Style

  1. Click the Stylus extension icon in your browser toolbar
  2. Click "Manage" to open the Stylus dashboard
  3. Click "Write new style" (or the + button)
  4. Give it a name like "BBC Dark Mode"

Step 3: Configure the URL Pattern

Important: You need to set this style to apply to all BBC pages. In the style editor:

  1. Click "Specify" next to "Applies to"
  2. Select "URLs starting with"
  3. Enter: https://www.bbc.co.uk/

Step 4: Paste the CSS

Copy and paste the following CSS into the code editor:

/* This media query checks the user's OS preference */
@media (prefers-color-scheme: dark) {

    /* 1. Base Colors: Set the background of the whole page and the main text color */
    body {
        background-color: #121212 !important; /* Dark gray background */
        color: #e0e0e0 !important;          /* Light gray text */
    }

    /* 2. Primary Containers: Override white backgrounds on main content blocks, HEADER, NAV, FOOTER, and individual news cards */
    header,
    nav,
    footer,
    article,
    aside,
    .nw-c-most-read-list, 
    .gs-c-promo-body, /* Targets the body of a promotional card */
    .gs-c-promo, /* Targets the promotional card itself */
    .nw-o-keyline, /* Targets common section separators/containers */
    .ssrcss-11vwucc-Container, /* Targets the specific content wrapper shown in Dev Tools */
    .ssrcss-1b2q7d0-GridItem, /* Targets a common list/grid item container */
    .ssrcss-17p825a-StyledWrapper, /* Targets another common section wrapper */
    .ssrcss-1pm1h7u-StyledBorders, /* Ensure background behind bordered elements is dark */
    .ssrcss-17c37qf-StyledBorders, /* Ensure background behind bordered elements is dark */
    .ssrcss-1yv54b, /* Example of a potential main article wrapper class */
    .ssrcss-17lvw4x-GridContainer, /* Example of a potential grid container */
    .ssrcss-vy1h6s-GlobalNavigationContainer, /* Targets large global navigation/content wrapper */
    .ssrcss-1k5z96v-Container, /* Targets the main grid/story wrapper */
    .ssrcss-de737q-Container, /* Targets the recurring child div content containers */
    *:not(img):not(svg) { /* NEW: Highly specific fix for any element with an explicit white background */
        background-color: #1a1a1a !important;
    }
    [role="main"] {
        background-color: #1a1a1a !important; 
        color: #e0e0e0 !important;
    }


    /* 3. Article Text and Headings: Ensure all foreground text is readable */
    h1, h2, h3, p, span {
        color: #f0f0f0 !important;
    }

    /* 4. Links: Change default blue/black links to a lighter, readable color */
    a:link, a:visited {
        color: #8ab4f8 !important; /* A light blue for contrast */
    }
    
    /* 4b. Specific Navigation Links: Ensure navigation text (e.g., "News", "UK") is white against the dark header */
    nav a, 
    header a,
    .ssrcss-rrm6an-RichTextContainer,
    .ssrcss-1j1rzn0-Stack {
        color: #f0f0f0 !important; 
    }

    /* 5. Borders: If borders exist, make them slightly darker than the background */
    .ssrcss-1pm1h7u-StyledBorders, .ssrcss-17c37qf-StyledBorders {
        border-color: #333333 !important;
    }

    /* 6. Image Background Fix: Prevent white flash when images are loading or transparent */
    img, 
    .ssrcss-153qrb0-ImageWrapper { /* Targets the image element and a common BBC image wrapper */
        background-color: #1a1a1a !important;
    }
    
    /* 7. Forms */
    input,
    textarea,
    button,
    .ssrcss-w94gox-TextAreaWrapper {
        color: #f0f0f0 !important; 
        border-color: #777 !important;
    }
}

Step 5: Save

Click "Save" (or press Ctrl+S). The style will immediately apply to any open BBC tabs.

The Result

Now when you visit bbc.co.uk with your OS set to dark mode, you'll get a proper dark theme instead of being blinded by white backgrounds.

Dear BBC...

This CSS took about 5 minutes to write. You have a team of developers. Please just add dark mode support. It's 2025. Thank you.

Github Copilot's problem with Powershell Here-strings

Problem

When GitHub Copilot (or similar AI coding assistants) uses run_command_in_terminal with PowerShell here-strings (@‘…’@ or @“…”@), the terminal enters continuation mode and hangs indefinitely, waiting for input that never comes.

Symptoms

• Terminal shows >> prompts repeatedly
• Command never completes
• Task eventually times out or must be cancelled with Ctrl+C

Root Cause

PowerShell here-strings require:

  1. The opening delimiter (@’ or @") at the end of a line
  2. Content on subsequent lines
  3. The closing delimiter ('@ or "@) at the start of its own line
    When the AI sends multi-line commands through terminal automation, line breaks aren’t preserved correctly, causing PowerShell to wait forever for the closing delimiter.

Solution: Add to copilot-instructions.md

Add this to your repository’s .github/copilot-instructions.md:

## ⚠️ Terminal Command Limitations

### NEVER Use PowerShell Here-Strings in Terminal Commands

When using `run_command_in_terminal`, **NEVER** use PowerShell here-strings (`@'...'@` or `@"..."@`). They cause the terminal to hang.

### ✅ Alternatives:
1. **For file edits**: Use the `edit_file` tool (preferred)
2. **For simple replacements**: Use single-line `-replace` with escaped patterns
3. **For complex changes**: Provide code to the user to paste manually
4. **If terminal is needed**: Write content to a temp file first

Key Takeaway

AI assistants should never use PowerShell here-strings in terminal commands. Always prefer dedicated file editing tools or provide code snippets for manual pasting when multi-line content is involved.

📝 Originally posted at: https://community.panoramicdata.com/t/github-copilots-problem-with-powershell-here-strings/113

Sunday, 7 December 2025

Toggl have crippled their API

It seems that Toggl have crippled their API by limiting even customers paying several thousand dollars a year to 600 calls per hour.

PER HOUR!

This unfortunately makes Toggl useless to us, as we are unable to execute HR reports or simple system integrations in a reasonable amount of time. We are currently looking around for alternatives.

Commonly-used Copilot phrases

Nuget publish script

Create "Publish.ps1" a script in the solution root that completes each of the following steps, stopping if any fails:

  • Check for git porcelein
  • Determine the Nerdbank git version
  • Check that nuget-key.txt exists, has content and is gitignored 
  • Run unit tests (unless -SkipTests is specified)
  • Publish to nuget.org

The script should not interact with the user.  It should exit with 0 if successful.