---
name: soloco-using-lark-cli
description: Read and send Lark/Feishu group messages with lark-cli already installed on the user's machine. Use when an Executor must inspect a user-visible chat or send user-approved content through that existing CLI.
---

# Use the user's existing lark-cli

Use this method only when the user's machine already has `lark-cli`. This Skill teaches the correct CLI calls; it does not install the CLI, manage its configuration, own login or token renewal, or grant permission to send messages.

The command facts below were re-audited against upstream `larksuite/cli` `v1.0.91` (originally sourced from `v1.0.89`); the read/send commands were also checked against `v1.0.92` without changing the `v1.0.91` acceptance baseline.

## Preconditions

1. Confirm the task actually requires Lark/Feishu group messages.
2. Check that `lark-cli` is already available with `command -v lark-cli`. There is no `--local` flag; never invent or append one.
3. If notification suppression is needed for machine-readable output, use `LARKSUITE_CLI_*` variables, for example:

   ```bash
   LARKSUITE_CLI_NO_UPDATE_NOTIFIER=1 LARKSUITE_CLI_NO_SKILLS_NOTIFIER=1 lark-cli auth status --json
   ```

   Do not use the nonexistent `LARK_CLI_*` prefix.

If the binary is missing, stop and tell the user that this path requires them to install `lark-cli`, then retry the task. Do not install or upgrade it on their behalf under this Skill.

Treat this Skill as the authoritative source for Feishu-specific installation and login guidance. Provider-neutral task surfaces may point users here; do not invent a second recovery path or different wording elsewhere.

## Hard boundaries

- Check only the scopes needed for the current operation. A read-only task must never request message-send scopes.
- A dry run previews request shape; it does not count as the user's approval to send.
- Do not send until the user has explicitly approved the exact group, final content and authorized user identity. If the user does not respond, stop and report the pending approval and exact proposed content.
- Treat a real send as a non-repeatable external side effect. Execute it once, then verify rather than probing with another send.

## Check local login and scopes

Read login state locally:

```bash
lark-cli auth status --json
```

Do **not** use `--verify` for any login-state decision under this Skill. `auth status --verify` makes network calls, can refresh the access token and extend the login, while its reported status fields still describe the pre-refresh local snapshot. For a trustworthy non-mutating check, use the command without `--verify` and report that fact.

Read the user identity under `identities.user`. The refresh-token expiry is `identities.user.refreshExpiresAt`; there is no equivalent top-level expiry field.

Before reading or searching chats, check only the stored read scopes. Use a whitespace-separated value, not a comma-separated list:

```bash
lark-cli auth check --scope "im:chat:read im:message:readonly" --json
```

If the user identity is missing, expired, or lacks a required read scope, stop before reading and explain the exact missing condition. Ask the user to complete the required login or scope authorization outside this Run, then retry. Never run `auth login`, request credentials or verification codes, or attempt account recovery on the user's behalf.

## Find the intended group

If the user supplied a `chat_id`, use it directly. Otherwise search by a distinctive group-name fragment:

```bash
lark-cli im +chat-search --as user --query "<group name>" --format json
```

Inspect the returned names and `chat_id` values. Never blindly select the first result when multiple groups could match; ask the user to confirm the exact target. If search returns no result, ask for a better name or the `chat_id` instead of falling back to an unfiltered chat list.

## Read messages

Read the requested window with explicit user identity:

```bash
lark-cli im +chat-messages-list --as user --chat-id <oc_xxx> --order desc --page-size 50 --format json
```

Add `--start` and `--end` when the user specified a time range. Follow pagination only as far as the task requires. Preserve sender, timestamp, message id, content and thread context needed for the requested output; do not claim to have read messages outside the fetched window.

For CLI JSON, success means `ok == true` or process exit code `0`. Do not test for a top-level `code == 0`; successful envelopes do not use that legacy shape.

## Produce and send the result

Choose `--text` for exact plain text and `--markdown` for a lightweight formatted report. A dry run may preview the exact request, but it does not authorize a real send.

Before the external side effect, confirm all three facts with the user:

- the exact target group;
- the final message content;
- that the message will be sent as the authorized user.

After that approval, check the write scopes separately:

```bash
lark-cli auth check --scope "im:message im:message.send_as_user" --json
```

If either write scope is missing, stop before sending and explain the exact missing condition. Ask the user to authorize the missing write scopes outside this Run, then retry; do not initiate login or expand the user's authorization on their behalf.

Derive the idempotency key deterministically from the stable current task identifier, target `chat_id` and exact approved content. For example, hash those three values with separators and use the first 40 hexadecimal characters. Record the task identifier, `chat_id`, approved content and derived key in task progress before the real send so a resumed Executor can reproduce it. Keep the key at most 50 characters.

Preview the exact request with that key:

```bash
lark-cli im +messages-send --as user --chat-id <oc_xxx> --text "<approved text>" --idempotency-key <derived-key> --format json --dry-run
```

Run the same command once without `--dry-run`. The same key deduplicates sends for one hour. If the result is ambiguous, do not send again. Re-read the latest messages with the existing read path:

```bash
lark-cli im +chat-messages-list --as user --chat-id <oc_xxx> --order desc --page-size 20 --format json
```

Look for the exact approved content sent by the authorized user at the attempted time. If that evidence identifies the message, treat it as sent and record its message id and timestamp; otherwise report the uncertainty without another send.

Record the send receipt fields that were actually returned, especially `message_id`, `chat_id` and `create_time`. Do not infer success from the prepared content alone.

## Completion report

Report these as separate facts:

- **Login status:** how it was checked locally, explicitly stating that `auth status --json` was used without `--verify`, plus any relevant `identities.user.status` and `identities.user.refreshExpiresAt` value.
- **Messages read:** the confirmed group, fetched time/page window, and which message ids or sender/timestamp/content evidence supported the produced result.
- **Send receipt:** whether a send was attempted and, if so, the returned `message_id`, `chat_id`, `create_time`, or the exact uncertainty/error.

Do not describe successful login, successful reading, a dry run, or prepared content as proof that the message was sent. Do not describe a send receipt alone as proof that the requested reading window was complete.
