Skip to content

PowerShell script for Windows Terminal "safe paste" configuration (hearkens back to conhost multiline paste behavior)

License

Notifications You must be signed in to change notification settings

nanoDBA/WindowsTerminal-SafePaste

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

1 Commit
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Windows Terminal Safe Paste Configuration 🎯

License: MIT PowerShell Platform

Transform Windows Terminal's paste behavior to match classic console (conhost) experience: eliminate annoying paste warnings, enable safe multi-line pasting, and get those beautiful > continuation prompts you remember from the good old days! 😎

Quick Links: Installation β€’ Documentation β€’ Contributing β€’ Changelog

What This Does

This PowerShell script configures Windows Terminal and PowerShell to provide a safe paste experience that matches classic console behavior:

βœ… No more paste warning dialogs - Paste multi-line content without interruption
βœ… Classic continuation prompts - Beautiful > markers instead of stacked full prompts
βœ… Safe multi-line pasting - Text lands in the buffer, doesn't auto-execute
βœ… Idempotent and reversible - Safe to run multiple times, full rollback support
βœ… Works everywhere - Windows PowerShell 5.1, PowerShell 7+, all Terminal variants

Quick Start πŸš€

Option 1: Paste into Console (Recommended)

  1. Copy the entire Set-TerminalPaste.ps1 file
  2. Paste it into your PowerShell console
  3. Run with preview first:
    Set-TerminalPaste -WhatIf
  4. Apply the changes:
    Set-TerminalPaste
  5. Restart Windows Terminal (close all instances)

Option 2: Run as Script File

# Preview changes
.\Set-TerminalPaste.ps1 -WhatIf

# Apply changes
.\Set-TerminalPaste.ps1

# Restart Windows Terminal

Usage Examples

Basic Usage (Most Common)

# Preview what will change (safe, no modifications)
Set-TerminalPaste -WhatIf

# Apply to most recent Terminal settings + current PowerShell profile
Set-TerminalPaste

Comprehensive Configuration

# Apply to ALL Terminal installations and BOTH PowerShell profiles
Set-TerminalPaste -AllTerminalSettings -AllPowerShellProfiles

Conservative Mode

# Don't override existing keybindings (preserves custom configs)
Set-TerminalPaste -Conservative

What Conservative Mode Does:

  • Windows Terminal: Won't override an existing Ctrl+Shift+V binding if it's already set to something other than 'paste'
  • PowerShell Profile: Won't override an existing PSReadLine Ctrl+V binding if one is already configured

When to Use:

  • You have custom keybindings you want to preserve
  • Other scripts or tools have already configured paste behavior
  • You're unsure what's already configured and want to be safe
  • You want to add Terminal configuration but keep existing PSReadLine bindings

Note: The conservative setting is embedded in your profile block. If you run the script again with or without -Conservative, it will update the profile block with the new setting.

Rollback (Undo)

# Restore from most recent backups
Set-TerminalPaste -Rollback

# Rollback everything (all settings + profiles)
Set-TerminalPaste -Rollback -AllTerminalSettings -AllPowerShellProfiles

What Gets Changed? πŸ”§

Windows Terminal Settings (settings.json)

  • Sets multiLinePasteWarning: false
  • Sets largePasteWarning: false
  • Unbinds Ctrl+V at terminal layer (passes to PowerShell)
  • Ensures Ctrl+Shift+V is bound to terminal paste

Note: Settings.json will be normalized (comments/formatting removed). Original is backed up automatically.

PowerShell Profiles

The script adds a code block to your PowerShell profile (typically Documents\PowerShell\Microsoft.PowerShell_profile.ps1 or Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1) that:

  • Configures PSReadLine to handle Ctrl+V paste with classic continuation prompts
  • Uses Insert() + AddLine() approach to produce > markers instead of stacked full prompts
  • Checks for ConsoleHost - only runs in console environments (not ISE/VS Code)
  • Respects conservative mode - won't override existing Ctrl+V bindings if you use -Conservative

What the code block does: When PowerShell starts, it loads PSReadLine and sets up a custom Ctrl+V handler that:

  1. Gets clipboard content
  2. Splits it into lines
  3. Inserts each line using Insert()
  4. Adds continuation prompts using AddLine() between lines

This produces the classic console experience where multi-line pastes show > continuation prompts instead of stacked full prompts.

Idempotent: The block is marked with # >>> WT_SAFE_PASTE (managed) >>> markers. If you run the script again, it finds and updates that same block instead of adding duplicates.

Conservative Mode in Profile: If you look at the profile block, you'll see a condition like if ($canQuery -and $false) or if ($canQuery -and $true). The $false/$true value reflects whether you ran with -Conservative:

  • $false (default) = Always set the handler (not in conservative mode)
  • $true = Check for existing binding first (conservative mode enabled)

Safety Features πŸ›‘οΈ

  • Timestamped backups - Every file gets a .bak.yyyyMMdd-HHmmss-ffff backup before modification
  • Pre-edit validation - Checks file structure before making changes
  • Post-edit validation - Verifies JSON is valid and structure is intact (aborts on corruption)
  • Change reports - Detailed audit trail saved to WindowsTerminal_SafePaste_Changes_TIMESTAMP.txt
  • WhatIf support - Preview changes without applying them
  • Full rollback - Restore from backups with -Rollback parameter

Requirements

  • Windows with Windows Terminal installed
  • PowerShell 5.1 or 7+ (Windows PowerShell or PowerShell Core)
  • PSReadLine module (usually pre-installed with PowerShell)

Important Notes & Potential Surprises πŸ“

Change Report Location

Change reports are saved next to the script file when run as a file, or in your current directory when pasted into console. Look for WindowsTerminal_SafePaste_Changes_TIMESTAMP.txt files.

Profile Directory Creation

If your PowerShell profile directory doesn't exist (e.g., Documents\PowerShell\), the script will create it automatically. This is normal and expected.

Default Behavior: Most Recent Settings Only

By default, the script patches only the most recently modified Windows Terminal settings file. If you have multiple Terminal installations (Stable + Preview), only one gets patched unless you use -AllTerminalSettings.

Profile Block Runs on Every PowerShell Start

The code block added to your profile runs every time PowerShell starts. It's lightweight (just checks and configures PSReadLine), but it does execute on startup. If you remove the managed block markers, the script won't find it to update it.

PSReadLine Availability

If PSReadLine isn't available when PowerShell starts, the profile block silently does nothing (wrapped in try/catch). This is safe but means paste behavior won't be configured until PSReadLine is available.

Known Limitations ⚠️

Multi-line Paste Rendering

Windows Terminal and classic console (conhost) render multi-line input differently:

Feature Windows Terminal Classic Console
Multi-line display Each line on separate row with stacked C:\ prompts Single wrapped line with inline >> markers
Escape key Clears ONE line at a time Clears entire input
Cancel all Ctrl+C required Escape works

This script solves the visual difference by using Insert() + AddLine() to produce classic > continuation prompts in Windows Terminal. Functionally, both work correctly (no warning, no auto-execute), but the editing experience is now consistent with classic console.

JSONC Conversion

Windows Terminal settings files often contain comments (JSONC format). This script reads JSONC but writes normalized JSON (comments removed). This is expected behavior - your original file is backed up automatically.

Settings UI Conflicts

If Windows Terminal Settings UI is open during script execution, it may rewrite settings.json after the script finishes. Close the Settings UI before running the script to avoid conflicts.

Troubleshooting πŸ”

"No Windows Terminal settings found"

The script looks for settings in:

  • %LOCALAPPDATA%\Packages\Microsoft.WindowsTerminal*8wekyb3d8bbwe\LocalState\settings.json (Store apps)
  • %LOCALAPPDATA%\Microsoft\Windows Terminal\settings.json (unpackaged)

If you have a custom installation location, you may need to manually patch that file.

"Could not determine profile path"

Use -AllPowerShellProfiles to explicitly patch both profile locations, or manually specify profiles.

Paste still shows warnings

  1. Ensure Windows Terminal Settings UI is closed
  2. Restart Windows Terminal completely (close all windows)
  3. Verify settings.json was actually modified (check backup timestamp)
  4. Check that multiLinePasteWarning and largePasteWarning are set to false

Multi-line paste still shows stacked prompts

  1. Ensure PowerShell profile was patched (check for managed block markers)
  2. Restart PowerShell session (or restart Windows Terminal)
  3. Verify PSReadLine is loaded: Get-Module PSReadLine
  4. Check key handler: Get-PSReadLineKeyHandler -Chord 'Ctrl+V'

How It Works 🧠

The Problem

Windows Terminal intercepts Ctrl+V at the terminal layer, showing warning dialogs and executing multi-line pastes line-by-line instead of inserting them into the edit buffer.

The Solution

  1. Disable warnings - Set multiLinePasteWarning and largePasteWarning to false
  2. Unbind Ctrl+V - Remove Ctrl+V binding from Terminal so it passes through to PowerShell
  3. Configure PSReadLine - Use Insert() + AddLine() to produce classic continuation prompts
  4. Preserve Terminal paste - Keep Ctrl+Shift+V for terminal-level paste operations

Technical Details

  • JSONC parsing - Custom parser handles comments and trailing commas (PowerShell's ConvertFrom-Json doesn't support JSONC)

  • Schema compatibility - Handles both modern "actions" schema and legacy "keybindings" schema

  • Idempotent operations - Safe to run multiple times. The script adds a marked code block to your PowerShell profile (between # >>> WT_SAFE_PASTE (managed) >>> and # <<< WT_SAFE_PASTE (managed) <<< markers). If you run the script again, it finds and updates that same block instead of adding duplicates.

    Example scenario: You run the script today, then update to a new version of the script next month. Running the new version finds your existing managed block and updates it with any improvements, rather than leaving you with duplicate code blocks or conflicting configurations.

  • Defensive programming - Extensive validation, error handling, and rollback support

Contributing 🀝

We welcome contributions! Please see our Contributing Guide for details on:

  • πŸ› Bug Reports: Help us improve by reporting issues
  • πŸ’‘ Feature Requests: Suggest new functionality
  • πŸ”§ Pull Requests: Submit code improvements
  • πŸ“– Documentation: Help improve our docs

Support & Community πŸ’¬

License πŸ“„

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgments πŸ™

  • Created for PowerShell users who miss classic console paste behavior
  • Inspired by the need for predictable, shell-friendly keybindings
  • Tested extensively on Windows Terminal v1.24+ across multiple configurations

⭐ Star this repo if it helped you! β€’ πŸ› Found an issue? Report it β€’ πŸ’‘ Have an idea? Share it

Enjoy your safe paste experience! πŸŽ‰

About

PowerShell script for Windows Terminal "safe paste" configuration (hearkens back to conhost multiline paste behavior)

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published