PhoneWork

Feishu bot that lets users control Claude Code CLI from their phone.

Architecture

┌─────────────┐    WebSocket     ┌──────────────┐    LangChain     ┌─────────────┐
│   Feishu    │ ◄──────────────► │   FastAPI    │ ◄──────────────► │  LLM API    │
│   (client)  │                  │   (server)   │                  │ (ZhipuAI)   │
└─────────────┘                  └──────────────┘                  └─────────────┘
                                        │
                                        ▼
                                 ┌─────────────┐
                                 │ Claude Code │
                                 │  (headless) │
                                 └─────────────┘

Components:

Module Purpose
main.py FastAPI entry point, starts WebSocket client + session manager
bot/handler.py Receives Feishu events via long-connection WebSocket
bot/feishu.py Sends text/file/card replies back to Feishu
bot/commands.py Slash command handler (/new, /list, /close, /switch, /help)
orchestrator/agent.py LangChain agent with per-user history + passthrough mode
orchestrator/tools.py Tools: create_conversation, send_to_conversation, list_conversations, close_conversation
agent/manager.py Session registry with persistence and idle timeout reaper
agent/pty_process.py Runs claude -p headlessly, manages session continuity via --resume
agent/audit.py Audit log of all interactions

Flow: User message → Feishu WebSocket → Handler → (passthrough or LLM) → Session Manager → claude -p → Response back to Feishu


Feishu App Setup

1. Create App

Go to Feishu Open PlatformCreate AppCustom App.

Record the App ID and App Secret from the Credentials page.

2. Enable Bot Capability

App FeaturesBot → Enable.

3. Subscribe to Events (Long-connection mode)

Event SubscriptionsRequest URL tab:

  • Switch to "Use long connection to receive events" (长连接接收事件)
  • No public URL required

Add event subscription:

Event Event Type
Receive messages im.message.receive_v1

4. Required Permissions (API Scopes)

Go to Permissions & Scopes and add the following:

Permission API Scope Used For
Read private messages sent to the bot im:message (read) Receiving user messages via WebSocket
Send messages im:message:send_as_bot Sending text replies
Upload files im:resource Uploading files before sending
Send messages in private chats im:message (write) Sending file messages

Minimal scope list to request:

im:message
im:message:send_as_bot
im:resource

Note: im:resource covers both file upload (im.v1.file.create) and sending file-type messages. Without it, send_file() will fail with a permission error.

5. Publish App

After adding all permissions:

  1. Version Management → Create a new version → Submit for review (or self-publish if in the same org)
  2. Install the app to your workspace

Configuration

Copy and fill in credentials:

cp keyring.example.yaml keyring.yaml

keyring.yaml fields:

FEISHU_APP_ID: cli_xxxxxxxxxxxxxxxx
FEISHU_APP_SECRET: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

OPENAI_BASE_URL: https://open.bigmodel.cn/api/paas/v4/
OPENAI_API_KEY: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
OPENAI_MODEL: glm-4.7

# Root directory for all project sessions (absolute path)
WORKING_DIR: C:/Users/yourname/projects

# Allowlist of Feishu open_ids that may use the bot.
# Leave empty to allow all users.
ALLOWED_OPEN_IDS:
  - ou_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Installation & Run

Requirements: Python 3.11+, Claude Code CLI installed and authenticated.

python -m venv .venv
source .venv/Scripts/activate   # Windows
# source .venv/bin/activate     # Linux/macOS

pip install -r requirements.txt
python main.py

Server listens on http://0.0.0.0:8000.

Health check: GET /health Claude smoke test: GET /health/claude Active sessions: GET /sessions


Bot Commands

Command Description
/new <dir> [msg] Create a new Claude Code session in <dir>
/new <dir> [msg] --timeout N Create with custom CC timeout (seconds)
/new <dir> [msg] --idle N Create with custom idle timeout (seconds)
/list List your active sessions
/switch <n> Switch active session to number <n> from /list
/close [n] Close active session (or session <n>)
/help Show command reference

Any message without a / prefix is forwarded directly to the active Claude Code session.


Security

  • Allowlist (ALLOWED_OPEN_IDS): only listed open_ids can use the bot. Empty = open to all.
  • Path sandbox: all session directories must be under WORKING_DIR; path traversal is blocked.
  • Session ownership: sessions are tied to the creating user; other users cannot send to them.
  • Audit log: all prompts and responses are written to agent/audit.log.
Description
No description provided
Readme 685 KiB
Languages
Python 100%