Skip to content

About

Self-hosted AI agent that runs your PC from Telegram — desktop (background computer-use via cua-driver, with UI-Automation/OCR fallback), browser, voice, and code, powered by Claude Code.

Topics

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

Threadwright icon

Threadwright — Control Your PC from Telegram with an AI Agent

License: MIT Build installer & release .NET 10 Platform: Windows

Text your computer. It does the work. Self-hosted Windows tray app bridging a Telegram bot to Claude Code, turning your phone into a remote control for an AI agent that runs on — and fully operates — your PC (mouse/keyboard, browser, files, code, reboot). Think remote desktop meets autonomous AI assistant.

⚠️ Full unattended PC control. Default mode lets the agent run any command on your machine with no per-action approval. Self-host only on a machine you own, and lock AllowedUserIds to yourself. See Permissions & safety.


What it can do

  • 🤖 Operate your PC — mouse/keyboard/hotkeys, screenshots, clipboard, windows/processes, launch apps, lock/reboot. Prefers cua-driver (background computer-use — drives apps without stealing focus) and falls back to built-in UI-Automation/OCR/screenshots.
  • 🌐 Drive the browser — Playwright, DOM-level (click/fill/scrape/login).
  • 🗣️ Any input — text, voice notes (auto-transcribed), photo/document/video (video → frames + timestamped transcript).
  • 💻 Real dev work — git, build, test, edit code, worktrees, tickets. Can edit its own source and restart itself.
  • 🧵 Multiple agents — spawn sessions per folder/project, each its own Telegram topic.
  • 🎫 Work your YouTrack queue on its own (opt-in, dry-run by default) — scans the tickets assigned to you, gives each one its own git worktree, branch (am/XT-18778, from a template you edit) and Claude session, runs your repo's build and tests itself before believing the work is done, then pushes and opens a draft merge request against the release branch from the ticket's Fixed in Version, updates the ticket, and notifies you. When QA sends a ticket back it resumes the same session, on the same branch and merge request. Approve the plan and the push from Telegram or from the task board in the window.
  • ⏰ Cron-style scheduled tasks.
  • 🧠 Memory — persistent facts (!remember) plus continuous learning: with Claude.ContinuousLearning=true (default), each session reads memory/learnings.md at task start and appends new learnings after tasks — the file Claude grows on its own, separate from user-set memory.
  • 🔒 Locked to you — allowlisted Telegram user IDs only, fails closed if unset; known secrets scrubbed from replies.
  • 🪟 Set-and-forget — runs at login, tray icon, auto-restart on crash.

How it works

Telegram message ──► Threadwright (tray app) ──► Claude Code session ──► your PC / browser / code
        ▲                                                │
        └──────────── formatted reply, screenshots ──────┘

Claude acts on the machine through MCP tool servers — cua-driver and machine-control (desktop) and Playwright (browser).

Requirements

  • Windows 11 + .NET 10 SDK
  • Claude Code CLI on PATH
  • A Telegram bot (@BotFather) + a forum-enabled supergroup (Topics ON)
  • (optional) Node.js/npx for the browser agent. Voice works out of the box (model auto-downloads).
  • (optional) cua-driver for background computer-use (drives the desktop without stealing focus). Install per-user (no admin) via the trycua/cua installer; the bridge auto-detects %LOCALAPPDATA%\Programs\Cua\... or set the path in Settings. Absent → the built-in machine-control server is used instead.

Quick start

  1. Get your Telegram user ID from @userinfobot.

  2. Create appsettings.local.json in repo root (gitignored):

    {
      "Telegram": {
        "BotToken": "123456:ABC...",
        "ChatId": -1001234567890,
        "AllowedUserIds": [ 827464027 ]
      },
      "Claude": { "PermissionMode": "bypassPermissions" }
    }
    • BotToken — from BotFather.
    • ChatId — your forum group's id (negative); add bot, post a message, then check https://api.telegram.org/bot<TOKEN>/getUpdates → chat.id.
    • AllowedUserIds — empty = bot ignores everyone (fails closed). Always set this.
  3. Run: dotnet run -c Release --project src/Threadwright (from repo root). Message the group's General topic to talk to the main session.

  4. Run at login (optional): dotnet run -c Release --project src/Threadwright -- install (drops Startup shortcut → supervisor.ps1, rebuilds+relaunches on restart requests).

Packaged installer

For a target machine with no SDK, build a self-contained Windows installer.

Build machine needs: .NET 10 SDK, git, Inno Setup 6 (ISCC.exe on PATH / Program Files / %LOCALAPPDATA%\Programs\Inno Setup 6).

pwsh installer/build-installer.ps1

Publishes app + MCP server self-contained (win-x64) into installer/stage/, stages config/assets, runs ISCC.exe → installer/output/Threadwright-Setup-<version>.exe. Close any running Threadwright/MachineControlMcp.exe first (file-lock).

CI: .github/workflows/release.yml builds + publishes a GitHub Release (v1.0.<commit-count>) with the installer attached, on every push to main.

Installed build: per-user install (%LOCALAPPDATA%\Threadwright, no admin), optional login/desktop shortcuts, proper uninstall entry, dark wizard. First launch with no config opens Settings automatically. Trade-off: no SDK/source → self-edit+rebuild and supervisor.ps1 don't apply; /restart still works via Launch.ps1. Claude CLI (and Node for browser) still required on target.

Versioning

1.0.<git-commit-count> — every commit bumps it (Directory.Build.props). Shown in window title, tray tooltip, startup log, --version.


Talking to it (Telegram)

  • Text / voice / photo / video / file → handed to Claude as a turn.

  • Claude /slash commands pass straight through.

  • ::keys → answer a blocked interactive dialog (::enter, ::y, ::1, …).

  • Bridge ! commands:

    Command Does
    !new <name> <dir> [prompt] spawn a new agent session (own topic)
    !sessions / !status / !cost list sessions / state / token usage
    !model <opus|sonnet|haiku> switch this session's model (keeps context)
    !remember <text> save a fact to persistent memory
    !git / !build / !test git, scoped build/test
    !worktree <branch> / !ticket <id> / !yt <id> worktree session / YouTrack ticket
    !screenshot [n] / !screenrecord <n> <secs> capture desktop
    !ps <list|kill|stats> process operations
    !repo / !cd <name|dir> repo registry / switch session folder
    !watch <project> [id] list a project's Claude sessions, or read-only mirror one (incl. IDE sessions) to its own topic
    !restart / !stop / !exit restart host / interrupt turn / close session
    !restartsys reboot machine
    !help list all commands
  • Ticket-agent ! commands (see Working your YouTrack queue):

    Command Does
    !agent <on|off|scan|status> start/stop scanning, scan now, status
    !tasks / !task <id> the queue / one ticket in detail
    !approve <id> [push] approve the plan, or the push
    !reject <id> <why> send the plan back with feedback
    !target <id> <branch> answer an unresolved merge target
    !pause / !unpause / !drop <id> pause, resume, or abandon a ticket

Working your YouTrack queue (opt-in)

Off by default. Switch it on in Settings → YouTrack ticket agent: paste your personal YouTrack token (there is a Test connection button), map each project to a repository, and leave Dry run on for the first tickets — it then does everything except push, open merge requests and write to YouTrack, and reports exactly what it would have done.

What each ticket gets: its own worktree and branch (template {user}/{ticket} → am/XT-18778), its own Telegram topic and chat, a plan you approve, and a merge request into the branch from the ticket's Fixed in Version (desktop/{version}; when that branch does not exist yet you choose what happens — use the default branch, ask you, or block). The host runs your repo's build and test commands and feeds failures back to the session, so "it built" is never taken on trust, and it refuses to push a protected branch or a change that touches a forbidden path.

Prefer no interruptions? Tick Work autonomously and it runs plan → implement → verify → push → merge request without stopping for approval; dry run and the push guards still apply.

In-app window & settings

  • Tray icon → Show / Settings… / Restart / Exit.
  • Task board — left rail lists every ticket and session with its phase; the header strip has Approve / Reject / Pause / Abort and links to the ticket and the merge request.
  • Settings — startup toggle, permission mode, Claude model, Claude CLI command (e.g. claude-me for a different subscription), bot token/chat id/allowed users, video limits, persistent memory, continuous-learning toggle, message verbosity (how much tool activity is relayed — Quiet/Normal/Verbose), scheduled tasks, extra dev MCP servers, and the whole YouTrack ticket agent (token, query, branch/target templates with a live preview, project→repository map, merge-request options). Saving restarts everything.
  • Open Terminal — hands-on claude terminal in the session's folder, tools pre-loaded.

Scheduled tasks (cron)

Settings → Scheduled tasks (or schedules.txt), one job per line:

name | spec | target | prompt
  • spec — daily HH:mm or every 30m / every 2h / every 1d.
  • target — session name (main/spawned) or spawn:C:/path.
morning | daily 09:00 | main                  | Summarize repo status and any failing tests.
nightly | daily 02:00 | spawn:C:/Projects/app | Run the test suite and report results.

Missed runs (app off during the scheduled minute) are not replayed.

Permissions & safety

Claude.PermissionMode in appsettings.local.json:

  • acceptEdits — auto-approves file edits only; other tools need a Claude.AllowedTools whitelist.
  • bypassPermissions (default) — Claude runs any command unattended. Only safe behind AllowedUserIds; the app auto-accepts the one-time consent screen.

This gives an AI agent full, unattended control of your PC. Run only on a machine you own, lock AllowedUserIds to yourself, and remember code/secrets transit Telegram (a third party). ProtectSecrets (default on) scrubs known secrets from outbound messages — defence-in-depth, not a sandbox.


Under the hood

.NET 10 WPF tray app (no console). Drives Claude Code via interactive PTY (ConPTY), reads output from its JSONL transcript, relays to Telegram. MCP tool servers:

  • cua-driver (trycua/cua, MIT) — primary desktop driver: background computer-use over UI-Automation patterns (no focus steal). External per-user install, invoked via config (not redistributed); path is Settings-editable.
  • machine-control (src/MCP/MachineControl/, bundled) — fallback desktop server: UI Automation, Windows OCR, Set-of-Mark annotation, vision screenshot/click, batched run_actions. Used whenever cua-driver is unavailable or can't act.
  • playwright (@playwright/mcp) — DOM-level browser control, snapshot → act on refs, multi-tab.

All auto-load every session, no approval prompt. Voice via Whisper.net/Concentus (no ffmpeg); video framing uses ffmpeg (auto-downloaded on first use).

dotnet build -c Release Threadwright.slnx               # whole solution
dotnet run -c Release --project src/Threadwright         # run tray app
dotnet test tests/Threadwright.Tests                    # E2E tests (PowerShell-host fallback)

Logs: logs/agent.log (app), logs/pty.log (raw Claude TUI stream). Deeper architecture map: CLAUDE.md.

Contributing / security

MIT licensed — see LICENSE. PRs welcome, see CONTRIBUTING.md. Read SECURITY.md before running this — full unattended machine control.

About

Self-hosted AI agent that runs your PC from Telegram — desktop (background computer-use via cua-driver, with UI-Automation/OCR fallback), browser, voice, and code, powered by Claude Code.

Topics

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Contributors

Languages