LangSync is a small menu-bar app for macOS. While you work in an Apple Screen Sharing window,
it keeps the keyboard layout identical on the Mac you sit at and the Mac you control, makes
⌘Space switch instantly without eating the next keystroke, pastes text from dictation apps such
as Superwhisper on the remote Mac, and delivers copied images to the remote clipboard. Outside
Screen Sharing it does nothing.
Contents
The problem
Apple Screen Sharing is great until you type in more than one language:
- The layouts drift apart. ⌘Space is forwarded to the remote Mac and switches its layout,
but the characters you type are produced by the layout of the Mac you sit at. After a few
switches the two Macs disagree and you get the wrong alphabet. No layout switcher fixes this,
because the two Macs don't know about each other.
- The keystroke right after ⌘Space gets lost while the switch is still travelling.
- Dictation pastes stale text. Superwhisper and similar tools put the text on the clipboard
and immediately send ⌘V. Screen Sharing only syncs the clipboard when its window becomes key,
and it forwards modifier keys separately — so the remote pastes whatever was on its clipboard
before, or a bare
v arrives instead of ⌘V.
- Image copy and paste is unreliable through Screen Sharing's own clipboard sync.
Features
- Same layout on both Macs, both directions. Switch on your Mac and the remote follows;
switch on the remote and your Mac follows. Only while you work in the Screen Sharing window
(UDP port 47811).
- ⌘Space that never loses a key. Inside Screen Sharing, ⌘Space (and your "next input source"
shortcut) is intercepted and switches instantly at key-down; the remote follows. The next
keystroke is typed in the new layout.
- Dictation on the remote Mac. When Superwhisper — or any tool that writes the clipboard and
fires ⌘V — pastes inside Screen Sharing, LangSync swallows only that synthetic ⌘V and sends the
text to the remote, which pastes it with a real ⌘V and restores its previous clipboard after
one second. A ⌘V you type yourself is untouched. Keys pressed during the paste wait for it
(TCP port 47812).
- Images reach the remote clipboard. An image copied on your Mac goes to the remote
clipboard when you enter its Screen Sharing window.
- Several Macs, both roles at once. One Mac can control several Macs and be controlled
itself — e.g. an office Mac that you control from home and that controls a server Mac. LangSync
picks the target from the title of the focused Screen Sharing window. Chains (A → B → C) relay
the layout and dictation. Windows to Macs without LangSync, or sitting at the login screen,
are left alone.
- Encrypted and authenticated. Every message is sealed with ChaCha20-Poly1305 under keys
derived from a 256-bit shared key that never travels over the network; replays are rejected,
and the controlled Mac accepts connections only from local networks and VPNs.
See Security model.
- Tiny and native. A single universal binary (Apple Silicon + Intel), Apple frameworks only,
no dependencies, signed with a Developer ID and notarized by Apple.
How it works
LangSync runs on both Macs. Screen Sharing keeps doing its job (screen, keyboard, mouse);
LangSync adds a small side channel next to it.
flowchart LR
subgraph local["Mac you sit at (controls)"]
direction TB
input["Keyboard · Superwhisper · clipboard"]
lsA["LangSync"]
ss["Screen Sharing window"]
end
subgraph remote["Controlled Mac"]
direction TB
lsB["LangSync"]
apps["Apps on the remote Mac"]
end
input --> lsA
ss -->|"screen, keys, mouse (Apple Screen Sharing, unchanged)"| apps
lsA <-->|"layout · UDP 47811"| lsB
lsA -->|"dictated text, images · TCP 47812"| lsB
lsB -->|"real ⌘V"| apps
| What | How |
|---|
| Layout | LangSync sends the exact input source (say, Ukrainian – PC), not "switch to the next one". The other Mac selects the same source, or one for the same language. The Mac you sit at sends and applies changes only while Screen Sharing is in front; bringing the window to the front syncs it too. |
| ⌘Space | An event tap on the controlling Mac catches ⌘Space and the "Select the previous / next input source" shortcuts from System Settings → Keyboard → Keyboard Shortcuts → Input Sources, but only inside Screen Sharing. It switches locally at key-down; the remote follows through layout sync. |
| Dictation | LangSync takes over a ⌘V only when the clipboard changed a moment ago (≤ 0.3 s), Command is not physically held, and the focused Screen Sharing window shows a Mac in your list that runs LangSync. The text goes to that Mac, which puts it on its clipboard, presses ⌘V and restores the previous clipboard after 1 s. Keys pressed meanwhile (Return, for example) are held and replayed after the paste. If the remote doesn't answer or refuses, the ⌘V goes through Screen Sharing as before and takeover pauses for 30 s. |
| Images | Sent once when you enter the Screen Sharing window, if you copied an image (a screenshot, an image from a browser, an image file in Finder) since you last left it. Clipboard changes made inside Screen Sharing are ignored, so images don't loop with Screen Sharing's own sync. |
| Several Macs | Each Mac reports its names and addresses on request (refreshed every few minutes and remembered). LangSync matches them against the focused Screen Sharing window's title to decide where layout, ⌘Space and dictation go. |
Install
Requirements: macOS 13 Ventura or later on every Mac, Apple Silicon or Intel, Apple's Screen
Sharing app, and a network path from the Mac you sit at to the Mac you control (same LAN, or a
VPN such as Tailscale).
On each Mac:
- Download LangSync.dmg
(or pick a version on the Releases page).
- Open the DMG and drag LangSync to Applications.
- Open LangSync from Applications. macOS asks once whether to open an app downloaded from the
Internet — click Open. The app is notarized; no other steps are needed.
- The current layout code (EN, UA, RU …) appears in the menu bar. Click it for the menu.
When it runs from /Applications, LangSync adds itself to the login items; switch that off in
the menu if you prefer.
To update, download the new DMG and replace the app. Settings and the key are kept (coming
from 1.5 or earlier, see Upgrading from 1.5 or earlier).
To uninstall, quit LangSync from its menu and delete /Applications/LangSync.app; optionally
remove ~/.config/langsync/, ~/Library/Logs/LangSyncApp.log and run
defaults delete com.nick.LangSync.
Note: the menu is in Ukrainian for now (see Contributing). The table
below maps the items used in this guide.
| Menu item (Ukrainian) | Meaning |
|---|
| Цей Мак керує через Screen Sharing | This Mac controls (list of Macs) |
| Додати Мак… / Прибрати зі списку | Add Mac… / Remove from list |
| Цим Маком керують (приймати мову) | This Mac is controlled (accept layout) |
| Адреса: … | Address of this Mac |
| Диктовка і вставка з цього Мака (Superwhisper тощо) | Dictation and paste from this Mac |
| Передавати зображення при вході в Screen Sharing | Send images when entering Screen Sharing |
| Ключ: … (відбиток; однаковий на всіх Маках) | Key fingerprint (must be the same on all Macs) |
| ⚠︎ Створено новий ключ — скопіюйте його на інші Маки | New key created — copy it to your other Macs |
| Скопіювати ключ · Вставити ключ із буфера | Copy key · Paste key from clipboard |
| Запускати при вході · Відкрити журнал · Вийти з LangSync | Launch at login · Open log · Quit LangSync |
| ⚠︎ Дати доступ: … | ⚠︎ Grant access: … (opens the right System Settings pane) |
Upgrading from 1.5 or earlier
Version 1.6 speaks a new encrypted protocol (v3) that older versions don't understand, and it
refuses keys from 1.5 and earlier, because those travelled over the network in clear text.
- Update LangSync on every Mac. A Mac on 1.6 and a Mac on 1.5 can't talk to each other.
- On first launch each Mac replaces its old key with a new one, and the menu shows
⚠︎ Створено новий ключ — скопіюйте його на інші Маки ("new key — copy it to your other Macs").
- Pick one Mac, choose Copy key there, and Paste key from clipboard on all the others.
The warning goes away, and the fingerprint next to Ключ ("Key") is the same on every Mac.
Setup
One Mac controls another
- On the controlled Mac, tick This Mac is controlled (Цим Маком керують). The menu
then lists its addresses (Адреса: …) — note one that the other Mac can reach, for example
192.0.2.10 on the LAN or 100.64.0.10 on Tailscale. A host name such as office-mac.local
works as well.
- On the controlling Mac, choose Add Mac… (Додати Мак…) and enter that address.
- Use the same key on both Macs. Every Mac creates its own key on first launch, so pick one:
choose Copy key (Скопіювати ключ) there, move it to the other Mac (Screen Sharing's
clipboard or Universal Clipboard is fine) and choose Paste key from clipboard (Вставити
ключ із буфера) there. A key looks like
v2: followed by 64 hex characters; keys from
LangSync before 1.6 are not accepted. The menu never shows the key itself, only a
12-character fingerprint next to Ключ (for example 3f9c7a-21bd05) — it must be the same on
all Macs. The copied key is cleared from the clipboard after 60 seconds.
- Grant permissions — see Permissions. The ⚠︎ items in the menu open the
right panes.
- Open the Screen Sharing window and switch layouts. The menu marks the Mac you're working on
with ← зараз ("now").
Several Macs and chains
A Mac can be in both roles at once: keep This Mac is controlled ticked and add the Macs it
controls. Example:
flowchart LR
home["home-macbook<br/>controls office-mac"] -->|Screen Sharing| office["office-mac<br/>is controlled · controls server-mac"]
office -->|Screen Sharing| server["server-mac<br/>is controlled"]
| Mac | This Mac is controlled | Macs in its list |
|---|
| home-macbook | off | office-mac (100.64.0.10) |
| office-mac | on | server-mac (192.0.2.20) |
| server-mac | on | — |
- Same key on all three — the fingerprint in the menu must match on every Mac.
- LangSync decides which Mac you're working on from the title of the focused Screen Sharing
window — the remote's computer name or the address you connected to. Each Mac reports its
own names and addresses, so either works. If two Macs share a name, LangSync leaves both
windows alone; give them distinct names in System Settings → General → Sharing.
- Chains: from home-macbook, inside the office-mac window, focus office-mac's window to
server-mac. The layout is passed on automatically, and dictated text is relayed
home-macbook → office-mac → server-mac.
- Screen Sharing windows to Macs without LangSync, or to a Mac at its login screen, are left
alone — ⌘Space and ⌘V go through Screen Sharing as usual, so you can type a password there.
- To tell several remote windows apart, the controlling Mac needs Accessibility (to read window
titles). With a single remote Mac it works without it.
Permissions
| Mac | Permission | Used for |
|---|
| Controlling | Accessibility | Intercepting ⌘Space and the dictation ⌘V; reading Screen Sharing window titles when you control several Macs |
| Controlling | Input Monitoring | The keyboard event tap for the hotkey and paste interception |
| Controlled | Accessibility | Pressing ⌘V to paste dictated text |
| Both | Local Network (if macOS asks) | Talking to the other Mac |
Both are in System Settings → Privacy & Security. Layout sync itself works without
Accessibility and Input Monitoring; without them the keystroke right after ⌘Space can still get
lost, and dictation falls back to Screen Sharing's own paste.
If a permission toggle looks on but LangSync still reports it missing (this can happen after
switching from a differently signed build), remove LangSync from the list with − and add it
again. Updates between official releases keep the permissions.
Security model
LangSync can make the controlled Mac paste text and press ⌘V, so it is worth being precise about
what protects it and what doesn't. This describes version 1.6 and later.
The key
- All your Macs share one key:
v2: followed by 64 hex characters (256 random bits). LangSync
creates it on first launch in ~/.config/langsync/token (file mode 0600); the
LANGSYNC_TOKEN environment variable, if set, takes precedence. The key itself never travels
over the network.
- The menu never shows the key, only a 12-character fingerprint of it (derived with SHA-256;
the key can't be recovered from it). Compare fingerprints to check that two Macs have the same
key.
- Copy key marks the clipboard entry as concealed and transient, so clipboard managers skip
it, and clears it after 60 seconds unless you have copied something else meanwhile.
Paste key from clipboard clears the clipboard once the key is saved, and refuses a key that
arrived through LangSync itself (from another Mac's clipboard) — copy keys by hand.
- Keys from LangSync 1.5 and earlier travelled over the network in clear text, so 1.6 refuses
them: on first launch it replaces such a key with a new one and the menu warns
⚠︎ Створено новий ключ — скопіюйте його на інші Маки ("new key — copy it to your other Macs").
On the wire
- Every message is encrypted and authenticated with ChaCha20-Poly1305. Separate keys for each
direction and kind of message — layout to the controlled Mac, layout back, clipboard request,
clipboard body, reply — are derived from the shared key with HKDF-SHA256, so a message
can't be reflected back or passed off as another kind. Forged or modified messages are dropped.
- Layout (UDP 47811). Each datagram carries a timestamp and a random nonce; anything more
than 2 minutes off, or seen before, is rejected. So the Macs' clocks must be roughly in
sync — keep Set time and date automatically on. Datagrams are padded to a fixed size. A
controlling Mac accepts layout messages only from the Mac it controls (any of its addresses); a
controlled Mac accepts them only from local networks, only if addressed to its own identity
(see below), and never ones sent before it started.
- Dictated text and images (TCP 47812). The controlled Mac opens every connection with a
fresh random 16-byte challenge and its identity — a random ID each Mac creates once. The
controlling Mac remembers that identity the first time it reaches a Mac (like an SSH host key)
and refuses it if it ever changes. The request header and body are sealed with the challenge
and the identity as associated data, and the reply also with the controlling Mac's own random
nonce. So a captured request can't be replayed on another connection, redirected to another
Mac or replayed after a restart; an old reply can't be passed off as a new one; and none of
this depends on the clocks. The header (padded to 1 KiB) is authenticated before anything else
is read. Bodies are padded to a multiple of 256 bytes (at least 512 for passwords) and replies
to 256 bytes, hiding exact lengths.
- Who may connect. The controlled Mac accepts connections only from local addresses —
loopback,
10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, link-local 169.254.0.0/16 and
100.64.0.0/10 (which includes Tailscale), and on IPv6 ::1, fe80::/10 and fc00::/7. It
allows at most 4 connections per address (per /64 on IPv6) and 16 in total, and drops a
connection that hasn't sent an authentic header within 2 seconds. Controlling Macs connect over
IPv4.
- The log records the names and addresses of remote Macs, sizes and timings — never the key,
clipboard contents or file names.
What is not protected
- The key is the only credential. Anyone who has it and can reach the controlled Mac can
switch its layout, put text or images on its clipboard and press ⌘V there — that is, type into
whatever app is in front. Keep the key private, like a password.
- The controlled Mac honours pastes even when no Screen Sharing session is active: while This
Mac is controlled is on, it accepts a paste request from anyone on a local network who has
the key.
- One key is shared by all your Macs and there is no revocation list: compromise of any of them
exposes the key. Mac identities are trusted on first contact: if the very first connection to a
Mac were intercepted, a wrong identity could be remembered — remove the Mac from the list and
add it again to reset it.
- No forward secrecy: the key is static, so someone who records traffic and later obtains the
key can decrypt it.
- Until a controlling Mac has reached a Mac once (and learned its identity), its layout packets
aren't addressed; within the 2-minute window such a packet could be replayed to another of your
Macs. All it can do is switch that Mac's layout.
- The Macs must reach each other directly, on a LAN or over a VPN; LangSync has no relay.
- The key file is plain text in your home folder, readable by your user account and anything
running as you.
- Encryption doesn't hide that two Macs are talking, or when, or roughly how much.
Recommendations
- Use LangSync on a trusted LAN or over a VPN such as Tailscale or WireGuard. Never expose
ports 47811/udp and 47812/tcp to the Internet.
- Run 1.6 or later on every Mac — see Upgrading from 1.5 or earlier.
- Turn off This Mac is controlled on Macs you don't need to control.
- Rotate the key if it may have leaked: quit LangSync on one Mac, delete
~/.config/langsync/token, open LangSync again (it creates a new random key), then
Copy key there and Paste key from clipboard on every other Mac. Check that the
fingerprints match.
Found a vulnerability? Please report it privately through GitHub's
security advisories
instead of a public issue. If that isn't available, open an issue asking for a contact, without
details.
Troubleshooting
The log is at ~/Library/Logs/LangSyncApp.log (menu → Open log, Відкрити журнал). To write
the current menu state into it — handy over SSH — run:
pkill -USR1 -f LangSync.app/Contents/MacOS/LangSync
tail -40 ~/Library/Logs/LangSyncApp.log
| Log line | What it means |
|---|
working on <name> (<address>) | The focused Screen Sharing window was recognised as a Mac in your list. If it never appears, the window title doesn't match: add the Mac by the address you use in Screen Sharing, or grant Accessibility (needed with several remotes). |
remote <address> is known as: <names> | That Mac answered and reported its names — network path and key are fine. |
event tap refused (accessibility false, input monitoring false); hotkeys pass through to remote | Accessibility / Input Monitoring are missing on the controlling Mac. LangSync retries every 5 s after you grant them. If the toggles already look on, remove LangSync with − and add it again. |
pasted on remote: text N chars in 0.0x s | Dictation worked. The remote logs clipboard text received: N chars. |
remote stored … but can't paste (grant it Accessibility) | Give the controlled Mac Accessibility. |
dictation ⌘V left to Screen Sharing: … | The focused Screen Sharing window isn't a Mac LangSync controls, so the ⌘V went through Screen Sharing. Check the window and the working on line. |
remote didn't take the paste (…); forwarding ⌘V, leaving dictation ⌘V alone for 30 s | The remote didn't answer or refused; LangSync fell back to Screen Sharing for 30 s. |
rejected N … message(s): wrong key, clocks more than 2 min apart, a replay, or not from a local network | The Macs have different keys (compare the fingerprints in the menu), one of them still runs 1.5 or earlier, a clock is more than 2 minutes off (layout messages only), or the sender's address isn't on a local network or VPN range. Update every Mac, copy the key again, turn on automatic time. |
the old key (sent in clear text before 1.6) was replaced; copy the new one to the other Macs | This Mac had a key from 1.5 or earlier and made a new one. Copy it to the other Macs — see Upgrading from 1.5 or earlier. |
send failed (startup): No route to host | Right after launch macOS checks Local Network access; LangSync retries by itself. If it persists, allow LangSync in . |
The menu also warns when port 47811 or 47812 is taken by another app.
Build from source
You need the Xcode command line tools (xcode-select --install). There is no Xcode project;
build.sh compiles with swiftc.
git clone https://github.com/developerscompany/langsync.git
cd langsync
LANGSYNC_LOCAL=1 ./build.sh # local build, no Apple Developer account needed
open build/LangSync.app
A local build produces build/LangSync.app, build/LangSync-<version>-local.dmg and the
command-line ./langsync. It is signed with your Apple Development identity if you have one,
ad hoc otherwise, so Gatekeeper blocks it on other Macs, and ad-hoc builds may need the
permissions granted again after each rebuild.
Distribution build — what the Releases are made with:
xcrun notarytool store-credentials langsync-notary --apple-id <apple-id> --team-id <TEAM_ID>
LANGSYNC_TEAM_ID=<TEAM_ID> ./build.sh
It needs a Developer ID Application certificate in the login keychain and the notarytool
keychain profile above (LANGSYNC_NOTARY_PROFILE picks another profile name). It builds a
universal binary (arm64 + x86_64), signs with the hardened runtime, notarizes and staples both
the app and the DMG, and checks them with Gatekeeper. If the certificate or profile is missing,
it stops with an error instead of producing an un-notarized build. The version is ver= in
build.sh.
./deploy.sh <ssh-host> installs the newest build/LangSync-*.dmg on another Mac over SSH
(./deploy.sh local on this one): it checks Gatekeeper on a quarantined copy first, replaces
/Applications/LangSync.app keeping its settings, restarts it and prints the log and menu.
Project layout
Sources/Core.swift core: layouts, layout sync, hotkey event tap, clipboard, wire protocol
Sources/app/main.swift the menu-bar app (LangSync.app), including its UI strings
Sources/cli/main.swift legacy command-line agent (langsync send <host> | recv | list | current)
Tests/wire/main.swift wire-protocol tests: crypto checks and a local clipboard round trip
test.sh builds and runs those tests
build.sh build, sign with Developer ID, notarize, staple, make the DMG
deploy.sh install the latest DMG on a Mac over SSH, keeping its settings
install.sh legacy installer of the command-line agent as a LaunchAgent
make-icon.swift draws the app icon
Як встановити.txt short install guide placed inside the DMG (Ukrainian)
docs/ landing page (GitHub Pages)
FAQ
Does it work over Tailscale?
Yes. Add the controlled Mac by its Tailscale address (e.g. 100.64.0.10) or MagicDNS name;
Tailscale's 100.64.0.0/10 range counts as a local network. If you use Tailscale ACLs, allow
47811/udp and 47812/tcp to that Mac.
Can I use it over the Internet without a VPN?
No. The controlled Mac accepts connections only from local network and VPN addresses, so it
won't answer a public address even if the ports are forwarded. Use a VPN such as Tailscale.
How do I check that the Macs have the same key?
Compare the 12-character fingerprint next to Ключ in the menu; it must be the same on every
Mac. Pasting a key also shows its fingerprint. The fingerprint is safe to show — the key can't be
recovered from it. A key itself looks like v2: followed by 64 hex characters.
I updated from 1.5 and the Macs stopped talking to each other.
That's expected: 1.6 uses a new protocol and refuses old keys. Update every Mac, then copy the
new key from one Mac to the others — see Upgrading from 1.5 or earlier.
Does the controlled Mac accept pastes when nobody is connected through Screen Sharing?
Yes. While This Mac is controlled is on, it pastes for anyone on a local network who has the
key. Keep the key private, and turn the option off on Macs you don't need to control.
Does it work with Screen Sharing started through an Apple ID, without a network path between the Macs?
No. LangSync talks to the other Mac directly, so the controlled Mac must be reachable from the
controlling one — on the same LAN or through a VPN. Screen Sharing sessions relayed by Apple
alone don't give LangSync a path.
Does it change or patch Screen Sharing?
No. Screen Sharing is untouched. LangSync watches which app and window are in front, reads the
window title, and intercepts only ⌘Space, the input-source shortcuts and the dictation ⌘V while
a Screen Sharing window to one of your Macs is focused. Everything else goes through Screen
Sharing as usual.
Does it work with other remote-desktop apps?
No, only with Apple's Screen Sharing.
Do I need it on both Macs?
Yes — on the Mac you sit at and on every Mac you control.
Does it send my clipboard all the time?
No. Text is sent only for a dictation-style ⌘V inside a Screen Sharing window; images only when
you enter that window and only if you copied one since you left it. An ordinary ⌘V uses Screen
Sharing's own clipboard sync, so copies made on the remote keep their formatting.
Which dictation apps work?
Superwhisper, and any tool that puts the text on the clipboard and immediately sends ⌘V.
The Macs have different layouts installed.
If the exact layout is missing on the other Mac, LangSync picks one for the same language.
Contributing
Issues and pull requests are welcome.
- Localization. The UI is in Ukrainian today; the strings live in
Sources/app/main.swift.
An English UI (and a proper localization setup) would be a great first contribution.
- Keep it dependency-free: Apple frameworks only, no Xcode project, built by
build.sh.
- Before opening a PR, make sure
LANGSYNC_LOCAL=1 ./build.sh succeeds, run ./test.sh
(it uses TCP port 47812, so turn off This Mac is controlled on that Mac first) and test with
two Macs.
- When reporting a bug, include the macOS version of both Macs, the LangSync version (top of the
menu), how they are connected (LAN, Tailscale…) and the relevant lines from
~/Library/Logs/LangSyncApp.log. The log contains addresses and computer names — redact them
if you like. Never post your key (the fingerprint is fine).
License
MIT © 2026 Nick Lishchenko.
LangSync is not affiliated with or endorsed by Apple. macOS and Screen Sharing are trademarks of
Apple Inc.; Superwhisper is a trademark of its owner.