Claude Code for pyperclip: Python Clipboard Access — Claude Skills 360 Blog
Blog / AI / Claude Code for pyperclip: Python Clipboard Access
AI

Claude Code for pyperclip: Python Clipboard Access

Published: February 18, 2028
Read time: 5 min read
By: Claude Skills 360

pyperclip reads and writes the system clipboard from Python. pip install pyperclip. Copy: import pyperclip; pyperclip.copy("hello world"). Paste: text = pyperclip.paste(). Error: from pyperclip import PyperclipException — raised when no clipboard mechanism found (headless Linux without xclip/xsel). Platform: macOS uses pbcopy/pbpaste, Windows uses ctypes win32 clipboard API, Linux uses xclip or xsel if available. Install xclip: apt install xclip. Fallback: try: pyperclip.copy(text); except PyperclipException: print(text). waitForNewPaste: pyperclip.waitForNewPaste() — blocks until clipboard changes, returns new content. pyperclip.waitForPaste() — blocks until clipboard is non-empty. Determine: pyperclip.determine_clipboard() — returns copy/paste fn pair. setClipboard: pyperclip.setclipboard("pbcopy") — force a specific mechanism. CLI copy: pipe output to clipboard — result = run_command(); pyperclip.copy(result); print("Copied!"). Template: generate code snippet, copy to clipboard for pasting into editor. Argparse: --copy flag that calls pyperclip.copy(output) after generating. Clipboard history: store sequence of pyperclip.paste() results. Multi-copy: copy formatted table, JSON, or CSV — paste into spreadsheet or terminal. Claude Code generates pyperclip copy/paste helpers, CLI copy flags, and clipboard pipeline utilities.

CLAUDE.md for pyperclip

## pyperclip Stack
- Version: pyperclip >= 1.8 | pip install pyperclip
- Copy: pyperclip.copy(text) — writes to system clipboard
- Paste: text = pyperclip.paste() — reads from system clipboard
- Error: catch PyperclipException on headless Linux without xclip/xsel
- Wait: pyperclip.waitForNewPaste() — blocks until clipboard changes
- CLI: add --copy flag that calls pyperclip.copy(output) after generating
- Linux: install xclip (apt install xclip) or xsel for clipboard support

pyperclip Clipboard Pipeline

# app/clipboard.py — pyperclip copy/paste, CLI --copy flag, and clipboard utilities
from __future__ import annotations

import json
import sys
import time
from typing import Any, Callable

try:
    import pyperclip
    from pyperclip import PyperclipException
    _PYPERCLIP_AVAILABLE = True
except ImportError:
    _PYPERCLIP_AVAILABLE = False
    PyperclipException = Exception


# ─────────────────────────────────────────────────────────────────────────────
# 1. Safe copy/paste wrappers
# ─────────────────────────────────────────────────────────────────────────────

def copy(text: str, silent: bool = False) -> bool:
    """
    Copy text to the system clipboard.
    Returns True on success, False when no clipboard mechanism is available
    (headless Linux without xclip/xsel, SSH sessions without X forwarding).
    """
    if not _PYPERCLIP_AVAILABLE:
        return False
    try:
        pyperclip.copy(text)
        if not silent:
            char_count = len(text)
            line_count = text.count("\n") + 1
            print(f"  Copied {char_count} chars ({line_count} lines) to clipboard.")
        return True
    except PyperclipException as e:
        if not silent:
            print(f"  Clipboard unavailable: {e}", file=sys.stderr)
        return False


def paste() -> str | None:
    """
    Read the current clipboard content.
    Returns None if clipboard is unavailable or empty.
    """
    if not _PYPERCLIP_AVAILABLE:
        return None
    try:
        return pyperclip.paste() or None
    except PyperclipException:
        return None


def copy_or_print(text: str, copy_flag: bool = False) -> None:
    """
    Utility used by CLI commands: copy if --copy passed, otherwise print.
    This is the canonical pattern for CLI tools that generate text output.
    """
    if copy_flag:
        ok = copy(text, silent=True)
        if ok:
            print(f"✓ Copied to clipboard ({len(text)} chars)")
        else:
            # Fall back to printing when clipboard isn't available
            print(text)
    else:
        print(text)


# ─────────────────────────────────────────────────────────────────────────────
# 2. Formatted copy helpers
# ─────────────────────────────────────────────────────────────────────────────

def copy_json(obj: Any, indent: int = 2, copy_flag: bool = True) -> str:
    """Serialize obj to JSON and copy to clipboard."""
    text = json.dumps(obj, indent=indent, ensure_ascii=False, default=str)
    copy_or_print(text, copy_flag)
    return text


def copy_table_csv(
    rows: list[dict],
    columns: list[str] | None = None,
    copy_flag: bool = True,
) -> str:
    """
    Format a list of dicts as CSV and optionally copy.
    Paste directly into Excel or Google Sheets.
    """
    import csv, io
    columns = columns or (list(rows[0].keys()) if rows else [])
    buf = io.StringIO()
    writer = csv.DictWriter(buf, fieldnames=columns, extrasaction="ignore")
    writer.writeheader()
    writer.writerows(rows)
    text = buf.getvalue()
    copy_or_print(text, copy_flag)
    return text


def copy_markdown_table(
    rows: list[dict],
    columns: list[str] | None = None,
    copy_flag: bool = True,
) -> str:
    """Format a list of dicts as a Markdown table and optionally copy."""
    if not rows:
        return ""
    columns = columns or list(rows[0].keys())
    widths  = {col: max(len(col), max(len(str(r.get(col, ""))) for r in rows)) for col in columns}

    header = "| " + " | ".join(f"{c:<{widths[c]}}" for c in columns) + " |"
    sep    = "| " + " | ".join("-" * widths[c] for c in columns) + " |"
    body   = "\n".join(
        "| " + " | ".join(f"{str(r.get(c,'')):<{widths[c]}}" for c in columns) + " |"
        for r in rows
    )
    text = f"{header}\n{sep}\n{body}"
    copy_or_print(text, copy_flag)
    return text


# ─────────────────────────────────────────────────────────────────────────────
# 3. Clipboard wait / watch
# ─────────────────────────────────────────────────────────────────────────────

def wait_for_new_paste(timeout: float = 30.0, prompt: str = "") -> str | None:
    """
    Block until the clipboard changes and return the new content.
    pyperclip.waitForNewPaste() polls the clipboard until it changes.
    timeout: how long to wait in seconds (0 = indefinite).
    """
    if not _PYPERCLIP_AVAILABLE:
        return None
    if prompt:
        print(prompt)
    try:
        if timeout > 0:
            # waitForNewPaste doesn't support timeout — implement with thread
            import threading
            result: list[str] = []
            exc:    list[Exception] = []

            def _wait():
                try:
                    result.append(pyperclip.waitForNewPaste())
                except Exception as e:
                    exc.append(e)

            t = threading.Thread(target=_wait, daemon=True)
            t.start()
            t.join(timeout=timeout)
            if exc:
                raise exc[0]
            return result[0] if result else None
        else:
            return pyperclip.waitForNewPaste()
    except PyperclipException:
        return None


def watch_clipboard(
    callback: Callable[[str], None],
    interval: float = 0.5,
    max_events: int = 0,
) -> None:
    """
    Poll clipboard every `interval` seconds and call callback on changes.
    Useful for clipboard-driven automation tools.
    max_events=0 → run forever (until KeyboardInterrupt).
    """
    if not _PYPERCLIP_AVAILABLE:
        raise RuntimeError("pyperclip is not available")
    last = paste() or ""
    seen = 0
    try:
        while True:
            current = paste() or ""
            if current != last and current:
                last = current
                callback(current)
                seen += 1
                if max_events and seen >= max_events:
                    break
            time.sleep(interval)
    except KeyboardInterrupt:
        pass


# ─────────────────────────────────────────────────────────────────────────────
# 4. argparse --copy flag integration
# ─────────────────────────────────────────────────────────────────────────────

def add_copy_argument(parser) -> None:
    """
    Add a --copy / -c flag to an argparse.ArgumentParser.
    The flag tells the tool to copy its output to the clipboard.
    """
    parser.add_argument(
        "--copy", "-c",
        action="store_true",
        default=False,
        help="Copy output to clipboard instead of printing",
    )


# ─────────────────────────────────────────────────────────────────────────────
# 5. Clipboard history (session-level)
# ─────────────────────────────────────────────────────────────────────────────

class ClipboardHistory:
    """
    Record a sequence of clipboard snapshots.
    Useful for building tools that process a series of pasted values.
    """

    def __init__(self, max_size: int = 50) -> None:
        self._history: list[str] = []
        self._max    = max_size

    def snapshot(self) -> str | None:
        """Take a snapshot of the current clipboard."""
        text = paste()
        if text and (not self._history or self._history[-1] != text):
            if len(self._history) >= self._max:
                self._history.pop(0)
            self._history.append(text)
        return text

    def last(self) -> str | None:
        return self._history[-1] if self._history else None

    def all(self) -> list[str]:
        return list(self._history)

    def clear(self) -> None:
        self._history.clear()


# ─────────────────────────────────────────────────────────────────────────────
# Demo
# ─────────────────────────────────────────────────────────────────────────────

if __name__ == "__main__":
    print("=== Basic copy/paste ===")
    ok = copy("Hello from pyperclip!")
    if ok:
        text = paste()
        print(f"  Read back: {text!r}")

    print("\n=== Copy JSON ===")
    data = {"name": "Alice", "score": 95, "tags": ["python", "cli"]}
    copy_json(data, copy_flag=True)

    print("\n=== Copy Markdown table ===")
    rows = [
        {"tool": "pyperclip", "version": "1.8", "use": "clipboard"},
        {"tool": "colorama",  "version": "0.4", "use": "colors"},
        {"tool": "rich",      "version": "13",  "use": "terminal UI"},
    ]
    copy_markdown_table(rows, copy_flag=True)

    print("\n=== Copy CSV ===")
    copy_table_csv(rows, copy_flag=True)

    print("\n=== Clipboard available ===")
    print(f"  pyperclip available: {_PYPERCLIP_AVAILABLE}")

    # Clipboard watch demo (fires once then exits due to max_events=1)
    # Uncomment to test interactively:
    # print("\n=== Watching clipboard (copy something within 5 seconds) ===")
    # watch_clipboard(lambda t: print(f"  New clipboard: {t[:80]}"), max_events=1)

For the subprocess pbcopy/pbpaste alternative — calling subprocess.run(["pbcopy"], input=text.encode()) works on macOS but fails on Linux and Windows, requiring platform-specific branching; pyperclip handles all three platforms with one API, using pbcopy/pbpaste on macOS, the Win32 clipboard API on Windows, and xclip/xsel on Linux, so the same pyperclip.copy(text) call works everywhere without sys.platform conditionals. For the tkinter.Tk().clipboard_get() alternative — tkinter can access the clipboard but requires a display connection and spinning up a Tk root window, which fails in headless environments and adds startup latency; pyperclip is a lightweight wrapper that uses native clipboard utilities directly without a GUI framework dependency. The Claude Skills 360 bundle includes pyperclip skill sets covering pyperclip.copy() and pyperclip.paste(), safe copy() wrapper with PyperclipException handling, copy_or_print() for —copy CLI flag pattern, copy_json() for JSON output, copy_table_csv() and copy_markdown_table() for formatted table output, wait_for_new_paste() with timeout, watch_clipboard() polling watcher, ClipboardHistory session recorder, and add_copy_argument() argparse integration. Start with the free tier to try clipboard integration code generation.

Keep Reading

AI

Claude Code for email.contentmanager: Python Email Content Accessors

Read and write EmailMessage body content with Python's email.contentmanager module and Claude Code — email contentmanager ContentManager for the class that maps content types to get and set handler functions allowing EmailMessage to support get_content and set_content with type-specific behaviour, email contentmanager raw_data_manager for the ContentManager instance that handles raw bytes and str payloads without any conversion, email contentmanager content_manager for the standard ContentManager instance used by email.policy.default that intelligently handles text plain text html multipart and binary content types, email contentmanager get_content_text for the handler that returns the decoded text payload of a text-star message part as a str, email contentmanager get_content_binary for the handler that returns the raw decoded bytes payload of a non-text message part, email contentmanager get_data_manager for the get-handler lookup used by EmailMessage get_content to find the right reader function for the content type, email contentmanager set_content text for the handler that creates and sets a text part correctly choosing charset and transfer encoding, email contentmanager set_content bytes for the handler that creates and sets a binary part with base64 encoding and optional filename Content-Disposition, email contentmanager EmailMessage get_content for the method that reads the message body using the registered content manager handlers, email contentmanager EmailMessage set_content for the method that sets the message body and MIME headers in one call, email contentmanager EmailMessage make_alternative make_mixed make_related for the methods that convert a simple message into a multipart container, email contentmanager EmailMessage add_attachment for the method that attaches a file or bytes to a multipart message, and email contentmanager integration with email.message and email.policy and email.mime and io for building high-level email readers attachment extractors text body accessors HTML readers and policy-aware MIME construction pipelines.

5 min read Feb 12, 2029
AI

Claude Code for email.charset: Python Email Charset Encoding

Control header and body encoding for international email with Python's email.charset module and Claude Code — email charset Charset for the class that wraps a character set name with the encoding rules for header encoding and body encoding describing how to encode text for that charset in email messages, email charset Charset header_encoding for the attribute specifying whether headers using this charset should use QP quoted-printable encoding BASE64 encoding or no encoding, email charset Charset body_encoding for the attribute specifying the Content-Transfer-Encoding to use for message bodies in this charset such as QP or BASE64, email charset Charset output_codec for the attribute giving the Python codec name used to encode the string to bytes for the wire format, email charset Charset input_codec for the attribute giving the Python codec name used to decode incoming bytes to str, email charset Charset get_output_charset for returning the output charset name, email charset Charset header_encode for encoding a header string using the charset's header_encoding method, email charset Charset body_encode for encoding body content using the charset's body_encoding, email charset Charset convert for converting a string from the input_codec to the output_codec, email charset add_charset for registering a new charset with custom encoding rules in the global charset registry, email charset add_alias for adding an alias name that maps to an existing registered charset, email charset add_codec for registering a codec name mapping for use by the charset machinery, and email charset integration with email.message and email.mime and email.policy and email.encoders for building international email senders non-ASCII header encoders Content-Transfer-Encoding selectors charset-aware message constructors and MIME encoding pipelines.

5 min read Feb 11, 2029
AI

Claude Code for email.utils: Python Email Address and Header Utilities

Parse and format RFC 2822 email addresses and dates with Python's email.utils module and Claude Code — email utils parseaddr for splitting a display-name plus angle-bracket address string into a realname and email address tuple, email utils formataddr for combining a realname and address string into a properly quoted RFC 2822 address with angle brackets, email utils getaddresses for parsing a list of raw address header strings each potentially containing multiple comma-separated addresses into a list of realname address tuples, email utils parsedate for parsing an RFC 2822 date string into a nine-tuple compatible with time.mktime, email utils parsedate_tz for parsing an RFC 2822 date string into a ten-tuple that includes the UTC offset timezone in seconds, email utils parsedate_to_datetime for parsing an RFC 2822 date string into an aware datetime object with timezone, email utils formatdate for formatting a POSIX timestamp or the current time as an RFC 2822 date string with optional usegmt and localtime flags, email utils format_datetime for formatting a datetime object as an RFC 2822 date string, email utils make_msgid for generating a globally unique Message-ID string with optional idstring and domain components, email utils decode_rfc2231 for decoding an RFC 2231 encoded parameter value into a tuple of charset language and value, email utils encode_rfc2231 for encoding a string as an RFC 2231 encoded parameter value, email utils collapse_rfc2231_value for collapsing a decoded RFC 2231 tuple to a Unicode string, and email utils integration with email.message and email.headerregistry and datetime and time for building address parsers date formatters message-id generators header extractors and RFC-compliant email construction utilities.

5 min read Feb 10, 2029

Put these ideas into practice

Claude Skills 360 gives you production-ready skills for everything in this article — and 2,350+ more. Start free or go all-in.

Back to Blog

Get 360 skills free