
Lark Unified
- 8 installs
- 33 repo stars
- Updated April 26, 2026
- bighardperson/computer-science-skills-collection
lark-unified is a Claude skill that wraps the Lark/Feishu CLI (lark-cli) to give agents access to messaging, documents, spreadsheets, calendars, tasks, and wikis across 11 business domains.
About
lark-unified gives an agent access to the Lark (Feishu) collaboration platform through the lark-cli command-line tool. It exposes over 200 commands across 11 domains including instant messaging, cloud documents, spreadsheets, base tables, calendars, mail, tasks, and wikis. A developer uses it to send messages, manage documents, or build custom Lark workflows without hand-writing API calls. It documents a strict non-interactive setup path so an agent never triggers the TTY-only config wizard.
- Unified Lark/Feishu CLI wrapper with 200+ commands across 11 business domains
- Covers messaging, cloud docs, spreadsheets, base/tables, calendars, mail, tasks, wikis, and video conferences
- Ships 19 AI-agent-optimized skills; installs via npm i -g @larksuite/cli
Lark Unified by the numbers
- 8 all-time installs (skills.sh)
- Ranked #1,522 of 2,719 Automation & Workflows skills by installs in the Skillselion catalog
- Data as of Jul 30, 2026 (Skillselion catalog sync)
lark-unified capabilities & compatibility
Free tool; requires a configured Lark app_id and credentials.
- Capabilities
- send message · manage documents · manage calendar · manage tasks
- Works with
- teams · slack
- Use cases
- orchestration · project management · documentation
- Pricing
- Free
What lark-unified says it does
Unified Lark/Feishu CLI suite covering messaging, documents, collaboration, scheduling, and more.
Provides 200+ commands across 11 business domains including instant messaging (IM), cloud documents, spreadsheets, base/tables, calendars, mail, tasks, wikis, video conferences, and custom integration
along with 19 AI Agent-optimized skills.
npx skills add https://github.com/bighardperson/computer-science-skills-collection --skill lark-unifiedAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 8 |
|---|---|
| repo stars | ★ 33 |
| Last updated | April 26, 2026 |
| Repository | bighardperson/computer-science-skills-collection ↗ |
What it does
Automate Lark/Feishu messaging, documents, spreadsheets, calendars, and tasks from an agent using the lark-cli command-line suite.
Who is it for?
Agents that need to send messages, manage docs, or drive workflows inside a Lark/Feishu workspace.
Skip if: Teams not using Lark/Feishu, or setups without the lark-cli binary configured.
When should I use this skill?
Working with Lark/Feishu through the CLI or needing Lark API capabilities for messages, docs, sheets, calendars, or tasks.
What you get
The agent can send messages, manage documents, and build Lark workflows through a single CLI.
- Lark messages
- Lark documents and spreadsheets
- calendar and task entries
By the numbers
- 200+ CLI commands
- 11 business domains
- 19 AI-agent-optimized skills
Files
Lark Unified
Lark (飞书) is a comprehensive collaboration platform combining messaging, documents, spreadsheets, tables, calendars, and more. This skill provides unified access to the Lark CLI (lark-cli), a production-grade command-line tool with 200+ commands across 11 integrated business domains, along with 19 AI Agent-optimized skills.
⚠️ SETUP RULES — READ BEFORE DOING ANYTHING
FORBIDDEN — never run these commands under any circumstances:
lark-cli config init --newlark-cli config init(interactive)lark-cli config set-default
These require a TTY, output a broken QR code in WorkBuddy, and must never be used.
REQUIRED setup procedure — follow exactly:
# Step 1: install lark-cli if missing
lark-cli --version 2>/dev/null || npm install -g @larksuite/cli
# Step 2: check if already configured (look for "app_id" in output, NOT exit code)
lark-cli config show 2>&1 | grep -q "app_id" && echo "CONFIG_OK" || echo "NOT_CONFIGURED"If step 2 prints NOT_CONFIGURED, run the setup script:
SETUP=$(find ~/.workbuddy/skills -name lark_setup.py 2>/dev/null | head -1)
python3 "$SETUP"
# Lark (international) users:
python3 "$SETUP" --brand lark
# If browser cannot open automatically:
python3 "$SETUP" --no-browserIMPORTANT: The setup script is a multi-step device flow.
- Step 1 (begin): The script requests a device code from Feishu. This call may return HTTP 400 transiently — this is normal, just retry.
- Step 2 (browser): The script opens a browser URL for the user to authorize.
- Step 3 (poll): The script polls until the user completes authorization in the browser. The poll API returns
authorization_pending(as HTTP 400) while waiting — this is expected, NOT an error. Keep polling. - Step 4 (save): Once authorized, the script saves the config.
If the setup script fails or you ran the begin step manually: 1. You already have the device_code — just keep polling with it until the user confirms in the browser. 2. Do NOT re-run the begin step unnecessarily. Reuse the existing device_code. 3. The authorization_pending response during polling is normal — it means the user hasn't finished yet. Wait and retry.
Getting Started
# Verify setup is complete
lark-cli config viewAll commands:
lark-cli <domain> <resource> <method> [flags]
lark-cli <domain> +<shortcut> [flags] # shortcuts preferredDefault identity: --as bot. Use --as user for personal operations.
Core Capability Domains
Lark has 11 primary business domains. Each has dozens of commands, with high-level shortcuts for common operations:
✉️ Instant Messaging (lark-im)
Send/receive messages, search chat history, manage groups, download files, and manage reactions.
Common shortcuts: +messages-send, +messages-search, +chat-messages-list, +chat-create
Use when: Messaging users, retrieving conversations, building chat-based workflows, downloading attachments
→ For detailed API reference, shortcuts, and permission requirements: See references/lark-im.md
📄 Cloud Documents (lark-doc)
Create and edit documents, insert media, manage document permissions, and link to wikis.
Common shortcuts: +documents-create, +documents-list
Use when: Creating documents programmatically, building document workflows, embedding content
→ For full reference: See references/lark-doc.md
💾 Cloud Drive & Files (lark-drive)
Upload/download files, manage file permissions, share links, and add comments on files.
Common shortcuts: +files-upload, +files-download
Use when: Managing file storage, automating uploads/downloads, sharing files
→ For full reference: See references/lark-drive.md
📊 Spreadsheets (lark-sheets)
Read/write/append to spreadsheets, query data, and manage sheet permissions.
Common shortcuts: +spreadsheets-read, +spreadsheets-append, +spreadsheets-find
Use when: Automating spreadsheet operations, reading/updating sheet data, building data workflows
→ For full reference: See references/lark-sheets.md
🗂️ Base & Multi-Dimensional Tables (lark-base)
Query and manage multi-dimensional table records, fields, views, dashboards, and run workflows.
Common shortcuts: +tables-records-list, +tables-records-create, +fields-list
Use when: Managing relational data, querying tables, automating base operations, triggering workflows
→ For full reference: See references/lark-base.md
📅 Calendar (lark-calendar)
Query events, check availability, suggest meeting times, and manage calendar settings.
Common shortcuts: +calendars-list, +events-list, +events-search-freebusy
Use when: Checking schedules, coordinating meetings, finding available time slots
→ For full reference: See references/lark-calendar.md
📋 Tasks & To-Do (lark-task)
Create tasks, organize into lists, manage reminders, and track subtasks.
Common shortcuts: +tasks-create, +tasks-list, +task-lists-list
Use when: Creating tasks, building task workflows, managing team task lists
→ For full reference: See references/lark-task.md
📧 Mail (lark-mail)
Compose emails, manage drafts, search messages, reply/forward, and send emails.
Common shortcuts: +messages-send, +messages-search, +drafts-create
Use when: Building email workflows, automating mail operations, searching email history
→ For full reference: See references/lark-mail.md
📚 Wiki & Knowledge Spaces (lark-wiki)
Create knowledge spaces, organize pages into hierarchies, and manage wiki permissions.
Common shortcuts: +spaces-create, +wiki-pages-create, +wiki-pages-list
Use when: Building knowledge bases, organizing documentation, creating wikis
→ For full reference: See references/lark-wiki.md
🎥 Video Conference & Meetings (lark-vc)
Search meeting recordings, retrieve meeting notes, and manage VC settings.
Use when: Accessing meeting data, retrieving recordings and notes, managing video settings
→ For full reference: See references/lark-vc.md
👥 Contacts & Directory (lark-contact)
Search users, fetch contact profiles, and query user directory.
Use when: Searching for users, building user lookups, retrieving contact information
→ For full reference: See references/lark-contact.md
Core Concepts & Common Patterns
Identity & Authentication
- User identity (
--as user): Operations run as the authenticated user. Usesuser_access_token. Permissions depend on the user's own access. - Bot identity (
--as bot): Operations run as the app's bot. Usestenant_access_token. Permissions depend on the bot's scopes and membership.
Most APIs support both modes, but behavior differs based on the caller's role and access.
Common Entity IDs
- User:
open_id,user_id,email - Chat:
chat_id(oc_xxx) - Message:
message_id(om_xxx) - Thread:
thread_id - Document:
document_id - File:
file_keyorfile_id - Table/Base:
base_id,table_id - Event:
event_id
Working with the CLI
Using Shortcuts (Recommended)
Shortcuts are high-level wrappers around common operations. Always use shortcuts when available:
lark-cli im +messages-send --chat-id oc_xxx --text "Hello"
lark-cli sheets +spreadsheets-read --spreadsheet-id spr_xxxUsing Raw APIs
For operations without shortcuts, use raw API commands with schema inspection:
lark-cli schema im.messages.create # View parameter structure
lark-cli im messages create --data '{...}' # Call with structured dataImportant: Always run schema before calling raw APIs to understand the exact parameter format.
Pagination & Filtering
Most list operations support:
--limit: Number of records to return (default varies by API)--offset/--page-token: Pagination cursor--filter: Server-side filtering (format varies by resource)
Output Formatting
By default, commands return JSON. Common options:
--table: Format output as ASCII table--csv: Export as CSV--yaml: YAML format--raw: Unformatted raw output
Workflows
Lark offers two built-in workflow skills:
- Meeting Summary Workflow (
lark-workflow-meeting-summary): Aggregate meeting notes - Standup Report Workflow (
lark-workflow-standup-report): Generate daily standup summaries
See references/workflows.md for details.
Advanced Features
Custom Skills & Integrations
Use lark-skill-maker to create custom skills by wrapping Lark APIs. See references/skill-maker.md.
OpenAPI Discovery
Use lark-openapi-explorer to discover and test Lark APIs directly. See references/openapi.md.
Event Subscriptions
Subscribe to real-time events via WebSocket with lark-event. See references/events.md.
Other Domains
- Minutes: Meeting minutes metadata (
lark-minutes) - Whiteboard: Drawing/diagram creation with DSL (
lark-whiteboard) - Shared: Core authentication rules and identity management (
lark-shared)
See references/other-domains.md for details.
Quick Example
Send a message to a chat
# First, find the chat
lark-cli im +chat-search --keyword "engineering"
# Then send a message
lark-cli im +messages-send --chat-id oc_xxx --text "Hello team!"Search past messages
lark-cli im +messages-search --query "deadline" --from-user ou_xxx --start-time 2024-01-01 --end-time 2024-01-31Create a spreadsheet and add data
lark-cli sheets +spreadsheets-create --title "Q1 Data"
lark-cli sheets +spreadsheets-append --spreadsheet-id spr_xxx --range "Sheet1!A1" --values "[[1,2,3]]"Query a base table
lark-cli base +tables-records-list --base-id app_xxx --table-id tbl_xxx --limit 100Need Help?
- View all domains:
lark-cli --help - Domain-specific help:
lark-cli <domain> --help - Inspect API schema:
lark-cli schema <domain>.<resource>.<method> - Permission requirements: Check the permission tables in each domain's reference file
Next Steps
1. Choose your domain from the list above 2. Read the domain reference (linked in each section) 3. Use shortcuts for common operations 4. Inspect schemas if using raw APIs 5. Check permissions in the reference documentation
Reference Documentation for Lark Unified
This is a placeholder for detailed reference documentation. Replace with actual reference content or delete if not needed.
Example real reference docs from other skills:
- product-management/references/communication.md - Comprehensive guide for status updates
- product-management/references/context_building.md - Deep-dive on gathering context
- bigquery/references/ - API references and query examples
When Reference Docs Are Useful
Reference docs are ideal for:
- Comprehensive API documentation
- Detailed workflow guides
- Complex multi-step processes
- Information too lengthy for main SKILL.md
- Content that's only needed for specific use cases
Structure Suggestions
API Reference Example
- Overview
- Authentication
- Endpoints with examples
- Error codes
- Rate limits
Workflow Guide Example
- Prerequisites
- Step-by-step instructions
- Common patterns
- Troubleshooting
- Best practices
Lark-Base - Multi-Dimensional Tables
Important: Read lark-shared reference first for authentication and permission basics.
Core Concepts
- Base: Container for tables (base_id: app_xxx)
- Table: Data table within base (table_id: tbl_xxx)
- Field: Column definition (field_id: fld_xxx) — text, number, select, date, lookup, formula, etc.
- Record: Row in table (record_id: rec_xxx)
- View: Saved query/filter on table (view_id: vew_xxx)
- Workflow: Automation rules in table
Resource Hierarchy
Base (app_xxx)
├── Table (tbl_xxx)
│ ├── Field (fld_xxx)
│ │ ├── Property (field type, formula, lookup)
│ │ └── Permission
│ ├── Record (rec_xxx)
│ │ ├── Field value
│ │ └── Link to other records
│ ├── View (vew_xxx)
│ │ ├── Filter
│ │ ├── Sort
│ │ └── Group
│ └── Form/Dashboard/Workflow
└── Role/Automation/NotificationCommon Shortcuts
| Shortcut | Description |
|---|---|
+tables-records-list | List records from table (supports filter, sort, pagination) |
+tables-records-create | Create new record in table |
+tables-records-update | Update existing record |
+tables-records-delete | Delete records |
+fields-list | List all fields in table |
+views-list | List all views in table |
Typical Workflow
1. List bases: lark-cli base bases list 2. List tables: lark-cli base tables list --base-id app_xxx 3. Get fields: lark-cli base +fields-list --base-id app_xxx --table-id tbl_xxx 4. Query records: lark-cli base +tables-records-list --base-id app_xxx --table-id tbl_xxx --limit 100 5. Filter & sort: lark-cli base +tables-records-list --base-id app_xxx --table-id tbl_xxx --filter "[condition]" --sort "[sort_spec]" 6. Create record: lark-cli base +tables-records-create --base-id app_xxx --table-id tbl_xxx --data '{"field_id":"value"}' 7. Update record: lark-cli base tables records update --base-id app_xxx --table-id tbl_xxx --record-id rec_xxx --data '{...}'
Field Types
- Text, Long Text, Email, URL, Phone
- Number (integer, decimal)
- Select (single/multi), Tag
- Date, Time, Datetime
- Checkbox, Rating, Progress
- User, Department, Lookup, Link
- Formula, Rollup, Count
- Attachment, Custom Fields
API Resources
bases
list— List all accessible basesget_meta— Get base metadata
tables
list— List tables in baseget_meta— Get table metadatacreate— Create new tabledelete— Delete table
fields
list— List fields in tableget— Get field definitioncreate— Create fieldupdate— Update fielddelete— Delete field
records
list— List records (supports filter, sort, pagination)search— Search recordscreate— Create recordupdate— Update recordbatch_update— Batch update recordsdelete— Delete recordbatch_delete— Batch delete records
views
list— List views in tableget_meta— Get view metadataquery— Query view data
dashboards
list— List dashboardsget_meta— Get dashboard metadata
workflows
list— List automation workflowstrigger— Manually trigger workflow
Permission Table
| Method | Required Scope |
|---|---|
| bases.list | bitable:base:read |
| tables.list | bitable:base:read |
| fields.list | bitable:base:read |
| records.list | bitable:base:read |
| records.create | bitable:base:edit |
| records.update | bitable:base:edit |
| records.delete | bitable:base:edit |
| workflows.trigger | bitable:base:edit |
Lark-Calendar - Scheduling & Events
Important: Read lark-shared reference first for authentication and permission basics.
Core Concepts
- Calendar: Personal or shared calendar
- Event: Meeting or appointment with attendees
- Freebusy: Busy/available time slots for user
- Attendee: Participant in event (RSVP status: accept, decline, tentative, no_reply)
- Organizer: Creator/owner of event
Common Scenarios
1. Book an Event
lark-cli calendar +create --user ou_xxx --title "Team Sync" --start-time 2024-02-15T10:00:00 --end-time 2024-02-15T11:00:00 --attendees "user1@example.com" "user2@example.com"2. Check Availability
lark-cli calendar +freebusy --user ou_xxx --start-time 2024-02-15T08:00:00 --end-time 2024-02-15T18:00:003. Suggest Meeting Times
lark-cli calendar +suggestion --user ou_xxx --duration 60 --start-time 2024-02-15 --end-time 2024-02-20 --attendees "user1@example.com" "user2@example.com"4. View Today's Agenda
lark-cli calendar +agendaCommon Shortcuts
| Shortcut | Description |
|---|---|
+agenda | Quick overview of today/upcoming events |
+create | Create event and optionally invite attendees |
+freebusy | Query user's busy/free times and RSVP status |
+suggestion | Suggest meeting times based on attendees' availability |
+list | List events in calendar |
+search | Search events by keyword/organizer/attendee |
API Resources
calendars
list— List user's calendarsget— Get calendar details
events
create— Create eventlist— List events in calendarsearch— Search eventsupdate— Update eventdelete— Delete eventget— Get event details
freebusy
query— Query user's free/busy times and RSVP status
calendars.events.attendees
create— Add attendee to eventdelete— Remove attendee
Permission Table
| Method | Required Scope |
|---|---|
| calendars.list | calendar:calendar:read |
| calendars.get | calendar:calendar:read |
| events.create | calendar:event:create |
| events.list | calendar:event:read |
| events.update | calendar:event:edit |
| events.delete | calendar:event:delete |
| freebusy.query | calendar:calendar:read |
Lark-Doc - Cloud Documents
Important: Read lark-shared reference first for authentication and permission basics.
Core Concepts
Document Types & Tokens
Different document types have different URL formats and token handling:
| URL Format | Example | Token Type | Usage |
|---|---|---|---|
/docx/ | larksuite.com/docx/doxcnxxxxxxx | file_token | Direct token from URL |
/doc/ | larksuite.com/doc/doccnxxxxxxx | file_token | Direct token from URL |
/wiki/ | larksuite.com/wiki/wikcnxxxxxxx | wiki_token | ⚠️ Must query to get obj_token |
/sheets/ | larksuite.com/sheets/shtcnxxxxxxx | file_token | Direct token from URL |
/drive/folder/ | larksuite.com/drive/folder/fldcnxxxx | folder_token | Folder token from URL |
Wiki Link Special Handling (Important!)
Wiki links may point to different document types (docx, doc, sheet, bitable, slides, file, mindnote). Cannot assume URL token is file_token.
Processing flow: 1. Query node: lark-cli wiki spaces get_node --params '{"token":"wiki_token"}' 2. Extract from response: node.obj_type (document type) and node.obj_token (real token) 3. Use appropriate API based on obj_type
| obj_type | Usage |
|---|---|
| docx | drive file.comments.*, docx.* |
| doc | drive file.comments.* |
| sheet | sheets.* |
| bitable | bitable.* |
| slides | drive.* |
| file | drive.* |
| mindnote | drive.* |
Common Shortcuts
| Shortcut | Description |
|---|---|
+docs-create | Create document from Markdown or plain text |
+docs-get | Get document content |
+docs-list | List documents in workspace |
+docs-search | Search documents by keyword |
+docs-update | Update document (append/replace/insert/delete) |
API Resources
docs
create— Create documentget— Get document contentlist— List user documentsupdate— Update documentdelete— Delete documentraw_content— Get raw document content
docx
document.blocks.*— Manage document blocksdocument.children.*— Manage child elements
drive (file operations)
file.comments.*— Manage document comments
Permission Table
| Method | Required Scope |
|---|---|
| docs.create | docs:document:create |
| docs.get | docs:document:read |
| docs.list | docs:document:read |
| docs.update | docs:document:edit |
| docs.delete | docs:document:delete |
| docx.document.blocks.* | docs:document:read/edit |
| file.comments.* | drive:file:read/write |
Lark-Drive - Cloud Storage & Files
Important: Read lark-shared reference first for authentication and permission basics.
Core Concepts
- Folder: Directory in cloud storage (folder_token: fldcn_xxx)
- File: Document or attachment (file_token, file_key, file_id)
- Permission: Access level (viewer, editor, owner)
- Comment: Annotation on file
Resource Hierarchy
Folder (folder_token)
└── File (file_token)
├── Comment (comment_id)
├── Permission (user_id, role)
└── Resource (attachment/version)Common Shortcuts
| Shortcut | Description |
|---|---|
+files-upload | Upload file to folder |
+files-download | Download file to local system |
+files-list | List files in folder |
+files-delete | Delete file or folder |
+files-copy | Copy file or folder |
+files-move | Move file to different folder |
Typical Workflow
1. List files: lark-cli drive +files-list --folder-token fldcn_xxx 2. Upload file: lark-cli drive +files-upload --folder-token fldcn_xxx --local-path "./data.csv" 3. Download file: lark-cli drive +files-download --file-token xxxxx --local-path "./output/" 4. Get permissions: lark-cli drive files permissions get --file-token xxxxx 5. Share file: lark-cli drive files copy --file-token xxxxx
API Resources
files
get_meta— Get file metadatacopy— Copy filedelete— Delete filedownload— Download file contentupload— Upload filetask_check— Check async task status
files.permissions
get— Get file permissionsbatch_get— Batch get permissionscreate— Grant permissionupdate— Update permissiondelete— Revoke permission
files.comments
create— Add comment on fileget— Get commentlist— List commentsupdate— Update commentdelete— Delete comment
folders
create— Create folderget_meta— Get folder metadatalist_children— List folder contentsdelete— Delete foldercopy— Copy folder
Permission Table
| Method | Required Scope |
|---|---|
| files.get_meta | drive:file:read |
| files.download | drive:file:read |
| files.upload | drive:file:create |
| files.copy | drive:file:edit |
| files.delete | drive:file:delete |
| files.permissions.* | drive:file:read/edit |
| files.comments.* | drive:file:read/edit |
| folders.* | drive:folder:* |
Lark-IM - Instant Messaging
Important: Read lark-shared reference first for authentication and permission basics.
Core Concepts
- Message: Individual message in a chat (message_id: om_xxx). Types: text, post, image, file, audio, video, sticker, interactive (card), share_chat, share_user, merge_forward
- Chat: Group chat or P2P conversation (chat_id: oc_xxx)
- Thread: Reply thread under a message (thread_id)
- Reaction: Emoji reaction on a message
Resource Hierarchy
Chat (oc_xxx)
├── Message (om_xxx)
│ ├── Thread (reply)
│ ├── Reaction (emoji)
│ └── Resource (image/file/video/audio)
└── Member (user/bot)Critical Notes
Identity Matters
--as user: Runs as authenticated user (user_access_token). Permissions depend on user's access.--as bot: Runs as app bot (tenant_access_token). Permissions depend on bot's scopes and membership.
Same API may succeed with one identity and fail with the other.
Sender Name Resolution with Bot
When using --as bot to fetch messages, sender names may not resolve (shown as open_id instead of display name). This happens when bot cannot access sender's contact info.
Solution: Check app visibility settings in Lark Developer Console to ensure bot's visible range covers the senders. Alternatively use --as user.
Card Messages (Interactive)
Card messages are not yet supported for compact conversion in event subscriptions. Raw event data will be returned.
Common Shortcuts
| Shortcut | Description |
|---|---|
+chat-create | Create group chat (bot-only; creates private/public, invites users/bots) |
+chat-messages-list | List messages in chat or P2P (supports time range, sort, pagination) |
+chat-search | Search visible group chats by keyword/member |
+chat-update | Update group name or description |
+messages-mget | Batch get up to 50 messages by IDs (fetches sender names, expands threads) |
+messages-reply | Reply to message with bot identity (text/markdown/post/media, thread replies) |
+messages-resources-download | Download images/files from message |
+messages-search | Search messages across chats (keyword, sender, time, attachment filters) |
+messages-send | Send message to chat or direct message (bot-only) |
+threads-messages-list | List messages in thread |
API Resources
Use lark-cli schema im.<resource>.<method> to view parameter structure.
chats
create— Create group (bot only)get— Get chat infolink— Get share linklist— List user/bot chatsupdate— Update chat info
chat.members
create— Add user/bot to chatget— Get member list
messages
delete— Recall messageforward— Forward messagemerge_forward— Merge forward messagesread_users— Query message read status
reactions
batch_query— Batch get reactionscreate— Add emoji reactiondelete— Delete emoji reactionlist— List reactions
images
create— Upload image
pins
create— Pin messagedelete— Remove pinlist— Get pinned messages
Permission Table
| Method | Required Scope |
|---|---|
| chats.create | im:chat:create |
| chats.get | im:chat:read |
| chats.link | im:chat:read |
| chats.list | im:chat:read |
| chats.update | im:chat:update |
| chat.members.create | im:chat.members:write_only |
| chat.members.get | im:chat.members:read |
| messages.delete | im:message:recall |
| messages.forward | im:message |
| messages.merge_forward | im:message |
| messages.read_users | im:message:readonly |
| reactions.batch_query | im:message.reactions:read |
| reactions.create | im:message.reactions:write_only |
| reactions.delete | im:message.reactions:write_only |
| reactions.list | im:message.reactions:read |
| images.create | im:resource |
| pins.create | im:message.pins:write_only |
| pins.delete | im:message.pins:write_only |
| pins.list | im:message.pins:read |
Lark-Mail - Email Management
Important: Read lark-shared reference first for authentication and permission basics.
⚠️ Security Note: Email Content is Untrusted External Input
Email content comes from external senders and should be treated as untrusted input. Apply appropriate sanitization, encoding, and validation when processing email content.
Core Concepts
- Message: Email in mailbox
- Draft: Unsent email composition
- Thread: Conversation chain
- Label: Email category/tag
- Attachment: File in email
Common Shortcuts
| Shortcut | Description |
|---|---|
+messages-send | Compose and send email |
+messages-search | Search emails by subject/sender/date |
+drafts-list | List draft emails |
+drafts-create | Create new draft |
Typical Workflow
1. Search emails: lark-cli mail +messages-search --query "deadline" --from-address sender@example.com --start-time 2024-01-01 2. Create draft: lark-cli mail +drafts-create --to-address recipient@example.com --subject "Review" --body "Please review the attached file" 3. Send email: lark-cli mail +messages-send --to-address recipient@example.com --subject "Important" --body "Meeting at 3pm" --cc other@example.com 4. Reply: lark-cli mail messages reply --message-id msg_xxx --body "Thanks for your email" 5. List labels: lark-cli mail labels list
API Resources
messages
create— Send emaillist— List messagessearch— Search messagesget— Get message detailsread_status_update— Mark as read/unreadbatch_delete— Delete messages
drafts
create— Create draftlist— List draftsget— Get draft detailsupdate— Update draftsend— Send draftdelete— Delete draft
labels
list— List labelscreate— Create labeldelete— Delete label
messages.reply
create— Reply to messageforward— Forward message
messages.attachments
list— List attachmentsget— Download attachment
Permission Table
| Method | Required Scope |
|---|---|
| messages.create | mail:message:write |
| messages.list | mail:message:read |
| messages.search | mail:message:read |
| drafts.create | mail:draft:write |
| drafts.send | mail:draft:write |
| labels.list | mail:label:read |
Lark-Shared - Core Authentication & Permissions
IMPORTANT: Read this FIRST before using any Lark CLI commands.
Recommended App Permissions
After creating the app via lark_setup.py, go to the app console and add these permissions before using the CLI. Without them, most commands will return empty results.
App console URL: https://open.feishu.cn/app (find your App ID with lark-cli config show)
Core permissions (add all of these)
| Category | Permission | Purpose |
|---|---|---|
| Contacts | contact:contact:readonly | Search users by name |
| Contacts | contact:user.base:readonly | Read user profile |
| IM | im:chat:readonly | List and search chats |
| IM | im:chat | Create/manage chats |
| IM | im:message | Read messages |
| IM | im:message:send_as_bot | Send messages as bot |
| Documents | docx:document | Read/write docs |
| Spreadsheets | sheets:spreadsheet | Read/write sheets |
| Drive | drive:drive:readonly | Browse files |
| Drive | drive:file | Upload/download files |
| Base | bitable:app | Read/write base tables |
| Calendar | calendar:calendar:readonly | Read calendars |
| Calendar | calendar:event | Create/manage events |
| Tasks | task:task | Read/write tasks |
| Wiki | wiki:wiki:readonly | Read wiki pages |
After adding permissions: publish a new version in the app console, then re-run the setup script to get a fresh token with the new scopes:
SETUP=$(find ~/.workbuddy/skills -name lark_setup.py 2>/dev/null | head -1)
python3 "$SETUP"Quick Start: Configure Credentials
Check if config already exists:
lark-cli config viewIf not configured, use the inline setup script from SKILL.md (no TTY required).
NEVER use `lark-cli config init` or `lark-cli config init --new` directly — these require an interactive TTY and will display a broken QR code or hang in WorkBuddy.
Manual alternative (if you already have an App ID and App Secret):
echo "<APP_SECRET>" | lark-cli config init --app-id <APP_ID> --app-secret-stdinPlatforms:
- Feishu (China): https://open.feishu.cn
- Lark (International): https://open.larksuite.com
Other config commands:
lark-cli config view # View current configuration
lark-cli config use-config <name> # Switch between configurationsIdentity: User vs Bot
Every Lark CLI operation runs with one of two identities:
User Identity (--as user)
- Token:
user_access_token - Permissions: Based on the authenticated user's own access
- Scope: Personal scopes (what the user can do)
- Usage:
lark-cli <domain> <resource> <method> --as user ... - When to use:
- User is performing personal actions (send message, check calendar)
- Need to respect user's own access boundaries
- Searching personal content (messages, documents, calendar)
Bot Identity (--as bot)
- Token:
tenant_access_token - Permissions: Based on app's scopes + bot's membership/configuration
- Scope: App-level scopes (what the bot can do)
- Usage:
lark-cli <domain> <resource> <method> --as bot ... - When to use:
- App/bot is performing actions (send message to others, create group)
- Need to use app's elevated permissions
- Bot has special roles (group owner, admin, etc.)
Same API, Different Behavior
The same API may succeed or fail depending on identity:
# May work: User sending message to own chat
lark-cli im messages.get --message-id om_xxx --as user
# May fail: User lacks permission
lark-cli im messages.get --message-id om_xxx --as user # If user not in chat
# May work: Bot has broader access
lark-cli im messages.get --message-id om_xxx --as bot # If bot in chatScopes: Permission Model
Operations require specific OAuth scopes. Each scope grants specific capabilities:
Common Scopes
Messaging: im:chat:read, im:chat:write, im:message, im:message:recall
Documents: docs:document:read, docs:document:edit, docs:document:create
Spreadsheets: sheets:spreadsheet:read, sheets:spreadsheet:edit
Base: bitable:base:read, bitable:base:edit
Calendar: calendar:calendar:read, calendar:event:create
Tasks: task:task:read, task:task:create
Mail: mail:message:read, mail:message:write
Wiki: wiki:space:read, wiki:space:create
Drive: drive:file:read, drive:file:write
Check each domain's reference file for complete scope requirements.
Configuration Files
Lark CLI stores configuration in ~/.lark/config.toml:
[default]
tenant_key = "xxxxxxx"
app_id = "xxxxxxx"
app_secret = "xxxxxxx"
[dev]
tenant_key = "yyyyyyy"
app_id = "yyyyyyy"
app_secret = "yyyyyyy"Switch between configs: lark-cli config use-config dev
Permission Errors
If an operation fails with a permission error:
1. Check identity: Is it using --as user or --as bot? 2. Check scopes: Does the app have the required OAuth scopes? 3. Check membership: Is the user/bot in the target group/chat? 4. Check role: Does the user/bot have required role (owner, admin, etc.)?
Example: Message Not Found
Error: message not found
Possible causes:
1. Message was deleted
2. User/bot not in the chat containing the message
3. Message is older than API retention period (usually 7 days for some operations)
4. Insufficient scopesCommon Permission Issues
Sender Name Not Resolving
When using bot identity and sender name shows as open_id instead of display name:
- Root cause: Bot cannot access sender's contact info
- Solution: Check app visibility in Developer Console. Ensure bot's visible range includes the senders.
- Alternative: Use
--as userinstead, which typically has broader contact access
Chat Not Found
- User identity: User must be a member of the chat
- Bot identity: Bot must be a member AND within app's availability range
Cannot Create Group
- Bot only: User identity cannot create groups
- Use:
--as botwithim:chat:createscope
Testing Permissions
# Check current credential status
lark-cli config view
# Test a simple operation (list chats)
lark-cli im chats list --as user
# If this fails, check:
# 1. Configuration is correct: lark-cli config view
# 2. Token is valid (might be expired)
# 3. Scopes include im:chat:read
# Re-authenticate if needed
lark-cli config set-defaultSecurity Best Practices
1. Keep tokens private: Never commit credentials to version control 2. Use environment variables for automation:
export LARK_TENANT_KEY="xxxxx"
export LARK_APP_ID="xxxxx"
export LARK_APP_SECRET="xxxxx"
lark-cli config import-env3. Minimize scopes: Only request scopes your app actually needs 4. Rotate credentials: Periodically rotate app secrets 5. Validate untrusted input: Email content, user input, etc. can be malicious
More Help
lark-cli config --help
lark-cli --versionLark-Sheets - Spreadsheets
Important: Read lark-shared reference first for authentication and permission basics.
Core Concepts
- Spreadsheet: Container for sheets (spreadsheet_id: spr_xxx)
- Sheet: Individual worksheet within spreadsheet (sheet_id, sheet_name)
- Range: Cell range in A1 notation (e.g., "Sheet1!A1:C10")
- Cell: Individual cell with value (row, col)
Common Shortcuts
| Shortcut | Description |
|---|---|
+spreadsheets-create | Create new spreadsheet |
+spreadsheets-read | Read cell values from range |
+spreadsheets-append | Append rows to end of sheet |
+spreadsheets-find | Find cells matching criteria |
+spreadsheets-update | Update specific cells |
Typical Workflow
1. Create spreadsheet: lark-cli sheets +spreadsheets-create --title "Data" 2. Write header row: lark-cli sheets +spreadsheets-append --spreadsheet-id spr_xxx --range "Sheet1!A1" --values "[[Header1,Header2,Header3]]" 3. Append data: lark-cli sheets +spreadsheets-append --spreadsheet-id spr_xxx --values "[[1,2,3],[4,5,6]]" 4. Read data: lark-cli sheets +spreadsheets-read --spreadsheet-id spr_xxx --range "Sheet1!A1:C100" 5. Find values: lark-cli sheets +spreadsheets-find --spreadsheet-id spr_xxx --find "SearchTerm"
API Resources
spreadsheets
create— Create spreadsheetquery— Get spreadsheet metadatabatch_query— Batch get spreadsheetsupdate— Update spreadsheet properties
spreadsheets.sheets
query— Get sheet propertiesbatch_query— Batch get sheet info
spreadsheets.values
get— Read cell rangebatch_get— Batch read rangesupdate— Update cell rangebatch_update— Batch update rangesappend— Append rowsclear— Clear range
spreadsheets.finds
find— Find cells by valuebatch_find— Batch find operations
Permission Table
| Method | Required Scope |
|---|---|
| spreadsheets.create | sheets:spreadsheet:create |
| spreadsheets.query | sheets:spreadsheet:read |
| spreadsheets.values.get | sheets:spreadsheet:read |
| spreadsheets.values.update | sheets:spreadsheet:edit |
| spreadsheets.values.append | sheets:spreadsheet:edit |
| spreadsheets.finds.find | sheets:spreadsheet:read |
Lark-Task - Tasks & To-Do Lists
Important: Read lark-shared reference first for authentication and permission basics.
Core Concepts
- Task: Individual to-do item
- Task List: Collection of tasks
- Subtask: Task nested under parent task
- Assignee: User assigned to task
- Milestone: Deadline or target date
- Priority: Task importance level (low, medium, high, urgent)
Common Shortcuts
| Shortcut | Description |
|---|---|
+tasks-create | Create new task |
+tasks-list | List tasks with filters/sorting |
+task-lists-list | List available task lists |
+tasks-update | Update task status/assignee |
Typical Workflow
1. View my tasks: lark-cli task +tasks-list --assignee me --status active 2. Create task: lark-cli task +tasks-create --title "Review PR #123" --due-date 2024-02-15 3. Assign task: lark-cli task tasks update --task-id task_xxx --assignee ou_yyy 4. Mark complete: lark-cli task tasks update --task-id task_xxx --status completed 5. Create subtask: lark-cli task subtasks create --task-id task_xxx --title "Subtask"
API Resources
tasks
create— Create tasklist— List tasksget— Get task detailsupdate— Update task (title, status, assignee, etc.)delete— Delete task
task_lists
create— Create task listlist— List task listsget— Get list detailsupdate— Update list name/descriptiondelete— Delete list
subtasks
create— Create subtasklist— List subtasksupdate— Update subtaskdelete— Delete subtask
tasks.collaborators
create— Add collaborator to tasklist— List task collaboratorsdelete— Remove collaborator
Status Values
- active
- completed
- archived
- cancelled
Permission Table
| Method | Required Scope |
|---|---|
| tasks.create | task:task:create |
| tasks.list | task:task:read |
| tasks.get | task:task:read |
| tasks.update | task:task:edit |
| tasks.delete | task:task:delete |
| task_lists.* | task:taskList:* |
Lark-Wiki - Knowledge Spaces & Documentation
Important: Read lark-shared reference first for authentication and permission basics.
Core Concepts
- Space: Knowledge space container (space_id)
- Node: Document/page in space (wiki_token, obj_token)
- Hierarchy: Nested page structure
- Shortcut: Quick link to document in space
- obj_type: Type of node (docx, doc, sheet, bitable, slides, file, mindnote)
Resource Hierarchy
Space (space_id)
└── Node (wiki_token)
├── obj_type: docx (cloud document)
├── obj_type: sheet (spreadsheet)
├── obj_type: bitable (multi-dimensional table)
├── obj_type: slides (presentation)
├── obj_type: file (regular file)
└── Child nodes (nested)Important Note: Wiki Links Require Resolution
Wiki links (wiki_token) cannot be used directly. Must query to get the actual object type and token:
lark-cli wiki spaces get_node --params '{"token":"wiki_token"}'
# Returns: obj_type, obj_token, titleThen use appropriate API based on obj_type (docs, sheets, bitable, drive, etc.).
Common Shortcuts
| Shortcut | Description |
|---|---|
+spaces-create | Create new knowledge space |
+wiki-pages-list | List pages in space |
+wiki-pages-create | Create page in space |
Typical Workflow
1. List spaces: lark-cli wiki spaces list 2. Get space details: lark-cli wiki spaces get_meta --space-id space_xxx 3. List nodes: lark-cli wiki spaces list_nodes --space-id space_xxx 4. Query wiki link: lark-cli wiki spaces get_node --params '{"token":"wiki_token"}' 5. Create page: lark-cli wiki spaces create_node --space-id space_xxx --title "New Page" --parent-node-token xxx 6. Move node: lark-cli wiki spaces move_node --wiki-token xxx --parent-node-token new_parent_xxx
API Resources
spaces
list— List knowledge spacesget_meta— Get space metadatalist_nodes— List nodes in spaceget_node— Get node info (critical: resolves wiki_token to obj_token)create_node— Create page in spaceupdate_node— Update node propertiesdelete_node— Delete nodemove_node— Move node to different parentcopy_node— Copy node to different parent
spaces.members
create— Add member to spacelist— List space membersdelete— Remove member
Permission Table
| Method | Required Scope |
|---|---|
| spaces.list | wiki:space:read |
| spaces.get_meta | wiki:space:read |
| spaces.list_nodes | wiki:space:read |
| spaces.get_node | wiki:space:read |
| spaces.create_node | wiki:space:create |
| spaces.update_node | wiki:space:edit |
| spaces.delete_node | wiki:space:delete |
| spaces.move_node | wiki:space:edit |
Additional Lark Domains
Lark-Contact - Contacts & User Directory
When to use: Search for users, fetch user profiles, query organizational structure.
Common Shortcuts
| Shortcut | Description |
|---|---|
+me | Get current user profile |
+users-search | Search users by name/email/phone |
+departments-list | List organization departments |
Typical Operations
# Get current user info
lark-cli contact +me
# Search users
lark-cli contact +users-search --query "John" --limit 20
# Get department structure
lark-cli contact departments listKey Resources
user.get— Get user profileuser.list— List usersuser.search— Search usersdepartment.list— List departmentsdepartment.get— Get department info
---
Lark-VC - Video Conferences & Meetings
When to use: Access meeting recordings, retrieve meeting notes, manage video conference settings.
Common Scenarios
1. Search past meetings: Find meetings from last week 2. Get meeting notes: Retrieve automated summaries, action items, or transcripts 3. Download recordings: Access meeting video recordings
Typical Operations
# Search meetings from past week
lark-cli vc +meetings-search --from-user ou_xxx --start-time 2024-02-08 --end-time 2024-02-15 --limit 100
# Get meeting minutes/notes
lark-cli vc minutes get --meeting-id vc_xxx
# Get meeting recording
lark-cli vc recordings get --meeting-id vc_xxxKey Resources
meetings.list— List meetingsmeetings.search— Search meetings by organizer/attendee/timemeetings.get— Get meeting detailsminutes.get— Get meeting notes/summaryrecordings.list— List recordingsrecordings.get— Get recording details
Note on Freebusy vs Meetings
- Use lark-calendar for future events and scheduling
- Use lark-vc for past meetings, recordings, and notes
---
Lark-Minutes - Meeting Minutes
When to use: Retrieve meeting minutes metadata and associated content.
Typical Operations
lark-cli minutes minutes-list --meeting-id vc_xxx
lark-cli minutes minutes-get --minutes-id minutes_xxx---
Lark-Whiteboard - Drawing & Diagrams
When to use: Create or manage diagrams using DSL (Domain Specific Language).
Rendering
Supports Mermaid syntax for flowcharts, sequence diagrams, state machines, etc.
Typical Operations
# Create whiteboard with Mermaid diagram
lark-cli whiteboard create --title "Architecture Diagram" --content "graph LR; A[Start] --> B[Process] --> C[End]"---
Lark-Event - Real-Time Event Subscriptions
When to use: Subscribe to real-time events (messages, document changes, base updates) via WebSocket.
Usage Pattern
# Subscribe to message events
lark-cli event subscribe --event-type message.receive --endpoint wss://your-endpointSupported Events
- Messages: create, update, delete
- Documents: updated
- Base: record created/updated/deleted
- Calendar: event changes
- And many more...
---
Lark-Shared - Core Authentication & Configuration
Always read this first before using any other Lark skill.
Key Concepts
- Identity: User vs Bot
- Token Types: user_access_token vs tenant_access_token
- Scopes: Permissions required for each operation
- Configuration: How to set up credentials
Critical Notes
- User operations (
--as user): Use user's permissions - Bot operations (
--as bot): Use bot's app scopes and membership - Some APIs support only one identity type
- Always check the reference for identity requirements
---
Lark-OpenAPI-Explorer - API Discovery
When to use: Discover and test Lark APIs directly, explore API schemas.
Usage
lark-cli openapi search --query "message" # Search available APIs
lark-cli openapi get --api im.messages.send # Get API details---
Lark-Skill-Maker - Create Custom Skills
When to use: Build custom skills by wrapping Lark APIs for specialized workflows.
Typical Usage
Skill-maker allows you to:
- Define custom commands
- Wrap complex API sequences
- Add business logic
- Export as reusable skills
See official documentation for detailed skill authoring guidelines.
#!/usr/bin/env python3
"""
lark_setup.py - Lark CLI auto-setup script
Implements the same device flow as `lark-cli config init --new` but
works in non-TTY environments (e.g. WorkBuddy, CI, headless shells).
Usage:
python3 lark_setup.py [--brand feishu|lark] [--no-browser]
Steps:
1. POST to feishu app registration API (begin)
2. Build verification URL
3. Open browser automatically (unless --no-browser)
4. Poll until user completes browser authorization
5. Write App ID + Secret to lark-cli config via non-interactive flag
"""
import argparse
import json
import subprocess
import sys
import time
import urllib.error
import urllib.parse
import urllib.request
# --- Endpoints (mirrors internal/core/endpoints.go) ---
ENDPOINTS = {
"feishu": {
"accounts": "https://accounts.feishu.cn",
"open": "https://open.feishu.cn",
},
"lark": {
"accounts": "https://accounts.larksuite.com",
"open": "https://open.larksuite.com",
},
}
CLI_VERSION = "1.0.0"
def post_form(url, data: dict) -> dict:
body = urllib.parse.urlencode(data).encode()
req = urllib.request.Request(url, data=body, method="POST")
req.add_header("Content-Type", "application/x-www-form-urlencoded")
try:
with urllib.request.urlopen(req, timeout=15) as resp:
return json.loads(resp.read())
except urllib.error.HTTPError as e:
# Feishu returns OAuth errors (e.g. authorization_pending) as HTTP 400
raw = e.read()
try:
return json.loads(raw)
except Exception:
raise RuntimeError(f"HTTP {e.code}: {raw.decode(errors='replace')}")
def begin_registration(brand: str) -> dict:
"""Step 1: Initiate the app registration device flow."""
# Registration begin always uses feishu accounts endpoint
url = ENDPOINTS["feishu"]["accounts"] + "/oauth/v1/app/registration"
resp = post_form(url, {
"action": "begin",
"archetype": "PersonalAgent",
"auth_method": "client_secret",
"request_user_info": "open_id tenant_brand",
})
if "error" in resp:
raise RuntimeError(f"Registration failed: {resp.get('error_description', resp['error'])}")
return resp
def build_verification_url(base_url: str) -> str:
"""Append CLI tracking params (mirrors BuildVerificationURL in Go)."""
sep = "&" if "?" in base_url else "?"
return (
base_url
+ sep
+ f"lpv={urllib.parse.quote(CLI_VERSION)}"
+ f"&ocv={urllib.parse.quote(CLI_VERSION)}"
+ "&from=cli"
)
def poll_registration(device_code: str, brand: str, interval: int, expires_in: int) -> dict:
"""Step 4: Poll until user completes browser authorization."""
url = ENDPOINTS[brand]["accounts"] + "/oauth/v1/app/registration"
deadline = time.time() + expires_in
current_interval = interval
attempts = 0
while time.time() < deadline and attempts < 200:
attempts += 1
time.sleep(current_interval)
resp = post_form(url, {"action": "poll", "device_code": device_code})
err = resp.get("error", "")
if not err and resp.get("client_id"):
return resp # success
if err == "authorization_pending":
print(" Waiting...", flush=True)
continue
elif err == "slow_down":
current_interval = min(current_interval + 5, 60)
continue
elif err in ("access_denied",):
raise RuntimeError("Authorization denied by user.")
elif err in ("expired_token", "invalid_grant"):
raise RuntimeError("Device code expired. Please try again.")
elif err:
raise RuntimeError(f"Poll error: {resp.get('error_description', err)}")
raise RuntimeError("Authorization timed out. Please try again.")
def save_config(app_id: str, app_secret: str, brand: str):
"""Step 5: Write config via lark-cli non-interactive flags."""
proc = subprocess.run(
["lark-cli", "config", "init",
"--app-id", app_id,
"--app-secret-stdin",
"--brand", brand],
input=app_secret,
capture_output=True,
text=True,
)
if proc.returncode != 0:
raise RuntimeError(f"lark-cli config init failed:\n{proc.stderr}")
print(f" {proc.stderr.strip()}" if proc.stderr.strip() else " Config saved.")
def open_browser(url: str, no_browser: bool):
"""Open URL in the default browser, or print it if --no-browser."""
if no_browser:
print(f"\n Open this URL in your browser:\n {url}\n")
return
try:
subprocess.run(["open", url], check=True) # macOS
print(f" Browser opened. If it didn't open, visit:\n {url}")
except Exception:
try:
subprocess.run(["xdg-open", url], check=True) # Linux
except Exception:
print(f" Could not open browser automatically.\n Please visit:\n {url}")
def main():
parser = argparse.ArgumentParser(description="Lark CLI auto-setup (no TTY required)")
parser.add_argument("--brand", choices=["feishu", "lark"], default="feishu",
help="Platform brand (default: feishu)")
parser.add_argument("--no-browser", action="store_true",
help="Print URL instead of opening browser")
args = parser.parse_args()
brand = args.brand
print(f"[lark-setup] Starting app registration flow (brand={brand})...")
# Step 1: Begin
print("[lark-setup] Step 1/4: Requesting device code...")
reg = begin_registration(brand)
device_code = reg["device_code"]
user_code = reg.get("user_code", "")
expires_in = int(reg.get("expires_in", 300))
interval = int(reg.get("interval", 5))
# Step 2: Use URL from API response directly (verification_uri_complete already has user_code)
verification_url = reg.get("verification_uri_complete") or reg.get("verification_uri", "")
# Step 3: Open browser
print(f"[lark-setup] Step 2/4: Opening browser for authorization...")
open_browser(verification_url, args.no_browser)
# Step 4: Poll
print("[lark-setup] Step 3/4: Waiting for you to complete authorization in browser...")
result = poll_registration(device_code, brand, interval, expires_in)
# Handle Lark brand retry (mirrors Go logic)
user_info = result.get("user_info", {}) or {}
tenant_brand = user_info.get("tenant_brand", brand)
if not result.get("client_secret") and tenant_brand == "lark":
print("[lark-setup] Detected Lark tenant, retrying with lark endpoint...")
result = poll_registration(device_code, "lark", interval, expires_in)
tenant_brand = "lark"
app_id = result["client_id"]
app_secret = result["client_secret"]
final_brand = tenant_brand if tenant_brand in ("feishu", "lark") else brand
print(f"[lark-setup] Authorization complete! App ID: {app_id}")
# Step 5: Save config
print("[lark-setup] Step 4/4: Saving configuration...")
save_config(app_id, app_secret, final_brand)
print(f"\n[lark-setup] Done! lark-cli is now configured.")
print(f" App ID: {app_id}")
print(f" Brand: {final_brand}")
print(f"\n Run `lark-cli config view` to verify.")
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
print("\n[lark-setup] Cancelled.")
sys.exit(1)
except Exception as e:
print(f"\n[lark-setup] Error: {e}", file=sys.stderr)
sys.exit(1)
Related skills
FAQ
Which platform does lark-unified target?
It targets Lark (Feishu), covering messaging, docs, spreadsheets, base tables, calendars, mail, tasks, wikis, and video conferences.
How is lark-cli installed?
If lark-cli is missing, install it globally with npm install -g @larksuite/cli.
Are there commands the agent must avoid?
Yes; the interactive config init and set-default commands are forbidden because they require a TTY and produce a broken QR code.