Skip to content

The-U-Project/Keyboard

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

3 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Β 


πŸ“– Table of Contents


What Is This?

Project Keyboard turns any vision-capable LLM into a computer-use agent. Point it at a goal and it will:

  1. Watch your screen at configurable FPS
  2. Understand what it sees (buttons, text, layouts)
  3. Decide what action to take next
  4. Execute clicks, keystrokes, scrolling, and typing

Think of it as a universal macro engine where you describe what you want instead of scripting how to do it.

keyboard start --goal "open Chrome, go to gmail.com, compose an email to alice@example.com saying 'hello'"

The agent sees the screen, finds Chrome, clicks it, types the URL, waits for Gmail to load, finds the compose button, and types the message β€” all autonomously.

πŸ‘©β€πŸ’» Developer? Jump to What Works Today for current status, Development for the dev loop, or docs/plan.md for the implementation plan.


✨ Features

  • πŸ–₯️ High-FPS Screen Capture β€” DXGI Desktop Duplication via dxcam, sub-10ms latency at 30 FPS
  • 🧠 Multi-Provider LLM β€” OpenAI GPT-4o, Anthropic Claude, Ollama (LLaVA, Gemma 3, etc.)
  • πŸ”§ Rich Tool Suite β€” click, type, keypress, scroll, move, wait, drag
  • πŸ›‘ Emergency Stop β€” Press Esc anytime, anywhere. Hardware-level hotkey (Windows RegisterHotKey)
  • πŸ’¬ Interactive Chat β€” Send new goals to a running agent from another terminal
  • 🏠 Fully Local Mode β€” Ollama + local models = zero cloud dependency
  • πŸ“Š Change Detection β€” Skips redundant frames, only sends new info to the LLM
  • πŸ“ Action Logging β€” Append-only JSONL log for debugging and replay
  • πŸŽ›οΈ CLI-First β€” Every feature accessible from the terminal. No GUI required.

πŸ”¬ How It Works

flowchart TD
    A[πŸ–₯️ Screen Capture\nDXGI / dxcam] --> B[πŸ–ΌοΈ Preprocessing\nresize / change-detect / encode]
    B --> C{Changed?}
    C -->|No| A
    C -->|Yes| D[πŸ€– Vision LLM\nGPT-4o / Claude / Ollama]
    D --> E{Tool Call?}
    E -->|Yes| F[⚑ Execute Action\nclick / type / scroll / wait]
    E -->|No| G[πŸ’¬ Text Response]
    F --> H[πŸ“ Log Action]
    G --> H
    H --> I{Done / Stopped?}
    I -->|No| A
    I -->|Yes| J[πŸ›‘ Shutdown]
Loading

The Pipeline in Detail

Stage Module What Happens
Capture capture.py Grabs raw BGR frame from monitor via DXGI. DPI-aware.
Preprocess preproc.py Resizes to max 1024px, detects pixel-diff vs previous frame, encodes to base64 JPEG
Think llm.py Sends frame + goal + history to vision LLM with tool definitions
Act actions.py Parses tool call, executes viapyautogui/pynput, returns result
Log safety.py Appends timestamped action to JSONL log for replay/debug
Repeat agent.py Loops at configured FPS until goal achieved or stopped

Provider Comparison

OpenAI GPT-4o Anthropic Claude Ollama (Local)
Latency ~1-3s ~2-5s ~0.5-2s (GPU)
Cost ~$0.01/image ~$0.02/image Free
Vision Quality Excellent Excellent Good (model-dependent)
Tool Calling Native JSON Native + computer-use JSON mode
Internet Required Yes Yes No
Setup API key API key ollama pull llava

🎬 Demo (Planned)

When the full pipeline is complete, here's what a session will look like:

β”Œβ”€ Terminal 1 (Agent) ────────────────────────────────────────────┐
β”‚ $ keyboard start --goal "search for cats on Google"              β”‚
β”‚                                                                  β”‚
β”‚ πŸš€ Project Keyboard v0.1.0 | Provider: openai | Model: gpt-4o   β”‚
β”‚                                                                  β”‚
β”‚ [12:00:01] πŸ‘οΈ  Observing... (1920Γ—1080 β†’ 1024Γ—576, 45KB)        β”‚
β”‚ [12:00:02] πŸ€” LLM: I see the Windows desktop with a Chrome icon. β”‚
β”‚            I'll click the Chrome icon on the taskbar.            β”‚
β”‚ [12:00:02] ⚑ click(x=150, y=1056, button="left")                β”‚
β”‚ [12:00:03] πŸ‘οΈ  Observing... (frame skipped β€” no change)          β”‚
β”‚ [12:00:04] πŸ‘οΈ  Observing... (1920Γ—1080 β†’ 1024Γ—576, 52KB)        β”‚
β”‚ [12:00:06] πŸ€” LLM: Chrome is open. I see the address bar.        β”‚
β”‚            I'll click it and type the search URL.                β”‚
β”‚ [12:00:06] ⚑ click(x=400, y=60, button="left")                  β”‚
β”‚ [12:00:07] ⚑ type("google.com")                                 β”‚
β”‚ [12:00:07] ⚑ keypress("enter")                                  β”‚
β”‚ [12:00:08] πŸ‘οΈ  Observing... (1920Γ—1080 β†’ 1024Γ—576, 78KB)        β”‚
β”‚ [12:00:10] πŸ€” LLM: Google homepage loaded. I see the search box. β”‚
β”‚            Typing the query...                                   β”‚
β”‚ [12:00:10] ⚑ type("cats")                                       β”‚
β”‚ [12:00:10] ⚑ keypress("enter")                                  β”‚
β”‚ [12:00:13] βœ… Goal completed: search results for "cats" shown.   β”‚
β”‚                                                                  β”‚
β”‚ ── Summary ──────────────────────────────────────────────────    β”‚
β”‚ Frames captured: 14 | Sent to LLM: 4 | Actions taken: 6         β”‚
β”‚ Duration: 12.4s | Avg LLM latency: 2.1s | Avg FPS: 30.1        β”‚
β”‚ Log saved: ~/.keyboard/actions.log                               β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

β”Œβ”€ Terminal 2 (Chat) ─────────────────────────────────────────────┐
β”‚ $ keyboard chat "click on the first image result"                β”‚
β”‚ β†’ Sent to agent. Response: "Clicked the first cat image."       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

This is the target experience. See Roadmap for current progress.


πŸ“¦ Installation

Prerequisites

  • Windows 10/11 (DXGI Desktop Duplication requires Windows)
  • Python 3.10+ (download)
  • Git (optional, for cloning)

From Source

# Clone the repo
git clone https://github.com/your-username/project-keyboard.git
cd project-keyboard

# Create a virtual environment (recommended)
python -m venv .venv
.venv\Scripts\activate   # Windows

# Install with dev dependencies
pip install -e ".[dev]"

Verify Installation

keyboard --help
# Should show all available commands

βœ… What Works Today

Project Keyboard is in active development. Here's what's functional right now:

Command Status What It Does
keyboard setup βœ… Interactive wizard β€” pick provider, set keys
keyboard config show βœ… Display current configuration
keyboard config set <k> <v> βœ… Update a setting (fps, model, provider…)
keyboard capture --fps N βœ… Save raw screen frames to disk for debugging
keyboard start 🟑 Stub β€” agent loop coming in Phase 2
keyboard chat / stop ⬜ IPC commands coming in Phase 3

Implemented Modules

Module Status Responsibility
capture.py βœ… DXGI screen capture via dxcam
config.py βœ… .env + YAML config loading
preproc.py βœ… Resize, change detection, base64 encoding
llm.py βœ… Provider abstraction (OpenAI/Anthropic/Ollama)
actions.py βœ… Tool schema + action execution
safety.py βœ… Emergency stop (Esc hotkey)
agent.py ⬜ Main observeβ†’thinkβ†’act loop (Phase 2)
server.py ⬜ HTTP IPC for multi-terminal control (Phase 3)

πŸš€ Quick Start

# 1. Set up your AI provider (interactive wizard)
keyboard setup

# 2. View your configuration
keyboard config show

# 3. Test screen capture β€” save 5 seconds of frames at 30 FPS
keyboard capture --fps 30 --duration 5

# 4. Run the test suite
pytest

πŸ€– Supported AI Providers

Provider Model Type Setup
OpenAI GPT-4o, GPT-4o-mini Cloud OPENAI_API_KEY in .env
Anthropic Claude 3.5 Sonnet, Claude 3 Opus Cloud ANTHROPIC_API_KEY in .env
Ollama LLaVA 13B, Gemma 3 12B, Llama 3.2 Vision Local ollama pull <model>

Switching Providers

keyboard config set provider anthropic
keyboard config set model claude-3-5-sonnet-20241022

Running Fully Locally

# Install Ollama (https://ollama.com)
ollama pull llava:13b

# Configure
keyboard config set provider ollama
keyboard config set model llava:13b

# No API keys. No internet. Fully private.
keyboard start --goal "organize my desktop icons"

βš™οΈ Configuration

Project Keyboard uses two configuration layers:

.env β€” Secrets (project root)

OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
OLLAMA_HOST=http://localhost:11434

~/.keyboard/config.yaml β€” Preferences

provider: openai          # openai | anthropic | ollama
model: gpt-4o             # Model name
fps: 5                    # Frames per second to capture
max_dim: 1024             # Max pixel dimension (resize larger dim to this)
change_threshold: 0.05    # Skip frame if < 5% pixels changed
quality: 85               # JPEG quality (1-100)
action_delay: 0.1         # Seconds between actions

CLI Config Commands

keyboard config show              # Print current config
keyboard config set fps 10        # Change capture rate
keyboard config set model gpt-4o-mini  # Switch to cheaper model

πŸ“‹ CLI Reference

Command Description Example
keyboard setup Interactive setup wizard (provider, API keys) keyboard setup
keyboard start [--goal "..."] Launch agent loop keyboard start --goal "open VS Code"
keyboard chat "<message>" Send message to running agent keyboard chat "click the save button"
keyboard stop Gracefully stop the agent keyboard stop
keyboard status Show agent status & stats keyboard status
keyboard config show Display current configuration keyboard config show
keyboard config set <k> <v> Update a config key keyboard config set fps 10
keyboard capture [--fps N] [--duration S] Debug: save raw frames to disk keyboard capture --fps 30 --duration 5

Global Options

--help, -h     Show help for any command
--version, -V  Show version number

πŸ—οΈ Architecture

project-keyboard/
β”œβ”€β”€ .github/                       # AI development infrastructure
β”‚   β”œβ”€β”€ copilot-instructions.md     # Always-on rules for AI assistants
β”‚   β”œβ”€β”€ skills/                     # Reusable on-demand workflows
β”‚   β”‚   β”œβ”€β”€ python-dev/             # Python conventions
β”‚   β”‚   β”œβ”€β”€ cli-designer/           # CLI design patterns
β”‚   β”‚   β”œβ”€β”€ screen-capture/         # dxcam/DXGI patterns
β”‚   β”‚   β”œβ”€β”€ llm-integration/        # LLM provider patterns
β”‚   β”‚   └── project-keyboard/       # Master project overview
β”‚   └── agents/                     # Specialist subagents
β”‚       β”œβ”€β”€ python-architect.agent.md
β”‚       β”œβ”€β”€ cli-designer.agent.md
β”‚       └── project-keyboard-dev.agent.md
β”œβ”€β”€ src/keyboard/                   # Main Python package
β”‚   β”œβ”€β”€ __init__.py                 # Package marker + version
β”‚   β”œβ”€β”€ __main__.py                 # CLI entry point (click)
β”‚   β”œβ”€β”€ capture.py                  # ScreenCapture (dxcam/DXGI)
β”‚   β”œβ”€β”€ preproc.py                  # Resize, change-detect, encode
β”‚   β”œβ”€β”€ llm.py                      # LLMProvider ABC + 3 implementations
β”‚   β”œβ”€β”€ actions.py                  # Tool schema + ActionExecutor
β”‚   β”œβ”€β”€ agent.py                    # Main observeβ†’thinkβ†’act loop
β”‚   β”œβ”€β”€ safety.py                   # Emergency stop (Esc hotkey)
β”‚   β”œβ”€β”€ config.py                   # .env + config.yaml loader
β”‚   └── server.py                   # HTTP IPC (CLI ↔ running agent)
β”œβ”€β”€ tests/                          # pytest test suite
β”œβ”€β”€ docs/
β”‚   └── plan.md                     # Detailed implementation plan
β”œβ”€β”€ pyproject.toml                  # Project config + dependencies
β”œβ”€β”€ .env.example                    # Template for API keys
β”œβ”€β”€ .gitignore
└── README.md                       # ← You are here

Dependency Map

graph LR
    A[__main__.py\nCLI Entry] --> B[agent.py\nMain Loop]
    B --> C[capture.py\ndxcam]
    B --> D[preproc.py\nPIL/Numpy]
    B --> E[llm.py\nOpenAI/Anthropic/Ollama]
    B --> F[actions.py\npyautogui/pynput]
    B --> G[safety.py\npynput/ctypes]
    H[config.py\ndotenv/PyYAML] --> B
    H --> E
    I[server.py\nhttpx] --> B
    A --> I
    A --> H

    style A fill:#4A90D9,color:#fff
    style B fill:#D94A4A,color:#fff
    style E fill:#4AD97A,color:#fff
Loading

Design Principles

# Rule Why
1 Pure Python v1 No C++, Rust, or other languages. Python only.
2 Flat package One concern per file. No deep nesting.
3 LLM does vision No OpenCV, no ONNX. The LLM sees and understands.
4 Continuous loop Watch β†’ Think β†’ Act β†’ Repeat until goal or stop.
5 Emergency stop only Esc hotkey +keyboard stop. No confirmation mode in v1.
6 Simple over clever If a pattern adds complexity without clear benefit, skip it.

πŸ› οΈ Development

Setup

pip install -e ".[dev]"

Quality Gates

ruff check src/          # Lint + format checking
ruff format --check src/ # Format verification
mypy src/                # Strict type checking
pytest                   # Run all tests
pytest --cov=keyboard --cov-report=html  # Coverage report

Test Markers

pytest -m "not slow"         # Skip slow tests
pytest -m "not integration"  # Skip tests needing real APIs
pytest tests/test_capture.py -v  # Run specific test file

Code Style

Rule Standard
Docstrings Every public function/class has"""Why this exists."""
Type Hints On ALL public APIs
Linter ruff (pycodestyle + pyflakes + isort + bugbear + pyupgrade)
Line Length 100 characters
Imports stdlib β†’ third-party β†’ local (isort-enforced)
Naming snake_case functions, PascalCase classes, UPPER_CASE constants

Development Loop

The typical workflow when hacking on Project Keyboard:

# 1. Make your changes
vim src/keyboard/capture.py

# 2. Lint + type-check
ruff check src/ && ruff format --check src/ && mypy src/

# 3. Run tests (skip slow/integration if needed)
pytest -m "not slow and not integration"

# 4. Run a specific test file with coverage
pytest tests/test_capture.py -v --cov=keyboard.capture --cov-report=term

AI-Assisted Development

This project was built with and for GitHub Copilot. The .github/ directory contains:

Tool Location Purpose
Instructions .github/copilot-instructions.md Always-on rules (auto-loaded)
Skills .github/skills/ On-demand workflows (/skill-name)
Agents .github/agents/ Specialist subagents (agent picker)

Create new ones with /create-skill or /create-agent.

Key Docs for Contributors

File Purpose
docs/plan.md Detailed phase-by-phase implementation plan
.github/copilot-instructions.md Always-on AI assistant rules (auto-loaded by Copilot)
.github/skills/ Reusable on-demand workflows for Python, CLI, screen capture, LLMs
.github/agents/ Specialist subagents for code review, CLI design, and feature work
pyproject.toml All dependencies, ruff/mypy/pytest config

πŸ—ΊοΈ Roadmap

Phase 1 β€” Skeleton + Capture 🟑 In Progress

  • ScreenCapture class (dxcam/DXGI)
  • Config system (.env + config.yaml)
  • keyboard setup + keyboard capture CLI
  • Initial test suite

Phase 2 β€” Core Pipeline ⬜

  • Frame preprocessing (resize, change-detect, encode)
  • LLM provider abstraction (OpenAI, Anthropic, Ollama)
  • Tool definitions + action executor
  • Main agent loop (observe β†’ think β†’ act)
  • Emergency stop (Esc hotkey)

Phase 3 β€” CLI Polish ⬜

  • HTTP IPC server (localhost:9876)
  • keyboard chat, stop, status commands
  • Config show/set commands

Phase 4 β€” Safety + Recording ⬜

  • Windows RegisterHotKey (cannot be blocked)
  • Pipeline hooks (on_observe, on_think, on_act)
  • Append-only JSONL action log
  • Graceful shutdown + atexit cleanup

Future

  • Recording & replay from action log
  • Voice input via Whisper STT
  • Optional confirmation mode
  • Cross-platform support (Linux, macOS)
  • GUI frontend (Electron/React)

❓ FAQ

Does this work without an internet connection?

Yes! Use Ollama with a local vision model like llava:13b or gemma3:12b. No API keys, no cloud β€” everything runs on your machine.

Is this safe? Can it do destructive things?

The agent only has the tools you give it (click, type, scroll, etc.). It can only interact with your desktop the same way you can. Press Esc at any time for an instant emergency stop.

We recommend:

  • Running with visible feedback (watch the screen while it works)
  • Starting with simple, reversible goals
  • Not running as administrator
How much does it cost to run?
Provider Approximate Cost
OpenAI GPT-4o ~$0.50–$2.00 / hour of agent runtime
Anthropic Claude ~$1.00–$4.00 / hour
Ollama (local) $0 (your electricity)

Use gpt-4o-mini for significant cost savings at slightly reduced accuracy.

What can I use it for?
  • Automating repetitive UI tasks
  • Testing GUI applications
  • Accessibility (control PC via natural language)
  • Data entry automation
  • "Computer, do X" β€” general-purpose desktop automation
Why Python? Why not Rust/C++?

v1 optimizes for development speed and iteration. The LLM is the bottleneck (1-3 seconds per inference), not capture or execution. If profiling shows Python is the bottleneck, we can optimize hot paths later.


🀝 Contributing

Contributions are welcome! Here's how:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feat/amazing-idea)
  3. Write code following the code style guide
  4. Add tests for new functionality
  5. Run quality gates: ruff check src/ && mypy src/ && pytest
  6. Commit (git commit -m "feat: add amazing idea")
  7. Push (git push origin feat/amazing-idea)
  8. Open a pull request

Commit Convention

We use Conventional Commits:

  • feat: β€” new feature
  • fix: β€” bug fix
  • docs: β€” documentation
  • test: β€” tests
  • refactor: β€” code restructuring
  • chore: β€” build/tooling

πŸ“„ License

MIT β€” see LICENSE for details.


About

LLM-controlled keyboard simulation with simple mouse actions!

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages