eitype
A library and CLI tool for typing text using the Emulated Input (EI) protocol on Wayland.
Features
- Type text using the EI (Emulated Input) protocol
- Support for special keys (enter, tab, escape, arrows, function keys, etc.)
- Support for modifier keys (shift, ctrl, alt, super)
- XDG RemoteDesktop portal support with session persistence
- Direct socket connection support
- Configurable delay between key events
- Keyboard layout configuration via CLI or environment variables
- Python bindings for use in Python applications
- Rust library for integration into other Rust projects
Installation
Using pixi (recommended)
Pixi handles all dependencies (including libxkbcommon) automatically:
# Build and install Python bindings
pixi run build
# Install CLI
pixi run install-cli
# Run tests
pixi run test
Manual Installation
System Dependencies
If not using pixi, install the required system libraries first:
| Distribution | Command |
|---|---|
| Debian/Ubuntu | sudo apt install libxkbcommon-dev |
| Fedora/RHEL | sudo dnf install libxkbcommon-devel |
| Arch Linux | sudo pacman -S libxkbcommon |
| openSUSE | sudo zypper install libxkbcommon-devel |
CLI
cargo install --path .
Python
pip install maturin
maturin develop --features python
Usage
# Type text (uses XDG RemoteDesktop portal by default)
eitype "Hello, World!"
# Type with delay between keys (10ms)
eitype -d 10 "Slow typing..."
# Press special keys
eitype -k return
eitype -k tab
eitype -k escape
# Hold modifier while typing
eitype -M ctrl c # Ctrl+C
# Press and release a modifier
eitype -P shift
# Multiple texts
eitype "First line" -k return "Second line"
# Verbose output
eitype -v "Debug mode"
eitype -vv "More debug"
Connection Methods
XDG RemoteDesktop Portal (Default)
By default, eitype connects via the XDG RemoteDesktop portal. This works with desktop environments that support it (GNOME, KDE, etc.).
eitype "Hello"
Session Persistence
eitype automatically saves a session token to avoid the authorization dialog on subsequent runs. The token is stored at ~/.cache/eitype/restore_token.
- First run: Shows the authorization dialog, saves token for future use
- Subsequent runs: Uses saved token, no dialog needed
- Token expiration: If the token becomes invalid, a new dialog will appear
To force a new authorization dialog (clear the saved token):
eitype --reset-token "Hello"
Direct Socket
Use the -s flag to specify a socket path, or set the LIBEI_SOCKET environment variable to bypass the portal:
eitype -s /path/to/ei/socket "Hello"
# or
export LIBEI_SOCKET=eis-0
eitype "Hello"
Special Keys
Supported special key names (case-insensitive):
escape,escreturn,entertabbackspacedeleteinserthome,endpageup,pagedownup,down,left,rightf1throughf12spacecapslock,numlock,scrolllockprint,printscreenpause,menu
Modifier Keys
Supported modifier names (case-insensitive):
shift,lshift,rshiftctrl,control,lctrl,rctrlalt,lalt,ralt,altgrsuper,meta,win,lsuper,rsuper
Keyboard Layout
eitype uses XKB for keyboard layout handling. The keymap is determined in the following order:
- EI server keymap - If the EI server provides a keymap, it is used automatically
- CLI/environment configuration - If no server keymap, uses specified layout
- System default - Falls back to the system's default XKB configuration
CLI Options
# Use German keyboard layout
eitype -l de "Hallo Welt"
# Use US Dvorak layout
eitype -l us --variant dvorak "Hello"
# Full XKB configuration
eitype -l us --variant dvorak --model pc104 --options "ctrl:nocaps" "Hello"
# Select a specific layout index when multiple layouts are available
eitype --layout-index 1 "Hello"
Multi-Layout Keymaps
When the EI server provides a keymap with multiple layouts (e.g., Dvorak + QWERTY), eitype uses layout index 0 by default. This is typically correct since layout 0 is the first/active layout.
If you need to use a different layout, specify it with --layout-index:
# Use the second layout (index 1)
eitype --layout-index 1 "Hello"
Use -vv to see all available layouts in the keymap.
Environment Variables
You can also set keyboard layout via environment variables (CLI options take precedence):
XKB_DEFAULT_LAYOUT- Keyboard layout (e.g., "us", "de", "fr")XKB_DEFAULT_VARIANT- Layout variant (e.g., "dvorak", "colemak", "nodeadkeys")XKB_DEFAULT_MODEL- Keyboard model (e.g., "pc104", "pc105")XKB_DEFAULT_OPTIONS- XKB options (e.g., "ctrl:nocaps")XKB_DEFAULT_RULES- XKB rules file
# Set German layout via environment
export XKB_DEFAULT_LAYOUT=de
eitype "Hallo"
# Override with CLI
XKB_DEFAULT_LAYOUT=de eitype -l fr "Bonjour" # Uses French layout
Python Usage
from eitype import EiType, EiTypeConfig
# Simple connection via portal
typer = EiType.connect_portal()
typer.type_text("Hello from Python!")
typer.press_key("Return")
# With custom configuration
config = EiTypeConfig(layout="de", delay_ms=10)
typer = EiType.connect_portal(config)
typer.type_text("Hallo Welt!")
# Modifier keys
typer.hold_modifier("ctrl")
typer.press_key("c")
typer.release_modifiers()
Token Persistence (for long-running apps)
For applications that run continuously (like voice typing tools), you can save and reuse the portal authorization token:
from eitype import EiType
# First run - will show authorization dialog
typer, token = EiType.connect_portal_with_token()
if token:
save_to_config(token) # Save for next time
# Subsequent runs - no dialog needed
saved_token = load_from_config()
typer, _ = EiType.connect_portal_with_token(saved_token)
typer.type_text("No dialog this time!")
Thread Safety
EiType is Send but not Sync. You can move an instance between threads —
for example, create it on one thread and call it from a thread pool — but you must
not call its methods from two threads concurrently.
- From Python, this is automatic on standard CPython: the GIL serializes every call. On a free-threaded (no-GIL) interpreter the GIL no longer protects you, so wrap the instance in your own lock if more than one thread can reach it.
- From Rust, serialize access yourself (e.g. behind a
Mutex) when sharing an instance across threads.
Rust Library Usage
Add to your Cargo.toml:
[dependencies]
eitype = { path = "../eitype" } # or from crates.io when published
use eitype::{EiType, EiTypeConfig, EiTypeError};
fn main() -> Result<(), EiTypeError> {
// Connect via portal
let mut typer = EiType::connect_portal(EiTypeConfig::default())?;
// Type text
typer.type_text("Hello from Rust!")?;
typer.press_key("Return")?;
// With modifiers
typer.hold_modifier("ctrl")?;
typer.press_key("c")?;
typer.release_modifiers()?;
Ok(())
}
Development
# Set up dev environment with pre-commit hooks
pixi run -e dev install-hooks
# Run linting (cargo fmt + clippy)
pixi run -e dev lint
Requirements
- Rust 1.70+
- Python 3.10+ (only for Python bindings)
- libxkbcommon (handled automatically by pixi, or install manually)
License
Apache 2.0
Release files for eitype 0.2.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| eitype-0.2.2-cp314-cp314-manylinux_2_34_aarch64.whl | CPython 3.14 | CPython 3.14 | Linux glibc 2.34+ ARM64 | Details |
| eitype-0.2.2-cp314-cp314-manylinux_2_28_x86_64.whl | CPython 3.14 | CPython 3.14 | Linux glibc 2.28+ x86-64 | Details |
| eitype-0.2.2-cp313-cp313-manylinux_2_34_aarch64.whl | CPython 3.13 | CPython 3.13 | Linux glibc 2.34+ ARM64 | Details |
| eitype-0.2.2-cp313-cp313-manylinux_2_28_x86_64.whl | CPython 3.13 | CPython 3.13 | Linux glibc 2.28+ x86-64 | Details |
| eitype-0.2.2-cp312-cp312-manylinux_2_34_aarch64.whl | CPython 3.12 | CPython 3.12 | Linux glibc 2.34+ ARM64 | Details |
| eitype-0.2.2-cp312-cp312-manylinux_2_28_x86_64.whl | CPython 3.12 | CPython 3.12 | Linux glibc 2.28+ x86-64 | Details |
| eitype-0.2.2-cp311-cp311-manylinux_2_34_aarch64.whl | CPython 3.11 | CPython 3.11 | Linux glibc 2.34+ ARM64 | Details |
| eitype-0.2.2-cp311-cp311-manylinux_2_28_x86_64.whl | CPython 3.11 | CPython 3.11 | Linux glibc 2.28+ x86-64 | Details |
| eitype-0.2.2-cp310-cp310-manylinux_2_34_aarch64.whl | CPython 3.10 | CPython 3.10 | Linux glibc 2.34+ ARM64 | Details |
| eitype-0.2.2-cp310-cp310-manylinux_2_28_x86_64.whl | CPython 3.10 | CPython 3.10 | Linux glibc 2.28+ x86-64 | Details |
Total release size: 16.2 MB
Release files / eitype-0.2.2-cp314-cp314-manylinux_2_34_aarch64.whl
| Download URL | eitype-0.2.2-cp314-cp314-manylinux_2_34_aarch64.whl |
|---|---|
| Size | 1.6 MB |
| Tags | CPython 3.14 Linux glibc 2.34+ ARM64 |
|
SHA-256 checksum How to use checksums |
5f8541e5ac8fff8b93df8c2abff0dd7a7ab9313db1f061a3028393cccaaafbf2
|
|
BLAKE2b-256 checksum How to use checksums |
54ee29ffb60dbf40aca7bebb750c81469f0d1280771f8ac66cc96295ea5ebb70
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 13, 2026.
Transparency logRelease files / eitype-0.2.2-cp314-cp314-manylinux_2_28_x86_64.whl
| Download URL | eitype-0.2.2-cp314-cp314-manylinux_2_28_x86_64.whl |
|---|---|
| Size | 1.6 MB |
| Tags | CPython 3.14 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
96afc0cde45845c9b4be3673fdcd9e0c9d10c789efcbf34abcbab29aad41c5f8
|
|
BLAKE2b-256 checksum How to use checksums |
e22dd1d33a83ccd6b00eeb6ed529e68b49073a06614d9b3662c8bcf00e5643bb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 13, 2026.
Transparency logRelease files / eitype-0.2.2-cp313-cp313-manylinux_2_34_aarch64.whl
| Download URL | eitype-0.2.2-cp313-cp313-manylinux_2_34_aarch64.whl |
|---|---|
| Size | 1.6 MB |
| Tags | CPython 3.13 Linux glibc 2.34+ ARM64 |
|
SHA-256 checksum How to use checksums |
37663e8f7d252d61a53fb78a035889dd035655d86d8bb447086f6c50f506f967
|
|
BLAKE2b-256 checksum How to use checksums |
e868bcc1729b3c8a97efe1a1d8aca5299f60e3860316b8ca1543bbe3429efde8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 13, 2026.
Transparency logRelease files / eitype-0.2.2-cp313-cp313-manylinux_2_28_x86_64.whl
| Download URL | eitype-0.2.2-cp313-cp313-manylinux_2_28_x86_64.whl |
|---|---|
| Size | 1.6 MB |
| Tags | CPython 3.13 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
0eff70098e3da4beaa838524831bd8732dc71eb3845b3188ad33ff902d3d4fa9
|
|
BLAKE2b-256 checksum How to use checksums |
8736dc4cf29be131882edfaf68d8d573c6249711d169b038f14196e659379503
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 13, 2026.
Transparency logRelease files / eitype-0.2.2-cp312-cp312-manylinux_2_34_aarch64.whl
| Download URL | eitype-0.2.2-cp312-cp312-manylinux_2_34_aarch64.whl |
|---|---|
| Size | 1.6 MB |
| Tags | CPython 3.12 Linux glibc 2.34+ ARM64 |
|
SHA-256 checksum How to use checksums |
2aacacb3f17dda524c151c2bbeb76909d083b69d4de044fa8c7b9b7c216fae4a
|
|
BLAKE2b-256 checksum How to use checksums |
2291291f596c8a65250c59e4f8f2413f4b71b336977d84d28583af787d767283
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 13, 2026.
Transparency logRelease files / eitype-0.2.2-cp312-cp312-manylinux_2_28_x86_64.whl
| Download URL | eitype-0.2.2-cp312-cp312-manylinux_2_28_x86_64.whl |
|---|---|
| Size | 1.6 MB |
| Tags | CPython 3.12 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
ae8831a2624bc41b3b2273aa3b2f769a2e27204a11a8642470a9ee2dbfb37992
|
|
BLAKE2b-256 checksum How to use checksums |
747e587bc0e072f339197cd6f8395e722d76601fd0cf80803aa5904ad9e78c17
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 13, 2026.
Transparency logRelease files / eitype-0.2.2-cp311-cp311-manylinux_2_34_aarch64.whl
| Download URL | eitype-0.2.2-cp311-cp311-manylinux_2_34_aarch64.whl |
|---|---|
| Size | 1.6 MB |
| Tags | CPython 3.11 Linux glibc 2.34+ ARM64 |
|
SHA-256 checksum How to use checksums |
ca1b5de8538dabf93a432c8c4cba6dd3f2acf1242636bd40a3a6b4fd92903f33
|
|
BLAKE2b-256 checksum How to use checksums |
10abb9e91057a14c9bb735e8c73deeda45a9e997b0285d9b6e175355938c5dab
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 13, 2026.
Transparency logRelease files / eitype-0.2.2-cp311-cp311-manylinux_2_28_x86_64.whl
| Download URL | eitype-0.2.2-cp311-cp311-manylinux_2_28_x86_64.whl |
|---|---|
| Size | 1.6 MB |
| Tags | CPython 3.11 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
cf4411ab41f2d008c520ac5e31a979b88fc84a34d7f88cb4a8d0b0296e75cb0b
|
|
BLAKE2b-256 checksum How to use checksums |
74fb550ad092b18673aebb4fb5676533a6b029d7119327fef49865e811410d48
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 13, 2026.
Transparency logRelease files / eitype-0.2.2-cp310-cp310-manylinux_2_34_aarch64.whl
| Download URL | eitype-0.2.2-cp310-cp310-manylinux_2_34_aarch64.whl |
|---|---|
| Size | 1.6 MB |
| Tags | CPython 3.10 Linux glibc 2.34+ ARM64 |
|
SHA-256 checksum How to use checksums |
670383e47d6929e583cec37e3433f001e9b6211e2d4b5474db531555f2a333c3
|
|
BLAKE2b-256 checksum How to use checksums |
6b22de7d2dd8a26edab2ec60b4ed89e4aabf879e042695bc00e5fdd66670ccf2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 13, 2026.
Transparency logRelease files / eitype-0.2.2-cp310-cp310-manylinux_2_28_x86_64.whl
| Download URL | eitype-0.2.2-cp310-cp310-manylinux_2_28_x86_64.whl |
|---|---|
| Size | 1.6 MB |
| Tags | CPython 3.10 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
326788c348a40df6338cbd8dfa2fcb7c4dedb5e63239e4f75fc3dfe8aa5ed6fc
|
|
BLAKE2b-256 checksum How to use checksums |
c9637db2eb5eec8d9251c7936197ad52bfc73d3a84cf6a6514f2333d575dbd68
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 13, 2026.
Transparency log