Files
PowerToys/doc/devdocs/modules/advancedpaste-python-scripts.md
Muyuan Li (from Dev Box) 214d80415a feat(AdvancedPaste): rename ap_from_* to advanced_paste_from_* for clarity
- Renamed function convention from ap_from_text/html/image/files to
  advanced_paste_from_text/html/image/files for explicit discoverability
- Updated C# regex detection, Python runner, and documentation
- Added multi-format demo script (reverse_all.py)
- Added AI summarize demo script (ai_summarize.py) using OpenAI

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-10 23:30:13 +08:00

6.6 KiB
Raw Permalink Blame History

Advanced Paste Python Scripts

Advanced Paste supports user-defined Python scripts that transform clipboard content. Scripts are discovered automatically from a configurable folder and appear as actions in the Advanced Paste UI.

Quick start

  1. Open the scripts folder — by default %LOCALAPPDATA%\Microsoft\PowerToys\AdvancedPaste\Scripts. You can change this in Settings → Advanced Paste → Python scripts → Scripts folder.
  2. Drop a .py file into the folder.
  3. Define one or more advanced_paste_from_* functions (see Writing a script).
  4. Open the Advanced Paste UI (Win+Shift+V) — your script will appear in the action list.

Important: Only .py files that define at least one advanced_paste_from_* function are loaded. Plain scripts without these functions are ignored.

Writing a script

You write normal Python functions whose names declare what clipboard input they accept. No imports from PowerToys are needed — zero setup, zero dependencies on our side.

Function naming convention

Function name Input parameter When it runs
advanced_paste_from_text(text) str — clipboard text Clipboard has text
advanced_paste_from_html(html) str — clipboard HTML Clipboard has HTML
advanced_paste_from_image(image_path) str — path to temp image file Clipboard has an image
advanced_paste_from_files(file_paths) list[str] — file paths Clipboard has files

A single script can define multiple functions to handle different input types.

Return value convention

The return value determines what gets placed on the clipboard:

Return type Effect
str Sets clipboard to text
pathlib.Path (.png, .jpg, etc.) Sets clipboard to image
pathlib.Path (other extension) Sets clipboard to file
list of Path/str Sets clipboard to multiple files
dict with "type" key Explicit output type (escape hatch — see below)
None No-op (clipboard unchanged)

Dict escape hatch

For cases where the return type can't be inferred from the value alone:

def advanced_paste_from_text(text):
    html = f"<b>{text.upper()}</b>"
    return {"type": "html", "value": html}

Supported "type" values: "text", "html", "image", "file", "files".

Examples

Minimal — uppercase text

def advanced_paste_from_text(text):
    return text.upper()

That's it. No headers required, no imports from PowerToys.

With optional metadata

# @advancedpaste:name   Reverse Text
# @advancedpaste:desc   Reverses clipboard text character by character

def advanced_paste_from_text(text):
    return text[::-1]

Image processing

from PIL import Image
from pathlib import Path
import tempfile

def advanced_paste_from_image(image_path):
    """Convert image to grayscale."""
    img = Image.open(image_path).convert("L")
    out = Path(tempfile.gettempdir()) / "gray.png"
    img.save(out)
    return out

Return HTML

def advanced_paste_from_text(text):
    return {"type": "html", "value": f"<pre><code>{text}</code></pre>"}

Multiple input types in one script

def advanced_paste_from_text(text):
    return f"Text ({len(text)} chars): {text[:100]}"

def advanced_paste_from_files(file_paths):
    return "\n".join(file_paths)

File listing

import os

def advanced_paste_from_files(file_paths):
    lines = []
    for p in file_paths:
        size = os.path.getsize(p)
        lines.append(f"{os.path.basename(p)} ({size} bytes)")
    return "\n".join(lines)

Header tags

All header tags are optional. Tags are placed in comment lines at the top of the script.

Tag Description
name Display name in the Advanced Paste UI. If omitted, the filename is used.
desc Short description / tooltip.
disabled Presence of this tag disables the script (it won't appear in the UI).
requires Declare Python package dependencies (see Dependencies).

Example header

# @advancedpaste:name   My Formatter
# @advancedpaste:desc   Formats clipboard text as markdown table

To disable a script without deleting it, add:

# @advancedpaste:disabled

Remove the line to re-enable.

Declaring dependencies

Use requires to declare Python packages the script needs:

# @advancedpaste:requires PIL=Pillow
# @advancedpaste:requires cv2=opencv-python-headless numpy requests

Each token is either:

  • import_name — the pip package is assumed to have the same name (e.g. requests).
  • import_name=pip_package — when the import name differs from the pip package (e.g. cv2=opencv-python-headless, PIL=Pillow).

Automatic import detection

Advanced Paste also scans the script body for import and from ... import statements and cross-references them against the Python standard library. Any non-stdlib import that is not already installed triggers a prompt to install it automatically.

Security — script trust

The first time a script is executed (or after it has been modified), Advanced Paste shows a confirmation dialog. Upon approval the SHA-256 hash of the script is stored. Subsequent runs of the unchanged file skip the dialog.

Error handling

When a script fails, Advanced Paste extracts the Python traceback from stderr and displays a user-friendly summary in the UI:

  • ModuleNotFoundError — identifies the missing module and suggests installing it.
  • SyntaxError — shows the file and line number.
  • Timeout — shows the configured timeout value (default 30 s; configurable in Settings).
  • Other errors — shows the last line of the traceback as a summary, with the full traceback available in the expandable Details section.

Settings

The following settings are available under Settings → Advanced Paste → Python scripts:

Setting Description Default
Python interpreter Path to the Python executable. Leave blank for auto-detection. (auto-detect)
Scripts folder Folder to scan for .py scripts. %LOCALAPPDATA%\Microsoft\PowerToys\AdvancedPaste\Scripts

Tips

  • A .py file without any advanced_paste_from_* function is ignored — use this for helper modules that other scripts can import.
  • Scripts can be tested from the command line:
    echo {"format":"text","text":"hello"} | python _runner.py my_script.py
    
  • The script's directory is added to sys.path at runtime, so you can import sibling .py files as helper modules.