Skip to main content

AI-powered desktop typing assistant with real-time ghost-text completions, personalized via local embeddings and semantic example retrieval

Project description

Kei Typing Assistant

An AI-powered desktop typing assistant that provides real-time text completions as ghost text via a floating overlay window, accessible from any application. Learns your writing style over time for increasingly personalized suggestions.

Features

  • Global hotkey opens a compact overlay window from any app; press it again to copy and close
  • Streaming AI suggestions appear as faint ghost text while you type
  • Accept a suggestion with Tab, dismiss with Esc
  • Three AI providers: local LLM (llama.cpp, runs fully offline), MiniMax, and OpenRouter
  • Hybrid mode: races the local model against a cloud provider and upgrades to the cloud result if it arrives first, within a configurable time window
  • Model warm-up loads the local model in the background at startup so the first suggestion isn't slowed by a cold start
  • Accepted suggestions are stored with semantic embeddings and retrieved as personalized few-shot context, with per-example search/shown counts tracked over time
  • Manage stored examples (view, search, add, delete) from a dedicated GUI window
  • Reusable, ordered context fragments — curated notes you can prepend to the AI system prompt — managed from their own GUI window
  • Mid-word suppression skips AI requests while the cursor sits inside a word
  • API keys stored securely in the system keychain
  • SQLite storage with Alembic-managed schema migrations

Requirements

  • Python 3.12+
  • macOS 12+ (primary), Windows 10/11, Linux supported
  • API key for MiniMax or OpenRouter (not required for the default local LLM provider)
  • macOS: Accessibility permission required for global hotkey

Quick Start

1. Install

git clone https://github.com/l0kifs/kei-typing-assistant.git
cd kei-typing-assistant
uv sync

2. Configure (optional)

Create a .env file in the project root to override defaults:

KEI__AI_PROVIDER=local_llm      # local_llm | minimax | openrouter
KEI__HOTKEY=ctrl+alt+space      # global hotkey
KEI__FLAVOUR="Concise, formal"  # personalization hint for AI

All settings with defaults are documented in src/kei_typing_assistant/config/settings.py.

3. Add your API key (cloud providers only)

If using MiniMax or OpenRouter, open Settings from the tray icon and enter your API key. Keys are stored in the system keychain — never in plaintext. The default local LLM provider needs no API key; the model is downloaded from Hugging Face on first run.

4. Grant Accessibility permission (macOS)

System Settings → Privacy & Security → Accessibility — add the app or your terminal to allow global hotkey capture.

5. Run

uv run kei

The app runs in the system tray. Press the hotkey (Ctrl+Alt+Space by default) to open the overlay.

Usage

Action Key
Open overlay Ctrl+Alt+Space (configurable)
Accept suggestion Tab
Copy text & close Ctrl+Alt+Space again
Dismiss without copying Esc

AI Providers

Provider Setting value Notes
Local LLM local_llm (default) Runs fully offline via llama.cpp; GGUF model auto-downloaded from Hugging Face; GPU-accelerated via Metal/CUDA where available
MiniMax minimax Cloud API, accessed via an Anthropic-compatible endpoint
OpenRouter openrouter Cloud API, accessed via an OpenAI-compatible endpoint; free-tier models available
Hybrid enable hybrid_mode Races the local model against a chosen cloud provider (MiniMax or OpenRouter) and swaps in the cloud result if it beats the local one within hybrid_upgrade_window_s

Settings Window

Tab Contents
General Writing-style ("flavour") hint injected into the AI system prompt
AI Model Provider selection (Local LLM / MiniMax / OpenRouter / Hybrid) and per-provider configuration (model, API key, context window, GPU layers, sampling params)
Behaviour Suggestion length, temperature, debounce delay, mid-word suppression, include-context-fragments toggle
Appearance Theme, ghost-text opacity, font family/size, overlay position
Hotkeys Global hotkey binding
Storage Data directory location (models, database)

Two standalone windows, opened from the tray/settings menu, manage personalization data directly:

  • Context Fragments — add, edit, reorder, search, and delete reusable prompt snippets prepended to the AI system prompt when enabled
  • Suggestion Examples — browse, search, add, and delete the accepted (input → suggestion) pairs used for semantic few-shot retrieval, including how often each has been searched/shown

Configuration Reference

Setting Default Description
KEI__HOTKEY ctrl+alt+space Global trigger hotkey
KEI__AI_PROVIDER local_llm local_llm, minimax, or openrouter
KEI__AI_MAX_TOKENS 60 Max suggestion length
KEI__AI_TEMPERATURE 0.8 Sampling temperature
KEI__AI_DEBOUNCE_MS 300 Delay before AI request (ms)
KEI__MID_WORD_SUPPRESSION false Skip requests while the cursor is mid-word
KEI__INCLUDE_CONTEXT_FRAGMENTS false Prepend saved context fragments to the AI system prompt
KEI__FLAVOUR `` Writing style hint for AI
KEI__THEME system system, dark, or light
KEI__HYBRID_MODE false Race local LLM against a cloud provider
KEI__HYBRID_UPGRADE_WINDOW_S 1.5 Seconds to wait for the cloud provider before keeping the local result
KEI__LOCAL_LLM_MODEL_ID Qwen/Qwen2.5-3B-Instruct-GGUF Hugging Face repo for the local model
KEI__LOCAL_LLM_N_GPU_LAYERS -1 GPU layers to offload (-1 = all, 0 = CPU only)
KEI__SEMANTIC_EXAMPLES_TOP_K 5 Max similar accepted examples injected as few-shot context
KEI__DATA_DIR ~/.kei_typing_assistant Base directory for models, database, and settings

Full list of settings, defaults, and validation ranges: src/kei_typing_assistant/config/settings.py.

Development

# Run tests
pytest

# Run tests with coverage
pytest --cov=src/kei_typing_assistant

# Lint & format
ruff check .
ruff format .

CLI Reference

kei-cli provides a command-line interface for testing suggestions, managing the semantic example store, local models, database migrations, and configuration.

uv run kei-cli [--verbose] COMMAND [ARGS]

Suggestion commands

Command Description
suggest TEXT Stream an AI suggestion for the given text
accept TEXT SUGGESTION Save an accepted (input, suggestion) pair to the semantic example store
test [--text TEXT] Full E2E flow: suggest → save accepted example

Typical workflow:

# 1. Get a suggestion
uv run kei-cli suggest "The weather today is"
#   → warm and sunny with clear skies

# 2. Accept it — embeds and saves for future retrieval
uv run kei-cli accept "The weather today is" "warm and sunny with clear skies"
#   ✓ Saved: 'The weather today is' → 'warm and sunny with clear skies'

# 3. Next suggest call retrieves similar stored examples as context
uv run kei-cli suggest "The weather this morning is"

suggest options: --flavour TEXT, --max-tokens INT test options: --text TEXT, --flavour TEXT, --max-tokens INT

Local model

uv run kei-cli model list             # List downloaded models
uv run kei-cli model status MODEL_ID  # Check if a model is downloaded
uv run kei-cli model delete MODEL_ID  # Delete a downloaded model from disk

Database

uv run kei-cli db upgrade   # Migrate the database to the latest schema revision
uv run kei-cli db current   # Show the currently applied schema revision

Configuration

uv run kei-cli config show      # Show current configuration

Architecture

The project follows Domain-Driven Design. See docs/ddd-architecture-rules.md for conventions and docs/BRD.md for the business requirements behind it.

src/kei_typing_assistant/
├── main.py          # Composition root: wiring, bootstrap, launch
├── config/          # Settings & logging
├── domains/         # Pure business logic (suggestion, context_fragments, local_model)
├── infrastructure/  # AI provider clients, SQLite database + Alembic migrations, keychain
└── entry_points/    # Qt GUI, hotkey listener, tray, CLI, background workers

Database schema changes are managed with Alembic; migrations run automatically at startup (kei-cli db upgrade for manual control).

Publishing

See docs/PUBLISHING.md. Releases are published to PyPI automatically via GitHub Actions on tag push. See CHANGELOG.md for release history.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

kei_typing_assistant-0.1.0.tar.gz (53.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

kei_typing_assistant-0.1.0-py3-none-any.whl (82.9 kB view details)

Uploaded Python 3

File details

Details for the file kei_typing_assistant-0.1.0.tar.gz.

File metadata

  • Download URL: kei_typing_assistant-0.1.0.tar.gz
  • Upload date:
  • Size: 53.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for kei_typing_assistant-0.1.0.tar.gz
Algorithm Hash digest
SHA256 8fa36a8da924ebef44846b0ae828b6a49155c3fe780798dee93a864b11e5408d
MD5 a618b1e59526332c58712e9184573df9
BLAKE2b-256 c64c2fd361cda0e57d8dbd7ae6589820750667c6ecb9a13801b8a4cd79b042aa

See more details on using hashes here.

Provenance

The following attestation bundles were made for kei_typing_assistant-0.1.0.tar.gz:

Publisher: publish-to-pypi.yml on l0kifs/kei-typing-assistant

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file kei_typing_assistant-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for kei_typing_assistant-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b57b6562d427c9f83ab386d918bd1b5db831488eb83827fcec944c283bd3b304
MD5 59078d70fa929a7e10d1a95ef50771f4
BLAKE2b-256 bd2bf6e4165d9a3d42ffd634913f1280840ed3229f0b4db03eded5657cc80b0f

See more details on using hashes here.

Provenance

The following attestation bundles were made for kei_typing_assistant-0.1.0-py3-none-any.whl:

Publisher: publish-to-pypi.yml on l0kifs/kei-typing-assistant

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page