This skill is a dws(DingTalk official Workspace CLI) minutes service'sread capability wrapper, focusing on "querying and reading AI Minutes content" —contains no write operations such as writing/modifying/recording control on the DingTalk server side(does not call update/upload/record and other write commands). All reads are performed through dws , without bypassing the CLI to call the HTTP API directly.
Note: "read-only" in this skill meansnot modifying DingTalk cloud data; however, archiving (archive), mirroring (mirror), and optional audio download are allexplicit operations that write already-read content to the user's local file system, requiring the user to actively run the corresponding script and specify a directory; this is not equivalent to unauthorized external transmission. See the sections "Local Archiving and Incremental Sync" and "Mirroring to External Folders" below for details.
Command reference (read-only type):references/01-commands.md。 Must-read for first deployment (installation/authorization/pitfalls):references/02-setup.md。
Dependencies
System dependencies
| Dependency | Installation method |
|---|---|
dws(DingTalk official Workspace CLI) |
macOS/Linux: download the installation script first, then execute it (see the command below; note the path is scripts/install.sh, not the root directory install.sh) |
python3(used by the sync script) |
macOS usually includes it; if missing, brew install python |
curl(used by the installation script) |
macOS usually includes it; if missing, brew install curl |
Install dws(download to a temporary file first, then execute, to avoid curl | sh executing a remote script directly):
curl -fsSL https://raw.githubusercontent.com/DingTalk-Real-AI/dingtalk-workspace-cli/main/scripts/install.sh -o /tmp/dws-install.sh
sh /tmp/dws-install.sh
PATH configuration: dws is installed to ~/.local/binby default and needs to be added to the shell PATH. The following command will modify your ~/.zshrc(persistent shell configuration), appending only one PATH line and being idempotent (skipped if already present); if you do not want to automatically modify the configuration, you can manually add export PATH="$HOME/.local/bin:$PATH" to your shell configuration:
grep -q '.local/bin' ~/.zshrc || echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc
Authorization and organization switch (both are indispensable)
This skill depends on three independent prerequisites; if any step is missing, reading will fail: install dws → enable the organization's "CLI Access Management" switch → authorize and log in. For detailed steps, the counterintuitive semantics of the switch, and pitfalls such as authorization must run in the background, see references/02-setup.md。
Out-of-the-box and dependency-required features
- Out-of-the-box: This skill's core read commands (list / +detail / get *) are all calls to dws; once dws is installed and authorized, they can be used.
- Requires local Python:
scripts/sync.py(local archiving and incremental sync),minutes_extract_todos.pyand other scripts requirepython3(standard library only, no third-party package dependencies).
Prerequisites
- dws is installed:
dws versionand can return normally (see the "Dependencies" installation instructions above). - Authorized:
dws auth statusshowsauthenticated: true. For authorization usedws auth login --device(run in the background, wait for the callback to complete after scanning the QR code; see the pitfalls document). - Organization switch enabled: DingTalk Open Platform → Developer Platform → More → Basic Information → CLI Access Management, when the toggle text is "Prohibit all members from using CLI", you need toturn it offOnly then is it allowed (see the pitfalls document for details).
- All
dwscommandsmust include--format jsonto get parseable output.
Core capabilities (read)
| User intent | Command |
|---|---|
| List my meeting notes | dws minutes list mine [--query "<关键词>"] [--start "<ISO>"] [--end "<ISO>"] |
| List all meeting notes I can access (including those shared by others) | dws minutes list all |
| List those shared with me by others | dws minutes list shared |
| Fetch everything at once (basic information/summary/keywords/verbatim transcript/todos) | dws minutes +detail --uuid <taskUuid> |
| Read AI summary | dws minutes get summary --id <taskUuid> |
| Read the original speech-to-text transcript (verbatim transcript) | dws minutes get transcription --id <taskUuid> |
| Read keywords | dws minutes get keywords --id <taskUuid> |
| Read todos | dws minutes get todos --id <taskUuid> |
| Read audio download URL | dws minutes get audio --id <taskUuid> |
| Merge recent meeting note summaries | python scripts/minutes_recent_summary.py --max 5 |
| Extract todos from a certain meeting | python scripts/minutes_extract_todos.py --id <taskUuid> |
Standard SOP
SOP-1 Query meeting note list (query-minutes)
- Choose scope (iron rule):
mine=created/initiated by me;shared=shared with me by others;all=all I can access (mine∪shared). When the user says "I can access/visible/all/my meeting notes", always useall; only when they explicitly say "created by me/initiated by me" usemine。 - Execute:
dws minutes list all|mine|shared --format json; add keywords with--query, add time with--start/--end, limit the number of items with--max <n>, paginate with--next-token <token>。 - Parse: from
itemList[]get the realtaskUuid+title+ time; if there are multiple candidates, have the user confirm, do not default to taking the first one.
SOP-2 Get meeting note details (get-minute-detail)
- Prerequisite: first follow SOP-1 to get the target
taskUuid。 - Execute (choose one as needed):
get summary/get transcription/get keywords/get todos/get info/get audio, all include--format json。 - Transcript pagination (required):
get transcriptionA single call returns at most about 50 segments; when the return includesnextToken, thenmustcontinue--next-tokenpagination to pull everything, then summarize. - Parse:
--id/--uuid/--task-uuidare equivalent,recommended to uniformly use--id; it is prohibited to fabricate taskUuid.
High-frequency hard constraints
- Automatic URL extraction: when the user provides a
shanji.dingtalk.com/app/transcribes/<taskUuid>-type link, automatically extract the hex string as--id; it is prohibited to use the entire URL as a parameter, and prohibited to open it in a browser. - Calculate time yourself: when the user says today/this week/last week/last N days/a certain date range, calculate
--start/--endyourself (ISO-8601, such as2026-05-11T00:00:00+08:00), do not ask back. - Server-side filtering first: when the time range and keywords can be filtered server-side, they must be put into the same
list all --start --end --query, do not pull everything back and filter locally. - Empty list fallback: for the same range
list all→ remove keywords and keep time → clearly inform that there is no data. It is prohibited to fabricate meeting note content to generate minutes. - Fetch data before generating: before generating minutes/documents/todos, you must first
list→ lock onto the realtaskUuid→get summary(if the original text/action items are needed, thenget transcription/get todos). If the data is not obtained, stop and explain the blocker. - Export the original text without downgrading: When the user wants to "download/export the verbatim transcript", you must retrieve it item by item
get transcriptionand page through to the end; do not downgrade to a summary. - Shell pipes are prohibited: Do not use
|、head、grep、jqto truncate the output; use--format jsonto process in memory.
Local archiving and incremental sync (archive / sync)
This skill supports syncing DingTalk AI meeting notesto the archive/ directory within the skill, creating a local backup to avoid forgetting historical content and to only incrementally pull new meeting notes.
⚠️ Privacy and compliance notice: Verbatim transcripts, summaries, and to-dos may contain client secrets, the personal privacy of involved parties, or internal business information. Archiving/mirroring will write the above contentto the local file system—do not commit
archive/or the mirror target directory to public repositories, shared directories, or third-party sync services;archive/and the local mirror configuration have been added by default to.gitignore. Before running, confirm that the target location is accessible only to you.
Archive structure
archive/
├── index.json # 同步状态:last_sync(上次同步时间) + synced_uuids + uuid_to_dir(uuid→目录名映射)
└── <YYMMDD>_<标题>/ # 目录名:日期(两位年,如 260508) + 下划线 + 听记标题
├── meta.json # 结构化元数据:uuid/标题/时间/时长/分享链接/创建人/关键词列表/音频信息
├── transcript.md # 语音转写逐字稿(已翻页拉全,含【发言人 N】前缀);文件头部含关键词/AI摘要/待办概览
├── summary.md # AI 生成的完整摘要(fullSummary 全文)
├── keywords.md # 关键词列表
└── todos.md # 待办事项(含负责人,来自 get todos 详细接口)
Goal: Store as much as possible in the internal archive. All textual information that can be extracted from a single meeting note will be saved to disk—verbatim transcript, AI summary, keywords, to-dos, audio download URL, and metadata. The audio file itselfis not downloaded by default(the URL carries expiring authentication, and a single item is about 150MB); if you need a local audio backup, run
python scripts/sync.py --with-audio。Directory name example:
260805_08-05 图书出版协作优化/. When there is a conflict with the same date and same title, append a short uuid suffix (e.g.,260805_xxx_3af2c1). Deduplication and incremental determination are based on uuid; the directory name is only for readability, and it is traced back via theindex.jsonofuuid_to_dir.
Sync command
python scripts/sync.py # 增量同步:仅拉取 last_sync 之后的新听记
python scripts/sync.py --full # 全量重扫(已存在 uuid 跳过,不重复拉逐字稿)
python scripts/sync.py --list-new # 只列出本次新增标题,不拉逐字稿
python scripts/sync.py --dry-run # 预览将执行的 dws 命令,不写文件
python scripts/sync.py --archive-dir /path/to/archive # 指定存档目录
python scripts/sync.py --no-mirror # 本次只存档,不自动镜像到外部文件夹
Automatic mirroring (enabled by default): When there are new archives in this run and
config/mirror-target.local.jsonexists, automatically call after the sync is completemirror_output.pyfor incremental mirroring (sha256 verification, also filling in files that previously failed to mirror); if no mirror target is configured, prompt to skip without affecting archiving. Mirror failure is also only reported—archive is the authoritative source.
Incremental principle
- Read
archive/index.jsonoflast_syncas the parameter ofdws minutes list all --start <last_sync>; the server returns only meeting notes after that time. - Existing local
synced_uuidsentries are skipped to avoid repeated pulls. - For each new meeting note: generate the directory name according to
YYMMDD_标题, pullget transcription(page through to pull everything) and savetranscript.md, pullget summary/get todos/get keywordsand savemeta.json; record the uuid-to-directory-name mapping inuuid_to_dir。 - Update
index.json: write thestartTimeISOof the latest meeting note intolast_sync, and merge the uuid intosynced_uuids。
Usage conventions
- On first run there is no
index.json→ full scan (limited by the dws list pagination; the script automatically pages through). - To know "where the last sync got to and what was newly added this time" → look at the
last_syncoutput by the script and the list of newly added titles, or directly readarchive/index.json。 - The archive directory is added to
.gitignoreper the AGENTS.md convention (or managed separately in a private repository), to avoid mistakenly committing verbatim transcripts to a public repository.
Mirroring to an external folder (mirror)
One-way copy of the finished meeting notes from archiveOne-way copyTo an external designated folder (such as the Obsidian / Clawd knowledge base), for manual review. The archive is the authoritative source; the mirrordoes not write back to the archiveand does not change the sync status.
sync.py When there are new items, by default it automatically mirrors(since v1.1.0) — once sync completes, the mirroring process below runs automatically, with no need to manually run the commands in this section; the commands in this section are used for manual gap-filling, changing the target, filtering by date/single item, and similar scenarios.
Usage
# 默认按 config/mirror-target.local.json 的 dest 镜像全部听记
python scripts/mirror_output.py
# 只镜像指定日期(YYMMDD)之后开始的听记
python scripts/mirror_output.py --since 260801
# 只镜像单条听记(指定 archive 内目录)
python scripts/mirror_output.py --archive "archive/260805_08-05 图书出版协作优化"
# 覆盖目标目录 / 自定义白名单
python scripts/mirror_output.py --dest /path/to/output
python scripts/mirror_output.py --items transcript,summary,todos,keywords
# 预览将复制哪些文件,不写入
python scripts/mirror_output.py --dry-run
Configuration
Copy the template to a local config and edit dest:
cp config/mirror-target.example.json config/mirror-target.local.json
# 编辑 .local.json 的 dest 字段(本机实际路径)
config/mirror-target.local.json has been .gitignore excluded (machine-specific path, not committed to the version repository). If the config file is missing and --dest is not passed, it exits with code 2 and a prompt.
Mirrored content (whitelist)
| key | File | Description |
|---|---|---|
transcript |
transcript.md |
Speech-to-text verbatim transcript (including overview) |
summary |
summary.md |
Full AI summary text |
todos |
todos.md |
To-do items |
keywords |
keywords.md |
Keywords (optional) |
meta |
meta.json |
Structured metadata (optional) |
By default only mirrors transcript,summary,todos(three md files).Does not copy meta.json(unless explicitly adding --items ... ,meta), to avoid leaking structured internal data. Missing files are skipped without error (some recordings themselves have no todos/summary).
Mirror directory structure
<dest>/
├─ 260805_08-05 图书出版协作优化/
│ ├─ transcript.md
│ ├─ summary.md
│ ├─ todos.md
│ └─ .mirror-manifest.json # 源路径 + 文件列表 + sha256,便于核对
└─ 260729_07-29 医疗损害鉴定听会/
└─ ...
Incremental and verification
- If the target file already exists and the sha256 matches → treated as already mirrored, skipped without overwriting (incremental).
- Each mirror run writes under the recording subdirectory
.mirror-manifest.json(source archive path, mirror time, file list + sha256), for later verification. - A mirror failure is only reported and does not affect the archive or sync status.
Cross-product collaboration
- Create tasks in bulk from to-dos → switch
dingtalk-todo - Send the summary to a colleague → switch
dingtalk-chat - Schedule/meeting room → switch
dingtalk-calendar - Save to disk as a document → switch
dingtalk-doc
Scope boundary of this skill (thin shell)
- ✅ Only wrapsreadcapabilities: list, summary, transcription, keywords, to-dos, audio addresses, recent merge, to-do extraction script.
- ❌ Does not include write operations: modifying title/summary (
update), full-text replacement (replace-text/+replace-batch), uploading audio (upload), recording control (record), permission management (permission), speaker matching/correction. If you need these, directly calldws minutes <cmd>or refer to DingTalk's official dws built-indingtalk-minutesfull documentation.
Dependencies
System dependency: requires installing dws(DingTalk's official Workspace CLI, version >= 1.0.15).
Python packages: no third-party dependencies (scripts underscripts/ use only the standard library).
References and acknowledgements
- The command contract originates from DingTalk's official
dingtalk-workspace-clibuilt-indingtalk-minutesskill; this skill refines it into a read-only thin shell. For command reference see references/01-commands.md。