Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
f03138b
feat(wiki): add +space-list / +node-list / +node-copy shortcuts (#392)
herbertliu May 15, 2026
4a45e00
docs: add svg whiteboard support to doc v2 skill (#901)
SunPeiYang996 May 15, 2026
7400226
feat(doc): add --width/--height flags to docs +media-insert (#832)
songyoung77 May 15, 2026
5778adf
fix(drive): preserve parent token on nested overwrite (#908)
fangshuyu-768 May 15, 2026
caff780
feat(config): lark-channel secret supports SecretInput protocol (#912)
mazhe-nerd May 15, 2026
14a3213
chore(release): v1.0.32 (#918)
liangshuo-1 May 15, 2026
0b72156
test: drop stale e2e yes flags (#920)
yxzhaao May 15, 2026
898e0ee
docs(lark-wiki): correct the --as default-identity claim (#919)
liujinkun2025 May 15, 2026
7bad9f2
fix: guide agents to yield during auth device flow (#933)
LawyerLyu May 18, 2026
ca6c6c3
fix: mark base field update high risk (#936)
zgz2048 May 18, 2026
33c292c
feat(extension): Plugin / Hook framework with command pruning (#910)
sang-neo03 May 18, 2026
2419524
feat: add drive version shortcut (#841)
wittam-01 May 18, 2026
4b721c0
fix(sheets): explicitly document safe JSON unmarshal ignore in DryRun…
KhanCold May 18, 2026
df4b657
feat(drive): add +sync workflow for Drive directories (#873)
fangshuyu-768 May 18, 2026
7af616b
feat(auth): add QR code support for device auth flow (#942)
JackZhao10086 May 18, 2026
67b16c5
feat(slides): improve slide planning and validation guidance (#847)
ethan-zhx May 18, 2026
de00343
feat: add markdown +patch shortcut (#857)
wittam-01 May 18, 2026
c8b9809
Revert "feat(auth): add QR code support for device auth flow (#942)" …
JackZhao10086 May 18, 2026
ef89d1f
chore(release): v1.0.33 (#952)
liangshuo-1 May 18, 2026
315e0ab
test: verify e2e resource cleanup (#949)
yxzhaao May 18, 2026
583349e
fix(docs): clarify replace_all selection errors (#954)
afengzi May 19, 2026
c4fb700
feat(wiki): add +node-get / +node-delete / +space-create shortcuts (#…
liujinkun2025 May 19, 2026
2bb69d1
feat: support Base attachment APIs (#887)
zgz2048 May 19, 2026
3354494
fix: address Base attachment review follow-ups (#958)
zgz2048 May 19, 2026
afa084e
chore(lint): exclude bidichk from test files (#959)
liangshuo-1 May 19, 2026
b8469d2
fix(auth): split bot and user identity diagnostics (#957)
mtsui-cmyk May 19, 2026
e511404
feat(mail): expose draft priority in --inspect projection and documen…
xzcong0820 May 19, 2026
95ffff4
docs(lark-im): clarify message activity search (#865)
BytedanceSearch May 19, 2026
0e70b05
feat(mail): bot+mailbox=me validation and dynamic --as help tests (#895)
xzcong0820 May 19, 2026
28c66be
fix(wiki): surface real node url for +node-create / +node-copy (#960)
liujinkun2025 May 19, 2026
4aa61db
feat(drive): add +inspect shortcut for document URL inspection with w…
fangshuyu-768 May 19, 2026
e6bc292
fix(identitydiag): harden verify path and tighten status semantics (#…
liangshuo-1 May 19, 2026
7c54f9b
feat(drive): switch markdown export to V2 docs_ai fetch API (#948)
fangshuyu-768 May 19, 2026
a4c5ec9
docs(drive): clarify add comment constraints (#967)
SunPeiYang996 May 19, 2026
939b7b6
docs(lark-vc): clarify meeting search evidence flow (#866)
BytedanceSearch May 19, 2026
13411d9
chore(release): v1.0.34 (#972)
liangshuo-1 May 19, 2026
d793790
feat(doc): warn before overwrite when document contains whiteboard or…
herbertliu May 20, 2026
fa45e1c
feat: add markdown +diff shortcut (#876)
wittam-01 May 20, 2026
69c3448
feat: Product CLI 4no-meego (#759)
yballul-bytedance May 20, 2026
0c4eadd
docs: add wiki base fast path (#982)
zgz2048 May 20, 2026
27a5eed
docs: prefer local comments for drive reviews (#981)
wittam-01 May 20, 2026
9272b9d
docs(skills): migrate docs +search to drive +search and fix creator_i…
liujinkun2025 May 20, 2026
8c73f49
docs: add media-preview reference (#990)
wittam-01 May 20, 2026
3a3fc31
feat: add incremental skills sync (#965)
zhangheng023 May 20, 2026
b2bff38
feat(mail): HTML lint lib + Larksuite-native autofix + lark-mail skill
bubbmon233 May 8, 2026
f961187
fix(mail): gate lint count fields behind --show-lint-details
bubbmon233 May 12, 2026
571f789
fix(mail): remove tip key from default draft-saved envelope
bubbmon233 May 12, 2026
51ebc5c
Revert "fix(mail): remove tip key from default draft-saved envelope"
bubbmon233 May 12, 2026
801030d
fix(mail): add draft_edit_hint and drop lint *_count fields
bubbmon233 May 14, 2026
61bcced
fix(mail): add HasFormat:true to MailSend/Reply/ReplyAll/Forward Shor…
bubbmon233 May 14, 2026
ef1c01b
fix(mail): add --body flag to +draft-edit shortcut
bubbmon233 May 15, 2026
65ee3f0
fix(mail): fix template li class and add --body-file to +send
bubbmon233 May 18, 2026
bd8d8a1
fix(mail): fix weekly--team-report template to pass --strict lint
bubbmon233 May 18, 2026
7c23a2f
fix(mail): fix research--market-report template to pass --strict lint
bubbmon233 May 18, 2026
0b8308a
fix(mail): address PR #787 review findings
bubbmon233 May 20, 2026
c7f9192
fix(mail): tweak palette 紧急橙 to a more recognizable orange
bubbmon233 May 20, 2026
97006ab
fix(mail): 修正 lark-mail-html.md 多级列表示例为正确嵌套结构
bubbmon233 May 21, 2026
b3f0c0c
docs(mail): 多级列表示例拆成全 ol 三级 + 全 ul 三级 两份
bubbmon233 May 21, 2026
4602a7e
fix(mail/templates): 修正团队周报 + 求职简历模板的多级列表嵌套结构
bubbmon233 May 21, 2026
6c7e5c5
清理代码注释和文档中的内部引用(共 15 文件,69 处)
bubbmon233 May 21, 2026
e40070c
fix(mail): 修复 PR #787 的 3 个 review finding
bubbmon233 May 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ jobs:
- name: Fetch meta data
run: python3 scripts/fetch_meta.py
- name: Run tests
run: go test -v -race -count=1 -timeout=5m ./cmd/... ./internal/... ./shortcuts/...
run: go test -v -race -count=1 -timeout=5m ./cmd/... ./internal/... ./shortcuts/... ./extension/...

lint:
needs: fast-gate
Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,13 @@ tests/mail/reports/

# Generated / test artifacts
.hammer/
.lark-slides/
internal/registry/meta_data.json
cmd/api/download.bin
app.log
/sidecar-server-demo
/server-demo
.tmp/
cover*.out

lark-env.sh
1 change: 1 addition & 0 deletions .gitleaks.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ id = "lark-session-token"
description = "Detect Lark session tokens"
regex = '''\bXN0YXJ0-[A-Za-z0-9_-]+-WVuZA\b'''
keywords = ["XN0YXJ0-", "-WVuZA"]

1 change: 1 addition & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ linters:
- path: _test\.go$
linters:
- bodyclose
- bidichk
- gocritic
- depguard
- forbidigo
Expand Down
74 changes: 74 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,77 @@

All notable changes to this project will be documented in this file.

## [v1.0.34] - 2026-05-19

### Features

- **drive**: Switch markdown export to V2 `docs_ai` fetch API (#948)
- **drive**: Add `+inspect` shortcut for document URL inspection with wiki unwrapping (#947)
- **wiki**: Add `+node-get` / `+node-delete` / `+space-create` shortcuts (#904)
- **base**: Support Base attachment APIs (#887)
- **mail**: Validate `bot` + `mailbox=me` and add dynamic `--as` help tests (#895)
- **mail**: Expose draft priority in `--inspect` projection and document `--set-priority` (#779)

### Bug Fixes

- **identitydiag**: Harden verify path and tighten status semantics (#961)
- **wiki**: Surface real node URL for `+node-create` / `+node-copy` (#960)
- **auth**: Split bot and user identity diagnostics (#957)
- **base**: Address Base attachment review follow-ups (#958)
- **docs**: Clarify `replace_all` selection errors (#954)

### Documentation

- **drive**: Clarify add comment constraints (#967)
- **lark-im**: Clarify message activity search (#865)

### Tests

- Verify e2e resource cleanup (#949)
- **lint**: Exclude `bidichk` from test files (#959)

## [v1.0.33] - 2026-05-18

### Features

- **markdown**: Add `+patch` shortcut (#857)
- **slides**: Improve slide planning and validation guidance (#847)
- **drive**: Add `+sync` workflow for Drive directories (#873)
- **drive**: Add drive version shortcut (#841)
- **extension**: Plugin / Hook framework with command pruning (#910)

### Bug Fixes

- **sheets**: Explicitly document safe JSON unmarshal ignore in `DryRun` (#935)
- **base**: Mark base field update high risk (#936)
- **auth**: Guide agents to yield during auth device flow (#933)

### Documentation

- **lark-wiki**: Correct the `--as` default-identity claim (#919)

### Tests

- Drop stale e2e `--yes` flags (#920)

## [v1.0.32] - 2026-05-15

### Features

- **doc**: Add `--width`/`--height` flags to `docs +media-insert` (#832)
- **wiki**: Add `+space-list` / `+node-list` / `+node-copy` shortcuts (#392)

### Bug Fixes

- **drive**: Preserve parent token on nested overwrite (#908)
- **selfupdate**: Use `LookPath` instead of `Executable` for binary verification (#886)
- **registry**: Wait for background meta refresh before test reset (#894)

### Documentation

- **doc**: Add SVG whiteboard support to `lark-doc` v2 skill (#901)
- **drive**: Add permission public patch error guidance (#863)

## [v1.0.31] - 2026-05-14

### Features
Expand Down Expand Up @@ -703,6 +774,9 @@ Bundled AI agent skills for intelligent assistance:
- Bilingual documentation (English & Chinese).
- CI/CD pipelines: linting, testing, coverage reporting, and automated releases.

[v1.0.34]: https://github.com/larksuite/cli/releases/tag/v1.0.34
[v1.0.33]: https://github.com/larksuite/cli/releases/tag/v1.0.33
[v1.0.32]: https://github.com/larksuite/cli/releases/tag/v1.0.32
[v1.0.31]: https://github.com/larksuite/cli/releases/tag/v1.0.31
[v1.0.30]: https://github.com/larksuite/cli/releases/tag/v1.0.30
[v1.0.29]: https://github.com/larksuite/cli/releases/tag/v1.0.29
Expand Down
37 changes: 34 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ DATE := $(shell date +%Y-%m-%d)
LDFLAGS := -s -w -X $(MODULE)/internal/build.Version=$(VERSION) -X $(MODULE)/internal/build.Date=$(DATE)
PREFIX ?= /usr/local

.PHONY: build vet test unit-test integration-test install uninstall clean fetch_meta
.PHONY: all build vet fmt-check test unit-test integration-test examples-build install uninstall clean fetch_meta gitleaks

all: test

fetch_meta:
python3 scripts/fetch_meta.py
Expand All @@ -19,13 +21,32 @@ build: fetch_meta
vet: fetch_meta
go vet ./...

# fmt-check fails when any file would be reformatted by gofmt. Keep this
# in sync with the fast-gate "Check formatting" step in CI.
fmt-check:
@unformatted=$$(gofmt -l . | grep -v '^\.claude/' || true); \
if [ -n "$$unformatted" ]; then \
echo "Unformatted Go files:"; \
echo "$$unformatted"; \
echo "Run 'gofmt -w .' and commit."; \
exit 1; \
fi

# ./extension/... keeps the public plugin SDK in the default test matrix.
unit-test: fetch_meta
go test -race -gcflags="all=-N -l" -count=1 ./cmd/... ./internal/... ./shortcuts/...
go test -race -gcflags="all=-N -l" -count=1 \
./cmd/... ./internal/... ./shortcuts/... ./extension/...

# examples-build keeps the shipped plugin-SDK examples compilable. If this
# breaks, the plugin author guide's "go build ./..." path is broken.
examples-build:
go build ./extension/platform/examples/audit-observer
go build ./extension/platform/examples/readonly-policy

integration-test: build
go test -v -count=1 ./tests/...

test: vet unit-test integration-test
test: vet fmt-check unit-test examples-build integration-test

install: build
install -d $(PREFIX)/bin
Expand All @@ -37,3 +58,13 @@ uninstall:

clean:
rm -f $(BINARY)

# Run secret-leak checks locally before pushing.
# Step 1: check-doc-tokens catches realistic-looking example tokens in reference
# docs and asks you to use _EXAMPLE_TOKEN placeholders instead.
# Step 2: gitleaks scans the full repo for real leaked secrets.
# Install gitleaks: https://github.com/gitleaks/gitleaks#installing
gitleaks:
@bash scripts/check-doc-tokens.sh
@command -v gitleaks >/dev/null 2>&1 || { echo "gitleaks not found. Install: brew install gitleaks"; exit 1; }
gitleaks detect --redact -v --exit-code=2
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ The official [Lark/Feishu](https://www.larksuite.com/) CLI tool, maintained by t
| 💬 Messenger | Send/reply messages, create and manage group chats, view chat history & threads, search messages, download media |
| 📄 Docs | Create, read, update, and search documents, read/write media & whiteboards |
| 📁 Drive | Upload and download files, search docs & wiki, manage comments |
| 📝 Markdown | Create, fetch, and overwrite Drive-native `.md` files |
| 📝 Markdown | Create, fetch, patch, and overwrite Drive-native `.md` files |
| 📊 Base | Create and manage tables, fields, records, views, dashboards, workflows, forms, roles & permissions, data aggregation & analytics |
| 📈 Sheets | Create, read, write, append, find, and export spreadsheet data |
| 🖼️ Slides | Create and manage presentations, read presentation content, and add or remove slides |
Expand Down Expand Up @@ -132,7 +132,7 @@ lark-cli auth status
| `lark-im` | Send/reply messages, group chat management, message search, upload/download images & files, reactions |
| `lark-doc` | Create, read, update, search documents (Markdown-based) |
| `lark-drive` | Upload, download files, manage permissions & comments |
| `lark-markdown` | Create, fetch, and overwrite Drive-native Markdown files |
| `lark-markdown` | Create, fetch, patch, and overwrite Drive-native Markdown files |
| `lark-sheets` | Create, read, write, append, find, export spreadsheets |
| `lark-slides` | Create and manage presentations, read presentation content, and add or remove slides |
| `lark-base` | Tables, fields, records, views, dashboards, data aggregation & analytics |
Expand Down
4 changes: 2 additions & 2 deletions README.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
| 💬 即时通讯 | 发送/回复消息、创建和管理群聊、查看聊天记录与话题、搜索消息、下载媒体文件 |
| 📄 云文档 | 创建、读取、更新文档、搜索文档、读写素材与画板 |
| 📁 云空间 | 上传和下载文件、搜索文档与知识库、管理评论 |
| 📝 Markdown | 创建、读取、覆盖更新 Drive 中的原生 `.md` 文件 |
| 📝 Markdown | 创建、读取、局部 patch、覆盖更新 Drive 中的原生 `.md` 文件 |
| 📊 多维表格 | 创建和管理数据表、字段、记录、视图、仪表盘、自动化流程、表单、角色权限,数据聚合分析 |
| 📈 电子表格 | 创建、读取、写入、追加、查找和导出表格数据 |
| 🖼️ 幻灯片 | 创建和管理演示文稿、读取演示文稿内容,以及新增或删除幻灯片页面 |
Expand Down Expand Up @@ -133,7 +133,7 @@ lark-cli auth status
| `lark-im` | 发送/回复消息、群聊管理、消息搜索、上传下载图片与文件、表情回复 |
| `lark-doc` | 创建、读取、更新、搜索文档(基于 Markdown) |
| `lark-drive` | 上传、下载文件,管理权限与评论 |
| `lark-markdown` | 创建、读取、覆盖更新 Drive 中的原生 Markdown 文件 |
| `lark-markdown` | 创建、读取、局部 patch、覆盖更新 Drive 中的原生 Markdown 文件 |
| `lark-sheets` | 创建、读取、写入、追加、查找、导出电子表格 |
| `lark-slides` | 创建和管理演示文稿、读取演示文稿内容,以及新增或删除幻灯片页面 |
| `lark-base` | 多维表格、字段、记录、视图、仪表盘、数据聚合分析 |
Expand Down
1 change: 1 addition & 0 deletions cmd/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ func NewCmdApiWithContext(ctx context.Context, f *cmdutil.Factory, runF func(*AP
cmdutil.RegisterFlagCompletion(cmd, "format", func(_ *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) {
return []string{"json", "ndjson", "table", "csv"}, cobra.ShellCompDirectiveNoFileComp
})
cmdutil.SetRisk(cmd, "write")

return cmd
}
Expand Down
26 changes: 26 additions & 0 deletions cmd/auth/auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,32 @@ func TestAuthLoginCmd_FlagParsing(t *testing.T) {
}
}

func TestAuthLoginCmd_HelpGuidesNonStreamingAgentsToSplitFlow(t *testing.T) {
f, stdout, _, _ := cmdutil.TestFactory(t, &core.CliConfig{
AppID: "test-app", AppSecret: "test-secret", Brand: core.BrandFeishu,
})

cmd := NewCmdAuthLogin(f, func(opts *LoginOptions) error { return nil })
cmd.SetOut(stdout)
cmd.SetErr(io.Discard)
cmd.SetArgs([]string{"--help"})
if err := cmd.Execute(); err != nil {
t.Fatalf("unexpected error: %v", err)
}

got := stdout.String()
for _, want := range []string{
"only delivers final turn messages",
"--no-wait --json",
"send the verification URL to the user as your final message",
"run --device-code in a later step",
} {
if !strings.Contains(got, want) {
t.Fatalf("help missing %q, got:\n%s", want, got)
}
}
}

func TestAuthCheckCmd_FlagParsing(t *testing.T) {
f, _, _, _ := cmdutil.TestFactory(t, &core.CliConfig{
AppID: "test-app", AppSecret: "test-secret", Brand: core.BrandFeishu,
Expand Down
1 change: 1 addition & 0 deletions cmd/auth/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ func NewCmdAuthCheck(f *cmdutil.Factory, runF func(*CheckOptions) error) *cobra.

cmd.Flags().StringVar(&opts.Scope, "scope", "", "scopes to check (space-separated)")
cmd.MarkFlagRequired("scope")
cmdutil.SetRisk(cmd, "read")

return cmd
}
Expand Down
1 change: 1 addition & 0 deletions cmd/auth/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ func NewCmdAuthList(f *cmdutil.Factory, runF func(*ListOptions) error) *cobra.Co
return authListRun(opts)
},
}
cmdutil.SetRisk(cmd, "read")

return cmd
}
Expand Down
11 changes: 7 additions & 4 deletions cmd/auth/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,12 @@ func NewCmdAuthLogin(f *cmdutil.Factory, runF func(*LoginOptions) error) *cobra.
Long: `Device Flow authorization login.

For AI agents: this command blocks until the user completes authorization in the
browser. Run it in the background and retrieve the verification URL from its output.`,
browser. If your harness only delivers final turn messages, use --no-wait --json,
send the verification URL to the user as your final message, end the turn, then
run --device-code in a later step after the user confirms authorization.`,
RunE: func(cmd *cobra.Command, args []string) error {
if mode := f.ResolveStrictMode(cmd.Context()); mode == core.StrictModeBot {
return output.ErrWithHint(output.ExitValidation, "strict_mode",
return output.ErrWithHint(output.ExitValidation, "command_denied",
fmt.Sprintf("strict mode is %q, user login is disabled in this profile", mode),
"if the user explicitly wants to switch to user identity, see `lark-cli config strict-mode --help` (confirm with the user before switching; switching does NOT require re-bind)")
}
Expand All @@ -62,6 +64,7 @@ browser. Run it in the background and retrieve the verification URL from its out
},
}
cmdutil.SetSupportedIdentities(cmd, []string{"user"})
cmdutil.SetRisk(cmd, "write")

cmd.Flags().StringVar(&opts.Scope, "scope", "", "scopes to request (space- or comma-separated). Combines additively with --domain/--recommend")
cmd.Flags().BoolVar(&opts.Recommend, "recommend", false, "request only recommended (auto-approve) scopes")
Expand Down Expand Up @@ -187,7 +190,7 @@ func authLoginRun(opts *LoginOptions) error {
log("View all options:")
log(msg.HintFooter)
log("")
log("Note: this command blocks until authorization is complete. Run it in the background and retrieve the verification URL from its output.")
log("Note: this command blocks until authorization is complete. For non-streaming agent harnesses, use --no-wait --json, send the verification URL as the final message of the turn, then run --device-code in a later step after the user confirms authorization.")
return output.ErrValidation("please specify the scopes to authorize")
}
}
Expand Down Expand Up @@ -266,7 +269,7 @@ func authLoginRun(opts *LoginOptions) error {
"verification_url": authResp.VerificationUriComplete,
"device_code": authResp.DeviceCode,
"expires_in": authResp.ExpiresIn,
"hint": fmt.Sprintf("Show verification_url to the user exactly as returned by the CLI and treat it as an opaque string. Do not URL-encode or decode it, do not normalize or rewrite it, do not add %%20, spaces, or punctuation, and do not wrap it as Markdown link text; prefer a fenced code block containing only the raw URL. Then immediately execute: lark-cli auth login --device-code %s (blocks until authorized or timeout). Do not instruct the user to run this command themselves.", authResp.DeviceCode),
"hint": fmt.Sprintf("Show verification_url to the user exactly as returned by the CLI and treat it as an opaque string. Do not URL-encode or decode it, do not normalize or rewrite it, do not add %%20, spaces, or punctuation, and do not wrap it as Markdown link text; prefer a fenced code block containing only the raw URL. For agent harnesses that only deliver final turn messages, make the URL the final message of the turn and return control to the user; do not block on --device-code in the same turn. After the user confirms authorization in a later step, run: lark-cli auth login --device-code %s", authResp.DeviceCode),
}
encoder := json.NewEncoder(f.IOStreams.Out)
encoder.SetEscapeHTML(false)
Expand Down
Loading