[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-77761":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":9,"language":10,"languages":9,"totalLinesOfCode":9,"stars":11,"forks":12,"watchers":13,"openIssues":14,"contributorsCount":15,"subscribersCount":15,"size":15,"stars1d":15,"stars7d":15,"stars30d":16,"stars90d":15,"forks30d":15,"starsTrendScore":15,"compositeScore":17,"rankGlobal":9,"rankLanguage":9,"license":18,"archived":19,"fork":19,"defaultBranch":20,"hasWiki":21,"hasPages":19,"topics":22,"createdAt":9,"pushedAt":9,"updatedAt":23,"readmeContent":24,"aiSummary":25,"trendingCount":15,"starSnapshotCount":15,"syncStatus":26,"lastSyncTime":27,"discoverSource":28},77761,"feishu-claude-code-bridge","zarazhangrui\u002Ffeishu-claude-code-bridge","zarazhangrui","Bot that bridges Feishu\u002FLark messenger with a local Claude Code CLI — streaming cards, per-chat sessions, multiple workspaces",null,"TypeScript",806,113,4,33,0,780,10.17,"MIT License",false,"main",true,[],"2026-06-12 02:03:44","# lark-channel-bridge\n\nA lightweight bot that bridges Feishu \u002F Lark messenger with your local Claude Code CLI. Run one command, scan a QR code to bind a Lark app, and talk to Claude from chat — read screenshots, edit code, anything you'd do at the terminal.\n\n[中文 README](.\u002FREADME.zh.md)\n\n## What it does\n\n- Forwards Feishu \u002F Lark messages (DM directly, or `@bot` in a group) to your local `claude` CLI, running in a working directory you control.\n- **Streaming card**: Claude's text and tool calls update on a single Lark card in real time — no waiting for the final reply.\n- **Per-chat sessions**: each chat keeps its own Claude session, so conversations resume where they left off.\n- **Preempt + batch**: a new message interrupts the running run; rapid-fire messages get coalesced into one request.\n- **Multiple workspaces**: `\u002Fws` switches between named project directories, with sessions tracked per workspace.\n- **Images and files**: send them to the bot directly — Claude reads the locally downloaded paths.\n- **Interactive cards**: `\u002Fhelp`, `\u002Fws list`, `\u002Fstatus` return cards with buttons you can click.\n\n## Prerequisites\n\n- Node.js **>= 20**\n- `claude` CLI installed and logged in — see https:\u002F\u002Fdocs.anthropic.com\u002Fen\u002Fdocs\u002Fclaude-code\u002Fquickstart\n- A Lark \u002F Feishu **PersonalAgent** app (the QR-code wizard on first launch can create one for you).\n\n## Install\n\n```bash\nnpm i -g lark-channel-bridge\n# or\npnpm add -g lark-channel-bridge\n```\n\n## First run\n\n```bash\nlark-channel-bridge start\n```\n\nThe first run detects there's no app configured and **opens a QR-code wizard**:\n\n1. A QR code renders in your terminal.\n2. Scan it with the Feishu \u002F Lark app.\n3. Pick or create a PersonalAgent app.\n4. Credentials are written to `~\u002F.lark-channel\u002Fconfig.json`.\n\n## Commands\n\n### Host CLI\n\n```\nlark-channel-bridge start [-c \u003Cconfig>]   Start the bot\nlark-channel-bridge ps                    List all running start processes on this machine\nlark-channel-bridge stop \u003Cid|#>           Stop a start process (SIGTERM, SIGKILL after 2s)\nlark-channel-bridge --help                List all commands\n```\n\n> When the same app is started multiple times, Lark's open platform routes events to one of the live WebSocket connections at random. `start` detects existing processes for the same app and (in a TTY) prompts: `[c]ontinue \u002F [k]ill old \u002F [a]bort`. In non-TTY mode it warns and continues.\n\n### Slash commands inside Feishu \u002F Lark\n\n| Command | Effect |\n|---|---|\n| `\u002Fnew`, `\u002Freset` | Clear the current chat's session |\n| `\u002Fcd \u003Cpath>` | Switch working directory (resets session) |\n| `\u002Fws list` | List named workspaces (card + buttons) |\n| `\u002Fws save \u003Cname>` | Save current cwd as a named workspace |\n| `\u002Fws use \u003Cname>` | Switch to a named workspace |\n| `\u002Fws remove \u003Cname>` | Delete a named workspace |\n| `\u002Fstatus` | Current cwd \u002F session \u002F agent (card + buttons) |\n| `\u002Fconfig` | Adjust preferences (reply style, tool-call display, ...) |\n| `\u002Fstop` | Stop the run in progress (also the `⏹` button on the card) |\n| `\u002Ftimeout [N\\|off\\|default]` | Idle-watchdog (minutes) for the current session. `\u002Fconfig` sets the global default. See FAQ below. |\n| `\u002Fps` | List all `start` processes on this host, marking the one replying |\n| `\u002Fexit \u003Cid\\|#>` | Stop a `start` process (your own → graceful; another's → SIGTERM) |\n| `\u002Freconnect` | Force a WebSocket reconnect (use when the bot stops responding after a network blip) |\n| `\u002Fdoctor [description]` | Feed recent logs and your description back to Claude for self-diagnosis |\n| `\u002Fhelp` | Help card |\n| Any other `\u002Fxxx` | Forwarded verbatim to Claude |\n\n**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: `\u002Fconfig` → \"Require @bot in groups\" → No.\n\n## Data directories\n\n| Path | Content |\n|---|---|\n| `~\u002F.lark-channel\u002Fconfig.json` | App credentials (App ID \u002F Secret), mode 600 |\n| `~\u002F.lark-channel\u002Fsessions.json` | Claude session id + cwd per chat \u002F topic (+ optional `\u002Ftimeout` override) |\n| `~\u002F.lark-channel\u002Fworkspaces.json` | Named-workspace map |\n| `~\u002F.lark-channel\u002Fprocesses.json` | Process registry for live `start` instances (used by `ps`\u002F`stop`); dead PIDs are auto-pruned |\n| `~\u002F.lark-channel\u002Fmedia\u002F\u003CchatId>\u002F` | Downloaded images \u002F files, cleaned up after 24h |\n| `~\u002F.lark-channel\u002Flogs\u002FYYYY-MM-DD.log` | Structured run logs (JSONL), rotated daily; older than 7 days are pruned at startup (`LARK_CHANNEL_LOG_DAYS` env var overrides). `\u002Fdoctor` reads these. |\n\n> Upgrading from before 0.1.11? Run `lark-channel-bridge migrate` once — it moves anything under `~\u002F.config\u002Flark-channel-bridge\u002F` and `~\u002F.cache\u002Flark-channel-bridge\u002F` to the new location and upgrades `config.json` to the new schema.\n\n## Access control (optional)\n\nOut 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 `\u002Faccount` or `\u002Fcd` are usable by all. **That's fine for personal use** — but for a shared team setup, or anywhere you don't want strangers calling `\u002Fcd \u002F`, you can tighten three allowlists by sending `\u002Fconfig` inside Feishu.\n\n### Common scenarios\n\n**Just me**\n\nIn the `\u002Fconfig` form:\n- **Allowed users**: your own `open_id`\n- Leave the other two blank\n\nMessages from anyone else are silently dropped — no denial reply, since that would just confirm the bot exists to outsiders.\n\n**A small team**\n\n- **Allowed users**: comma-separated `open_id`s of team members\n- Other two blank\n\n**Bot only responds in specific work groups**\n\nDMs are unaffected; only listed groups trigger responses:\n- **Allowed chats**: comma-separated `chat_id`s of the groups\n- DMs are **always** exempt from this list — so you can always DM the bot to change config later.\n\n**Anyone can chat with the bot, but only I can change settings**\n\n- **Admins**: your own `open_id`\n- Other two blank\n\nOthers running `\u002Faccount`, `\u002Fconfig`, `\u002Fexit`, `\u002Freconnect`, `\u002Fdoctor`, `\u002Fcd`, or `\u002Fws` get a `❌ 此命令仅管理员可用` reply. Normal conversation (asking the bot to do things) is unaffected.\n\n**Lock everything down**\n\nFill all three. The `\u002Fconfig` 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.\n\n### Finding `open_id` and `chat_id`\n\nEasiest path: have the target user send the bot a message (or `@`-mention it in the target group), then in your terminal:\n\n```bash\ngrep '\"event\":\"enter\"' ~\u002F.lark-channel\u002Flogs\u002F$(date +%Y-%m-%d).log | tail -5\n```\n\nEvery line carries `chatId` (group or DM id) and `senderId` (the user's `open_id`). Copy them from there.\n\nThe 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.\n\n### Worth knowing\n\n- Changes take effect on the **next message** — no restart needed.\n- An empty field means **unrestricted**, not \"nobody allowed\".\n- To revert a restricted list back to fully open, clear that field in `\u002Fconfig` and submit.\n- 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 `\u002Fconfig`** to recover.\n\n### Advanced: editing the config file directly\n\nThe `\u002Fconfig` form writes to `~\u002F.lark-channel\u002Fconfig.json` under `preferences.access`:\n\n```json\n{\n  \"preferences\": {\n    \"access\": {\n      \"allowedUsers\": [\"ou_xxxxxxxxxxxxx\"],\n      \"allowedChats\": [\"oc_xxxxxxxxxxxxx\"],\n      \"admins\":       [\"ou_xxxxxxxxxxxxx\"]\n    }\n  }\n}\n```\n\nAfter a manual edit, **restart the bridge** or send **`\u002Freconnect`** 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.\n\n## FAQ\n\n**The bot stays silent \u002F Claude never replies.** Usually the `claude` CLI itself is not logged in, or the session points to a cwd that no longer exists. Send `\u002Fstatus` to inspect; `\u002Fnew` to start a fresh session.\n\n**Claude subprocess looks frozen (card stuck on the last frame).** Since 0.1.20 there's an idle watchdog: if Claude 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 `\u002Fconfig` (global, in minutes), or `\u002Ftimeout 10` to set it on the current session; `\u002Ftimeout off` disables for the session; `\u002Ftimeout default` clears the session override.\n\n**Claude says it can't see the image I sent.** Upgrade to the latest version — releases before 0.1.0 had a filename-dedup bug.\n\n## License\n\n[MIT](.\u002FLICENSE)","该项目是一个轻量级的机器人，用于连接飞书\u002F蓝信与本地Claude Code CLI。其核心功能包括消息转发、实时更新卡片、独立会话管理、多工作区切换等，支持发送图片和文件，并提供交互式卡片命令如帮助、状态查询等。技术上采用TypeScript编写，要求Node.js版本不低于20及已安装并登录的`claude` CLI。适用于需要在聊天中直接调用代码编辑或执行命令的开发者，特别是在团队协作环境中希望保持开发流程连贯性的场景。",2,"2026-06-01 03:46:37","CREATED_QUERY"]