Skip to content

Instantly share code, notes, and snippets.

@linktohack
Created February 23, 2026 21:54
Show Gist options
  • Select an option

  • Save linktohack/3a754330adccb659aef9c3350693471f to your computer and use it in GitHub Desktop.

Select an option

Save linktohack/3a754330adccb659aef9c3350693471f to your computer and use it in GitHub Desktop.
Type into (Qemu) VNC session
#!/usr/bin/env -S uv run --with vncdotool
# /// script
# requires-python = ">=3.12"
# dependencies = ["vncdotool"]
# ///
"""Type stdin text into a VNC session.
Usage:
echo "hello" | uv run vnc_type.py [host] [options]
pbpaste | uv run vnc_type.py 127.0.0.1:9 --caps
host format: host:display (e.g. 127.0.0.1:9) or host::port (e.g. 127.0.0.1::5909)
Default: 127.0.0.1::5909
Options:
--caps Invert shift key up/down (use when caps lock is stuck)
"""
import sys
import argparse
import time
import os
from vncdotool import api
DELAY = 0.02
SHIFT_MAP = {
'~': '`', '!': '1', '@': '2', '#': '3', '$': '4', '%': '5',
'^': '6', '&': '7', '*': '8', '(': '9', ')': '0', '_': '-',
'+': '=', '{': '[', '}': ']', '|': '\\', ':': ';', '"': "'",
'<': ',', '>': '.', '?': '/',
}
SPECIAL = {
'\n': 'enter',
'\t': 'tab',
' ': 'space',
}
parser = argparse.ArgumentParser(description="Type stdin into VNC")
parser.add_argument("host", nargs="?", default="127.0.0.1::5909",
help="host:display or host::port (default: 127.0.0.1::5909)")
parser.add_argument("--caps", action="store_true",
help="Invert shift key up/down (use when caps lock is stuck)")
args = parser.parse_args()
text = sys.stdin.read()
client = api.connect(args.host)
# reset modifier keys
client.keyUp('shift')
client.keyUp('ctrl')
client.keyUp('alt')
time.sleep(0.05)
def shift_on():
if args.caps:
client.keyUp('shift')
else:
client.keyDown('shift')
def shift_off():
if args.caps:
client.keyDown('shift')
else:
client.keyUp('shift')
for ch in text:
if ch in SPECIAL:
client.keyPress(SPECIAL[ch])
elif ch == '\r':
continue
elif ch in SHIFT_MAP:
shift_on()
time.sleep(DELAY)
client.keyPress(SHIFT_MAP[ch])
time.sleep(DELAY)
shift_off()
elif ch.isupper():
shift_on()
time.sleep(DELAY)
client.keyPress(ch)
time.sleep(DELAY)
shift_off()
else:
client.keyPress(ch)
time.sleep(DELAY)
client.disconnect()
os._exit(0)
@linktohack
Copy link
Author

If typefile is working fine for you, use that!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment