# https://github.com/larksuite/cli Project Manual

Generated at: 2026-06-17 12:18:26 UTC

## Table of Contents

- [Overview, Installation & Quick Start](#page-overview)
- [Three-Layer Command System & Domain Shortcuts](#page-commands)
- [Authentication, Identity Switching & Scope Management](#page-auth)
- [AI Agent Skills, Events & Platform Extensibility](#page-skills)

<a id='page-overview'></a>

## Overview, Installation & Quick Start

### Related Pages

Related topics: [Three-Layer Command System & Domain Shortcuts](#page-commands), [Authentication, Identity Switching & Scope Management](#page-auth)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [README.md](https://github.com/larksuite/cli/blob/main/README.md)
- [cmd/api/api.go](https://github.com/larksuite/cli/blob/main/cmd/api/api.go)
- [cmd/api/api_test.go](https://github.com/larksuite/cli/blob/main/cmd/api/api_test.go)
- [extension/platform/README.md](https://github.com/larksuite/cli/blob/main/extension/platform/README.md)
- [extension/platform/examples/README.md](https://github.com/larksuite/cli/blob/main/extension/platform/examples/README.md)
- [internal/client/pagination.go](https://github.com/larksuite/cli/blob/main/internal/client/pagination.go)
- [internal/client/api_errors.go](https://github.com/larksuite/cli/blob/main/internal/client/api_errors.go)
- [internal/qualitygate/config/README.md](https://github.com/larksuite/cli/blob/main/internal/qualitygate/config/README.md)

</details>

# Overview, Installation & Quick Start

## What is lark-cli?

`lark-cli` is an open-source command-line client for the Lark/Feishu Open Platform, designed primarily as an **agent-native interface** for AI agents (Claude Code, Cursor, etc.) to operate the Lark ecosystem. The project ships under the MIT license and is distributed as a standard Node.js / Go hybrid package — "MIT license, ready to use, just `npm install`" as the README puts it. Source: [README.md](https://github.com/larksuite/cli/blob/main/README.md).

The project is not a thin API wrapper. It delivers:

- **24+ structured Skills** compatible with popular AI tools, so agents can operate Lark with zero extra setup.
- **18 business domains**, **200+ curated commands**, and a growing Skills library.
- **Three-layer architecture** so users can choose the right granularity: Shortcuts (human & AI friendly) → API Commands (platform-synced) → Raw API (full coverage via `lark-cli api`).
- **AI-friendly defaults** — concise parameters, structured output, and short error hints designed to maximize agent call success rates.

Source: [README.md](https://github.com/larksuite/cli/blob/main/README.md).

```mermaid
graph TB
    A[AI Agent / User] --> B[Shortcuts<br/>lark im +messages-send]
    B --> C[API Commands<br/>lark-cli api POST /im/v1/messages]
    C --> D[Raw OpenAPI<br/>/open-apis/*]
    D --> E[(Lark / Feishu<br/>Open Platform)]
    style A fill:#e1f5ff
    style E fill:#ffe1e1
```

## Feature Coverage

The README's domain table summarizes the breadth of the project:

| Category      | Capabilities                                                                                                                      |
| ------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| 📅 Calendar   | View, create, update events; invite attendees; find rooms; RSVP; free/busy & time suggestions                                     |
| 💬 Messenger  | Send/reply messages; create/manage group chats; view 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, patch, and overwrite Drive-native `.md` files                                                                      |
| 📊 Base       | Tables, fields, records, views, dashboards, workflows, forms, roles & permissions, data aggregation & analytics                  |
| 📈 Sheets     | Create, read, write, append, find, export spreadsheets                                                                            |
| 🖼️ Slides     | Create and manage presentations; read content; add/remove slides                                                                  |
| ✅ Tasks      | Create, query, update, complete tasks; manage lists, subtasks, comments, reminders                                                |
| 📚 Wiki       | Knowledge spaces, nodes, documents                                                                                                |
| 👤 Contact    | Search users by name/email/phone, get profiles                                                                                    |
| 📧 Mail       | Browse, search, read, send, reply, forward, drafts, watch new mail                                                               |
| 🎥 Meetings   | Search meeting records; query minutes (summary, todos, transcript)                                                                |
| ✍️ Approval   | Query approval tasks; approve/reject/transfer/cancel/CC                                                                            |
| 🎯 OKR        | OKR objectives, key results, alignment                                                                                            |

Source: [README.md](https://github.com/larksuite/cli/blob/main/README.md). The skill library (`lark-doc`, `lark-sheets`, `lark-base`, `lark-mail`, `lark-vc`, etc.) is bundled inside `skills/` and listed in the same README.

## Installation & First API Call

The README markets a **3-minute path from install to first API call**: "One-click app creation, interactive login, from install to first API call in just 3 steps." Concretely:

1. **Install** the CLI (`npm install -g <pkg>` for the published distribution).
2. **Bootstrap credentials** — create a Lark/Feishu app and run the interactive login; credentials are stored in the **OS-native keychain**.
3. **Run a first command** — either a shortcut (`lark im +messages-send …`), a synced API command, or a raw OpenAPI call via the `api` subcommand.

The raw-API entry point is the `api` cobra command in [cmd/api/api.go](https://github.com/larksuite/cli/blob/main/cmd/api/api.go). It accepts `METHOD PATH` positional arguments plus flags for params, body, identity, output, pagination, format, jq, dry-run, and file payload. Its unit tests in [cmd/api/api_test.go](https://github.com/larksuite/cli/blob/main/cmd/api/api_test.go) confirm it supports `--as bot`, `--params null --page-size 50`, and `--dry-run` modes.

```bash
# Schema introspection — see any method's params, scopes, identities
lark-cli schema
lark-cli schema im.messages.delete

# Dry run for side-effectful calls
lark-cli im +messages-send --chat-id oc_xxx --text "hello" --dry-run

# Raw OpenAPI escape hatch
lark-cli api GET /open-apis/calendar/v4/calendars
```

## Common Operational Flags

The CLI standardizes several cross-command flags for predictable agent behavior:

| Flag           | Purpose                                                |
| -------------- | ------------------------------------------------------ |
| `--dry-run`    | Print the request that would be sent, no execution     |
| `--as bot|user`| Pick the identity (user vs. bot) for the call          |
| `--page-all`   | Auto-paginate until exhaustion                         |
| `--page-size`  | Items per page                                         |
| `--page-limit` | Max pages to fetch (default 10)                        |
| `--page-delay` | Delay (ms) between page requests                       |
| `--format`     | Output format (json / table / ndjson)                  |
| `--jq`         | Server-side jq expression over the response            |

The pagination flags are honored by the shared client in [internal/client/pagination.go](https://github.com/larksuite/cli/blob/main/internal/client/pagination.go), which merges per-page payloads into a single result and prints a `[pagination] merged N pages, M total items` line. Error responses are normalized into typed `errs.*` problems in [internal/client/api_errors.go](https://github.com/larksuite/cli/blob/main/internal/client/api_errors.go) (for example, `InternalError{SubtypeInvalidResponse}` with a hint telling the agent to "rerun with --output" for non-JSON file downloads).

## Security & Risk Warnings

The README has a prominent "Security & Risk Warnings" block. Because the tool is invoked by AI Agents, it "carries inherent risks such as model hallucinations, unpredictable execution, and prompt injection." After a user authorizes permissions, the agent "will act under your user identity within the authorized scope," which can lead to sensitive data leakage or unauthorized operations. Source: [README.md](https://github.com/larksuite/cli/blob/main/README.md).

Mitigations baked into the default configuration include input injection protection, terminal output sanitization, and OS-native keychain credential storage. The README explicitly warns against relaxing these defaults and recommends using the bot "as a private conversational assistant" — do not add it to group chats.

## Extensibility: Plugins & Quality Gate

Beyond the core CLI, the project ships a **Plugin SDK** for policy and observability plugins. The [extension/platform/README.md](https://github.com/larksuite/cli/blob/main/extension/platform/README.md) describes a hook chain (Observer → Wrap → Restrict → On(Startup/Shutdown)) that plugins register against. Runnable examples live under [extension/platform/examples/README.md](https://github.com/larksuite/cli/blob/main/extension/platform/examples/README.md): `audit-observer` (one Observer that logs to stderr) and `readonly-policy` (a `Restrict()` plugin enforcing `MaxRisk=read` with `FailClosed` auto-pairing). Both are built by CI via `make examples-build` so they cannot silently drift from the SDK.

The project also enforces a machine-facing **quality gate** over CLI contracts: command/flag naming, Skills command references, executable `--dry-run` examples, default-output facts, and command-boundary error contracts. Local invocation is `make quality-gate`. Source: [internal/qualitygate/config/README.md](https://github.com/larksuite/cli/blob/main/internal/qualitygate/config/README.md).

## Known Community Concerns (Overview-relevant)

Several recurring community themes are worth flagging during onboarding:

- **Skill directory pollution** — installing skills drops them into the root `~/.agents/skills/` directory alongside the user's own skills, making the list hard to scan. Tracked in [issue #1497](https://github.com/larksuite/cli/issues/1497) and echoed in [issue #1385](https://github.com/larksuite/cli/issues/1385).
- **Context bloat from full-install** — with 20+ skills installed, on-disk footprint grows to hundreds of files and tens of thousands of lines, bloating the agent's context window. Tracked in [issue #501](https://github.com/larksuite/cli/issues/501).
- **App creation required for personal use** — the onboarding flow assumes you create a Lark/Feishu app; there is no first-class "personal identity" path yet. Tracked in [issue #234](https://github.com/larksuite/cli/issues/234).
- **Multi-user authorization** — agents cannot currently distinguish per-`openid` authorizations, which limits enterprise multi-user deployments. Tracked in [issue #204](https://github.com/larksuite/cli/issues/204).

These do not block evaluation, but they are reasonable caveats to communicate to new users during the quick-start walkthrough.

## See Also

- [Skills Catalog & Authoring Guide](#) (planned)
- [Three-Layer Architecture: Shortcuts vs. API Commands vs. Raw API](#) (planned)
- [Plugin SDK & Observability](#) (planned)

---

<a id='page-commands'></a>

## Three-Layer Command System & Domain Shortcuts

### Related Pages

Related topics: [Overview, Installation & Quick Start](#page-overview), [Authentication, Identity Switching & Scope Management](#page-auth)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [README.md](https://github.com/larksuite/cli/blob/main/README.md)
- [cmd/api/api.go](https://github.com/larksuite/cli/blob/main/cmd/api/api.go)
- [cmd/api/api_test.go](https://github.com/larksuite/cli/blob/main/cmd/api/api_test.go)
- [internal/client/pagination.go](https://github.com/larksuite/cli/blob/main/internal/client/pagination.go)
- [extension/platform/README.md](https://github.com/larksuite/cli/blob/main/extension/platform/README.md)
- [extension/platform/examples/README.md](https://github.com/larksuite/cli/blob/main/extension/platform/examples/README.md)
- [extension/platform/examples/readonly-policy/README.md](https://github.com/larksuite/cli/blob/main/extension/platform/examples/readonly-policy/README.md)
- [internal/qualitygate/config/README.md](https://github.com/larksuite/cli/blob/main/internal/qualitygate/config/README.md)
</details>

# Three-Layer Command System & Domain Shortcuts

## 1. Overview

`lark-cli` exposes the Lark/Feishu Open Platform through three concentric layers, letting users and AI agents pick the right level of abstraction for a task. The README states this explicitly: a **Three-Layer Architecture** with *Shortcuts (human & AI friendly)* → *API Commands (platform-synced)* → *Raw API (full coverage)*, where the user "choose[s] the right granularity" for each invocation. Source: [README.md](https://github.com/larksuite/cli/blob/main/README.md).

The design reflects a recurring community concern: as the project grew past 20 domain skills, users reported context bloat and trigger ambiguity. Issue #501 ("按需加载 skill 内容，替代全量本地安装模式") and #1385 ("技能太多了，claude code都提醒技能描述超过限制了") both argue that a single monolithic skill list is hard for agents to navigate. The three-layer system responds by separating **opinionated, AI-tuned shortcuts** from **fully exhaustive API surface**, so agents can call a focused command and humans can drop down to the raw endpoint only when needed. Source: [README.md](https://github.com/larksuite/cli/blob/main/README.md).

```mermaid
flowchart TB
    A[Layer 1: Domain Shortcuts<br/>e.g. lark-cli im +messages-send] --> B[Layer 2: API Commands<br/>e.g. lark-cli im messages list]
    B --> C[Layer 3: Raw API<br/>e.g. lark-cli api GET /open-apis/...]
    A -.uses.-> D[(Underlying OpenAPI)]
    B -.uses.-> D
    C -.uses.-> D
    A -.wrapped by.-> E[Plugin Hook Chain<br/>Observer / Wrap / Restrict]
    B -.wrapped by.-> E
    C -.wrapped by.-> E
```

## 2. Layer 1 — Domain Shortcuts (Human & AI Friendly)

Shortcuts are hand-authored, high-level commands prefixed with a `+` symbol and grouped under a business domain. They are the primary surface tested with real AI agents and the surface most users interact with. The README lists more than 20 shortcut-bearing skills (`lark-im`, `lark-doc`, `lark-drive`, `lark-sheets`, `lark-slides`, `lark-base`, `lark-task`, `lark-mail`, `lark-contact`, `lark-wiki`, `lark-event`, `lark-vc`, `lark-whiteboard`, `lark-minutes`, `lark-openapi-explorer`, `lark-skill-maker`, `lark-attendance`, `lark-approval`, `lark-workflow-meeting-summary`, etc.) covering 18 business domains. Source: [README.md](https://github.com/larksuite/cli/blob/main/README.md).

Each shortcut encapsulates:

- **AI-friendly parameters** — concise, with smart defaults and structured output to maximize agent call success rate.
- **Pre-checks** — typed validation errors emitted from shared pre-checks (added in v1.0.47 per `feat(common): emit typed validation errors from shared shortcut pre-checks (#1242)`).
- **Dry-run support** — preview the request before side effects fire.

These shortcuts are also what the project's internal **quality gate** polices. `internal/qualitygate/config/README.md` defines rules for "command and flag naming, Skills command references, executable examples under `--dry-run`, default-output facts for semantic review, command boundary error contracts", and ships a `command-manifest.json` snapshot of hand-authored commands used by the naming and default-output rules. The legacy-naming allowlists (`legacy-commands.txt`, `legacy-flags.txt`) record historical hand-authored shortcut names that cannot be renamed immediately — a sign that shortcuts are treated as a stable, public contract. Source: [internal/qualitygate/config/README.md](https://github.com/larksuite/cli/blob/main/internal/qualitygate/config/README.md).

A worked policy example, `readonly-policy`, shows how Layer 1 commands are filtered in practice: the plugin calls `Restrict(&Rule{Allow: ["docs/**", "im/**"], MaxRisk: platform.RiskRead})`, and any write shortcut (e.g. `docs +update`) is rejected with a structured `command_denied` envelope, while read shortcuts like `docs +fetch` pass through normally. Source: [extension/platform/examples/readonly-policy/README.md](https://github.com/larksuite/cli/blob/main/extension/platform/examples/readonly-policy/README.md).

## 3. Layer 2 — API Commands (Platform-Synced)

The middle layer exposes individual Lark OAPI endpoints as one-to-one commands, e.g. `lark-cli calendar calendars list` or `lark-cli calendar events instance_view --params '{...}'`. These commands are auto-generated from Lark OAPI metadata and "curated through evaluation and quality gates" — the quality gate notes they are intentionally excluded from `command-manifest.json` (which covers only hand-authored shortcuts) but are included in `command-index.json` "only so command references can be checked against the real CLI surface". Source: [internal/qualitygate/config/README.md](https://github.com/larksuite/config) and [README.md](https://github.com/larksuite/cli/blob/main/README.md).

Layer 2 commands share the runtime features of Layer 1 — output formats, pagination, dry-run, schema introspection — so an agent can seamlessly move from a shortcut to its underlying endpoint.

## 4. Layer 3 — Raw API Calls (Full Coverage)

When neither a shortcut nor a curated command exists, the `api` command lets callers hit any of the 2,500+ Lark endpoints directly. The implementation lives in `cmd/api/api.go`, whose `APIOptions` struct captures `Method`, `Path`, `Params`, `Data`, `As` (identity), `Output`, `PageAll`, `PageSize`, `PageLimit`, `PageDelay`, `Format`, `JqExpr`, `DryRun`, and `File`. Source: [cmd/api/api.go:20-45](https://github.com/larksuite/cli/blob/main/cmd/api/api.go).

Key behaviors at this layer:

- **Path normalization** — `normalisePath` strips a host prefix and prepends `/open-apis/` when missing, so `https://open.feishu.cn/open-apis/im/v1/messages` and `im/v1/messages` are equivalent. Source: [cmd/api/api.go:47-55](https://github.com/larksuite/cli/blob/main/cmd/api/api.go).
- **Strict-mode enforcement** — `f.CheckStrictMode(opts.Ctx, opts.As)` is called before dispatch, so unannotated commands fail closed under strict identity resolution. Source: [cmd/api/api.go:64-66](https://github.com/larksuite/cli/blob/main/cmd/api/api.go).
- **Mutual-exclusion guard** — `--output` and `--page-all` cannot be combined, because binary downloads and JSON pagination are incompatible. Source: [cmd/api/api.go:68-75](https://github.com/larksuite/cli/blob/main/cmd/api/api.go).
- **Identity-aware JSON envelope** — identity info is folded into the response envelope instead of being printed to stderr, so piped consumers see a single clean JSON stream. Source: [cmd/api/api.go:96-100](https://github.com/larksuite/cli/blob/main/cmd/api/api.go).

Pagination itself is handled by `internal/client/pagination.go`, where `PaginationOptions` defaults `PageLimit` to 10 pages and `PageDelay` to 200 ms, then `mergePagedResults` discovers the array field via `output.FindArrayField` and concatenates pages. Source: [internal/client/pagination.go:14-30](https://github.com/larksuite/cli/blob/main/internal/client/pagination.go).

## 5. Cross-Layer Concerns

All three layers pass through the same plugin hook chain. Per the extension platform README, on every command dispatch the host runs hooks in registration order — `Observer Before` → `Wrap` (around `RunE`) → `Observer After` — and a `command_denied` decision from `Restrict` or strict mode bypasses the `Wrap` chain entirely (observers still fire so audit plugins see the rejected dispatch). This means a policy plugin written for one layer automatically protects the other two, because the hook chain is the shared choke point. Source: [extension/platform/README.md](https://github.com/larksuite/cli/blob/main/extension/platform/README.md) and [extension/platform/examples/README.md](https://github.com/larksuite/cli/blob/main/extension/platform/examples/README.md).

The test suite in `cmd/api/api_test.go` exercises the same surface — e.g. `TestApiCmd_NullParamsWithPageSize` confirms that `--params null` followed by `--page-size 50` correctly overlays `page_size` without panicking, which is a Layer 3 behavior agents can rely on regardless of which upper layer they came from. Source: [cmd/api/api_test.go](https://github.com/larksuite/cli/blob/main/cmd/api/api_test.go).

## 6. Common Failure Modes

- **Strict-mode rejection** — calling an unannotated command under strict identity resolution returns a `command_denied` envelope. Always run a shortcut with `--dry-run` first when its identity is unclear. Source: [cmd/api/api.go:64-66](https://github.com/larksuite/cli/blob/main/cmd/api/api.go).
- **`--output` + `--page-all` collision** — the API command refuses the combination; drop one flag. Source: [cmd/api/api.go:68-75](https://github.com/larksuite/cli/blob/main/cmd/api/api.go).
- **Policy plugin veto** — a read-only policy will reject any write shortcut with a structured `command_denied` envelope; this is enforced across all three layers via the shared hook chain. Source: [extension/platform/examples/readonly-policy/README.md](https://github.com/larksuite/cli/blob/main/extension/platform/examples/readonly-policy/README.md).

## See Also

- [Plugin SDK & Hook Chain](https://github.com/larksuite/cli/blob/main/extension/platform/README.md) — how the three layers are wrapped and policed
- [CLI Quality Gate](https://github.com/larksuite/cli/blob/main/internal/qualitygate/config/README.md) — naming, manifest, and semantic review of hand-authored shortcuts
- [Linter Domains](https://github.com/larksuite/cli/blob/main/lint/README.md) — source-level guards on the command surface

---

<a id='page-auth'></a>

## Authentication, Identity Switching & Scope Management

### Related Pages

Related topics: [Overview, Installation & Quick Start](#page-overview), [AI Agent Skills, Events & Platform Extensibility](#page-skills)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [README.md](https://github.com/larksuite/cli/blob/main/README.md)
- [cmd/api/api.go](https://github.com/larksuite/cli/blob/main/cmd/api/api.go)
- [internal/client/client.go](https://github.com/larksuite/cli/blob/main/internal/client/client.go)
- [internal/client/api_errors.go](https://github.com/larksuite/cli/blob/main/internal/client/api_errors.go)
- [sidecar/server-demo/README.md](https://github.com/larksuite/cli/blob/main/sidecar/server-demo/README.md)
- [extension/platform/README.md](https://github.com/larksuite/cli/blob/main/extension/platform/README.md)
- [cmd/api/api_test.go](https://github.com/larksuite/cli/blob/main/cmd/api/api_test.go)
- [internal/client/api_errors_test.go](https://github.com/larksuite/cli/blob/main/internal/client/api_errors_test.go)

</details>

# Authentication, Identity Switching & Scope Management

lark-cli is a command-line client for the Lark/Feishu Open Platform that operates under two distinct identities — a **bot** identity (derived from `app_id` + `app_secret`, always available after `config init`) and a **user** identity (derived from an OAuth refresh token granted during `auth login`). Every command resolves one of these identities, acquires a matching access token, and enforces an authorization scope. This page documents how the CLI acquires credentials, switches between identities, validates scopes, and propagates authentication failures back to the caller.

## Authentication Model

The CLI separates **configuration** (app credentials) from **authorization** (user-delegated permissions). The two flows are independent:

| Flow | Command | Persisted In | Identity Issued |
| --- | --- | --- | --- |
| App bootstrap | `lark-cli config init --new` | Local config file | Bot (tenant_access_token) |
| User authorization | `lark-cli auth login` | OS-native keychain | User (user_access_token) |

`auth login` is only required for user identity. If a deployment will only ever issue bot requests — for example, a sandboxed `sidecar-server-demo` that mints a tenant access token (TAT) on the fly from `app_id` + `app_secret` — `config init` alone is sufficient. Source: [sidecar/server-demo/README.md](https://github.com/larksuite/cli/blob/main/sidecar/server-demo/README.md)

The bot path never requires an interactive prompt, which is what makes unattended Agent deployments viable; the user path always requires a browser-based consent screen and stores the resulting `refresh_token` in the OS keychain. Source: [README.md](https://github.com/larksuite/cli/blob/main/README.md)

## `auth login` Variants and Scope Selection

The login command accepts four mutually-reinforcing knobs that control **which scopes** the resulting refresh token can exercise. Source: [README.md](https://github.com/larksuite/cli/blob/main/README.md)

| Flag | Behavior |
| --- | --- |
| `--domain calendar,task` | Pre-fills the consent screen with these business domains |
| `--recommend` | Asks the server for auto-approval scopes appropriate to a default install |
| `--scope "calendar:calendar:read"` | Pins the login to an exact scope string (used for least-privilege Agents) |
| `--no-wait` | Returns the verification URL immediately and exits (non-blocking Agent mode) |
| `--device-code <CODE>` | Resumes polling a previously-started device-code flow |

The combination of `--domain` and `--recommend` is the most common pattern for new users: the consent page opens pre-populated with the platform's standard scope set, and the agent never has to re-prompt. `--scope` is preferred when an Agent should be locked to the smallest possible permission surface — for example, a read-only reporting Agent that only needs `calendar:calendar:read`.

## Identity Switching with `--as`

Every command that touches the platform accepts an `--as` flag whose value is a `core.Identity` (either `user` or `bot`). The flag is plumbed into `APIOptions.As` and validated against the strict-mode policy before any request is built. Source: [cmd/api/api.go](https://github.com/larksuite/cli/blob/main/cmd/api/api.go)

```bash
# Read the calendar as the authorized user
lark-cli calendar +agenda --as user

# Send a chat message as the bot
lark-cli im +messages-send --as bot --chat-id "oc_xxx" --text "Hello"
```

The selection of identity is enforced by `f.CheckStrictMode(ctx, opts.As)`, which is called immediately after parsing in the `api` command. This is the runtime hook used to lock a sandboxed Agent to a single identity — see the next section. Source: [cmd/api/api.go](https://github.com/larksuite/cli/blob/main/cmd/api/api.go)

## Strict Mode and the Auth-Proxy Sandbox

When the CLI is launched inside an untrusted sandbox (the sidecar demo is the canonical example), the parent process sets two environment variables to constrain the child:

| Variable | Purpose |
| --- | --- |
| `LARKSUITE_CLI_AUTH_PROXY` | Loopback HTTP endpoint that mints scoped tokens for the sandbox |
| `LARKSUITE_CLI_PROXY_KEY` | HMAC key authenticating the sandbox to the proxy |
| `LARKSUITE_CLI_APP_ID` | App ID the proxy will use to mint tokens |
| `LARKSUITE_CLI_BRAND` | `feishu` or `lark` — selects the Open Platform tenant |
| `LARKSUITE_CLI_DEFAULT_AS` | Force a default identity when a command omits `--as` |
| `LARKSUITE_CLI_STRICT_MODE` | Lock the sandbox to a single identity (e.g. `user` only) |

The proxy URL is validated on startup: it must use `http://` (or a bare `host:port`), resolve to a loopback address or one of the recognized same-host aliases (`localhost`, `host.docker.internal`, `host.containers.internal`, `host.lima.internal`, `gateway.docker.internal`), and carry no path, query, fragment, or `user:pass@`. The same-machine constraint is intentional — cross-machine credential brokering is treated as a different product requiring mTLS and per-client key rotation. Source: [sidecar/server-demo/README.md](https://github.com/larksuite/cli/blob/main/sidecar/server-demo/README.md)

```mermaid
sequenceDiagram
    participant Agent
    participant CLI as lark-cli (sandbox)
    participant Proxy as Auth Proxy (loopback)
    participant Lark as Lark Open Platform

    Agent->>CLI: lark-cli calendar +agenda --as user
    CLI->>CLI: CheckStrictMode(ctx, user) → ok
    CLI->>Proxy: GET /token (HMAC-signed, scoped to user)
    Proxy->>Lark: POST /auth/v3/tenant_access_token/internal
    Lark-->>Proxy: TAT
    Proxy-->>CLI: scoped user token
    CLI->>Lark: GET /open-apis/calendar/v4/...
    Lark-->>CLI: events
    CLI-->>Agent: table output
```

## Token Lifecycle and Error Mapping

When the credential chain cannot produce a token for the requested identity, the SDK boundary converts the failure into a typed `errs.AuthenticationError` with a recoverable hint. Source: [internal/client/client.go](https://github.com/larksuite/cli/blob/main/internal/client/client.go)

```text
no access token available for user
  → run: lark-cli auth login to re-authorize
```

The CLI also distinguishes transport-level failures at the SDK boundary: JSON-decode failures become `InternalError{SubtypeInvalidResponse}` (with a hint to retry with `--output` for file endpoints), and `x509.UnknownAuthorityError` / `net.DNSError` are folded into `NetworkError` subtypes (`tls`, `dns`). These are emitted by `WrapDoAPIError` and pass through `errs.ProblemOf` so downstream layers can pattern-match with `errors.As`. Source: [internal/client/api_errors.go](https://github.com/larksuite/cli/blob/main/internal/client/api_errors.go)

The combination of typed errors, content-safety blocks (e.g. `CategoryPolicy / SubtypeContentSafety / Rules: ["pagination"]` when `--page-all` is misused with `--output`), and a dedicated migration path for legacy bare `error` returns is enforced by the quality gate's **command boundary error contract**. Source: [cmd/api/api_test.go](https://github.com/larksuite/cli/blob/main/cmd/api/api_test.go) and [internal/client/api_errors_test.go](https://github.com/larksuite/cli/blob/main/internal/client/api_errors_test.go)

## Plugin Interaction and Community Considerations

The plugin SDK observes the same identity flow: `Restrict()` rules may declare `MaxRisk`, allow/deny lists, and required identities, and the engine combines them with OR semantics. A `command_denied` decision bypasses the wrap chain entirely, but observers still fire so audit plugins see the rejected dispatch. Source: [extension/platform/README.md](https://github.com/larksuite/cli/blob/main/extension/platform/README.md)

Three recurring community requests surface against the current model and are worth noting:

- **Personal identity without an app** — Issue #234 asks whether user-only flows can run without first creating a Lark app; today every installation requires an `app_id` because bot identity is what issues the TAT used by the sidecar proxy.
- **Multi-user authorization** — Issue #204 notes that a shared CLI install cannot distinguish between two `openid`s and therefore cannot apply per-user scopes. Multi-tenant agent support is still an open direction.
- **Bot-only message sending** — Issue #89 reports cases where the user wanted to send a message as themselves; the current default is bot identity, and explicit `--as user` plus a completed `auth login` is required.

These limitations explain why `--as user` and `--scope` are documented as first-class flags: they are the only knobs available today for tightening the trust boundary on top of a single-app, single-user installation.

## See Also

- [README.md](https://github.com/larksuite/cli/blob/main/README.md) — top-level usage, including the `auth login` flag matrix
- [sidecar/server-demo/README.md](https://github.com/larksuite/cli/blob/main/sidecar/server-demo/README.md) — full sandbox env-var contract and loopback validation rules
- [extension/platform/README.md](https://github.com/larksuite/cli/blob/main/extension/platform/README.md) — plugin observer/wrap/restrict lifecycle
- [internal/qualitygate/config/README.md](https://github.com/larksuite/cli/blob/main/internal/qualitygate/config/README.md) — command boundary error contract and the rollout sequence that gates typed-error enforcement

---

<a id='page-skills'></a>

## AI Agent Skills, Events & Platform Extensibility

### Related Pages

Related topics: [Three-Layer Command System & Domain Shortcuts](#page-commands), [Authentication, Identity Switching & Scope Management](#page-auth)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [cmd/skill/skill.go](https://github.com/larksuite/cli/blob/main/cmd/skill/skill.go)
- [cmd/event/event.go](https://github.com/larksuite/cli/blob/main/cmd/event/event.go)
- [cmd/event/subscribe.go](https://github.com/larksuite/cli/blob/main/cmd/event/subscribe.go)
- [cmd/event/consume.go](https://github.com/larksuite/cli/blob/main/cmd/event/consume.go)
- [cmd/event/list.go](https://github.com/larksuite/cli/blob/main/cmd/event/list.go)
- [cmd/event/stop.go](https://github.com/larksuite/cli/blob/main/cmd/event/stop.go)
- [extension/platform/README.md](https://github.com/larksuite/cli/blob/main/extension/platform/README.md)
- [extension/platform/examples/README.md](https://github.com/larksuite/cli/blob/main/extension/platform/examples/README.md)
- [internal/qualitygate/config/README.md](https://github.com/larksuite/cli/blob/main/internal/qualitygate/config/README.md)
- [scripts/skill-format-check/README.md](https://github.com/larksuite/cli/blob/main/scripts/skill-format-check/README.md)
- [scripts/pr-labels/README.md](https://github.com/larksuite/cli/blob/main/scripts/pr-labels/README.md)
- [README.md](https://github.com/larksuite/cli/blob/main/README.md)
</details>

# AI Agent Skills, Events & Platform Extensibility

## Overview

`lark-cli` is an agent-native command-line client for the Lark/Feishu Open Platform. Beyond the three-layer command surface (Shortcuts → API Commands → Raw API), the binary exposes three subsystems that turn it into a programmable agent runtime: a curated **Skills** catalog consumed by AI agents, an **Events** command family for real-time WebSocket subscriptions, and a **Plugin SDK** that lets third-party Go binaries extend, observe, and restrict CLI execution. Source: [README.md:9-10]()

## Skills Subsystem

### Purpose and Layout

Each `lark-*` skill is a directory of Markdown files plus a `SKILL.md` frontmatter. The catalog ships 24 structured skills covering 18 business domains and provides 200+ curated commands. Source: [README.md:9-13]() The skills are installed into a user-local directory (for example `~/.agents/skills/`) and loaded into the host AI agent's context.

### Install Command

The `lark skills` command group (rooted at `cmd/skill/skill.go`) handles installation and lifecycle operations. Community discussion has requested installing into a dedicated `lark/` subdirectory rather than the skills root, to separate the 20+ shipped skills from user-authored content. Source: [cmd/skill/skill.go]() (see also feature request #1497).

### Format Enforcement

Skill files must conform to a YAML frontmatter template defined in `skill-template/skill-template.md`. The required fields are `name` and `description`; a missing `metadata` block produces a warning rather than a failure. Source: [scripts/skill-format-check/README.md:7-12]() The script runs in CI on every PR that touches `skills/` and the `lark-shared` skill is explicitly excluded. Source: [scripts/skill-format-check/README.md:16]()

### Quality Gate Integration

The `internal/qualitygate/config/README.md` defines a deterministic analyzer that protects machine-facing contracts: command/flag naming, executable examples under `--dry-run`, default-output facts for semantic review, and a command-boundary error contract. Source: [internal/qualitygate/config/README.md:3-9]() Semantic categories such as `skill_quality` are blocking once `SEMANTIC_REVIEW_BLOCK=true` is enabled, with TSV waivers providing time-bounded relief. Source: [internal/qualitygate/config/README.md:21-23, 53-58]()

## Events Subsystem

The `cmd/event/` command family provides real-time event subscriptions, with the surface split across focused files: `event.go` for the root command, `subscribe.go` for new subscription creation, `consume.go` for pulling events, `list.go` for inventorying active subscriptions, and `stop.go` for tearing them down. Source: [cmd/event/event.go](), [cmd/event/subscribe.go](), [cmd/event/consume.go](), [cmd/event/list.go](), [cmd/event/stop.go]() This pattern matches the `lark-event` skill shipped in the catalog, which advertises "real-time event subscriptions (WebSocket), regex routing & agent-friendly format". Source: [README.md:38]()

## Platform Extensibility (Plugin SDK)

### Plugin Lifecycle

The `extension/platform` package exposes a Go SDK for in-process plugins. A plugin implements one or more capabilities — `Observer`, `Wrap`, `Restrict`, and lifecycle hooks `On(Startup)` / `On(Shutdown)` — and registers them with the host via `Install(Registrar)`. Source: [extension/platform/README.md:33-37]()

```mermaid
sequenceDiagram
    participant Host as CLI Host
    participant SDK as Plugin SDK
    participant Plugin as Plugin

    Note over Host,Plugin: Process start
    Host->>SDK: Load plugin .so / main
    Plugin->>SDK: Install(Registrar)
    SDK->>Plugin: On(Startup) fire

    Note over Host,Plugin: Each command dispatch
    Host->>SDK: hook chain (in registration order)
    SDK->>Plugin: Observer Before
    SDK->>Plugin: Wrap (around RunE)
    SDK->>Plugin: Observer After

    Note over Host,Plugin: Process exit
    Host->>SDK: Emit(Shutdown)
    SDK->>Plugin: On(Shutdown) fire
```

Source: [extension/platform/README.md:21-37]()

### Safety Contract

A plugin that calls `Restrict()` must declare `FailClosed`; the builder auto-flips it and the lower-level `Plugin` interface rejects mismatches with `restricts_mismatch`. Source: [extension/platform/README.md:53-56]() Multiple `Restrict()` calls combine with OR across axes, and a `command_denied` decision bypasses the `Wrap` chain entirely while still firing observers — so audit plugins see the rejected dispatch. Source: [extension/platform/README.md:33-39]()

### Reference Examples

The `extension/platform/examples/` directory ships fork-and-blank imports built by CI: `audit-observer` (one Observer matching every command, logging to stderr) and `readonly-policy` (a `Restrict` policy with `MaxRisk=read` that demonstrates the `FailClosed` + `Restricts=true` auto-pairing). CI runs `make examples-build` so examples cannot silently drift from the SDK. Source: [extension/platform/examples/README.md:5-15]()

## Auxiliary Tooling

### PR Label Sync

`scripts/pr-labels/index.js` classifies PRs by effective lines of code (`size/S|M|L|XL`) and tags them with `domain/*` labels (`im`, `vc`, `ccm`, `base`, `mail`, `calendar`, `task`, `contact`) to give reviewers an immediate sense of impact scope. Source: [scripts/pr-labels/README.md:5-20]()

### Common Failure Modes

- **Plugin rule mismatch** — A `Restrict` call without `FailClosed` returns `restricts_mismatch`. Source: [extension/platform/README.md:55]()
- **Multiple restrict plugins** — Two distinct plugins each calling `Restrict()` triggers `multiple_restrict_plugins`, enforcing single-owner semantics. Source: [extension/platform/README.md:57-63]()
- **Skill frontmatter drift** — Missing `name`/`description` in `SKILL.md` fails CI via the format check. Source: [scripts/skill-format-check/README.md:7-12]()
- **Skill context bloat** — Community request #501 reports that the all-skills-install pattern causes 212 files / ~22k lines to load into agent context, motivating on-demand loading.

## See Also

- [README.md](https://github.com/larksuite/cli/blob/main/README.md) — Project overview, features, and security warnings
- [internal/qualitygate/config/README.md](https://github.com/larksuite/cli/blob/main/internal/qualitygate/config/README.md) — Quality gate taxonomy, waivers, and rollout policy
- [extension/platform/README.md](https://github.com/larksuite/cli/blob/main/extension/platform/README.md) — Plugin SDK contract and safety guarantees
- [scripts/skill-format-check/README.md](https://github.com/larksuite/cli/blob/main/scripts/skill-format-check/README.md) — SKILL.md frontmatter validation rules

---

<!-- evidence_pipeline_checked: true -->
<!-- evidence_injected: true -->

---

## Pitfall Log

Project: larksuite/cli

Summary: Found 18 structured pitfall item(s), including 1 high/blocking item(s). Top priority: Installation risk - Installation risk requires verification.

## 1. Installation risk - Installation risk requires verification

- Severity: high
- Evidence strength: source_linked
- Finding: Project evidence flags a installation risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/larksuite/cli/issues/1497

## 2. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this installation risk before relying on the project: Feature request: Install skills into a dedicated subdirectory/category instead of root skills directory
- User impact: Developers may fail before the first successful local run: Feature request: Install skills into a dedicated subdirectory/category instead of root skills directory
- Evidence: failure_mode_cluster:github_issue | https://github.com/larksuite/cli/issues/1497

## 3. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this installation risk before relying on the project: v1.0.52
- User impact: Upgrade or migration may change expected behavior: v1.0.52
- Evidence: failure_mode_cluster:github_release | https://github.com/larksuite/cli/releases/tag/v1.0.52

## 4. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this configuration risk before relying on the project: v1.0.47
- User impact: Upgrade or migration may change expected behavior: v1.0.47
- Evidence: failure_mode_cluster:github_release | https://github.com/larksuite/cli/releases/tag/v1.0.47

## 5. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this configuration risk before relying on the project: v1.0.51
- User impact: Upgrade or migration may change expected behavior: v1.0.51
- Evidence: failure_mode_cluster:github_release | https://github.com/larksuite/cli/releases/tag/v1.0.51

## 6. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this configuration risk before relying on the project: v1.0.53
- User impact: Upgrade or migration may change expected behavior: v1.0.53
- Evidence: failure_mode_cluster:github_release | https://github.com/larksuite/cli/releases/tag/v1.0.53

## 7. Capability evidence risk - Capability evidence risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: README/documentation is current enough for a first validation pass.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: capability.assumptions | https://www.npmjs.com/package/@larksuite/cli

## 8. Runtime risk - Runtime risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this runtime risk before relying on the project: v1.0.50
- User impact: Upgrade or migration may change expected behavior: v1.0.50
- Evidence: failure_mode_cluster:github_release | https://github.com/larksuite/cli/releases/tag/v1.0.50

## 9. Maintenance risk - Maintenance risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a maintenance risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://www.npmjs.com/package/@larksuite/cli

## 10. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: no_demo
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: downstream_validation.risk_items | https://www.npmjs.com/package/@larksuite/cli

## 11. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: no_demo
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: risks.scoring_risks | https://www.npmjs.com/package/@larksuite/cli

## 12. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: issue_or_pr_quality=unknown。
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://www.npmjs.com/package/@larksuite/cli

## 13. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: release_recency=unknown。
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://www.npmjs.com/package/@larksuite/cli

## 14. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: Developers should check this maintenance risk before relying on the project: v1.0.46
- User impact: Upgrade or migration may change expected behavior: v1.0.46
- Evidence: failure_mode_cluster:github_release | https://github.com/larksuite/cli/releases/tag/v1.0.46

## 15. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: Developers should check this maintenance risk before relying on the project: v1.0.48
- User impact: Upgrade or migration may change expected behavior: v1.0.48
- Evidence: failure_mode_cluster:github_release | https://github.com/larksuite/cli/releases/tag/v1.0.48

## 16. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: Developers should check this maintenance risk before relying on the project: v1.0.49
- User impact: Upgrade or migration may change expected behavior: v1.0.49
- Evidence: failure_mode_cluster:github_release | https://github.com/larksuite/cli/releases/tag/v1.0.49

## 17. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: Developers should check this maintenance risk before relying on the project: v1.0.54
- User impact: Upgrade or migration may change expected behavior: v1.0.54
- Evidence: failure_mode_cluster:github_release | https://github.com/larksuite/cli/releases/tag/v1.0.54

## 18. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: Developers should check this maintenance risk before relying on the project: v1.0.55
- User impact: Upgrade or migration may change expected behavior: v1.0.55
- Evidence: failure_mode_cluster:github_release | https://github.com/larksuite/cli/releases/tag/v1.0.55

<!-- canonical_name: larksuite/cli; human_manual_source: deepwiki_human_wiki -->
