JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 18
  • Score
    100M100P100Q91725F
  • License Apache-2.0

Hands off your desk, hand off control to your phone. Monitor and control AI coding assistants from anywhere.

Package Exports

  • handsoff
  • handsoff/dist/cli/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (handsoff) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

Handsoff

npm version npm beta License Node.js

Hands off your desk, hand off control to your phone.

Leave your desk, not your code.

Handsoff is a local gateway that bridges AI programming assistants (like Claude Code) with messaging platforms (like Telegram, Feishu). It captures agent events in real-time and forwards them to your phone, letting you monitor and control your AI assistant from anywhere.


The Problem

You're running Claude Code on your workstation. It asks for permission to execute a tool. You're away from your desk—maybe grabbing coffee, in a meeting, or simply stepping out. The session sits there waiting. Time ticks away.

The Solution

Handsoff keeps you connected to your coding sessions wherever you are:

  • Monitor — Get notified when Claude starts or finishes tasks
  • Control — Approve or deny tool execution requests right from your phone
  • Stay informed — Receive execution summaries with token usage and results

No more tethering yourself to your desk. Your code doesn't stop when you step away.


Install globally via npm or pnpm:

npm install -g handsoff

Or run without installing:

npx handsoff init

Quick start (TL;DR)

# 1. Configure (interactive wizard)
handsoff init

# 2. Start the gateway daemon
handsoff gateway start

# 3. Start using Codex from your bound chat channel
# Example: send "/codex explain the latest failing test"

Done. Codex requests, permission prompts, and task completions will now arrive on your connected channels.


How it works

Claude Code + Telegram integration

The core workflow bridges Claude Code with Telegram:

  1. Session Monitoring — Handsoff listens for Claude Code session start/end events and notifies you on Telegram
  2. Permission Control — When Claude requests to execute a tool, you receive a permission prompt on Telegram with Allow/Deny buttons
  3. Real-time Decisions — Click the button in Telegram to grant or deny the tool execution
  4. Task Completion — Receive final notifications when tasks complete, including execution duration, token usage, and results

Claude + Telegram workflow    Permission request and task completion on Telegram


How it works

Data flow

┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│  Claude Code    │     │   Telegram /    │     │   Web / Mobile  │
│  (agent)        │     │   Feishu        │     │   (-dashboard)  │
└────────┬────────┘     └────────▲────────┘     └────────▲────────┘
         │                       │                       │
         │ hooks                 │ push                  │ ws / http
         │                       │                       │
         v                       │                       │
┌─────────────────┐              │                       │
│  ClaudeHook     │              │                       │
│  Adapter        │              │                       │
└────────┬────────┘              │                       │
         │                       │                       │
         │ event                 │                       │
         │                       │                       │
         v                       │                       │
┌─────────────────┐     ┌────────┴───────────────────────┴────────┐
│   Handsoff      │     │              Gateway                    │
│   Gateway       │     │  ┌─────────┐  ┌─────────────────────┐  │
│                 │     │  │EventBus │  │ InteractionService  │  │
│  ┌───────────┐  │     │  │Session  │  │ NotificationHandler │  │
│  │ HTTP/WS   │  │◄────┼──│Manager  │  │ EventPublisher      │  │
│  │  Server   │  │     │  └────┬────┘  └──────────┬──────────┘  │
│  └───────────┘  │     │       │                   │             │
└─────────────────┘     └───────┼───────────────────┼─────────────┘
                                │                   │
                                │ subscribe         │ publish
                                │                   │
                                v                   v
                       ┌─────────────────┐ ┌─────────────────┐
                       │ ChannelManager  │ │   Dashboard /   │
                       │  (Telegram/     │ │     Logger      │
                       │   Feishu)       │ └─────────────────┘
                       └─────────────────┘
  1. Agent hooks — Claude Code fires lifecycle hooks (SessionStart, PermissionRequest, Stop, etc.)
  2. Gateway ingestsClaudeHookAdapter normalizes events and feeds them into the Gateway
  3. Gateway routesEventBus routes events to the right handler:
    • Session events → NotificationHandler → push to channels
    • Permission requests → InteractionService → wait for user response
    • Commands from channels → Command Handler → control the agent
  4. Channels notifyChannelManager forwards messages to Telegram / Feishu with interactive buttons
  5. Web dashboard — HTTP + WebSocket server exposes live sessions and event history

Request/response cycle

A typical permission-request flow looks like this:

Claude needs to run Bash
        │
        ▼
Gateway receives PermissionRequest
        │
        ▼
NotificationHandler sends card to Telegram/Feishu
        │
        ▼
User clicks Allow / Deny on phone
        │
        ▼
ChannelManager posts interaction response
        │
        ▼
InteractionService resolves the pending request
        │
        ▼
Claude continues with the result

Supported platforms

  • CLI agent support: claude, codex
  • Chat channel support: Telegram, Feishu, App

Main commands

  • handsoff init — initialize or update ~/.handsoff/config.toml
  • handsoff gateway start — start or restart the gateway daemon
  • handsoff gateway stop — stop the gateway daemon
  • handsoff gateway restart — restart the gateway daemon
  • handsoff gateway status — show gateway health and active sessions
  • handsoff attach <agent-type> — attach a supported agent to the gateway
  • handsoff status — view CLI status
  • handsoff logs — inspect logs
  • handsoff stop — stop the daemon

Configuration

Most configuration is handled by handsoff init interactive wizard, which guides you through:

  1. Setting up your Claude Code hook server port
  2. Enabling Codex agent integration
  3. Configuring Telegram bot credentials
  4. Testing channel connectivity

For manual setup or advanced options, edit ~/.handsoff/config.toml. Key sections:

General settings:

  • default_agent — default agent to use (currently claude)
  • hook_server_port — local port for receiving agent hooks (default 9876)
  • log_level — logging verbosity (debug, info, warn, error)

Telegram channel:

  • bot_token — your Telegram bot token from BotFather
  • allowed_users — list of Telegram user IDs allowed to interact with the bot (e.g., [123456789, 987654321])
  • notify_types — which event types to forward (permission_request, question_request, finished, session_start, error)

App channel:

  • enabled — whether to start the App channel WebSocket server with the gateway
  • channel_id — unique identifier for this app client (e.g., app:desktop-001)
  • auth_token — token used to authenticate app clients
  • heartbeat_interval_ms — optional heartbeat interval in milliseconds (default: 30000)
  • notify_types — which event types to forward (*, permission_request, question_request, finished, session_start, error)

Connect to: ws://localhost:<port>/ws/channels/app

Claude agent:

  • adapter — integration method (always hooks)
  • binary — Claude Code binary name
  • permission_mode — how to handle tool permissions

Codex agent:

  • enabled — whether to start the Codex adapter with the gateway
  • command — command used to launch codex app-server
  • work_dir — default working directory for chat-triggered Codex sessions
  • model — default Codex model for new sessions
  • approval_policy — default approval policy passed to Codex

Example ~/.handsoff/config.toml:

[general]
default_agent = "claude"
log_level = "info"
hook_server_port = 9876

[channel.telegram]
enabled = true
bot_token = "YOUR_BOT_TOKEN"
allowed_users = ["123456789"]
notify_types = ["permission_request", "question_request", "finished", "session_start", "error"]

[channels.app]
enabled = false
channel_id = "app:desktop-001"
auth_token = "change-me"
notify_types = ["*"]
heartbeat_interval_ms = 30000

[agent.claude]
adapter = "hooks"
binary = "claude"
work_dir = ""
model = ""
permission_mode = ""

[agent.codex]
enabled = true
command = ["codex", "app-server", "--listen", "stdio://"]
work_dir = ""
model = ""
approval_policy = ""

Using Codex from Telegram / Feishu

After the gateway is running and the channel is bound to codex, send one of these commands in chat:

  • /codex <prompt> — run a Codex task in the current chat
  • /codex status — inspect the active Codex session for the current chat
  • /codex stop — stop the active Codex session
  • /codex help — show the Codex command help

From source (development)

Requires Node.js >= 20.

# Clone the repo
git clone https://github.com/tapclaw/handsoff.git
cd handsoff

# Install dependencies
pnpm install

# Development mode
pnpm run dev -- init

# Run tests
pnpm test

# Build for production
pnpm run build

Future plan

  • Add more agent adapters
  • Add more channel adapters

Notes

  • Use config.example.toml as the starting point.
  • Runtime files are stored in ~/.handsoff.