FFFF GitHub - bbw9n/elark: Lark/Feishu Emacs integration · GitHub
[go: up one dir, main page]

Skip to content
bbw9nPublic

About

Lark/Feishu Emacs integration

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

151 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

elark — Emacs Interface to Lark/Feishu

https://melpa.org/packages/elark-badge.svg

An Emacs package that wraps lark-cli to bring Lark/Feishu into Emacs. Transient menus for command dispatch, mu4e-style mail, dired-like drive browsing, org-table spreadsheets, and async execution throughout.

Demos

Short screen recordings of each domain in action.

AI shell

Natural-language prompts drive the agent loop — skills routing, lark-cli tool calls, streamed markdown answers — via a local ACP agent (Claude Code), no API key.

lark-ai.mp4

Docs

Fetching a Lark doc as org-mode, images rendered from the persistent cache.

lark-doc.mp4

Messenger

Group search and message history with inline image and video thumbnails.

lark-im.mp4

Mail

mu4e-style inbox and the magit-commit-style compose/reply panel.

lark-mail.mp4

Meetings

Meeting search with notes and transcript rendering.

lark-meeting.mp4

Tasks

Task lists and the org-agenda–style due-date view.

lark-task.mp4

Prerequisites

  • Emacs 29.1+
  • lark-cli installed and on your PATH
  • org-lark (available on MELPA) — used by the Docs domain to convert Lark Markdown to Org
  • shell-maker (available on MELPA, includes markdown-overlays) — the AI shell interface

Installing lark-cli

npm install -g @larksuite/cli

Verify it works:

lark-cli --help

Installation

From source (straight.el)

(straight-use-package
 '(elark :type git :host github :repo "bbw9n/elark"
        :files ("*.el" "core" "domain" "ai")))

From source (manual)

Clone this repo and add it to your load-path:

(add-to-list 'load-path "/path/to/elark")
(require 'elark)
(elark-setup-prefix-key) ;; binds C-c l

use-package

(use-package elark
  :load-path "/path/to/elark"
  :config
  (elark-setup-prefix-key))

Doom Emacs

Add in packages.el from the source of github repo

(package! elark
  :recipe (:host github :repo "bbw9n/elark" :branch "main"
           :files ("*.el" "core" "domain" "ai")))

Ensure to setup (elark-setup-prefix-key) in your config.el

(use-package! elark
  :config
  (elark-setup-prefix-key))

Quick Start: First-Time Setup

This section walks you through initial configuration, authentication, and pulling up your calendar — all from within Emacs.

Step 1: Configure lark-cli (one-time)

Before elark can talk to Lark, you need to register an app. Run this in your terminal (or use M-x shell):

lark-cli config init

This is an interactive prompt that asks for:

  1. Brand: choose feishu (China) or lark (international)
  2. App ID & App Secret: from the Feishu Open Platform (or Lark Developer Console)
    • Go to the console, create an app (or use an existing one)
    • Copy the App ID and App Secret
  3. The CLI stores credentials locally in ~/.config/lark-cli/

If you prefer non-interactive setup:

echo "YOUR_APP_SECRET" | lark-cli config init \
  --app-id cli_xxxxxxxxxxxx \
  --app-secret-stdin \
  --brand feishu

Verify:

lark-cli config show

Step 2: Authenticate (OAuth login)

Now authenticate your Lark user account. You can do this either from the terminal or from Emacs:

Option A: From Emacs

M-x elark-auth-login

Or use the keybinding: C-c l l then press L (Login).

This will:

  1. Call lark-cli auth login --no-wait in the background
  2. Open your browser to the Lark authorization page
  3. Poll automatically until you approve in the browser
  4. Show “Lark: login successful!” in the echo area

Option B: From terminal first

lark-cli auth login --domain calendar

The --domain flag requests scopes for a specific domain. Available domains: calendar, task, im, mail, contact, docs, drive, base, sheets, wiki, vc, approval, event, minutes, or all.

You can request multiple domains:

lark-cli auth login --domain calendar,task,im

Or request everything:

lark-cli auth login --domain all

Verify authentication

From Emacs:

M-x elark-auth-status

Or: C-c l s

This shows your login status in the echo area. You should see something like “Lark: authenticated as Your Name (your-tenant)”.

From terminal:

lark-cli auth status

Step 3: View your calendar

Now the fun part:

C-c l a

Or: M-x elark-calendar-agenda

This fetches today’s agenda and displays it in a *Lark Agenda* buffer:

Daily Standup
  Start:      2026-04-12 09:00
  End:        2026-04-12 09:30
  Location:   Meeting Room A
  Organizer:  Alice
  RSVP:       accept

Sprint Planning
  Start:      2026-04-12 10:00
  End:        2026-04-12 11:00
  Location:   Room 301
  Organizer:  Bob
  RSVP:       accept

1:1 with Manager
  Start:      2026-04-12 14:00
  End:        2026-04-12 15:00
  Organizer:  Carol
  RSVP:       tentative

Keybindings in the agenda buffer

KeyAction
RETOpen event detail
gRefresh (re-fetch from Lark)
cCreate a new event
dDelete event at point
yCopy event ID to kill ring
?Open Calendar transient menu
qQuit buffer

Open the full Calendar menu

C-c l l   (opens main dispatch)
c         (opens Calendar submenu)

Or directly: M-x elark-calendar-dispatch

The Calendar transient menu:

-- Lark Calendar commands --

Quick Actions
 a  Agenda (today)
 n  New event
 f  Free/busy
 s  Suggest time
 r  RSVP

Browse
 l  List calendars
 e  List events

Usage Reference

Global Keybindings (prefix C-c l)

KeyCommandDescription
C-c l lelark-dispatchMain transient menu
C-c l aelark-calendar-agendaToday’s agenda
C-c l telark-tasks-listMy tasks
C-c l melark-im-dispatchMessenger menu
C-c l eelark-mail-inboxMail inbox
C-c l delark-docs-dispatchDocs menu
C-c l felark-drive-listDrive root listing
C-c l kelark-contacts-dispatchContacts menu
C-c l selark-auth-statusAuth status
C-c l ielark-ai-askAsk AI (natural language)
C-c l Ielark-ai-chatAI chat buffer
C-c l .elark-ai-actAI action at point

Main Dispatch (C-c l l)

The main transient menu provides access to all 12 Lark domains:

KeyDomainKeyDomain
cCalendarsSheets
mMessengereMail
dDocswWiki
fDrivekContacts
bBasevMeetings
tTasksWWhiteboard

AI commands: i ask AI, I AI chat, . AI act at point. AI workflows: 1 standup report, 2 meeting summary, 3 schedule meeting. Auth: a status, L login, O logout, X identity switch, S schema.

Calendar

CommandDescription
elark-calendar-agendaShow today’s agenda
elark-calendar-eventsList events (optional calendar ID)
elark-calendar-listList all calendars
elark-calendar-create-eventCreate event (transient form)
elark-calendar-freebusyCheck free/busy for a user
elark-calendar-suggest-timeGet meeting time suggestions
elark-calendar-rsvpRSVP to an event

Tasks

CommandDescription
elark-tasks-listList my tasks
elark-tasks-createCreate task (transient form)
elark-tasks-openOpen task detail (at point)
elark-tasks-completeMark task complete (at point)
elark-tasks-editEdit task title (at point)
elark-tasks-deleteDelete task (at point)
elark-tasks-subtask-createAdd subtask (at point)
elark-tasks-tasklistsList task lists

Messenger

CommandDescription
elark-im-chatsList chats
elark-im-messagesShow message history for a chat
elark-im-sendSend a message
elark-im-replyReply to a message
elark-im-reactAdd reaction to a message
elark-im-searchSearch messages
elark-im-group-createCreate group chat (transient form)
elark-im-subscribeStart real-time event subscription
elark-im-unsubscribeStop event subscription

Mail

mu4e-style interface with flag indicators and shr-rendered HTML bodies.

CommandDescription
elark-mail-inboxShow inbox
elark-mail-readRead mail (at point)
elark-mail-composeCompose new mail (transient form)
elark-mail-replyReply to mail
elark-mail-forwardForward mail
elark-mail-deleteDelete mail (at point)
elark-mail-searchSearch mail
elark-mail-draftsList drafts

Keybindings in the mail list:

KeyAction
RETRead message
cCompose new mail
rReply
fForward
dDelete
/Search
nNext message
pPrevious message
gRefresh

Docs

CommandDescription
elark-docs-searchSearch documents
elark-docs-fetchFetch document content (URL or token)
elark-docs-createCreate document (transient form)
elark-docs-updateUpdate document (transient form)
elark-docs-media-downloadDownload media from a document
elark-docs-media-insertInsert media into a document
elark-docs-media-previewPreview media

Drive

Dired-like file browser for Lark Drive. Owner names are resolved from contact open_ids automatically.

CommandDescription
elark-drive-listList root (or folder by token)
elark-drive-openOpen item at point (RET)
elark-drive-view-contentView doc/docx/sheet content (v)
elark-drive-uploadUpload local file
elark-drive-downloadDownload file at point
elark-drive-mkdirCreate folder (+)
elark-drive-copyCopy file (C)
elark-drive-moveMove/rename file (R)
elark-drive-importImport local file to Drive
elark-drive-exportExport cloud doc to local

Keybindings in the drive buffer:

KeyAction
RETOpen (descend into folder / show detail)
vView doc/docx/sheet content
^Go up to parent folder
wCopy file token
WCopy file URL
n/pNext/previous file

In the file detail buffer, press RET to view the content of doc/docx/sheet files directly.

Sheets

Spreadsheet data is displayed as editable org-mode tables.

CommandDescription
elark-sheets-infoShow spreadsheet info
elark-sheets-readRead range as org table
elark-sheets-write-tableWrite org table back to sheet
elark-sheets-append-tableAppend rows from org table
elark-sheets-createCreate spreadsheet (transient)
elark-sheets-create-from-tableCreate from org table at point
elark-sheets-findFind cells by text
elark-sheets-exportExport as xlsx/csv

In the sheet info buffer, press RET on a sheet line to read the first 100 rows as an org table.

Contacts

CommandDescription
elark-contact-get-userLook up user by ID
elark-contact-searchSearch contacts by keyword
elark-contact-resolve-nameResolve open_id to name (cached)

Meetings

CommandDescription
elark-meetings-searchSearch meeting records
elark-meetings-openOpen meeting detail (auto-fetches recording)
elark-meetings-notesFetch meeting notes (summary, todos, chapters)
elark-meetings-recordingQuery recording for a meeting
elark-meetings-download-recordingDownload recording by minute token

Meeting detail pages automatically check for recordings and show a clickable download link when available.

AI Layer

elark includes an AI-native orchestration layer that turns natural-language prompts into multi-step lark-cli execution plans. Instead of remembering which commands to chain together, you describe what you want and the AI figures out the steps.

How it works

  1. You type a prompt (e.g., “what’s on my plate today?”)
  2. elark selects the relevant lark-cli skill files (SKILL.md) based on keywords in your prompt
  3. The skills + your prompt are sent to an LLM, which returns a JSON execution plan
  4. The plan is shown in a review buffer — you can inspect, remove steps, or cancel
  5. On confirmation, elark executes the CLI commands (in parallel where possible), collecting results
  6. If the plan includes a synthesis step, results are sent back to the LLM for a human-readable summary
  7. The final output is rendered in a buffer

Write operations (create, update, delete, send) are flagged in the plan and require explicit confirmation before execution.

Prerequisites

  • An LLM backend: a local ACP agent such as Claude Code or Gemini CLI via acp.el (recommended, the default — no API key), gptel, or any OpenAI-compatible HTTP endpoint
  • lark-cli skills installed in ~/.agent/skills/:
npx skills add larksuite/cli -g -y

Setup

With a local ACP agent (default, no API key)

The default backend drives a locally installed Agent Client Protocol agent — the same mechanism agent-shell uses — so the agent’s own login is reused and no API key is needed. Requires the acp.el package and an ACP agent binary:

npm install -g @zed-industries/claude-code-acp   # Claude Code adapter
;; Nothing to configure: `elark-ai-backend' defaults to `acp' and the
;; default agent is claude-code-acp.

;; To use Gemini CLI instead:
(setq elark-ai-acp-command "gemini"
      elark-ai-acp-command-params '("--experimental-acp")
      ;; Gemini ignores the session _meta systemPrompt extension, so
      ;; send elark's system prompt inline with the user message:
      elark-ai-acp-system-prompt-placement 'inline)

The agent process is started on first use and kept alive; M-x elark-ai-acp-shutdown kills it. Each LLM call runs in a fresh ACP session, and the agent’s own tools are disabled — it acts purely as the text engine behind elark’s agent loop.

With gptel

(use-package gptel
  :config
  ;; configure your preferred provider
  (setq gptel-model 'claude-sonnet-4-20250514))

(setq elark-ai-backend 'gptel)

With a raw HTTP endpoint

(setq elark-ai-backend 'http
      elark-ai-http-endpoint "https://api.openai.com/v1/chat/completions"
      elark-ai-http-api-key "sk-...")

Or set the ELARK_AI_API_KEY environment variable instead of hardcoding the key.

Keybindings

KeyCommandDescription
C-c l ielark-ai-askNatural-language prompt
C-c l Ielark-ai-chatConversational AI buffer
C-c l .elark-ai-actContext-aware action at point

These are also available from the main dispatch (C-c l l) under the “AI” and “AI Workflows” sections.

Examples

Standup report

C-c l i  "what's on my plate today?"

The AI generates a plan:

Lark AI -- Execution Plan
----------------------------------------

  [0] Fetch today's agenda  (read-only)  [group 1]
      lark-cli calendar +agenda
  [1] Fetch open tasks  (read-only)  [group 1]
      lark-cli task +get-my-tasks
  [2] Summarize schedule and tasks  (AI synthesis)

----------------------------------------
  RET Execute  x Remove step  q Cancel

Steps 0 and 1 run in parallel (same group). After execution, the LLM synthesizes results into:

## 2026-04-13 Sunday

### Agenda
| Time        | Event              | Organizer | Status   |
|-------------+--------------------+-----------+----------|
| 09:00-09:30 | Daily Standup      | Alice     | accepted |
| 14:00-15:00 | 1:1 with Manager   | Carol     | tentative|

### Open Tasks
- [ ] Review PR #142 (due: today)
- [ ] Update API docs (due: Apr 14)

### Notes
- No scheduling conflicts
- Free slots: 10:00-14:00, 15:00-18:00

Or use the dedicated command: M-x elark-ai-workflow-standup.

Meeting summary

C-c l i  "summarise my meetings this week"

The AI chains vc +search -> vc +notes -> synthesis, producing a structured report of all meetings with their notes and action items.

Or: M-x elark-ai-workflow-meeting-summary.

Schedule a meeting

C-c l i  "set up a 30min sync with Alice next Tuesday afternoon"

The AI plan:

[0] Search contact "Alice"  (read-only)
[1] Find available time slots  (read-only)
[2] Check room availability  (read-only)
[3] Create calendar event  CAUTION writes

Step 3 is marked as a side-effect and will prompt for confirmation before executing.

Or: M-x elark-ai-workflow-schedule.

Context-aware actions

When you’re in a Lark buffer (agenda, chat, task list, etc.), press C-c l . to perform an AI action on the item at point. The AI automatically knows the domain and which item you’re looking at.

For example, in the *Lark Agenda* buffer with point on an event:

C-c l .  "reschedule to tomorrow at 3pm"

Conversational chat

C-c l I opens a persistent AI chat buffer where you can ask follow-up questions. Type your message and press C-c C-c to send.

You: how many meetings do I have tomorrow?
----------------------------------------
AI: Generated a plan. Review it in the plan buffer.
(after execution)
AI: You have 3 meetings tomorrow:
- 09:00-09:30  Daily Standup
- 11:00-12:00  Design Review
- 15:00-16:00  Sprint Retro

Built-in workflows

CommandDescription
elark-ai-workflow-standupToday’s agenda + open tasks
elark-ai-workflow-mee 9283 ting-summarySummarise recent meetings
elark-ai-workflow-scheduleSchedule a meeting with AI help

These are shortcuts for common multi-step operations. They also appear in the dispatch menu under “AI Workflows” (keys 1, 2, 3).

Customization

All options are under M-x customize-group RET elark.

VariableDefaultDescription
elark-cli-executable"lark-cli"Path to the lark-cli binary
elark-default-format"json"Output format (json/table/csv/pretty)
elark-default-identity"user"Identity type (user/bot)
elark-dry-runnilPass –dry-run to destructive commands
elark-im-message-limit50Messages to fetch in chat history
elark-mail-page-size20Emails per page
elark-calendar-default-days1Days in agenda view
elark-ai-backendacpLLM backend (acp, gptel, or http)
elark-ai-modelnilModel ID (nil uses backend default)
elark-ai-skills-directory~/.agents/skills/Path to lark-cli SKILL.md files
elark-ai-skill-routingllmSkill picker: llm (ask the model) or keyword
elark-ai-skills-log-lines10Top N lines of each skill shown in the debug log (nil = full)
elark-ai-step-timeout1800Seconds before a plan step’s CLI call is killed (nil = none)
elark-ai-execute-modeconfirm-writesPlan execution: auto / confirm-writes / review
elark-ai-auto-execute-commands("docs +create" "docs +update")Write cmds that skip the confirm prompt
elark-ai-http-endpointnilURL for the http backend
elark-ai-http-api-keynilAPI key (or set ELARK_AI_API_KEY)
elark-ai-acp-command"claude-code-acp"ACP agent binary for the acp backend
elark-ai-acp-command-paramsnilExtra args for the ACP agent (e.g. --experimental-acp)
elark-ai-acp-cwd"~"Working directory for ACP sessions
elark-ai-acp-system-prompt-placementsessionSystem prompt via session meta (session) or inline text (inline)

Troubleshooting

“Cannot find lark-cli executable”

lark-cli is not on your PATH. Either:

  • Install it: npm install -g @larksuite/cli
  • Set the full path: (setq elark-cli-executable "/path/to/lark-cli")

“Lark: not authenticated”

Run M-x elark-auth-login or authenticate from terminal:

lark-cli auth login --domain all

Empty agenda / “no events found”

  1. Check you have calendar scopes: lark-cli auth check --scope calendar:readonly
  2. Try from terminal first: lark-cli calendar +agenda
  3. If the terminal works but Emacs doesn’t, enable debug logging: (setq elark--debug t) and check the *elark-log* buffer

Permission errors

Some operations require specific scopes. Re-login with the needed domain:

lark-cli auth login --domain calendar,task

Debugging

Enable debug logging to see all CLI invocations:

(setq elark--debug t)

Then check *elark-log* buffer (C-x b *elark-log*) to see every command that elark runs, including arguments and exit codes.

Architecture

elark.el                         Entry point, defgroup, prefix keymap, load-path setup

core/
  elark-core.el                  Process management, JSON parsing, CLI debug line stripping
  elark-auth.el                  OAuth device-code login, status, identity switching
  elark-transient.el             Top-level transient dispatch menu

ui/
  elark-ui.el                    Shared presentation helpers (loading spinner)

domain/
  elark-calendar.el              Calendar: agenda, events, create, free/busy, RSVP
  elark-tasks.el                 Tasks: list, create, complete, subtasks, tasklists
  elark-im.el                    Messenger: chats, messages, send, reply, events
  elark-mail.el                  Mail: mu4e-style inbox, shr HTML rendering, compose
  elark-docs.el                  Docs: search, fetch, create, update, media operations
  elark-drive.el                 Drive: dired-like browser, upload/download, owner names
  elark-sheets.el                Sheets: org-table read/write, create, find, export
  elark-contact.el               Contacts: user lookup, search, name resolution cache
  elark-meetings.el              Meetings: search, notes, recording with download links
  elark-whiteboard.el            Whiteboard: create and update whiteboards

ai/
  elark-ai.el                    AI: prompt -> plan -> execute -> synthesize -> present
  elark-ai-skills.el             AI: skill registry, loader, system prompt assembly
  elark-ai-context.el            AI: buffer context extraction for all domain modes
  elark-ai-llm.el                AI: LLM backend dispatch (gptel / acp / http)
  elark-ai-acp.el                AI: ACP agent backend (Claude Code, Gemini CLI, ... via acp.el)

test/
  elark-*-test.el                ERT tests for each module

demo/
  elark-native-ui-demo.el        Runnable magit-section / tabulated-list UI preview
  elark-*.mp4                    Domain screen-recording sources (hosted copies
                                are embedded in the Demos section)

All CLI calls funnel through elark--run-command (async) or elark--run-command-sync. Output is --format json by default, parsed with json-parse-string. CLI debug lines ([cmd +sub] prefixes and tip lines) are automatically stripped before JSON parsing.

elark.el automatically adds core/, ui/, domain/, and ai/ to the load-path at load time, so a single (add-to-list 'load-path "/path/to/elark") is sufficient.

License

GNU GPLv3

About

Lark/Feishu Emacs integration

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

0