# How to Handle Cross-Platform Compatibility in Document Generation: Lessons from the Anthropic Skills Repository

> Learn to handle cross-platform compatibility in document generation by combining OS detection, universal path handling, portable wrappers, and conditional dependencies.

- Repository: [Anthropic/skills](https://github.com/anthropics/skills)
- Tags: how-to-guide
- Published: 2026-02-16

---

**Handle cross-platform compatibility in document generation by combining runtime OS detection with `platform.system()`, universal path handling via `pathlib.Path`, portable LibreOffice subprocess wrappers with environment shims, and conditional dependency paths for macOS and Linux.**

The `anthropics/skills` repository demonstrates enterprise-grade patterns for cross-platform document generation across Linux, macOS, and Windows. By abstracting OS-specific commands, filesystem paths, and sandbox restrictions into portable Python utilities, the codebase ensures consistent behavior regardless of the underlying operating system.

## Runtime OS Detection and Command Adaptation

The foundation of cross-platform compatibility lies in explicit OS detection using Python’s built-in `platform` module. The [`skills/xlsx/scripts/recalc.py`](https://github.com/anthropics/skills/blob/main/skills/xlsx/scripts/recalc.py) file queries `platform.system()` to distinguish between "Linux", "Darwin" (macOS), and other systems, then adapts subprocess commands accordingly.

### Timeout Handling Example

When executing time-bounded operations, the repository selects the appropriate timeout utility based on the host OS:

```python
import platform
import subprocess

cmd = ["soffice", "--headless", "--convert-to", "pdf", "input.xlsx"]

if platform.system() == "Linux":
    cmd = ["timeout", "30"] + cmd
elif platform.system() == "Darwin":
    cmd = ["gtimeout", "30"] + cmd  # Homebrew GNU timeout

result = subprocess.run(cmd, capture_output=True, text=True)

```

This pattern ensures that document generation pipelines fail gracefully on hung processes without requiring users to install OS-specific wrappers manually.

## Universal Path Handling with pathlib

All filesystem interactions in the repository rely on `pathlib.Path` rather than string manipulation or `os.path` functions. This abstraction automatically handles Windows backslashes versus POSIX forward slashes, eliminating path separator bugs.

### Portable Path Construction

The [`skills/pdf/scripts/convert_pdf_to_images.py`](https://github.com/anthropics/skills/blob/main/skills/pdf/scripts/convert_pdf_to_images.py) script demonstrates idiomatic path handling:

```python
from pathlib import Path

def save_image(image, out_dir, page):
    out_path = Path(out_dir) / f"page_{page}.png"
    image.save(out_path)
    print(f"Saved {out_path}")

```

By constructing paths with the `/` operator, the same code executes correctly on Windows, macOS, and Linux without conditional logic for path separators.

## Portable Subprocess Execution for LibreOffice

Document generation frequently requires invoking external tools like LibreOffice (`soffice`). The repository centralizes this logic in [`skills/xlsx/scripts/office/soffice.py`](https://github.com/anthropics/skills/blob/main/skills/xlsx/scripts/office/soffice.py), which configures environment variables and handles sandbox restrictions that vary across platforms and deployment environments.

### Environment Shim Implementation

The wrapper prepares a headless, portable execution environment:

```python
from office.soffice import run_soffice

# Convert a DOCX file to PDF, regardless of sandbox restrictions

result = run_soffice(["--headless", "--convert-to", "pdf", "input.docx"])
print(result.stdout)

```

Under the hood, [`soffice.py`](https://github.com/anthropics/skills/blob/main/soffice.py) performs three critical tasks:

1. **Disables GUI dependencies** by setting `SAL_USE_VCLPLUGIN=svp`, ensuring LibreOffice runs in server environments without X11 or display servers.
2. **Detects sandbox restrictions** on `AF_UNIX` sockets and injects an `LD_PRELOAD` shim to emulate socket functionality when running in restricted containers.
3. **Normalizes environment variables** through the `run_soffice` wrapper, ensuring consistent behavior across macOS, Linux, and Windows Subsystem for Linux (WSL).

## Conditional Dependencies and Graceful Degradation

When tools or resources reside in OS-specific locations, the repository implements conditional path construction rather than hardcoding directories. This pattern appears in [`recalc.py`](https://github.com/anthropics/skills/blob/main/recalc.py) when locating LibreOffice macro directories.

### Macro Directory Selection

LibreOffice stores user macros in different locations depending on the operating system:

```python
import platform
from pathlib import Path

def get_macro_path():
    system = platform.system()
    if system == "Darwin":
        return Path.home() / "Library/Application Support/LibreOffice/4/user/Scripts/python"
    else:
        # Linux and other POSIX systems

        return Path.home() / ".config/libreoffice/4/user/Scripts/python"

```

By detecting the platform at runtime, the same script installs macros correctly on macOS (`~/Library/Application Support/`) and Linux (`~/.config/`) without user intervention.

## Summary

- **Use `platform.system()`** to detect the operating system and select appropriate system commands like `timeout` versus `gtimeout`.
- **Adopt `pathlib.Path`** for all filesystem operations to automatically handle Windows and POSIX path separators.
- **Wrap external tools** like LibreOffice in portable subprocess helpers that configure environment variables and handle sandbox restrictions via `LD_PRELOAD` shims.
- **Implement conditional logic** for OS-specific file locations such as macro directories or configuration paths.
- **Prefer standard library solutions** over third-party OS-specific binaries to minimize external dependencies and maximize portability.

## Frequently Asked Questions

### How do I detect the operating system in Python for document generation tasks?

Use the `platform` module's `system()` function, which returns strings like "Linux", "Darwin" (macOS), or "Windows". In the `anthropics/skills` repository, [`recalc.py`](https://github.com/anthropics/skills/blob/main/recalc.py) uses this to choose between the native `timeout` command on Linux and the Homebrew `gtimeout` on macOS, ensuring subprocess calls work across platforms without modification.

### What is the best way to handle file paths in cross-platform Python scripts?

Always use `pathlib.Path` instead of string manipulation or `os.path`. The `Path` class automatically handles OS-specific path separators, allowing you to use the `/` operator to join paths on both Windows and POSIX systems. The [`convert_pdf_to_images.py`](https://github.com/anthropics/skills/blob/main/convert_pdf_to_images.py) script in the skills repository demonstrates this pattern by constructing output paths using `Path(out_dir) / f"page_{page}.png"`.

### How can I run LibreOffice in sandboxed or headless environments across different operating systems?

Use a wrapper module that configures environment variables and handles socket restrictions. The [`soffice.py`](https://github.com/anthropics/skills/blob/main/soffice.py) helper in the skills repository sets `SAL_USE_VCLPLUGIN=svp` to disable GUI dependencies and injects an `LD_PRELOAD` shim when `AF_UNIX` sockets are blocked by the sandbox. This ensures `soffice` runs consistently on Linux, macOS, and containerized environments without platform-specific modifications.

### How do I handle OS-specific dependency paths like LibreOffice macro directories?

Implement conditional path construction based on `platform.system()` detection. In [`recalc.py`](https://github.com/anthropics/skills/blob/main/recalc.py), the script checks for "Darwin" to build the macOS macro path (`~/Library/Application Support/LibreOffice/4/user/Scripts/python/`) and defaults to the Linux XDG path (`~/.config/libreoffice/4/user/Scripts/python/`) for other systems. This pattern allows the same codebase to locate resources correctly regardless of the host OS.