Skip to content

yaways/feishu-ksgc-bridge

 
 

Repository files navigation

lark-ksgc-bridge

A lightweight bot that bridges Feishu / Lark messenger with your local KSGC CLI. Run one command, scan a QR code to bind a Lark app, and talk to KSGC from chat — read screenshots, edit code, anything you'd do at the terminal.

中文 README

What it does

  • Forwards Feishu / Lark messages (DM directly, or @bot in a group) to your local ksgc CLI, running in a working directory you control.
  • Streaming card: KSGC's text and tool calls update on a single Lark card in real time — no waiting for the final reply.
  • Per-chat sessions: each chat keeps its own KSGC session, so conversations resume where they left off.
  • Preempt + batch: a new message interrupts the running run; rapid-fire messages get coalesced into one request.
  • Multiple workspaces: /ws switches between named project directories, with sessions tracked per workspace.
  • Images and files: send them to the bot directly — KSGC reads the locally downloaded paths.
  • Interactive cards: /help, /ws list, /status return cards with buttons you can click.

Prerequisites

Install

npm i -g lark-ksgc-bridge
# or
pnpm add -g lark-ksgc-bridge

First run

lark-ksgc-bridge run

The first run detects there's no app configured and opens a QR-code wizard:

  1. A QR code renders in your terminal.
  2. Scan it with the Feishu / Lark app.
  3. Pick or create a PersonalAgent app.
  4. Credentials are written to ~/.lark-channel/config.json.

Commands

Host CLI

Process-level (run the bridge directly in your shell):

lark-ksgc-bridge run [-c <config>]     Run the bot in the foreground
lark-ksgc-bridge ps                    List all running bridge processes on this machine
lark-ksgc-bridge kill <id|#>           Kill a bridge process (SIGTERM, SIGKILL after 2s)
lark-ksgc-bridge --help                List all commands

Service-level (run the bridge as a background OS-managed daemon):

⚠️ Install globally before using service-level commands. The daemon's launchd plist / systemd unit / Windows task hard-codes the path to the bridge CLI; if you invoke via npx lark-ksgc-bridge start, that path lives in npm's temp cache (~/.npm/_npx/<hash>/...) and will be garbage-collected — your daemon stops working as soon as the cache is cleaned. Use npm install -g lark-ksgc-bridge first, then run lark-ksgc-bridge start. bridge run is fine via npx (one-shot process).

lark-ksgc-bridge start                 Install (if needed) and start the daemon
lark-ksgc-bridge stop                  Stop the daemon and disable autostart
lark-ksgc-bridge restart               Restart the daemon in place
lark-ksgc-bridge status                Show daemon status (pid, log paths, last exit)
lark-ksgc-bridge unregister            Remove the service definition and stop

The daemon auto-restarts on crash and on user login. Platform mapping:

  • macOSlaunchd user agent at ~/Library/LaunchAgents/ai.lark-ksgc-bridge.bot.plist
  • Linuxsystemd user unit at ~/.config/systemd/user/lark-ksgc-bridge.bot.service. For the daemon to survive logout, run loginctl enable-linger $USER once.
  • Windows → Task Scheduler task LarkKsgcBridge.Bot, triggered ONLOGON. Launcher script at ~/.lark-channel/daemon-launcher.cmd.

Daemon logs go to ~/.lark-channel/logs/daemon-stdout.log and daemon-stderr.log alongside the bridge's per-day structured logs.

When the same app is started multiple times, Lark's open platform routes events to one of the live WebSocket connections at random. run detects existing processes for the same app and (in a TTY) prompts: [c]ontinue / [k]ill old / [a]bort. In non-TTY mode it warns and continues.

Slash commands inside Feishu / Lark

Command Effect
/new, /reset Clear the current chat's session
/cd <path> Switch working directory (resets session)
/ws list List named workspaces (card + buttons)
/ws save <name> Save current cwd as a named workspace
/ws use <name> Switch to a named workspace
/ws remove <name> Delete a named workspace
/status Current cwd / session / agent (card + buttons)
/config Adjust preferences (reply style, tool-call display, ...)
/stop Stop the run in progress (also the button on the card)
/timeout [N|off|default] Idle-watchdog (minutes) for the current session. /config sets the global default. See FAQ below.
/ps List all start processes on this host, marking the one replying
/exit <id|#> Stop a start process (your own → graceful; another's → SIGTERM)
/reconnect Force a WebSocket reconnect (use when the bot stops responding after a network blip)
/doctor [description] Feed recent logs and your description back to KSGC for self-diagnosis
/help Help card
Any other /xxx Forwarded verbatim to KSGC

Reply policy: in a DM, the bot replies to anything. In a group (including topic groups), the bot only replies when @-mentioned (default since 0.1.22); unmentioned messages are ignored. @all is never answered. Cloud-doc comments must mention the bot. To restore the older "always answer in groups" behaviour: /config → "Require @bot in groups" → No.

Data directories

Path Content
~/.lark-channel/config.json App credentials (App ID / Secret), mode 600
~/.lark-channel/sessions.json KSGC session id + cwd per chat / topic (+ optional /timeout override)
~/.lark-channel/workspaces.json Named-workspace map
~/.lark-channel/processes.json Process registry for live start instances (used by ps/stop); dead PIDs are auto-pruned
~/.lark-channel/media/<chatId>/ Downloaded images / files, cleaned up after 24h
~/.lark-channel/logs/YYYY-MM-DD.log Structured run logs (JSONL), rotated daily; older than 7 days are pruned at startup (LARK_KSGC_LOG_DAYS env var overrides). /doctor reads these.

Upgrading from before 0.1.11? Run lark-ksgc-bridge migrate once — it moves anything under ~/.config/lark-channel-bridge/ and ~/.cache/lark-channel-bridge/ to the new location and upgrades config.json to the new schema.

Access control (optional)

Out of the box the bot is open: anyone who can find it can DM it, any group member can @-mention it to trigger a run, and commands like /account or /cd are usable by all. That's fine for personal use — but for a shared team setup, or anywhere you don't want strangers calling /cd /, you can tighten three allowlists by sending /config inside Feishu.

Common scenarios

Just me

In the /config form:

  • Allowed users: your own open_id
  • Leave the other two blank

Messages from anyone else are silently dropped — no denial reply, since that would just confirm the bot exists to outsiders.

A small team

  • Allowed users: comma-separated open_ids of team members
  • Other two blank

Bot only responds in specific work groups

DMs are unaffected; only listed groups trigger responses:

  • Allowed chats: comma-separated chat_ids of the groups
  • DMs are always exempt from this list — so you can always DM the bot to change config later.

Anyone can chat with the bot, but only I can change settings

  • Admins: your own open_id
  • Other two blank

Others running /account, /config, /exit, /reconnect, /doctor, /cd, or /ws get a ❌ 此命令仅管理员可用 reply. Normal conversation (asking the bot to do things) is unaffected.

Lock everything down

Fill all three. The /config form catches common mistakes — e.g. if your admin list doesn't include yourself, or your chat allowlist doesn't include the chat you're submitting from, the submit is rejected with a message explaining why, so you can't accidentally lock yourself out.

Finding open_id and chat_id

Easiest path: have the target user send the bot a message (or @-mention it in the target group), then in your terminal:

grep '"event":"enter"' ~/.lark-channel/logs/$(date +%Y-%m-%d).log | tail -5

Every line carries chatId (group or DM id) and senderId (the user's open_id). Copy them from there.

The Feishu open-platform "Get user info" API also works but needs the contact:user scope, which is overkill if you just need a couple of IDs.

Worth knowing

  • Changes take effect on the next message — no restart needed.
  • An empty field means unrestricted, not "nobody allowed".
  • To revert a restricted list back to fully open, clear that field in /config and submit.
  • DMs are deliberately exempt from the chat allowlist — meaning if you ever accidentally restrict the bot out of every group, DM the bot and send /config to recover.

Advanced: editing the config file directly

The /config form writes to ~/.lark-channel/config.json under preferences.access:

{
  "preferences": {
    "access": {
      "allowedUsers": ["ou_xxxxxxxxxxxxx"],
      "allowedChats": ["oc_xxxxxxxxxxxxx"],
      "admins":       ["ou_xxxxxxxxxxxxx"]
    }
  }
}

After a manual edit, restart the bridge or send /reconnect from any allowed chat to pick up the changes. The form is usually faster; direct edits make sense mostly for deployment scripts where you want to pre-seed access policy.

FAQ

The bot stays silent / KSGC never replies. Usually the ksgc CLI itself is not logged in, or the session points to a cwd that no longer exists. Send /status to inspect; /new to start a fresh session.

KSGC subprocess looks frozen (card stuck on the last frame). Since 0.1.20 there's an idle watchdog: if KSGC emits nothing for N minutes the process is killed and the card is annotated ⏱ N min no response, auto-terminated. Disabled by default. Enable with /config (global, in minutes), or /timeout 10 to set it on the current session; /timeout off disables for the session; /timeout default clears the session override.

KSGC says it can't see the image I sent. Upgrade to the latest version — releases before 0.1.0 had a filename-dedup bug.

License

MIT

About

Bot that bridges Feishu/Lark messenger with a local KSGC CLI — streaming cards, per-chat sessions, multiple workspaces

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages

  • TypeScript 100.0%