Metadata-Version: 2.5
Name: pytailcat
Version: 0.1.4
Summary: Peer-to-peer WireGuard tunnels with NAT traversal and zero coordination server
Author: pytailcat contributors
License-Expression: BSD-3-Clause
License-File: LICENSE
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: System :: Networking
Requires-Python: >=3.8
Provides-Extra: dev
Requires-Dist: pytest>=7.0.0; extra == 'dev'
Requires-Dist: wheel>=0.40.0; extra == 'dev'
Description-Content-Type: text/markdown

<p align="center">
  <b>English</b> · <a href="README.es.md">Español</a>
</p>

<p align="center">
  <img src="https://raw.githubusercontent.com/joseluisfalcon/pytailcat/main/assets/tailcat.png" alt="Tailcat" width="140" height="165">
</p>

<p align="center">
  <em>"Tailscale without Tailscale, for Python"</em>
</p>

<p align="center">
  <a href="https://pypi.org/project/pytailcat/"><img src="https://img.shields.io/pypi/v/pytailcat.svg?color=blue" alt="PyPI version"></a>
  <a href="https://pypi.org/project/pytailcat/"><img src="https://img.shields.io/pypi/pyversions/pytailcat.svg" alt="Python Versions"></a>
  <a href="LICENSE"><img src="https://img.shields.io/badge/license-BSD--3--Clause-green.svg" alt="License"></a>
</p>

---

# pytailcat

**`pytailcat`** is the Python distribution and library for [**Tailcat**](https://github.com/tailscale/tailcat), an open-source peer-to-peer network pipe built on Tailscale's data plane (`magicsock`) providing end-to-end WireGuard® encryption and automatic NAT traversal **without requiring a Tailscale account, root permissions, or a coordination server**.

When installed via `pip` or `uv`, `pytailcat` bundles native, precompiled standalone binaries for your exact operating system and CPU architecture, making the `tailcat` command immediately accessible in your terminal alongside a Python management API.

---

## Key Features

- 🚀 **1-Second Installation**: No Go toolchain or C compilers required.
- 🔒 **End-to-End WireGuard® Encryption**: Direct peer-to-peer tunnels authenticated with Noise IK.
- 🌐 **Automatic NAT Traversal (`magicsock`)**: Traverses firewalls and symmetric NATs via STUN and public or private DERP relays; automatically upgrades to a direct UDP connection when possible.
- 🛡️ **Zero Root Permissions Required**: Powered by Google gVisor's userspace TCP/IP stack, avoiding any routing table modifications or kernel `tun0` virtual network interfaces.
- 📦 **Cross-Platform**: Official binary wheels for Linux (x86_64 & ARM64), macOS (Intel & Apple Silicon M1-M4), and Windows (x86_64).

---

## Installation

Using **`pip`**:
```bash
pip install pytailcat
```

Using **`uv`**:
```bash
uv add pytailcat
```

---

## Terminal Usage (CLI)

Once installed, the `tailcat` command is available directly in your terminal:

### 1. Simple stdin / stdout pipe between two machines
On the **server** machine:
```bash
$ tailcat
# Selected bootstrap relay region 302, San Francisco
# 🐈 Server listening with new address: tcomFwWCCcjS5nKNqAod034nWoJZW0LZqDhhC8U_dKdnDRYQ8uNGFpGQEu
```

On the **client** machine:
```bash
$ echo "Hello through WireGuard!" | tailcat tcomFwWCCcjS5nKNqAod034nWoJZW0LZqDhhC8U_dKdnDRYQ8uNGFpGQEu
```
The text will instantly appear in the server terminal!

### 2. Transfer files with real-time progress (using `dd`)
You can stream files between machines and monitor transfer speed and progress in real time using `dd status=progress`.

> **Important**: Always execute the **receiver** command first (`tailcat | dd of=...`) so that Tailcat starts listening and prints the connection token. Then, use that token on the **sender** machine.

**Step 1: On the receiver machine (starts server and waits for incoming data):**
```bash
tailcat | dd of=received_file.iso status=progress bs=1M
# Selected bootstrap relay region 303, Frankfurt
# 🐈 Server listening with new address: tcomFwWCCcjS5nKNqAod034n...
```
*(Tailcat outputs its listening address to stderr so you can copy the token, while piping incoming file data from stdout directly into `dd`)*.

**Step 2: On the sender machine (connects using the token and streams the file):**
```bash
dd if=my_file.iso status=progress bs=1M | tailcat tcomFwWCCcjS5nKNqAod034n...
```
Both terminals will display live transfer statistics (bytes copied, elapsed time, and transfer speed in MB/s).

### 3. Expose a local port through the tunnel
Server:
```bash
tailcat --serve=8080
```
Client:
```bash
tailcat tcXXXXXXXXX 8080
```

### 4. Passwordless SSH Server
```bash
tailcat --serve=no-auth-ssh
```
Client:
```bash
tailcat ssh tcXXXXXXXXX
```

### 5. SOCKS5 Proxy Mode
Route any command's traffic through the secure tunnel:
```bash
tailcat socks <token> curl http://server.tailcat:8080/
```

### 6. Test connectivity and upgrade to direct UDP
```bash
tailcat ping --until-direct <token>
```

---

## Python API Usage (`import pytailcat`)

In addition to the CLI, `pytailcat` includes Python classes and utilities to manage Tailcat programmatically:

### Start a background server
```python
from pytailcat import ServerProcess

# Start server exposing local port 8080
with ServerProcess(serve="8080") as server:
    print(f"Server ready! Connection token: {server.token}")
    # The server runs for the duration of the 'with' block
    input("Press Enter to stop the server...")

print("Server stopped.")
```

### Run Tailcat commands via API
```python
import pytailcat

# Execute tailcat command and capture its output
res = pytailcat.run(["parse", "tcomFwWCCcjS5n..."], capture_output=True)
print("Token information:")
print(res.stdout)
```

---

## Distribution Architecture (PyPI Wheels)

`pytailcat` solves the complexity of packaging Go code for Python by distributing precompiled PEP 427 *Platform Wheels* (`.whl`):

| Platform | Architecture | Wheel Tag | Bundled Binary |
| :--- | :--- | :--- | :--- |
| **Linux** | x86_64 (Intel/AMD) | `manylinux_2_17_x86_64` | `tailcat` (static) |
| **Linux** | aarch64 (ARM 64-bit / RPi) | `manylinux_2_17_aarch64` | `tailcat` (static) |
| **macOS** | arm64 (Apple Silicon M1-M4)| `macosx_11_0_arm64` | `tailcat` |
| **macOS** | x86_64 (Intel) | `macosx_10_9_x86_64` | `tailcat` |
| **Windows** | x86_64 (64-bit) | `win_amd64` | `tailcat.exe` |

When an end user installs `pytailcat`, Python package managers download only the wheel matching their exact system, installing in milliseconds without compilation.

---

## Local Development and Building

To contribute or build the project locally using **`uv`**:

### 1. Clone repository with submodules and set up virtual environment
```bash
git clone --recursive https://github.com/joseluisfalcon/pytailcat.git
cd pytailcat
uv venv .venv
source .venv/bin/activate
```

### 2. Build local binary and install in editable mode
```bash
# Build the native binary for your current host
uv run python scripts/build_binaries.py --local

# Install pytailcat and test tools
uv pip install -e ".[dev]"
```

### 3. Run test suite
```bash
uv run pytest tests/ -v
```

### 4. Build all cross-platform wheels
```bash
uv run python scripts/build_binaries.py --all
ls -lh dist/
```

---

## Roadmap

- [x] **Phase 1 (Completed - Option B)**: 
  - Cross-platform packaging via PyPI binary wheels.
  - Transparent `tailcat` CLI wrapper supporting all upstream arguments.
  - Python `ServerProcess` helper and `run()` wrapper.
  - Automated CI/CD with GitHub Actions for PyPI publishing.
- [ ] **Phase 2 (Upcoming - Option A)**:
  - Go C-Shared library (`libtailcat.so` / `.dll`).
  - In-memory bindings via `cffi` to interface directly with Python TCP streams (`socket` and `asyncio`) without subprocesses.

---

## License

This project is licensed under the **BSD 3-Clause License**, matching the upstream Tailscale / Tailcat license. See [LICENSE](LICENSE) for details.
