Skip to content

Mouse, keyboard, and clipboard sharing across multiple devices.

License

Notifications You must be signed in to change notification settings

fizzi01/Perpetua

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

311 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Perpetua Logo

Perpetua

Perpetua is an open-source, cross-platform KVM software that lets you share a single keyboard and mouse across multiple devices. Inspired by Apple's Universal Control, it provides seamless cursor movement between devices, keyboard sharing, and automatic clipboard synchronization. All secured with TLS encryption.

Built with Python, leveraging high-performance uvloop (macOS) and winloop (Windows) for low-latency, responsive input handling.

Perpetua Server View

Download

GitHub Downloads (all assets, latest release)

Supported Operating Systems

Actually only Windows and MacOS are supported.

Known Issues

This section is reserved for documenting platform-specific issues and workarounds as they are identified.

Important

  • Windows: You can't control a Windows client if there is no real mouse connected to the machine.

  • Input Capture Conflicts: Perpetua cannot control the mouse when other applications have exclusive input capture (e.g., video games). This is an architectural limitation.

Usage

Download the latest release.

  • macOS: Extract the .zip and launch Perpetua.app.
  • Windows: Extract the archive and run Perpetua.exe inside the Perpetua folder.

The GUI will guide you through choosing server or client mode and the initial configuration.

Tip

For detailed configuration options, including client-server pairing, and security settings, see the Configuration section below.

Background Mode

You can run Perpetua as a background service using the daemon mode:

# Run in daemon mode (you'll choose server or client later)
./Perpetua --daemon

# Automatically start as server
./Perpetua --daemon -s

# Automatically start as client
./Perpetua --daemon -c

For a full list of available commands and options:

./Perpetua --help
# or
./Perpetua -h

Development / Building from Source

Prerequisites
  • Python Environment:

    • Python 3.11 or 3.12
    • Poetry
  • GUI Framework:

    • Node.js
    • Rust
Platform-Specific Requirements
  • macOS:

    • Xcode Command Line Tools
      xcode-select --install
    • Dependencies needed to build uvloop
      brew install automake
      brew install autoconf
      brew install libtool
      brew install ccache
  • Windows:

Note

Windows versions prior to Windows 10 (1803) require Microsoft Edge WebView2 Runtime to be installed manually.

Quick Start

The project includes both a build script and Makefile for convenient building.

  1. Clone the repository:

    git clone https://github.com/fizzi01/Perpetua.git
    cd Perpetua
  2. Install Python dependencies:

    poetry install
    # or
    pip install .
    # or
    make install-build
  3. Run the build:

    poetry run python build.py
    # or
    make build

Development Setup

To work on Perpetua in development mode:

  1. Install Python dependencies:

    poetry install
  2. Run in development mode:

    python launcher.py

    The launcher will automatically start the GUI in development mode and the daemon in background.

    To run the daemon only:

    python src/service/daemon.py

Note

Make sure all prerequisites and dependencies are installed before running launcher.py or daemon.py.

  1. Install GUI dependencies (optional, if you need to modify the GUI):
    cd src-gui
    npm install
Advanced Build Options

Using Poetry

# Debug build
poetry run python build.py --debug

# Skip GUI build (build daemon only)
poetry run python build.py --skip-gui

# Skip daemon build (build GUI only)
poetry run python build.py --skip-daemon

# Clean build artifacts before building
poetry run python build.py --clean

Using Make

# Debug build
make build-debug

# Build daemon only
make build-daemon

# Build GUI only
make build-gui

# Release build with clean
make build-release

# Clean build artifacts
make clean
Manual Build Steps

For manual builds or troubleshooting, follow these steps:

Build GUI:

cd src-gui
npm install
cargo tauri build

Build Daemon:

# From project root
poetry run python build.py --skip-gui

Configuration

Perpetua uses JSON to define client and server settings. Configuration file is automatically generated on first launch with sensible defaults, requiring minimal manual intervention for most use cases.

Configuration File Locations:

  • macOS: $HOME/Library/Caches/Perpetua
  • Windows: %LOCALAPPDATA%\Perpetua
Server Configuration

The server configuration is managed automatically for basic setup (certificate generation, network binding). However, to accept client connections, you must manually add each client to the server configuration (or in Server > Clients section), specifying:

  • Client IP or Hostname
  • Screen Position: The spatial arrangement relative to the server (left, right, top, bottom)

This configuration defines how devices are arranged in your workspace for a seamless cursor transition between them.

Client Configuration

Clients can find servers in two ways:

Auto Discovery (Default):

  • Scans the local network for available servers
  • Works out of the box, no configuration needed

Manual Configuration:

  • Set the server's hostname or IP address directly in the config file (or in the appropiate field in Client > Options)
  • Use this when auto-discovery doesn't work or you have a static network setup
First Connection and OTP Pairing

When a client connects to a new server for the first time, it needs to get the server's TLS certificate to establish a secure connection. Here's how it works:

  1. The client starts the connection process
  2. On the Server (which must be running and listening), generate an OTP through the GUI in the Security section ("Secure connection" must be enabled!)
  3. Enter the OTP on the Client when prompted (the GUI walks you through this)
  4. If the certificate exchange succeeds and the client is in the server's allowlist, the connection is established
  5. Done!

The OTP is just for the initial certificate exchange. After that, connections (to the same server) authenticate automatically using the saved certificates.

Configuration File Structure

The configuration json file is split into three sections: server, client, and general.

Server Section

streams_enabled controls what the server will manage on each connected client:

  • 1: Mouse
  • 4: Keyboard
  • 12: Clipboard

log_level sets the logging verbosity:

  • 0: Debug (detailed logs)
  • 1: Info (standard logs)

authorized_clients lists the clients that can connect. To add a new client, you only need to specify:

  • uid: Unique identifier
  • host_name or ip_address: Client's network address
  • screen_position: Where the client is positioned relative to the server (left, right, top, bottom)

Other fields are automatically populated by the system.

Client Section

The same field names have the same meaning as in the server section. The server_info block tells the client which server to connect to (leave it empty for auto-discovery or fill in the host field for manual configuration).

General Section

These parameters affect the application's internal behavior. Only modify them if you know what you're doing.

File Structure

{
    "server": {
        "uid": "...",
        "host": "0.0.0.0",
        "port": 55655,
        "heartbeat_interval": 1,
        "streams_enabled": {
            "1": true,
            "4": true,
            "12": true
        },
        "ssl_enabled": true,
        "log_level": 1,
        "authorized_clients": [
            {
                "uid": "...",
                "host_name": "MYCLIENT",
                "ip_address": "192.168.1.66",
                "first_connection_date": "2026-02-02 19:09:00",
                "last_connection_date": "2026-02-02 19:16:12",
                "screen_position": "top",
                "screen_resolution": "1920x1080",
                "ssl": true,
                "is_connected": true,
                "additional_params": {}
            }
        ]
    },
    "client": {
        "server_info": {
            "uid": "",
            "host": "",
            "hostname": null,
            "port": 55655,
            "heartbeat_interval": 1,
            "auto_reconnect": true,
            "ssl": true,
            "additional_params": {}
        },
        "uid": "...",
        "client_hostname": "MYSERVER",
        "streams_enabled": {
            "1": true,
            "4": true,
            "12": true
        },
        "ssl_enabled": true,
        "log_level": 1
    },
    "general": {
        "default_host": "0.0.0.0",
        "default_port": 55655,
        "default_daemon_port": 55652
    }
}

Note

When multiple Perpetua servers are detected on the network (on auto-discovery mode), the GUI will present a selection dialog allowing the user to choose the desired server.

Roadmap

Current Development Priorities:

  • Enhanced Platform Support

    • Linux support
  • Feature Enhancements

    • File transfers
    • Advanced clipboard format support (including proprietary formats)