Install
openclaw skills install add-feishuAdd Feishu (Lark) as a channel. Uses WebSocket long connection — no public URL or ngrok needed. Works alongside WhatsApp, Telegram, Slack, or as a standalone...
openclaw skills install add-feishuThis skill adds Feishu (飞书/Lark) support to NanoClaw using the skills engine for deterministic code changes, then walks through interactive setup.
Read .nanoclaw/state.yaml. If feishu is in applied_skills, skip to Phase 3 (Setup). The code changes are already in place.
Use AskUserQuestion to collect configuration:
AskUserQuestion: Do you have a Feishu (Lark) app already created, or do you need to create one?
If they have one, ask for the App ID and App Secret. If not, walk them through creation in Phase 3.
Run the skills engine to apply this skill's code package. The package files are in this directory alongside this SKILL.md.
If .nanoclaw/ directory doesn't exist yet:
npx tsx scripts/apply-skill.ts --init
npx tsx scripts/apply-skill.ts .claude/skills/add-feishu
This deterministically:
src/channels/feishu.ts (FeishuChannel class with self-registration via registerChannel)src/channels/feishu.test.ts (unit tests)import './feishu.js' to the channel barrel file src/channels/index.ts@larksuiteoapi/node-sdk npm dependency.env.example with FEISHU_APP_ID and FEISHU_APP_SECRET.nanoclaw/state.yamlIf the apply reports merge conflicts, read the intent file:
modify/src/channels/index.ts.intent.md — what changed and invariantsnpm test
npm run build
All tests must pass (including the new feishu tests) and build must be clean before proceeding.
If the user doesn't have an app, tell them:
I need you to create a Feishu app:
- Go to Feishu Open Platform (or Lark Open Platform for international)
- Click Create App → Custom App
- Fill in app name and description (e.g., "NanoClaw Assistant")
- Go to Credentials & Basic Info — copy the App ID and App Secret
- Go to Event Subscriptions → Add Events → search and add:
im.message.receive_v1(Receive messages — v2.0)- Go to Permissions & Scopes → add the following permissions:
im:message(Send & receive messages)im:message:send_as_bot(Send messages as bot)im:chat(Read chat info)im:chat.members:read(Read chat members)- Go to Bot tab → enable the bot feature
- Click Publish / Apply for Release
Note: For enterprise use, your IT admin may need to approve the app.
Wait for the user to provide the App ID (format: cli_xxxxxxxxxxxxxxxxxx) and App Secret.
Add to .env:
FEISHU_APP_ID=cli_xxxxxxxxxxxxxxxxxx
FEISHU_APP_SECRET=your_app_secret_here
Channels auto-enable when their credentials are present — no extra configuration needed.
Sync to container environment:
mkdir -p data/env && cp .env data/env/env
The container reads environment from data/env/env, not .env directly.
npm run build
launchctl kickstart -k gui/$(id -u)/com.nanoclaw # macOS
# Linux: systemctl --user restart nanoclaw
Tell the user:
To register a Feishu chat with NanoClaw, I need the chat's ID:
For a direct (p2p) chat:
- Add the bot to your Feishu contacts
- Open a direct message to the bot
- Send any message — NanoClaw will log the JID as
fs:p2p:<your_open_id>- Check
logs/nanoclaw.logfor:Message from unregistered Feishu chatFor a group chat:
- Add the bot to the group: Group Settings → Members → Add Bot
- Send any message in the group (or @mention the bot)
- NanoClaw will log the JID as
fs:oc_<chat_id>- Check
logs/nanoclaw.logfor:Message from unregistered Feishu chat
Tell user to check the log:
tail -f logs/nanoclaw.log | grep "unregistered Feishu"
Wait for the user to provide the JID (format: fs:oc_xxxxx or fs:p2p:ou_xxxxx).
For a main chat (responds to all messages):
registerGroup("fs:<chat-id>", {
name: "<chat-name>",
folder: "feishu_main",
trigger: `@${ASSISTANT_NAME}`,
added_at: new Date().toISOString(),
requiresTrigger: false,
isMain: true,
});
For additional chats (trigger-based, responds only when @mentioned or triggered):
registerGroup("fs:<chat-id>", {
name: "<chat-name>",
folder: "feishu_<group-name>",
trigger: `@${ASSISTANT_NAME}`,
added_at: new Date().toISOString(),
requiresTrigger: true,
});
Tell the user:
Send a message to your registered Feishu chat:
- For main chat: Any message works
- For non-main: @mention the bot or include a question/request keyword
The bot should respond within a few seconds.
tail -f logs/nanoclaw.log
Check:
im.message.receive_v1 event is added in the app's Event SubscriptionsFEISHU_APP_ID and FEISHU_APP_SECRET are set in .env AND synced to data/env/envlaunchctl list | grep nanoclaw (macOS) or systemctl --user status nanoclaw (Linux)By default, NanoClaw only responds in groups when:
To make the bot respond to all messages in a group, register it with requiresTrigger: false.
This is normal — it means the bot is receiving messages, but the chat isn't registered yet. Follow Phase 4 to register.
If the log message is hard to find:
sqlite3 store/messages.db "SELECT DISTINCT chat_jid FROM chats WHERE channel = 'feishu'"
The App Secret is sensitive. Store it only in .env and data/env/env. Do NOT commit these files to version control.
| Chat type | JID format | Example |
|---|---|---|
| Group chat | fs:oc_<id> | fs:oc_4e359893776d45f7cd05d40e3ee10f55 |
| Direct (p2p) | fs:p2p:<open_id> | fs:p2p:ou_7a66d6bd1baa3e6e3d7b3df9a8c90000 |
If running npm run dev while the service is active:
# macOS:
launchctl unload ~/Library/LaunchAgents/com.nanoclaw.plist
npm run dev
# When done testing:
launchctl load ~/Library/LaunchAgents/com.nanoclaw.plist
# Linux:
# systemctl --user stop nanoclaw
# npm run dev
# systemctl --user start nanoclaw
To remove Feishu integration:
src/channels/feishu.ts and src/channels/feishu.test.tsimport './feishu.js' from src/channels/index.tsFEISHU_APP_ID and FEISHU_APP_SECRET from .envsqlite3 store/messages.db "DELETE FROM registered_groups WHERE jid LIKE 'fs:%'"npm uninstall @larksuiteoapi/node-sdknpm run build && launchctl kickstart -k gui/$(id -u)/com.nanoclaw (macOS) or npm run build && systemctl --user restart nanoclaw (Linux)