AI-powered linking and automation tool
Project description
Dev Linker
Dev Linker runs frontend and backend dev servers, proxies both through a single local port (8000), and creates a single public URL via Cloudflare or ngrok.
Features
- Launches frontend automatically (when frontend exists)
- Auto-detects backend runtime (Docker Compose, Dockerfile, Node, or Python)
- Auto-starts Python/Node backends; Docker is manual by default for reliability
- Detects common frontend/backend ports
- Detects Vite frontend across dynamic fallback ports (5173-5190, plus common alternatives)
- Supports Docker backend port auto-detection
- Works with dynamic container host ports
- No config needed for standard FastAPI or Flask plus Docker flows
- Serves both through one proxy at http://localhost:8000
- Creates a public tunnel for sharing (Cloudflare first, ngrok fallback)
- Terminal-first workflow
- Supports CLI version output with --version
Project Structure
devlinker/
├── devlinker/
│ ├── __init__.py
│ ├── main.py
│ ├── runner.py
│ ├── detector.py
│ ├── proxy.py
│ └── tunnel.py
├── setup.py
├── README.md
└── requirements.txt
Install
For local development:
pip install .
After publishing to PyPI:
pip install devlinker
Run
devlinker
Typical startup output:
Dev Linker v1.2.2
[INFO] Mode: Auto (FastAPI async proxy + Docker detection)
[INFO] Booting local services...
[INFO] Detecting frontend/backend ports...
[OK] Frontend -> 5173
[OK] Backend -> 5000
[OK] Proxy ready at http://localhost:8000
[OK] Tunnel provider: Cloudflare
[OK] Public URL:
https://xxxx.trycloudflare.com
Tip: Press Ctrl+Click to open link
[INFO] Share this link with collaborators.
DevLinker Ready (in 2.4s)
Frontend: http://localhost:5173
Backend: http://localhost:5000
Access Links:
Local: http://localhost:8000
WLAN: http://192.168.1.5:8000
Public: https://xxxx.trycloudflare.com
Tip: Press Ctrl+Click to open link
Version check:
devlinker --version
Optional overrides:
devlinker --frontend 5173 --backend 5000
Backend override alias:
devlinker --backend-port 3001
Enable Docker auto-start explicitly:
devlinker --docker
Run local-only mode without tunnel:
devlinker --no-tunnel
Disable WLAN URL output:
devlinker --no-lan
Interactive backend selection (when local and Docker are both detected):
devlinker --interactive-backend
Disable interactive backend selection (keeps local-first behavior):
devlinker --no-interactive-backend
If port 8000 is already in use:
devlinker --frontend 5173 --backend 5000 --proxy-port 18000
Default behavior also tries fallback ports automatically when 8000 is busy:
[WARN] Port 8000 in use
[INFO] Using proxy port: 8001
- 8001
- 8002
- 18000
Frontend detection behavior:
- Scans Vite defaults and fallback ports (
5173through5190) - Also checks common alternatives (
3000,4173,8080) - Retries during startup to catch slow boot cases
- Performs readiness gating before proxy startup (waits until frontend looks like Vite and backend responds)
Important Frontend Rule
Frontend requests must use relative API paths:
fetch("/api/endpoint")
Do not hardcode backend host URLs in frontend code.
Backend Auto-Detection
Backend port detection runs in this order:
- Check localhost port 5000
- If not found, query Docker via Docker SDK (
docker.from_env()) for published host-to-container port mappings - Prioritize containers using labels when present (
devlinker.role=backend, optionaldevlinker.port=<container-port>) - Otherwise rank containers by likely backend identity (name hints like backend/api plus project-name hints)
- Use the best mapped host port automatically, even when internal port is not 5000
- If nothing is found, print next-step guidance and exit
If Docker SDK is unavailable, Dev Linker falls back to Docker CLI parsing as a compatibility path.
When both Local and Docker backends are available, Dev Linker prompts you to choose one (TTY mode) unless --no-interactive-backend is used.
If backend detection fails, Dev Linker prints a clear checklist showing what it checked and how to recover.
Detection messages include source labels, for example:
[OK] Backend detected (Local) -> port 5000
Example Docker dynamic-port message:
[WARN] Backend not found on port 5000
[INFO] Checking Docker containers...
[OK] Backend detected (Docker) -> port 32768
Dev Linker checks backend runtime in this order:
- Docker Compose (
backend/docker-compose.yml,docker-compose.yaml,compose.yml, orcompose.yaml) - Docker (
backend/Dockerfile) - Node (
backend/package.json) - Python (
backend/requirements.txtorbackend/app.py)
Backend startup commands:
- Docker Compose (default): manual run
docker compose up --buildinbackend/ - Dockerfile (default): manual run
docker build -t devlinker-backend .thendocker run --rm -p 5000:5000 devlinker-backend - Docker Compose/Dockerfile with
--docker: Dev Linker runs those Docker commands for you - Node:
npm run dev(ornpm startwhendevis missing) - Python:
python app.py
For containerized Flask backends, ensure:
- App binds to all interfaces:
app.run(host="0.0.0.0", port=5000) - Port mapping is present:
-p 5000:5000
Notes
- runner.py expects frontend project in frontend and Python app in backend/app.py.
- If those paths do not exist, Dev Linker skips launch and only tries to detect already-running services.
- Tunnel selection order is: cloudflared (TryCloudflare), then ngrok.
- If cloudflared is unavailable and ngrok is not configured, Dev Linker prints one-time setup guidance.
- You may need to set ngrok auth once on your machine using ngrok config add-authtoken .
- Dev Linker prints a public URL with
ngrok-skip-browser-warning=trueonly when ngrok is used. - Startup output includes selected tunnel provider (
cloudflareorngrok). - Proxy layer now supports WebSocket upgrades, including Vite HMR over shared links.
- Proxy listens on
0.0.0.0and can print a WLAN URL for same-network sharing. - If WLAN access fails on Windows, allow the proxy port in firewall and confirm devices are on the same network.
Runtime Smoke Test
Run this test to validate proxy behavior end-to-end (frontend HTTP route, backend API forwarding, and WebSocket pass-through):
python -m unittest tests.test_proxy_runtime
The test spins up lightweight local frontend and backend apps, starts Dev Linker proxy, and verifies:
GET /is routed to frontendPOST /api/loginis routed to backendws://.../hmrround-trip works through proxy
Real-Time Development
- Run
devlinkerto share one combined frontend/backend URL. - Vite HMR and other WebSocket flows are proxied end-to-end through Dev Linker.
- Keep using relative frontend API paths (for example,
/api/endpoint) so routing stays consistent locally and over tunnel.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file devlinker-1.2.7.tar.gz.
File metadata
- Download URL: devlinker-1.2.7.tar.gz
- Upload date:
- Size: 18.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
280be7ceae3ed362ab8ad1ecfae6f72bd894156ab1944783d53b31bd17a8b2f3
|
|
| MD5 |
d661fe988083d0ac1024921e207a3c57
|
|
| BLAKE2b-256 |
4cd7204b4d801a59414290833de5a9199d484d1967d60fbeab3528d79efba34e
|
Provenance
The following attestation bundles were made for devlinker-1.2.7.tar.gz:
Publisher:
publish.yml on mani1028/devlinker
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
devlinker-1.2.7.tar.gz -
Subject digest:
280be7ceae3ed362ab8ad1ecfae6f72bd894156ab1944783d53b31bd17a8b2f3 - Sigstore transparency entry: 1192676456
- Sigstore integration time:
-
Permalink:
mani1028/devlinker@f6ff51bb7fc61bd69fa7cc21647510bdebb4e45c -
Branch / Tag:
refs/tags/v1.2.7 - Owner: https://github.com/mani1028
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f6ff51bb7fc61bd69fa7cc21647510bdebb4e45c -
Trigger Event:
push
-
Statement type:
File details
Details for the file devlinker-1.2.7-py3-none-any.whl.
File metadata
- Download URL: devlinker-1.2.7-py3-none-any.whl
- Upload date:
- Size: 17.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7aef7f3cfd5c11e6a2385e58955fe45d4481d7554ef948841db44880aab9f3ce
|
|
| MD5 |
c440c848495e709a2bd9d6e7d9fe1a30
|
|
| BLAKE2b-256 |
89945fbea10944936b248d4f10fe606187969e33d2105d759a4f02cf0012b85c
|
Provenance
The following attestation bundles were made for devlinker-1.2.7-py3-none-any.whl:
Publisher:
publish.yml on mani1028/devlinker
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
devlinker-1.2.7-py3-none-any.whl -
Subject digest:
7aef7f3cfd5c11e6a2385e58955fe45d4481d7554ef948841db44880aab9f3ce - Sigstore transparency entry: 1192676506
- Sigstore integration time:
-
Permalink:
mani1028/devlinker@f6ff51bb7fc61bd69fa7cc21647510bdebb4e45c -
Branch / Tag:
refs/tags/v1.2.7 - Owner: https://github.com/mani1028
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f6ff51bb7fc61bd69fa7cc21647510bdebb4e45c -
Trigger Event:
push
-
Statement type: