{
  "markdown": "# Meegle CLI\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Node.js](https://img.shields.io/badge/node-%3E%3D16-brightgreen.svg)](https://nodejs.org/)\n[![npm version](https://img.shields.io/npm/v/@lark-project/meegle.svg)](https://www.npmjs.com/package/@lark-project/meegle)\n\n[English](./README.md) | [简体中文](./README.zh-CN.md)\n\nCommand-line tool for [Meegle](https://meegle.com?utm_source=github&utm_medium=readme&utm_campaign=meegle_cli) ([Lark Project](https://project.feishu.cn?utm_source=github&utm_medium=readme&utm_campaign=meegle_cli)). Manage work items, schedules, and data from your terminal — no browser needed.\n\n[Install](#installation) · [Quick Start](#quick-start-human-users) · [Agent Skill](#ai-agent-skill) · [Commands](#commands) · [Enterprise Extensions](#enterprise-cli-extensions) · [Auth](#authentication) · [Config](#configuration) · [Security](#security--risk-warnings) · [Contributing](#contributing)\n\n## Why Meegle CLI?\n\n- **Agent-Native** — The setup wizard installs the bundled AI Agent Skill for Trae, Claude Code, Cursor, Windsurf, Gemini CLI and other agents. Every CLI command is designed for both humans and agents, with structured JSON output, `--dry-run` previews, and `--device-code` flows for non-TTY environments\n- **Broad Coverage** — 16 business domains (work items, workflow, subtasks, comments, work hours, relations, my-work, views, charts, team, user, project, attachments, deliverables, resource library, WBS plan tables) and 50+ commands mapping to Meegle's core capabilities\n- **Two-Layer Parameters** — Ergonomic `--flag-name` for everyday use, fallback `--params <json>` for complex payloads like `fields[]` — pick the right granularity per call\n- **Flexible Output** — `json` / `table` / `ndjson` / `raw`, with `--select` dot-path projection for piping to other tools\n- **Secure by Default** — OS keychain credential storage, `${VAR}` env-var templating so secrets never land in config files, multi-profile switching for staging / prod\n- **Enterprise-Extensible** — Build a company distribution without forking this repository by importing the public `cmd`, Credential, Transport, and Platform packages at compile time\n\n## Features\n\n| Category                                           | Capabilities                                                                                   |\n| -------------------------------------------------- | ---------------------------------------------------------------------------------------------- |\n| 📋 [Work Items](#workitem--work-items)             | Create, read, update, batch-read, query (MQL), list operation records, inspect metadata        |\n| 🔀 [Workflow](#workflow--workflow)                 | Transition nodes & states, update node fields, list available transitions and required fields |\n| ✅ [Subtasks](#subtask--subtasks)                  | Create, update, complete, rollback subtasks                                                    |\n| 💬 [Comments](#comment--comments)                  | Add and list comments on work items                                                            |\n| ⏱️ [Work Hours](#workhour--work-hours)             | List work hour records, view team-member schedules                                             |\n| 🔗 [Relations](#relation--relations)               | List related work items, inspect relation-type definitions                                     |\n| 📌 [My Work](#mywork--my-work)                     | View this week / overdue / completed to-dos                                                    |\n| 👁️ [Views](#view--views)                           | Create and update fixed views, search views by name                                            |\n| 📊 [Charts](#chart--charts)                        | List charts under a view, fetch chart details                                                  |\n| 👥 [Team & User](#team--user--people)              | List teams, team members, search users, view current login                                     |\n| 🗂️ [Projects](#project--projects)                  | Search projects by keyword                                                                     |\n| 📎 [Attachments](#attachment--attachments)         | Two-stage upload/download protocol — `prepare-*` basic commands plus `+upload` / `+download` end-to-end shortcuts |\n| 📦 [Deliverables](#deliverable--deliverables)      | List deliverables with their root and source work items                                        |\n| 🧩 [Resource Library](#resource--resource-library) | Create resource templates, inspect resource library configuration                              |\n| 🗓️ [WBS Plan Tables](#wbs--wbs-plan-tables)        | List draft / published plan rows, create / edit / publish / reset drafts, query draft progress, list element templates |\n| 🔐 [Auth & Config](#authentication)                | OAuth login, device-code flow, multi-profile config, env-var injection                         |\n| 🔗 [URL Parsing](#url--url-parsing)                | Offline decode of Meegle / Feishu Project URLs into `url_kind` + structured fields             |\n| 🤖 [Agent Skill](#ai-agent-skill)                  | Pre-built skill for Trae / Claude Code / Cursor / Windsurf / Gemini CLI / Copilot              |\n\n## Installation\n\n### Requirements\n\n- Node.js >= 16 (ships with `npm` / `npx`)\n\nRun the setup wizard:\n\n```bash\nnpx @lark-project/meegle@latest install\n```\n\nThe wizard installs or upgrades the CLI globally, installs the AI Agent Skill, configures the Meegle host, and starts login.\n\n### Automatic update prompt\n\nThe npm-distributed CLI checks npm for a newer version at most once every 24 hours when it starts in an interactive terminal. When an update is available, it reads the released `Added` and `Changed` entries between the installed and latest versions from the [CHANGELOG](https://github.com/larksuite/meegle-cli/blob/main/CHANGELOG.md#changed), then shows an interactive prompt:\n\n```text\n✨ Meegle CLI update available: v<current> → v<latest>\n\nWhat's new:\n  v<version>\n    • Added: <feature summary>\n\n❯ Update now (recommended)\n  Remind me later\n  Use ↑/↓ to select, then press Enter\n```\n\nPressing Enter first upgrades the CLI with `npm install -g @lark-project/meegle@latest`, then makes a best-effort attempt to upgrade the Meegle Agent Skill through the same installer used by `meegle install`, and finally continues the original command. A missing or incompatible Skill installer, or a Skill download failure, never changes a successful CLI upgrade into a failure. Choosing **Remind me later** defers the next check for 24 hours. This lightweight update does not reconfigure the host or trigger login; use `meegle install` when you want the full setup wizard.\n\nThe check is skipped for non-interactive/CI execution, piped stdout, `install`, and shell-completion commands, so structured command output remains unchanged. Set `MEEGLE_NO_UPDATE_CHECK=1` to disable it explicitly.\n\n## Quick Start (Human Users)\n\n> **Note for AI assistants:** if you are an AI Agent helping the user set this up, jump directly to [Quick Start (AI Agent)](#quick-start-ai-agent--ci--headless) — it contains the non-interactive command you need.\n\n```bash\n# 1. Install CLI + Skill, configure host, and log in\nnpx @lark-project/meegle@latest install\n\n# 2. View this week's to-dos\nmeegle mywork todo --action this_week --page-num 1\n\n# 3. View help\nmeegle --help\nmeegle workitem --help\n\n# 4. Inspect command parameters\nmeegle inspect workitem.create\n```\n\n## Quick Start (AI Agent / CI / Headless)\n\nThe default browser OAuth flow requires a real TTY. In CI runners, pipes, and agent shells like Claude Code, run the same setup wizard with an explicit host and Device Code login:\n\n```bash\nnpx -y @lark-project/meegle@latest install --host <host> --device-code --lang en\n```\n\nExamples of `<host>`: `project.feishu.cn`, `meegle.com`, or your self-hosted tenant domain such as `your-tenant.example.com`. The Device Code flow prints an authorization URL; send it to the user and keep the command running until authorization completes.\n\nVerify:\n\n```bash\nmeegle auth status\n```\n\nFor fully unattended CI (no human-in-the-loop), inject a token via environment variables instead — see [Sandbox / CI](#sandbox--ci-direct-environment-variable-injection).\n\n## AI Agent Skill\n\nThe setup wizard installs `skills/meegle/`, a drop-in skill for Trae, Claude Code, Cursor, Windsurf, Gemini CLI, GitHub Copilot CLI, and other agents. It teaches agents how to operate Meegle through this CLI instead of guessing command shapes from prose.\n\n### What it covers\n\n- **Command reference** — every `meegle` resource / method with required parameters and examples\n- **MQL search** — syntax for `workitem query`, operators, scope keywords\n- **Field values** — how to shape complex field payloads (arrays, nested JSON, date ranges)\n- **Rich text** — Markdown subset supported by Meegle's rich-text editor\n- **SOPs** — step-by-step playbooks for creating work items, transitioning nodes, transitioning states, and updating fields\n- **Auth guard** — the skill refuses to run business commands until `meegle auth status` succeeds\n\n### Usage\n\nOnce the setup wizard has run, ask the agent in natural language. For example:\n\n```\nShow me this week's P0 stories in the PROJ space.\n```\n\nThe agent consults the skill, picks the right `meegle` commands, and runs them for you. Pair with `--dry-run` (see [Security](#security--risk-warnings)) to preview side-effectful operations before the agent commits them.\n\n## Commands\n\n### workitem — Work Items\n\n| Command | Description |\n|---------|-------------|\n| `workitem create` | Create a work item |\n| `workitem get` | View work item details |\n| `workitem +batch-get` | Batch-read work items by IDs (client-side fan-out over `workitem get`; `+` marks scenario/sugar commands) |\n| `workitem update` | Update work item fields |\n| `workitem query` | Search work items using MQL |\n| `workitem list-op-records` | View operation records |\n| `workitem meta-types` | List work item types |\n| `workitem meta-create-fields` | List fields available at creation |\n| `workitem meta-fields` | List field configurations |\n| `workitem meta-roles` | List role configurations |\n\n### workflow — Workflow\n\n| Command | Description |\n|---------|-------------|\n| `workflow transition` | Transition or rollback a node |\n| `workflow transition-state` | Transition a state-flow state |\n| `workflow get-node` | View node details |\n| `workflow update-node` | Update a node |\n| `workflow meta-node-fields` | List node field configurations |\n| `workflow list-state-transitions` | List available state transitions |\n| `workflow list-state-required` | List required fields for transitions |\n\n### subtask — Subtasks\n\n| Command | Description |\n|---------|-------------|\n| `subtask update` | Create / update / complete / rollback subtasks |\n\n### comment — Comments\n\n| Command | Description |\n|---------|-------------|\n| `comment add` | Add a comment |\n| `comment list` | List comments |\n\n### workhour — Work Hours\n\n| Command | Description |\n|---------|-------------|\n| `workhour list-records` | List work hour records |\n| `workhour list-schedule` | View team member schedules |\n\n### relation — Relations\n\n| Command | Description |\n|---------|-------------|\n| `relation list` | List related work items |\n| `relation meta-definitions` | List relation type definitions |\n\n### mywork — My Work\n\n| Command | Description |\n|---------|-------------|\n| `mywork todo` | View my to-dos / completed items |\n\n### view — Views\n\n| Command | Description |\n|---------|-------------|\n| `view create-fixed` | Create a fixed view |\n| `view get` | View details of a view |\n| `view update-fixed` | Update a fixed view |\n| `view search` | Search views by name |\n| `view list-multi-project-workitems` | List work items under a multi-project (panoramic) view |\n\n### chart — Charts\n\n| Command | Description |\n|---------|-------------|\n| `chart get` | View chart details |\n| `chart list` | List charts under a view |\n\n### team / user — People\n\n| Command | Description |\n|---------|-------------|\n| `team list` | List teams in a project |\n| `team list-members` | List team members |\n| `user me` | View current logged-in user information |\n| `user search` | Search user information |\n\n### project — Projects\n\n| Command | Description |\n|---------|-------------|\n| `project search` | Search projects |\n\n### attachment — Attachments\n\n| Command | Description |\n|---------|-------------|\n| `attachment prepare-upload` | Upload preprocess — returns the signed object-storage URL and multipart plan |\n| `attachment prepare-download` | Download preprocess — returns the signed object-storage URL and multipart plan |\n| `attachment +upload` | End-to-end upload: preprocess + signed HTTP POST(s); returns the resulting `file_token` and file metadata |\n| `attachment +download` | End-to-end download: preprocess + signed HTTP GET(s) + atomic write — for `file_url`s embedded in `workitem get` / `comment list` responses |\n\n### deliverable — Deliverables\n\n| Command | Description |\n|---------|-------------|\n| `deliverable list` | List deliverables with their root and source work items |\n\n### resource — Resource Library\n\n| Command | Description |\n|---------|-------------|\n| `resource create` | Create a resource template (resource instance) under a resource-library-enabled work item type |\n| `resource meta-fields` | List resource library configuration (resource fields and roles) |\n\n### wbs — WBS Plan Tables\n\n| Command | Description |\n|---------|-------------|\n| `wbs list-draft-rows` | List rows in a WBS draft, filtered by query and projected to selected fields |\n| `wbs list-instance-rows` | List rows in a published WBS instance, filtered by query and projected to selected fields |\n| `wbs create-draft` | Create a new WBS draft for a work item instance |\n| `wbs edit-draft` | Apply one atomic operation to a single draft row (add / delete / restore / sort / rename / owner / schedule); operation type via `--params` |\n| `wbs publish-draft` | Publish a WBS draft online |\n| `wbs reset-draft` | Reset a draft to match the published instance, discarding unpublished changes |\n| `wbs get-draft-progress` | Get the execution progress of a WBS draft operation (create / edit / publish) |\n| `wbs list-element-templates` | List element templates (resource nodes and tasks) from the flow resource library |\n\n### ai-handoff — AI Assistant Handoff\n\nThese commands are registered locally in the CLI and are not MCP tools. `availability` is an optional preflight before preparing `query` or related context; an expected business rejection is a successful probe and includes stable `reject_code` and display-only `reject_msg` fields. Dependency and transport failures use the standard CLI error model.\n\n`availability` reads the Handoff section of the generic `GET /goapi/v5/meeglecli/config` discovery response, including its `mode` (`off`, `ask`, or `auto`). The complete successful config snapshot is cached locally per profile for up to 1 hour; dependency or transport errors are never cached. The config cache is invalidated immediately on a successful `preference handoff auto|ask|off`, on `auth login`, and whenever `create-link` is rejected server-side. `create-link` never reads the cache: it always re-validates server-side and creates the link directly.\n\nThe create-link HTTP response always includes `available`: success returns HTTP 200 with `available=true` and `url`; the CLI then replaces only that URL's host (including the configured port) with the active login host, preserving its scheme, path, query, and fragment. This keeps links in the currently selected Meegle or Lark Project environment. An expected business rejection returns HTTP 200 with `available=false`, `reject_code`, and `reject_msg`, and clears the local config cache. Unexpected failures use the standard API error response.\n\nSet `MEEGLE_AI_HANDOFF=disabled` to hard-disable Handoff in the local installation. Both `availability` and a valid `create-link` invocation then return `available=false` with `reject_code=LOCAL_DISABLED` and a display-only `reject_msg`; they do not require authentication, read the CLI configuration cache, or call the Handoff API. Unset values and values other than `disabled` preserve the normal server-controlled behavior. This local gate can only disable the feature—it cannot override the server business switch, entitlement, or personal preference to enable it.\n\n| Command | Description |\n|---------|-------------|\n| `ai-handoff availability` | Check the business switch, rollout, AI entitlement, personal preference, and link-service readiness |\n| `ai-handoff create-link` | Create an AI assistant link from required `--query` and optional, repeatable typed `--related-context` JSON objects |\n\n```bash\nmeegle ai-handoff availability --format json\n\nMEEGLE_AI_HANDOFF=disabled meegle ai-handoff availability --format json\n\nmeegle ai-handoff create-link --params '{\n  \"query\": \"Summarize the risks and propose next actions\",\n  \"related_context\": [{\n    \"type\": 3,\n    \"work_item\": {\n      \"project_key\": \"PROJ\",\n      \"work_item_type_key\": \"story\",\n      \"work_item_id\": \"123\"\n    }\n  }]\n}' --format json\n\nmeegle ai-handoff create-link --help\nmeegle inspect ai-handoff create-link\n```\n\nEach `related_context` item must set `type` and exactly one matching payload. The facade contract uses business identifiers and never exposes the AI service's generic `key`; facade fills that field only while converting to the internal `query + entities` contract:\n\n| Type | Payload | Required fields | Optional fields |\n|------|---------|-----------------|-----------------|\n| `1` Project | `project` | `project_key` | — |\n| `3` WorkItem | `work_item` | `project_key`, `work_item_type_key`, `work_item_id` | — |\n| `4` View | `view` | `project_key`, `view_id` | `work_item_type_key` |\n| `5` MeasureChart | `measure_chart` | `project_key`, `chart_id` | — |\n\nContext type `2` is reserved by the IDL for the currently unsupported WorkItemType context and must not be used.\n\nEach attempt is bounded by a per-attempt timeout, and transient transport failures (timeout, HTTP 5xx/429, network errors) are retried up to 3 times with exponential backoff and jitter. `create-link` sends a stable idempotency key that is reused across those retries, so a retried request never creates a second link. Policy, validation, and 4xx errors fail fast without retrying. Facade invalid-parameter envelopes are reported as `HANDOFF_API_INVALID_PARAM` with `retryable=false`, including payloads that exceed the negotiated query or context limits. Internal Facade biz error IDs, causes, and chains are not exposed; the CLI returns a concise message plus a suggestion to inspect the current limits with `ai-handoff availability`.\n\n### preference — Personal Preferences\n\nHandoff suggestion mode is stored in the server-side unified user preference service. It has no project or tenant argument and defaults to `auto` when no override exists. The generic write request carries a `preferences` list with `type=handoff_suggestions`; its payload is `{\"mode\":\"off|ask|auto\"}`. A successful mode update invalidates the local `ai-handoff availability` cache.\n\n| Command | Description |\n|---------|-------------|\n| `preference handoff auto` | Automatically show AI handoff recommendations |\n| `preference handoff ask` | Ask before showing an AI handoff recommendation |\n| `preference handoff off` | Disable AI handoff recommendations |\n\nUse `meegle preference handoff --help` for mode behavior and `meegle inspect preference handoff auto` (or `ask` / `off`) for the command-level parameter view.\n\n`reset` is intentionally not exposed until the preference service provides an atomic unset operation.\n\n### auth — Authentication\n\n| Command | Description |\n|---------|-------------|\n| `auth login` | Log in (browser or `--device-code`) |\n| `auth logout` | Log out |\n| `auth status` | View login status (validates the token against the server) |\n\n### config — Configuration\n\n| Command | Description |\n|---------|-------------|\n| `config init` | Initialize configuration |\n| `config show` | Show current configuration |\n| `config set` | Set a configuration value |\n| `config get` | Get a configuration value |\n| `config profile create\\|list\\|use\\|current\\|delete` | Manage configuration profiles |\n\n### url — URL Parsing\n\nOffline, no-network utility for parsing Meegle / Feishu Project URLs into structured fields. Skills and pipelines branch on the returned `url_kind` instead of guessing from raw paths.\n\n| Command | Description |\n|---------|-------------|\n| `url decode --url <URL>` | Decode a URL into `url_kind` + `simple_name` / `work_item_type` / `work_item_id` / `view_id` / `chart_id` / `query` / `redirected_from` etc. Unrecognised URLs return `url_kind: \"unknown\"`. |\n\n### Other Commands\n\n| Command | Description |\n|---------|-------------|\n| `version` | Print the CLI version (`meegle --version` is an alias) |\n| `inspect [command]` | Inspect command parameters |\n| `completion bash\\|zsh\\|fish` | Generate shell completion script |\n| `completion install` | Auto-install shell completion |\n\n## Common Examples\n\n### To-dos\n\n```bash\n# This week's to-dos\nmeegle mywork todo --action this_week --page-num 1\n\n# Completed items\nmeegle mywork todo --action done --page-num 1\n\n# Overdue items\nmeegle mywork todo --action overdue --page-num 1\n```\n\nIf `mywork todo` fails with `get action info fail`, refresh command metadata first:\n`meegle --refresh mywork todo --action this_week --page-num 1`. If your account\nbelongs to multiple workspaces, pass the workspace key explicitly:\n`meegle mywork todo --action this_week --page-num 1 --asset-key Asset_xxx`.\n\n### Querying Work Items\n\n```bash\n# View work item details\nmeegle workitem get --work-item-id 12345\n\n# View workflow node details\nmeegle workflow get-node --work-item-id 12345 --need-sub-task\n```\n\n### Batch Reading Work Items\n\n`workitem +batch-get` fans out to `workitem get` for each ID and aggregates the\nresults into one response. Shared flags (e.g. `--project-key`) apply to every\nper-item call. The `+` prefix marks it as a scenario/sugar command — the CLI\ncomposes multiple `get` calls client-side instead of mapping to a single\nbackend endpoint.\n\n```bash\n# Comma-separated IDs in one invocation\nmeegle workitem +batch-get --project-key PROJ --work-item-ids \"12345,12346,12347\"\n\n# Read IDs from a file (one per line; lines starting with '#' are comments)\nmeegle workitem +batch-get --project-key PROJ --ids-file ./ids.txt\n\n# Stream one JSON row per item; summary row is emitted last\nmeegle workitem +batch-get --project-key PROJ --work-item-ids \"12345,12346\" -o ndjson\n```\n\nResponse envelope (JSON):\n\n```json\n{\n  \"summary\": { \"total\": 3, \"succeeded\": 2, \"failed\": 1 },\n  \"results\": [\n    { \"work_item_id\": 12345, \"data\": { /* ... */ } },\n    { \"work_item_id\": 12346, \"data\": { /* ... */ } },\n    { \"work_item_id\": 12347, \"error\": { \"code\": \"...\", \"message\": \"...\" } }\n  ]\n}\n```\n\nConstraints: up to 200 IDs per invocation, 3 concurrent workers (fixed).\nPartial failures do **not** abort the batch — check `summary.failed` or the\nper-item `error` field. A 401 from the server aborts the whole run.\n\n### Creating Work Items\n\n```bash\n# Pass fields[] via --params (JSON)\nmeegle workitem create --project-key PROJ --work-item-type story \\\n  --params '{\"fields\":[\n    {\"field_key\":\"name\",\"field_value\":\"Optimize login flow\"},\n    {\"field_key\":\"priority\",\"field_value\":\"P1\"}\n  ]}'\n\n# Complex field values (arrays, nested JSON) also go through --params\nmeegle workitem create --project-key PROJ --work-item-type story \\\n  --params '{\"fields\":[\n    {\"field_key\":\"name\",\"field_value\":\"Scheduled task\"},\n    {\"field_key\":\"schedule\",\"field_value\":[1722182400000,1722355199999]}\n  ]}'\n```\n\n### Updating Fields\n\n```bash\n# Update work item name\nmeegle workitem update --work-item-id 12345 \\\n  --params '{\"fields\":[{\"field_key\":\"name\",\"field_value\":\"New title\"}]}'\n\n# Update multiple fields at once\nmeegle workitem update --work-item-id 12345 \\\n  --params '{\"fields\":[\n    {\"field_key\":\"name\",\"field_value\":\"New title\"},\n    {\"field_key\":\"priority\",\"field_value\":\"P0\"}\n  ]}'\n```\n\n### Attachments\n\nThe `attachment` domain exposes Lark project's two-stage attachment protocol\nin two layers:\n\n- **Basic commands** (`attachment prepare-upload`, `attachment prepare-download`)\n  return the raw signed-URL preprocess payload — handy for scripting your own\n  HTTP transfer or inspecting the multipart plan.\n- **Shortcuts** (`attachment +upload`, `attachment +download`) chain the basic\n  preprocess with the signed HTTP POST/GET to object storage end-to-end. The\n  `+` prefix marks them as scenario commands — the CLI orchestrates the\n  preprocess output plus the out-of-band byte transfer client-side.\n\n`--resource-type` tells the backend what the file will be attached to:\n\n| `--resource-type` | Target |\n|-------------------|--------|\n| `15` | Workitem attachment field |\n| `16` | Image embedded in a workitem rich-text field |\n| `13` | Attachment on a comment |\n| `14` | Image embedded in a comment |\n\n**Scoping the preprocess**: every upload needs either `--work-item-id` or\n`--work-item-type`. **Always prefer `--work-item-id`** when the target workitem\nexists (update / comment scenarios); only use `--work-item-type` for the\ncreate-with-attachment path where the workitem hasn't been created yet. If\nboth are supplied, `--work-item-id` wins and `--work-item-type` is ignored.\n\n```bash\n# Upload a file for a workitem attachment field (resource-type 15)\nmeegle attachment +upload ./a.pdf \\\n  --resource-type 15 \\\n  --project-key PROJ --work-item-id 12345 --field-key files_field\n\n# Create-with-attachment path — workitem doesn't exist yet, pass --work-item-type\nmeegle attachment +upload ./a.pdf \\\n  --resource-type 15 \\\n  --project-key PROJ --work-item-type story --field-key files_field\n\n# Upload an image for a rich-text field (resource-type 16)\nmeegle attachment +upload ./diagram.png \\\n  --resource-type 16 \\\n  --project-key PROJ --work-item-id 12345 --field-key spec_field\n\n# Upload a comment attachment (resource-type 13)\nmeegle attachment +upload ./report.pdf \\\n  --resource-type 13 \\\n  --project-key PROJ --work-item-id 12345\n\n# Upload a comment image (resource-type 14)\nmeegle attachment +upload ./screen.png \\\n  --resource-type 14 \\\n  --project-key PROJ --work-item-id 12345\n\n# Download: pass the opaque file_url from another command's response.\nURL=$(meegle workitem get --project-key PROJ --work-item-id 12345 \\\n        --fields files_field --format json \\\n      | jq -r '.fields.files_field[0].url')\nmeegle attachment +download \"$URL\" \\\n  --project-key PROJ --work-item-id 12345 \\\n  --output ./local.pdf --overwrite\n```\n\n**Integrity check (`+download`)**: `+download` performs an extra integrity check\non each downloaded file and aborts — writing nothing — if the file fails\nvalidation or cannot be verified. On a failed check you get a\n`CLIENT_FILE_SIGN_MISMATCH` error (unverifiable response →\n`CLIENT_FILE_SIGN_UNVERIFIED`); both are transient, so just retry.\n\n**Custom headers / env routing**: any custom headers configured for the active\nprofile are applied to the download GET as well as the preprocess call, so an\nenvironment-routing header pins the whole download to the same environment. Auth\nheaders are stripped before the GET so the token never reaches the\nobject-storage host.\n\n`+upload` returns a JSON object with the file token and metadata:\n\n```json\n{\n  \"file_token\": \"...\",\n  \"file_url\": \"https://...\",\n  \"name\": \"a.pdf\",\n  \"size\": 12345,\n  \"mime_type\": \"application/pdf\"\n}\n```\n\nTo wire the result into a downstream command, parse the response with `jq`\nor your scripting language of choice:\n\n```bash\n# Comment attachment — comment add takes file_token directly\nTOKEN=$(meegle attachment +upload ./report.pdf --resource-type 13 \\\n        --project-key PROJ --work-item-id 12345 | jq -r '.file_token')\nmeegle comment add --work-item-id 12345 --content \"See attached\" --file-token \"$TOKEN\"\n```\n\n**Field-level attachment formats** (how to assemble `--fields` payloads):\n\n- **Workitem attachment field** (`--resource-type 15`) — `field_value` is a\n  JSON *string* whose parsed form is `[{\"name\",\"type\",\"size\",\"fileToken\"}]`.\n  Note: `fileToken` is camelCase (other backend fields are snake_case) and\n  `size` is a string, not a number.\n- **Rich-text field / comment image** (`--resource-type 16` / `14`) — embed\n  images as `![name](file_url) <!-- file_token -->`.\n- **Comment attachment** (`--resource-type 13`) — `comment add --file-token`\n  takes `file_token` directly.\n\n### MQL Search\n\n```bash\n# Query P0 stories in a project\nmeegle workitem query --project-key PROJ \\\n  --mql \"SELECT \\`name\\`, \\`priority\\` FROM \\`ProjectName\\`.\\`Story\\` WHERE \\`priority\\` = 'P0'\"\n```\n\n### Viewing Schedules\n\n```bash\n# View team member schedules\nmeegle workhour list-schedule --project-key PROJ \\\n  --start-time 2026-03-01 --end-time 2026-03-31 \\\n  --user-keys \"Alice,Bob,Charlie\"\n```\n\n### Searching Users\n\n```bash\nmeegle user search --user-keys \"Alice,Bob\" --project-key PROJ\n```\n\n## Parameter Passing\n\n### Basic Flags\n\nEach command takes parameters via `--flag-name`:\n\n```bash\nmeegle workitem get --work-item-id 12345 --project-key PROJ\n```\n\nIf one invocation omits multiple required flags or positional arguments, the\nCLI reports every missing input in a single `CLIENT_MISSING_REQUIRED` error,\nin the same order as the command definition. A single missing input keeps the\noriginal singular message.\n\n```text\n$ meegle workflow list-state-transitions --project-key demo --work-item-id 1 --dry-run\nmissing required parameters: --user-key, --work-item-type\n```\n\n### --set key=value (Generic)\n\n`--set` is an alternate syntax for writing **top-level** parameters — `--set key=value` is equivalent to typing `--key value`. Useful when scripting with a uniform `key=value` form, or for writing nested top-level params via dot-path. Values are auto-typed (int / float / bool / string).\n\n```bash\n# These two are equivalent:\nmeegle mywork todo --action this_week --page-num 1\nmeegle mywork todo --set action=this_week --set page_num=1\n\n# Dot-path builds nested maps (rarely used in Meegle, but supported):\n--set extra.flag=true          # becomes {\"extra\":{\"flag\":true}}\n```\n\n`--set` only writes **top-level** parameters. To write a work item's `fields[]`, use `--params '{\"fields\":[...]}'` (see below).\n\n### --params JSON\n\n`--params` takes a JSON object; **each top-level key is merged in as a CLI flag**.\nUse either the MCP's `snake_case` parameter name or the CLI flag's `kebab-case`\nname. The key must be a valid parameter of the current command — it is not a\nfree-form payload.\n\n```bash\n# These two are equivalent:\nmeegle workitem get --work-item-id 12345 --project-key PROJ\nmeegle workitem get --params '{\"work_item_id\":12345,\"project_key\":\"PROJ\"}'\n```\n\nUse `--params` when:\n\n- the value is a nested object or array (`fields[]`, `schedule{}`) — too awkward to inline as a flag\n- you want to set many parameters at once, or feed a payload from a file (see `@file.json` below)\n\nRequired top-level parameters can also be supplied through `--params`; they are equivalent to passing the corresponding flags directly.\n\n```bash\nmeegle workitem create --project-key PROJ --work-item-type story \\\n  --params '{\"fields\":[{\"field_key\":\"name\",\"field_value\":\"Title\"}]}'\n```\n\n#### Common pitfall: not every name is a top-level flag\n\nSome values that *look* like top-level fields are actually work-item field\nvalues, and must be wrapped in `fields[]` rather than placed at the top\nlevel. For example, on `workitem update` the `priority` value belongs to\nthe work item's fields, not to the command's flags:\n\n```bash\n# ❌ \"priority\" is not a flag of workitem update — CLI prints a stderr warning, backend ignores it\nmeegle workitem update --work-item-id 12345 --params '{\"priority\":\"P1\"}'\n\n# ✓ Wrap field values inside fields[]\nmeegle workitem update --work-item-id 12345 \\\n  --params '{\"fields\":[{\"field_key\":\"priority\",\"field_value\":\"P1\"}]}'\n```\n\nThe CLI surfaces unknown top-level keys as a `validation.unknown_params`\nlist under `--dry-run`, and as a one-line stderr warning at run time. They\nare still forwarded to the backend (in case your local tool-schema cache\nis stale — refresh with `--refresh`).\n\nRun `meegle workitem meta-fields --project-key PK --work-item-type TK`\nto look up valid `field_key`s for a work item type.\n\n#### Reading from a file (`@file.json`)\n\nInline JSON is unergonomic on Windows because CMD requires `\\\"` escaping\nand PowerShell mangles backslashes when forwarding native-command arguments.\nPrefix the value with `@` to load the JSON from a file instead — works\nidentically on macOS, Linux, and Windows shells:\n\n```bash\n# body.json:\n# {\"fields\":[{\"field_key\":\"name\",\"field_value\":\"Optimize login flow\"}]}\n\nmeegle workitem create --project-key PROJ --work-item-type story \\\n  --params @body.json\n\n# Absolute path also works\nmeegle workitem update --work-item-id 12345 --params @/tmp/patch.json\n\n# PowerShell — same syntax, no escaping headaches\nmeegle workitem create --project-key PROJ --work-item-type story --params '@body.json'\n```\n\nThe path is read with the OS's default encoding; both relative and absolute\npaths are accepted. A missing file fails with `PARAM_INVALID`; a file whose\ncontents are not valid JSON fails with `INVALID_PARAMS_JSON`.\n\n### Priority\n\nWhen `--set`, `--params`, and regular flags are used together:\n\n1. Regular CLI flags beat `--params` / `--set` for the same top-level key\n2. `--set` overrides the same top-level key from `--params`\n\n### Array Parameters\n\nSeparate multiple values with commas:\n\n```bash\n--user-keys \"Alice,Bob,Charlie\"\n--field-keys \"name,status,priority\"\n```\n\n### Boolean Parameters\n\nAdd the flag to set `true`; omit it for `false`:\n\n```bash\nmeegle workflow get-node --work-item-id 12345 --need-sub-task\n```\n\n## Global Flags\n\n| Flag | Short | Description |\n|------|-------|-------------|\n| `--format` | `-o` | Output format: `json` (default), `table`, `ndjson`, `raw` |\n| `--select` | | Field projection with dot paths |\n| `--set` | | Set nested parameters (repeatable) |\n| `--params` | `-P` | Full JSON parameter body; prefix with `@` to read from a file (e.g. `--params @body.json`) |\n| `--dry-run` | | Render request without executing |\n| `--envelope` | | Wrap success output as `{data, meta, error}` — `meta.logid` carries the backend trace id when present |\n| `--verbose` | `-v` | Verbose output |\n| `--profile` | | Use a specific configuration profile |\n| `--refresh` | | Refresh cached commands from server (bypass the local 24 h cache) |\n| `--auto-paginate` | | Automatically fetch and merge all pages when the response contains pagination signals (`next_page_token` or `pagination.has_more`); merged list arrays are concatenated, and a 200-page safety cap plus a 3-empty-page streak guard prevent runaway loops |\n| `--version` | | Print the CLI version and exit (alias of `meegle version`) |\n\n`--version` is treated as the version alias only when it is a standalone flag. If a preceding string flag is waiting for a value, the literal `--version` remains that flag's value.\n\n## Advanced Usage\n\n### Output Formats\n\n```bash\n# JSON (default)\nmeegle workitem get --work-item-id 12345\n\n# NDJSON (suitable for piping)\nmeegle mywork todo --action this_week --page-num 1 -o ndjson\n\n# Table\nmeegle mywork todo --action this_week --page-num 1 -o table\n```\n\n### Field Projection with `--select`\n\n`--select` projects fields using `.` notation. A segment after an array\nbroadcasts the remaining path over every record of the array and\ncollects the results while preserving the enclosing structure.\n\n| Expression | Response | Projection |\n|---|---|---|\n| `list` | `{\"list\":[{\"a\":1}], \"total\":1}` | `{\"list\":[{\"a\":1}]}` |\n| `list.a` | `{\"list\":[{\"a\":1,\"b\":2},{\"a\":3,\"b\":4}]}` | `{\"list\":[{\"a\":1},{\"a\":3}]}` |\n| `list.a,list.b` | same as above | `{\"list\":[{\"a\":1,\"b\":2},{\"a\":3,\"b\":4}]}` (merged per index) |\n| `list.work_item_info.work_item_name` | `{\"list\":[{\"work_item_info\":{\"work_item_name\":\"x\"}}]}` | `{\"list\":[{\"work_item_info\":{\"work_item_name\":\"x\"}}]}` |\n| `nodes.0` | `{\"nodes\":[{\"id\":\"a\"},{\"id\":\"b\"}]}` | `{\"nodes\":{\"0\":{\"id\":\"a\"}}}` (numeric = index) |\n\n```bash\n# Top-level selection\nmeegle workitem get --work-item-id 12345 --select \"id,name,status\"\n\n# Broadcast across arrays — extract fields from nested records\nmeegle mywork todo --action done --page-num 1 \\\n  --select \"list.work_item_info.work_item_name,list.state_info.end_state_key_name\"\n\n# Mix top-level metadata with broadcast — total is retained alongside projected list items\nmeegle mywork todo --action done --page-num 1 \\\n  --select \"total,list.work_item_info.work_item_name\"\n```\n\n### Metadata preservation\n\nThe default render preserves the full response shape across every\n`--format`: list endpoints return `{\"list\":[...], \"total\":N,\n\"pagination\":{...}}` verbatim — you see `total` / `pagination` even\nwhen you do not project them. Drill into records explicitly via\n`--select` (and the broadcast syntax above). Under `--format table`\nand `--format ndjson`, a single-key wrapper like `{\"list\":[...]}`\n(no sibling metadata) is still peeled into rows — the peel is\nloss-less.\n\n### Tracing with `--envelope`\n\nWhen something looks wrong (silent success, unexpected payload) and you\nwant to ask oncall to trace the exact call, add `--envelope`:\n\n```bash\nmeegle workflow update-node --work-item-id 12345 \\\n  --set node_schedule.points=10 --envelope\n```\n\nThe success output is wrapped as `{data, meta, error}`, and `meta.logid`\ncarries the backend trace id (when the server returns one). Hand that id\nto oncall to look up the request in argos. Without `--envelope` the id is\nsuppressed so the default output stays clean for piping.\n\nAI handoff Config, Preference, and Create Link responses also copy the gateway\n`x-tt-logid` response header to `meta.logid`. Successful calls expose it only\nwith `--envelope`; failures include it in their structured error envelope\nautomatically. No debug logging is required.\n\n### Dry Run\n\nFor commands with side effects, preview the rendered request with `--dry-run` before executing:\n\n```bash\nmeegle workitem create --project-key PROJ --work-item-type story \\\n  --params '{\"fields\":[{\"field_key\":\"name\",\"field_value\":\"Test\"}]}' --dry-run\n```\n\n### Command Introspection\n\nUse `inspect` to view full parameter information for any command:\n\n```bash\n# List all commands\nmeegle inspect\n\n# View parameters for a specific command\nmeegle inspect workitem.create\n```\n\n### Programmatic Command Strings\n\nApplications that embed the Go command-string SDK can represent line breaks\nwith `\\n`. For example, a value such as\n`--content \"Line 1\\n\\nLine 2\"` reaches the command as two paragraphs. Use\n`\\\\n` when the value must contain the literal characters `\\n`; unsupported\nescape sequences retain their backslash.\n\nThis decoding only applies to programmatic command-string entry points such as\n`CommandClient.Execute` and `ExecuteCommandString`. The `meegle` binary receives\nan argument array from the shell, so normal shell quoting rules apply there.\nThe command-string Go SDK used by Facade for remote RPC execution registers only\nMCP-discovered commands. Local CLI API commands such as `ai-handoff` and\n`preference handoff` are available only in the npm-distributed `meegle` CLI;\ndirect `CallTool` also continues to address MCP tools only.\n\n## Authentication\n\n### Browser Login (Default)\n\n```bash\nmeegle auth login\n```\n\nAutomatically opens the browser for OAuth authorization. If the browser doesn't open, the terminal displays the authorization URL for manual copying.\n\n### Device Code Login (No Browser)\n\n```bash\nmeegle auth login --device-code\n```\n\nThe terminal displays a QR code and authorization code. Scan with your phone to authorize. Ideal for SSH remote servers and other headless environments.\n\n### Other Auth Commands\n\n```bash\n# Check login status (issues a lightweight tools/list call to validate the\n# token against the server — safe to use as a cron preflight)\nmeegle auth status\n\n# Log out\nmeegle auth logout\n```\n\n`auth status` exit codes and `reason` field let scripts (cron jobs, CI\npreflights) react correctly without having to parse human text:\n\n| Exit | `reason` | Meaning | Recommended action |\n|------|----------|---------|--------------------|\n| 0    | —        | Token is present locally and accepted by the server | Proceed |\n| 1    | `no local token` | No token stored | Run `meegle auth login` |\n| 1    | `token rejected by server` | Token expired or revoked; refresh exhausted | Run `meegle auth login` |\n| 2    | `server unreachable: <err>` | Network, timeout, or 5xx — the call itself failed | Retry later; do not re-login |\n\nJSON output example (`auth status --format json`) on a rejected token:\n\n```json\n{\"authenticated\": false, \"host\": \"meegle.com\", \"reason\": \"token rejected by server\"}\n```\n\nFor credentials managed by `meegle auth login`, token refresh is serialized\nacross CLI processes that share a profile. Invalid refresh responses are\nrejected without overwriting the previous credentials, and a late 401 from an\nolder process cannot clear a token that another process has already refreshed.\n\n## Configuration\n\n### Config File\n\nConfiguration is stored in `~/.meegle/config.json`:\n\n```bash\n# Initialize config\nmeegle config init\n\n# View current config\nmeegle config show\n\n# Set a config value\nmeegle config set host project.feishu.cn\n\n# Get a config value\nmeegle config get host\n```\n\nMain config options:\n\n| Field | Description | Examples |\n|-------|-------------|----------|\n| `host` | Site domain | `project.feishu.cn`, `meegle.com` |\n| `user_access_token` | User access token; use `${VAR}` to read from an environment variable | `${CI_MEEGLE_TOKEN}` |\n| `access_token_header` | Custom HTTP header name that carries the token; empty falls back to default `Authorization: Bearer <token>` | `x-meegle-auth` |\n| `user_agent` | Caller suffix appended to the default `User-Agent` (form: `meegle-cli/<ver> <user_agent>`); supports `${VAR}` template; overridden by the `MEEGLE_USER_AGENT` env var | `my-service/1.0` |\n\n### Sandbox / CI: Direct Environment-Variable Injection\n\nThe following well-known environment variables are read directly by the CLI without requiring any `config set`:\n\n```bash\nexport MEEGLE_HOST=project.feishu.cn\nexport MEEGLE_USER_ACCESS_TOKEN=<your-user-token>\nexport MEEGLE_USER_AGENT=ci-runner  # optional; appended to User-Agent, highest priority over config.user_agent\nexport MEEGLE_AI_HANDOFF=disabled   # optional; locally hard-disable AI Handoff\nmeegle workitem get --work-item-id 123\n```\n\nThese variables may be set independently. When `MEEGLE_USER_ACCESS_TOKEN` is set, the CLI bypasses the keychain and does not attempt to refresh on 401 — the caller is responsible for rotating the env value. Setting only `MEEGLE_HOST` (without a token) still uses the keychain-stored credentials. `MEEGLE_AI_HANDOFF=disabled` is a disable-only local gate and does not alter profile configuration.\n\n### Custom Auth Header\n\nBy default the token is sent via the standard `Authorization: Bearer <token>` header. If the backend requires a different header (and rejects requests that carry `Authorization`), opt in with `access_token_header`:\n\n```bash\nmeegle config set access_token_header x-meegle-auth\n```\n\nOr override at runtime via env var:\n\n```bash\nexport MEEGLE_ACCESS_TOKEN_HEADER=x-meegle-auth\n```\n\nWhen enabled the CLI sends `<header>: <token>` with the raw token (no `Bearer ` prefix) and **omits `Authorization` entirely** — suitable for backends that reject requests carrying both headers.\n\n### Environment Variable Templates\n\nIf your runtime exposes a variable with a name other than `MEEGLE_*`, bind it through `config.json` using a `${VAR}` placeholder. The placeholder is resolved against the process environment at runtime. This keeps secrets out of `config.json` while adapting to whatever variable name your runtime (Docker, Kubernetes, CI system) already injects.\n\n```json\n{\n  \"current\": \"prod\",\n  \"profiles\": {\n    \"prod\":    { \"host\": \"project.feishu.cn\", \"user_access_token\": \"${PROD_CI_TOKEN}\" },\n    \"staging\": { \"host\": \"staging.feishu.cn\", \"user_access_token\": \"${STAGING_CI_TOKEN}\" }\n  }\n}\n```\n\nRules:\n- Only whole-string placeholders are recognized. `\"${X}\"` is expanded; `\"Bearer ${X}\"` is treated as a literal.\n- When a referenced variable is unset or empty, commands that require credentials fail fast and report the field path and variable name. Recovery entry points such as `--help`, `version`, `auth login --help`, and `config set` remain available so the profile can be repaired.\n- When `user_access_token` is configured, it takes precedence over any token stored locally by `meegle auth login`. Because this mode has no refresh path, rotate the environment value yourself when the server returns 401.\n\n### Multi-Environment Profiles\n\nManage multiple environment configurations (different sites, different accounts). Each profile stores its own host and auth credentials independently.\n\n```bash\n# Create a new profile (interactive host selection + login)\nmeegle config profile create staging\n\n# List all profiles\nmeegle config profile list\n\n# Switch default profile\nmeegle config profile use staging\n\n# View current profile\nmeegle config profile current\n\n# Temporarily use another profile (without changing default)\nmeegle mywork todo --action this_week --page-num 1 --profile staging\n\n# Delete a profile\nmeegle config profile delete staging\n```\n\n## Enterprise CLI Extensions\n\nCompanies can depend on this Go module, register trusted in-process adapters, and build their own `meegle` binary without modifying the official repository. V1 supports three extension seams:\n\n- `extension/credential` selects an account and supplies an existing Meegle user token. Known local/recovery commands bootstrap without invoking Credential providers, so a slow OIDC provider cannot block help, version, configuration repair, completion, URL parsing, or extension diagnostics; commands that need identity still resolve the provider and fail closed on any provider error.\n- `extension/transport` observes or blocks CLI HTTP requests while retaining redirect and TLS-downgrade protections. Provider and hook callbacks have a 30-second safety timeout, but the real MCP, OAuth, and attachment request keeps the caller's Context and original HTTP client timeout, so enabling an extension does not shorten large uploads, downloads, or slow server operations. Its trusted in-process pre-hook sees the credential-injected live request and can technically change authentication headers; the CLI does not provide in-process isolation or freeze header values. Its post-hook receives an isolated metadata snapshot with `http.NoBody` and a cloned TLS state, so a stalled hook cannot consume, retain, or mutate the live response stream. Credential-bearing MCP requests—default Bearer or custom token header—retain a 10-redirect limit and are never redirected away from their exact original origin.\n- `extension/platform` observes, wraps, or restricts both static commands and MCP-discovered dynamic commands. Plugin metadata/Install and each Startup hook have a two-second safety boundary; a timed-out fail-open plugin is skipped, while fail-closed stops the CLI, and late registration is ignored. Restrict plugins must be fail-closed; a hand-written plugin that declares `Restricts=true` with `FailurePolicy=FailOpen` fails startup instead of being silently skipped.\n\nUse `cmd.ExecuteWithVersion(version)` for an enterprise binary whose plugins declare `RequireCLI`; `cmd.Execute()` remains the compatible default entry point. A `dev` build deliberately cannot satisfy a version constraint and its compatibility error points to `ExecuteWithVersion`; this fail-closed check is not bypassed. Extensions are linked at build time—there is no runtime plugin download—and the SDK does not load CLI extension registries. See [all extension examples](./examples/README.md) and the [architecture contract](./docs/design/CLI-EXTENSION-ARCHITECTURE.md).\n\nAn extension-enabled binary exposes non-secret diagnostics under `meegle extension doctor|credentials|transport|plugins|policy|discovery`. Credential and transport diagnostics distinguish `not-evaluated`, `active`, and `failed` instead of re-running providers during an offline diagnostic command. Restrict rules also govern these commands, so a readonly allow-list should include `extension/**` when operators need troubleshooting access.\nPolicy denials honor explicit structured output modes and use the stable `CLIENT_COMMAND_DENIED` error code. Credential and Platform failures that happen before CLI App construction also honor explicit JSON/NDJSON output and expose `CLIENT_CREDENTIAL_RESOLUTION_FAILED` or `CLIENT_EXTENSION_INSTALL_FAILED` instead of plain text.\nErrors and panic values returned by extension callbacks stay behind a guarded Go error-chain boundary: custom `Is`, `As`, `Unwrap`, `Error`, or payload methods cannot crash the CLI, and panic details cannot enter public output. Extension code should still return ordinary, context-aware errors because it runs as trusted code in the CLI process.\nEvery JSON-RPC response is bounded before decoding: `tools/list` uses an 8 MiB discovery limit and all other calls use a 32 MiB per-response limit.\nDynamic discovery accepts nullable JSON Schema types such as `\"type\": [\"string\", \"null\"]` and exposes them as the underlying CLI/SDK parameter type. Unions containing multiple non-null types are isolated with the stable `unsupported_schema_union` diagnostic instead of silently removing unrelated tools.\n\n## FAQ\n\n### Empty Command List\n\nThe CLI fetches available commands from the server at startup. If the network is unreachable or you're not logged in, dynamic commands won't be registered. Make sure you're logged in first:\n\n```bash\nmeegle auth login\n```\n\nThe command list is cached automatically and refreshed silently in the background when expired.\nWhen server-side command discovery fails with no usable cache, local commands such as `auth`, `config`, `inspect`, `completion`, and `url` still start normally; dynamic business commands report a `TOOL_DISCOVERY_FAILED` server error until connectivity recovers.\n\n## Security & Risk Warnings\n\nThis tool is designed to be called by AI Agents to automate Meegle operations, which carries inherent risks — model hallucinations, unpredictable execution, and prompt injection. Once you authorize Meegle permissions, the Agent will act under your user identity within the granted scope, and may perform high-impact actions (field updates, status transitions, work item creation) on your behalf. Use with care.\n\nRecommended safeguards:\n\n- Preview side-effectful commands with `--dry-run` before running them\n- Use a dedicated profile (`meegle config profile create`) for Agent-driven sessions so you can audit and revoke independently\n- For CI / shared environments, prefer short-lived env-var token injection (`MEEGLE_USER_ACCESS_TOKEN`) and rotate on 401 — do not relax default security settings\n\nBy using this tool you are deemed to voluntarily assume all related responsibilities.\n\n## Star History\n\n[![Star History Chart](https://api.star-history.com/svg?repos=larksuite/meegle-cli&type=Date)](https://star-history.com/#larksuite/meegle-cli&Date)\n\n## Contributing\n\nCommunity contributions are welcome. For bugs and feature requests, open an [Issue](https://github.com/larksuite/meegle-cli/issues) or [Pull Request](https://github.com/larksuite/meegle-cli/pulls). For major changes, please start a discussion via an Issue first.\n\n## License\n\nThis project is licensed under the **MIT License**.\n\nWhen running, it calls Lark/Feishu Open Platform APIs. To use these APIs, you must comply with the following agreements and privacy policies:\n\n- [Feishu User Terms of Service](https://www.feishu.cn/terms)\n- [Feishu Privacy Policy](https://www.feishu.cn/privacy)\n- [Feishu Open Platform App Service Provider Security Management Specifications](https://open.feishu.cn/document/uAjLw4CM/uMzNwEjLzcDMx4yM3ATM/management-practice/app-service-provider-security-management-specifications)\n- [Lark User Terms of Service](https://www.larksuite.com/user-terms-of-service)\n- [Lark Privacy Policy](https://www.larksuite.com/privacy-policy)\n",
  "bytes": 52349,
  "sha": "57001cd4ceb8d4be67814496e7614fb13c583f0bd028156b6f306b6efd42a849",
  "repo_slug": "larksuite/meegle-cli",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/skl_larksuite_meegle_cli_meegle_d088fbe5/readme"
}