ShiXiangYu2 / dsh-feishu-remote

Listed

Control your DeepSeek Harness agent from Feishu/Lark: DM a task, get results back, push notifications. Powered by lark-cli.

mainTool View source

Installation

npx -y @deepseek-ai/dsh plugin --profile web add github:ShiXiangYu2/dsh-feishu-remote

This installation command is an unverified starting point generated from the GitHub repository address.

README

Maintainer-authored documentation snapshot.

View on GitHub ↗
Commit 0f8a1e0Synced Aug 18, 2026

📱 DSH Feishu Remote

Control your DeepSeek Harness agent from Feishu / Lark on your phone. Send a task by DM — get the result back in chat. Fully working closed loop.

dsh-plugin DeepSeek Harness License: MIT

✨ What it does

  • 📨 Feishu → Agent → Feishu: DM your bot a task (e.g. 2+3等于几?), a DSH agent runs it with your configured LLM, and the answer comes back to the chat.
  • 🖼️ Image understanding: send a screenshot or photo — it's downloaded and analyzed by a vision model (Qwen3-VL), then the agent replies with what it sees.
  • 🎨 Image generation round-trip: the agent can generate an image (generate_image), download it locally (feishu_download), and send the actual image back to your Feishu chat (feishu_send_image) — not just a link.
  • 📤 Agent → Feishu: the model gets feishu_send / feishu_send_image / feishu_download tools to push results, files, and generated images to any user or chat.
  • 🧹 Retention cleanup: downloaded images are kept for 7 days (configurable via FEISHU_IMG_RETENTION_DAYS), then auto-deleted — no unbounded disk growth.
  • 🤖 Long connection: uses lark-cli's WebSocket event bus — no public webhook server needed, works on localhost/LAN/private servers.
  • 🔒 Secure: reuses lark-cli's OS-keychain credential storage and permission system; event listener runs unsandboxed by design (it must hold the WebSocket).

🚀 Install

0. Prerequisites

  1. A Feishu/Lark self-built app with:

    • Bot ability enabled
    • Event subscription im.message.receive_v1 (long-connection mode)
    • Permissions: im:message, im:message:send_as_bot, im:message.p2p_msg:readonly, im:chat:read, im:resource
    • A published version
    • (Setup in the Feishu developer console — the CLI can enable the bot ability via API, but events/permissions need the console.)
  2. lark-cli installed & authenticated once:

npm i -g @larksuite/cli
lark-cli config init            # paste your App ID / Secret
lark-cli auth login --recommend # scan QR to authorize

1. Install the plugin

dsh plugin --profile demo add github:ShiXiangYu2/dsh-feishu-remote

The bundle contains two pieces:

  • index.js — the Cordis plugin: registers the feishu_send model tool and attempts an in-process event listener.
  • feishu-resident.mjs — the recommended resident launcher: boots the web profile and runs the long-connection event loop in a detached process (see below).

2. Configure the model

The DSH profile must have a working LLM route (e.g. DeepSeek via SiliconFlow):

# profile cordis.patch.yml
- id: llm-deepseek
  config:
    apiKeyEnv: SILICONFLOW_API_KEY
    baseURL: https://api.siliconflow.cn/v1
    thinking: disabled
    reasoningEffort: off
    models:
      - id: deepseek-ai/DeepSeek-V3.2
        name: DeepSeek-V3.2 (via SiliconFlow)
        contextWindow: 65536
        maxTokens: 8192

- id: agent-default-model
  config:
    provider: deepseek-official
    model: deepseek-ai/DeepSeek-V3.2

The closed loop must live in a long-lived process. Use the included resident launcher:

# Adjust the absolute paths in feishu-resident.mjs (LARK_HOME, CLI) to your setup.
DSH_HOME=~/.dsh SILICONFLOW_API_KEY=sk-... \
  node --import tsx/esm feishu-resident.mjs

It boots the web profile, spawns lark-cli event consume as a detached process (holding stdin open via a tail -f /dev/null pipe so the listener never exits on EOF), and for each inbound DM: ack → create agent → run task → extract final text → reply.

4. Use it

DM your Feishu bot anything, e.g. 帮我总结一下 ~/projects 的 README — the agent runs and the result comes back to the chat.

🛠 Tools

ToolDescription
feishu_sendModel-facing: send a message to a Feishu user (ou_) or chat (oc_).
feishu_send_imageModel-facing: send a local image file to a Feishu user or chat.
feishu_downloadModel-facing: download a URL to a local file (so generated images can be sent via feishu_send_image).

🔌 How it works

Feishu DM ──► lark-cli event consume (WebSocket long-connection, detached process)
                  │  NDJSON event on stdout
                  ▼
        feishu-resident.mjs (long-lived process)
                  │  image? → download (messages-resources-download)
                  │          → vision describe (Qwen3-VL via SiliconFlow)
                  │  agents.create + followup(task) + whenIdle()
                  ▼
        final assistant text (ev.data.message.content)
                  │  lark-cli im +messages-send
                  ▼
        Feishu chat reply

Image handling

  • The event content for an image arrives as [Image: img_v3_xxx].
  • The resident detects that pattern, downloads the resource via lark-cli im +messages-resources-download (using the event's real message_id
    • the image_key), then asks a SiliconFlow vision model (Qwen/Qwen3-VL-8B-Instruct, overridable with FEISHU_VISION_MODEL) to describe the picture.
  • The description is prepended to the user's message and fed to the DSH agent, so the agent can reason about the image and reply in Feishu.
  • Downloaded images land in the IMG_DIR (/root/dsh /feishu-images by default; the download command requires a relative --output path, so the resident cds into that directory first).

⚠️ Notes

  • Why a resident process? DSH's shell service binds background processes to the calling plugin fiber; a listener started inside a plugin's apply() is killed when the fiber settles. The resident launcher owns the listener in its own process, so it survives.
  • Text extraction: the final answer is read from the session log's assistant/message events (ev.data.message.content, mirroring the official headless summarize()).
  • Long tasks: replies are truncated to the final text block; very long runs may exceed Feishu message limits.
  • lark-cli event output streams as NDJSON on stdout (stderr carries [event] log lines) — both are parsed.

📄 License

MIT

Project files and signals

Shown items are public repository signals detected in the directory snapshot.

DocumentationDetected

Repository information

Language
JavaScript
License
Not reported
Last updated
Aug 16, 2026, 10:34 AM

Install deliberately

Review source code, permissions, lifecycle hooks, dependencies and network access. Test untrusted plugins in an isolated environment.