- name
- dingtalk-workspace-cli
- description
- DingTalk Workspace CLI (dws) — cross-platform tool for managing DingTalk enterprise data (contacts, calendars, docs, todos, AI tables, chat) via command line and AI agents
- triggers
- ["search DingTalk contacts or users","create a DingTalk calendar event or meeting","query DingTalk AI table records","search DingTalk documents","create or list DingTalk todos","send a DingTalk message","manage DingTalk drive files","get DingTalk attendance records"]
# DingTalk Workspace CLI (dws)
> Skill by [ara.so](https://ara.so) — Devtools Skills collection.
DingTalk Workspace CLI (`dws`) is an officially open-sourced cross-platform CLI tool from DingTalk that unifies DingTalk's full suite of product capabilities (contacts, calendars, documents, todos, AI tables, chat, drive, attendance, reports, meetings) into a single package. It's designed for both human users and AI agent scenarios, with structured JSON responses, OAuth device-flow authentication, and enterprise-grade security.
## Installation
**macOS / Linux:**
```bash
curl -fsSL https://raw.githubusercontent.com/DingTalk-Real-AI/dingtalk-workspace-cli/main/scripts/install.sh | sh
```
**Windows (PowerShell):**
```powershell
irm https://raw.githubusercontent.com/DingTalk-Real-AI/dingtalk-workspace-cli/main/scripts/install.ps1 | iex
```
**npm (requires Node.js):**
```bash
npm install -g dingtalk-workspace-cli
```
**Build from source (Go 1.25+):**
```bash
git clone https://github.com/DingTalk-Real-AI/dingtalk-workspace-cli.git
cd dingtalk-workspace-cli
go build -o dws ./cmd
cp dws ~/.local/bin/
```
**Upgrade (requires v1.0.7+):**
```bash
dws upgrade # interactive upgrade
dws upgrade --check # check without installing
dws upgrade --version v1.0.7 # specific version
dws upgrade --rollback # rollback
```
## Authentication
**Interactive login (browser):**
```bash
dws auth login
```
**Device flow (headless environments):**
```bash
dws auth login --device
```
**Custom app (CI/CD, ISV integration):**
```bash
dws auth login --client-id $DINGTALK_CLIENT_ID --client-secret $DINGTALK_CLIENT_SECRET
```
**Check auth status:**
```bash
dws auth status
```
**Logout:**
```bash
dws auth logout
```
## Core Architecture
### Product Services
DingTalk Workspace is organized into product services:
| Service | Commands | Use Cases |
|---------|----------|-----------|
| `contact` | user, dept, org | Search users, list departments, get org info |
| `calendar` | event | Create/list/update/delete calendar events |
| `aitable` | space, base, table, record, field, view | Query/create AI table records, manage schema |
| `doc` | search, create | Search DingTalk Docs, create documents |
| `todo` | task, category | Create/list/update todos, manage categories |
| `chat` | send, list | Send messages, list conversations |
| `drive` | list, upload, download | Manage DingTalk drive files |
| `attendance` | record, shift | Get attendance records, query shifts |
| `report` | list | List reports (inbox/sent/created) |
| `minutes` | list, detail | Get AI meeting minutes |
| `im` | group, message | Manage IM groups, send messages |
### Global Flags
```bash
# Output formats
-f, --format table|json|raw # table (human), json (structured), raw (API response)
# JQ filtering (extract specific fields)
--jq '.result[0].name' # save tokens, extract precisely
# Dry run (preview without executing)
--dry-run # see request payload before sending
# Skip confirmation (required for AI agents)
--yes, -y # auto-confirm destructive operations
# Debug
--debug # verbose logging
```
## Key Commands & Patterns
### Contact Management
**Search users:**
```bash
# Basic search
dws contact user search --query "engineering"
# With filtering and formatting
dws contact user search --query "zhang" -f json --jq '.result[] | {name: .name, userId: .userId, mobile: .mobile}'
# Dry run
dws contact user search --query "zhang" --dry-run
```
**Get current user:**
```bash
dws contact user get-self -f json --jq '.result[0].orgEmployeeModel | {name: .orgUserName, userId: .userId, depts: [.depts[].deptName]}'
```
**Get user by ID:**
```bash
dws contact user get --user-id "USER_ID"
```
**List departments:**
```bash
# Root departments
dws contact dept list
# Subdepartments
dws contact dept list --dept-id "DEPT_ID"
# Extract specific fields
dws contact dept list --jq '.result[] | {id: .deptId, name: .name}'
```
**List department members:**
```bash
dws contact dept members --dept-id "DEPT_ID" -f json
```
### Calendar Events
**List events:**
```bash
# Today's events
dws calendar event list
# Date range
dws calendar event list --start-time "2026-05-20T00:00:00+08:00" --end-time "2026-05-21T00:00:00+08:00"
# Extract fields
dws calendar event list --jq '.result[] | {title: .summary, start: .start.dateTime, attendees: [.attendees[].displayName]}'
```
**Create event:**
```bash
# Basic event
dws calendar event create \
--summary "Team Sync" \
--start-time "2026-05-20T14:00:00+08:00" \
--end-time "2026-05-20T15:00:00+08:00" \
--yes
# With attendees
dws calendar event create \
--summary "Quarterly Review" \
--start-time "2026-05-25T10:00:00+08:00" \
--end-time "2026-05-25T11:30:00+08:00" \
--attendees "USER_ID_1,USER_ID_2" \
--location "Meeting Room A" \
--description "Q2 business review" \
--yes
```
**Update event:**
```bash
dws calendar event update \
--event-id "EVENT_ID" \
--summary "Updated Title" \
--start-time "2026-05-20T15:00:00+08:00" \
--end-time "2026-05-20T16:00:00+08:00" \
--yes
```
**Delete event:**
```bash
dws calendar event delete --event-id "EVENT_ID" --yes
```
### AI Table (AITable)
**List spaces:**
```bash
dws aitable space list -f json --jq '.result[] | {id: .spaceId, name: .name}'
```
**List bases in space:**
```bash
dws aitable base list --space-id "SPACE_ID"
```
**List tables in base:**
```bash
dws aitable table list --base-id "BASE_ID"
```
**Query records:**
```bash
# All records
dws aitable record query --base-id "BASE_ID" --table-id "TABLE_ID"
# With filters (filterByFormula)
dws aitable record query \
--base-id "BASE_ID" \
--table-id "TABLE_ID" \
--filter-by-formula '{Status}="Done"' \
--limit 10
# Sort and paginate
dws aitable record query \
--base-id "BASE_ID" \
--table-id "TABLE_ID" \
--sort '[{"field":"CreatedTime","order":"desc"}]' \
--page-size 20
# Extract specific fields
dws aitable record query \
--base-id "BASE_ID" \
--table-id "TABLE_ID" \
--jq '.result.records[] | {id: .recordId, fields: .fields}'
```
**Create records:**
```bash
# Single record
dws aitable record create \
--base-id "BASE_ID" \
--table-id "TABLE_ID" \
--records '[{"fields":{"Name":"Test Item","Status":"In Progress","Priority":1}}]' \
--yes
# Multiple records
dws aitable record create \
--base-id "BASE_ID" \
--table-id "TABLE_ID" \
--records '[
{"fields":{"Name":"Item 1","Status":"Todo"}},
{"fields":{"Name":"Item 2","Status":"Done"}}
]' \
--yes
```
**Update records:**
```bash
dws aitable record update \
--base-id "BASE_ID" \
--table-id "TABLE_ID" \
--records '[{"recordId":"RECORD_ID","fields":{"Status":"Done"}}]' \
--yes
```
**Delete records:**
```bash
dws aitable record delete \
--base-id "BASE_ID" \
--table-id "TABLE_ID" \
--record-ids "RECORD_ID_1,RECORD_ID_2" \
--yes
```
**List fields (schema):**
```bash
dws aitable field list --base-id "BASE_ID" --table-id "TABLE_ID"
```
### Todo Management
**List todos:**
```bash
# All incomplete todos
dws todo task list
# With filters
dws todo task list --is-done false --jq '.result[] | {id: .taskId, title: .subject, due: .dueTime}'
# Specific category
dws todo task list --category-id "CATEGORY_ID"
```
**Create todo:**
```bash
dws todo task create \
--title "Review PR #123" \
--executors "USER_ID" \
--due-time "2026-05-22T18:00:00+08:00" \
--priority 10 \
--yes
# With description and multiple executors
dws todo task create \
--title "Quarterly Report" \
--description "Complete Q2 summary" \
--executors "USER_ID_1,USER_ID_2" \
--due-time "2026-05-30T23:59:59+08:00" \
--yes
```
**Update todo:**
```bash
dws todo task update \
--task-id "TASK_ID" \
--is-done true \
--yes
# Update fields
dws todo task update \
--task-id "TASK_ID" \
--title "Updated Title" \
--priority 20 \
--yes
```
**Delete todo:**
```bash
dws todo task delete --task-id "TASK_ID" --yes
```
**List categories:**
```bash
dws todo category list -f json
```
### Document Search
**Search documents:**
```bash
# Basic search
dws doc search --query "quarterly report"
# With type filter
dws doc search --query "roadmap" --doc-type "doc" --jq '.result[] | {title: .title, url: .url, author: .creator.name}'
# Pagination
dws doc search --query "API" --max-results 50
```
### Chat & IM
**Send message:**
```bash
# To user
dws chat send \
--receiver-id "USER_ID" \
--msg-type "text" \
--content "Hello from dws!" \
--yes
# To group
dws chat send \
--receiver-id "GROUP_ID" \
--msg-type "text" \
--content "Team update" \
--yes
# Markdown message
dws chat send \
--receiver-id "USER_ID" \
--msg-type "markdown" \
عرض على GitHub