Portal is a cross-platform Python application for sharing your mouse, keyboard, clipboard, and audio across multiple devices on the same network. It supports both Linux and Windows.
Portal was inspired by tools like Barrier and Synergy, which pioneered cross-device input sharing.
This project aims to provide a simpler, Python-based alternative with audio sharing and a customizable GUI.
- Seamless Input Sharing: Mouse & keyboard transition across screens
- Full Keyboard Support: Works in all contexts including password fields and lock screens
- Bidirectional Clipboard: Text and images sync automatically when switching controls
- Audio Streaming: Share or receive audio between devices
- Log Viewer: GUI-based log viewer for debugging
- Cross-Platform: Works on Windows and Linux
Portal is fully open-source and community-driven.
You’re welcome to explore, modify, and enhance the codebase — whether you want to improve performance, add features, or port it to more platforms.
License: MIT License
We’d love your help to make Portal even better!
Here’s how you can contribute:
- Fork the repository
- Create a branch for your feature or bugfix
git checkout -b feature/amazing-feature
- Commit your changes with clear messages
git commit -m "Add amazing feature" - Push to your branch
git push origin feature/amazing-feature`` - Open a Pull Request — we’ll review it together!
If you find a bug, open an issue describing:
- Your OS (Windows/Linux)
- Steps to reproduce the problem
- Any console/log output
- Note: ffmpeg is used internally for capturing and streaming audio across systems. Make sure it's installed and available in your system PATH.
Install Python 3.8+ and then:
pip install -r requirements.txtpip install pywin32sudo apt install ffmpeg xclip pactl
# For better keyboard support in secure contexts:
sudo apt install xdotoolpython main.pyUpdate config.json or use the GUI to:
- Set Server / Client mode
- Set audio to Share / Receive
- Define client direction (Top / Left / Right / Bottom)
- Enter audio receiver IP
Run build.bat:
- Output:
dist/Portal-v1.0.exe(single file)
Run build.sh:
Make it executable and run:
chmod +x build.sh
./build.sh- Output:
dist/Portal-v1.0(single file)
portal/
├── main.py # Main entry point
├── config.json # Configuration file
├── requirements.txt # Python dependencies
├── build.bat # Windows build script
├── build.sh # Linux build script
├── portal.ico # Application icon
├── portal.png # Application icon (Linux)
├── README.md # This file
│
├── controllers/ # Input/output device controllers
│ ├── __init__.py
│ ├── keyboard_controller.py
│ ├── mouse_controller.py
│ ├── clipboard_controller.py
│ └── audio_controller.py
│
├── network/ # Network communication modules
│ ├── __init__.py
│ ├── share_manager.py # Main input sharing manager
│ ├── audio_manager.py # Audio streaming manager
│ ├── connection_handler.py # Connection management
│ └── input_handler.py # Input event handling
│
├── gui/ # User interface components
│ ├── __init__.py
│ ├── main_window.py # Main GUI window
│ └── log_viewer.py # Log viewer window
│
└── utils/ # Utility functions
├── __init__.py
└── config.py # Configuration management
Use the GUI Stop button to gracefully stop the app. All subprocesses, sockets, and overlays are properly cleaned up.
If the app crashes or is killed without cleanup, you might encounter errors like:
[Errno 98] Address already in use # Linux
[WinError 10048] Only one usage of each socket address is normally permitted # WindowsFind process using all ports (50007,50008,50009)
netstat -aon | findstr :<PORT> #replace <PORT>
TCP 0.0.0.0:<PORT> 0.0.0.0:0 LISTENING <PID>
taskkill /PID <PID> /F #replace <PID> Find process using all ports (50007,50008,50009)
sudo lsof -i :<PORT> #replace <PORT>
python3 <PID> user 3u IPv4 ... TCP *:<PORT> (LISTEN)
kill -9 <PID> #replace <PID>