PCLink turns a spare PC into a browser-managed remote desktop server
Cross-platform desktop app for secure remote PC control and management, featuring a lightweight built-in WebUI and API for local or remote access.
At a glance
- What is it?
- PCLink is a Python server for controlling a personal PC remotely from a browser or an Android companion app, pairing over a local WebUI on port 38080. It is a good fit for a home machine you own, and a poor fit if you need a hardened multi-user server.
- Who is it for?
- PCLink suits an engineer or a home lab operator who owns the machine being controlled, drives it from a browser or an Android phone, and is comfortable with a beta server component that shares its ecosystem with a licence that the platform itself could not classify. It does not suit a shared server, a multi-tenant deployment or anyone who needs an audit trail of sessions.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 14 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
PCLink puts the control surface of a PC in a browser tab
PCLink is a desktop server that turns a personal computer into something you can drive from elsewhere. The server runs on the machine you want to control, and the interfaces on the other side are a browser and a phone app. That pairing is the design decision worth understanding first, because it explains most of what follows.
The project describes itself as a web-first server for remote PC management and screen streaming, and the README names the audience twice: end users on a desktop and people writing extensions. It is not a team administration console and it does not present a multi-user directory. There is one PC, one server process, and a set of clients that get paired to it by an explicit approval step.
The practical cases that fit are personal. You have a machine at home or in a rack, you want its screen, its files and its command line without giving anyone a full remote desktop session, and you would rather open a URL than install a heavy client. The Android companion app is listed on the Google Play Store, and the mobile app and the server are separate downloads that pair by scanning a QR code that the server shows.
The security posture is built around that single-machine assumption. The feature list names mandatory HTTPS, manual device approval and cryptographically secure sessions, and the pairing flow in the quick start requires a human to approve a scanned code. That is a sensible default for a personal tool, and it is also why the server is not something to expose to the internet unchanged.
FastAPI, uvicorn and a websocket terminal make up the server core
The dependency list in pyproject.toml describes the shape of the server quite precisely. It is a Python package named pclink, version 5.0.0, built with setuptools, with a console entry point declared as pclink = "pclink.__main__:cli". The web layer sits on fastapi>=0.95.0 with uvicorn[standard]>=0.22.0, and jinja2>=3.0.0 is there to render the pages of the Web UI that the README calls responsive.
The interesting pieces are the ones that reach out of the process. psutil>=5.9.0 covers process and system inspection for the remote explorer and the process manager. mss>=9.0.0 and av>=11.0.0 handle screen capture and video encoding, and the README points at a separate project, ferrumcast, as the engine behind the screen streaming. pynput>=1.7.6 handles keyboard and mouse input. For the integrated shell, websockets>=12.0 gives the browser a persistent channel rather than a request and response loop, and the README describes it as WebSocket-powered terminal access.
Two supporting libraries are easy to miss. qrcode>=7.3 and Pillow>=9.0.0 generate the pairing code you scan from the phone. cryptography>=41.0.0 is listed, which matches the claim of cryptographically secure sessions. pyperclip>=1.8.2 handles clipboard transfer, and pystray>=0.19.0 provides the system tray icon.
Notably, the dependency set is not uniform across platforms. evdev>=1.6.0 is conditional on sys_platform == 'linux', while comtypes, pycaw, pywin32 and a group of winrt runtime packages are conditional on sys_platform == 'win32'. Input and peripheral control are implemented per operating system, and macOS has no conditional block at all. The README platform badge says Windows and Linux.
Four install routes, and only one command for Linux
The quick start gives you a platform menu. On Linux the automated route pipes a shell script straight into bash, which is the shortest path to a running server and also the one that deserves a look before you paste it.
bash <(curl -fsSL https://raw.githubusercontent.com/BYTEDz/PCLink/main/install.sh)That command downloads install.sh from the main branch and executes it immediately, so you are running code you have not read. The repository root also ships pre-install-pclink.sh and force-purge-pclink.sh, plus nfpm.yaml, which is the packaging configuration used to build the .deb and .rpm packages, and PKGBUILD for Arch. If you would rather read first, the manual route downloads the .deb or .rpm from the releases page.
On Windows the README points to a .exe installer on the releases page. On Arch Linux the package lives in the AUR, maintained by Mark Wagie rather than by the core team, and installs with:
yay -S pclinkOnce installed, the server starts with the console script declared in pyproject.toml:
pclinkThe repository also contains dev-setup.ps1 for Windows development, and the presence of a .pre-commit-config.yaml and a tests/ directory indicates a conventional Python layout under src/. The pyproject metadata marks the release as Development Status :: 4 - Beta, and requires-python is set to >=3.8 while the classifiers list 3.8 through 3.11.
Pairing happens through a localhost WebUI and a QR code the phone reads
The first real use is a pairing dance, and it starts on the machine itself. After the server starts, you open the Web UI in a desktop browser:
https://localhost:38080/ui/That address is served over HTTPS on port 38080, which is the only port the README names anywhere. The UI displays a QR code, the PCLink Mobile App scans it, and the desktop side approves the connection. The approval step is the manual one referenced in the feature list under manual device approval, so an unknown device cannot silently attach itself.
After pairing, the Web UI is where configuration and device management happen. The README lists a remote file browser and system process manager, an integrated shell over websockets, and peripheral control for keyboard, mouse, system volume and media playback. The extension system, described in the project wiki as the Extension Development page, is the stated route for adding further capabilities, and the extensions repository is a separate one under the same organisation.
Two operational notes are worth carrying into a real deployment. The first is that the pairing UI lives on localhost, which means an operator who wants remote access to the Web UI itself has to expose that path deliberately, and the README does not document a reverse proxy setup or the specific certificate and hostname configuration. The second is that everything on the checklist of features is local input, screen capture and terminal access, so the server process needs to sit close to the desktop session it is capturing.
Screen streaming and input are separate jobs with separate dependencies
It helps to separate the display path from the input path, because PCLink treats them differently in the dependency list and in the README.
Display work is split across a capture library, an encoding library and an external streaming component. mss performs screen capture, av performs encoding, and the README credits ferrumcast with the high-performance streaming layer. ferrumcast lives in its own repository under the same organisation, which means the streaming behaviour of PCLink is only partly visible in the code you would read here.
Input work is delegated to the operating system. pynput provides a cross-platform keyboard and mouse hook, and evdev supplies Linux with direct access to input devices. The Windows side is heavier: pycaw for audio control, comtypes for COM automation, pywin32, and a stack of winrt runtime packages covering Windows.Foundation, Windows.Data.Xml.Dom, Windows.UI.Notifications and Windows.Media.Control, the last of which matches the media playback control the feature list mentions.
The practical consequence is that feature availability follows the platform. A peripheral feature that depends on a winrt runtime package has no Linux implementation behind it, and the absence of any macOS conditional dependency suggests that path is not covered at all. If your requirement list includes system volume control or media keys, the target operating system decides whether that requirement is met, and the README does not publish a per-platform feature matrix that would settle it faster than testing.
The extension system widens the surface area and the maintenance load
PCLink advertises an extensible architecture, with an extension development guide in the wiki and a separate pclink-extensions repository for community work. In practice this means the capability set of a given install is not fixed by the server release alone. If an install includes extensions, its behaviour, its attack surface and its upgrade cost depend on code that sits outside the versioned server package.
The security model page in the wiki is listed under Reference, next to the API endpoints page and a quick reference. The API is part of the same picture. A FastAPI application with a documented endpoint set is a network surface, and the endpoint list lives in the wiki rather than in the README, so the full set of callable operations is not visible from the repository root.
Upgrading also is not a single step. The version history shows v4.7.0 on 2026-08-08, v4.8.0 on 2026-09-01 and v5.0.0 on 2026-10-08, which is a fast cadence across two months. A major version in that sequence is exactly the point at which an extension written against the older API can break. The CHANGELOG.md file sits at the repository root, so the release notes are the place to check for breaking changes before pulling a new tag onto a machine you depend on.
Maintenance status itself is straightforward. The repository is not archived, and the last push was on 2026-10-08, minutes before the v5.0.0 release timestamp of 2026-10-08.
The licence metadata and the packaged licence files do not agree
There is a discrepancy here that a reader who checks before adopting will hit immediately. The licence field on the repository says Other, which the platform notes it cannot classify, with a pointer to the LICENSE file. The README badge says AGPL v3. The pyproject.toml metadata declares license = "AGPL-3.0-or-later". The repository root contains both a LICENSE file and a separate LICENSE.AGPL, plus a NOTICES file and a CLA.md contribution licence.
So the project clearly intends AGPL, and ships a named AGPL file, but the machine readable licence field is set to something the platform could not map. Anyone building a compliance process that reads repository metadata rather than the file tree will get the wrong answer for this project, and anyone who needs the actual terms has to open the two licence files and read them.
This is not legal advice, and the point is narrow: verify the terms from the LICENSE file and LICENSE.AGPL directly, and do not assume the badge and the metadata agree with each other. The same care applies to the extension ecosystem, where the licence of each third party extension is its own question and is not settled by the server package.
One more practical warning comes from the README itself, and it is unusually candid. The project states that because PCLink integrates deeply with the system through remote input, screen capture and terminal access, it can occasionally trigger false positive alerts from Windows Defender, naming Wacatac.B!ml as an example, and says every release is verified via VirusTotal. On a managed endpoint, that alert is an event your security tooling will act on.
Editorial conclusion
PCLink suits an engineer or a home lab operator who owns the machine being controlled, drives it from a browser or an Android phone, and is comfortable with a beta server component that shares its ecosystem with a licence that the platform itself could not classify. It does not suit a shared server, a multi-tenant deployment or anyone who needs an audit trail of sessions. Before adopting it, read the LICENSE file and LICENSE.AGPL side by side, check the antivirus false positive warning in the README against your own endpoint tooling, and confirm that port 38080 is reachable only over a path you control.
Frequently asked questions
How do I install the PCLink server on Linux?
The README gives an automated install route that pipes the repository install script into bash, and also points to .deb and .rpm packages on the releases page for a manual install. Arch users can install it from the AUR with yay -S pclink, and that AUR package is maintained by Mark Wagie rather than by the core team.
How do I connect the PCLink mobile app to the server?
Start the server with pclink, open https://localhost:38080/ui/ in a desktop browser, then scan the QR code shown in the Web UI with the PCLink Mobile App and approve the connection on the desktop side.
Which operating systems does PCLink support?
The README platform badge lists Windows and Linux. The dependency list conditions the Linux input library evdev on Linux and a group of comtypes, pycaw, pywin32 and winrt packages on Windows, with no macOS specific packages listed.
Will Windows Defender flag the PCLink server?
The README says it can, because remote input, screen capture and terminal access can trigger false positive alerts such as Wacatac.B!ml, and it states that every release is verified via VirusTotal.
What licence is PCLink released under?
The pyproject.toml metadata declares AGPL-3.0-or-later and the README badge says AGPL v3, while the licence field on the repository says Other and points to the LICENSE file. The repository root carries both LICENSE and LICENSE.AGPL, so read those files for the actual terms.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/bytedz-pclink)Was this useful?