Primary Purpose:
DingTalk Workspace CLI (dws) is a command-line tool designed to manage DingTalk workspace operations efficiently. It serves as an interface for developers and AI agents, enabling seamless interaction with DingTalk's ecosystem.
Key Features:
For Humans: The tool offers intuitive commands such as --help for usage guidance, --dry-run to preview actions without execution, and flexible output formats (-f table/json/raw) for data presentation.
For AI Agents: It provides structured JSON responses and built-in Agent Skills, facilitating integration with AI tools like Claude Code and Cursor.
For Enterprise Admins: The tool features a zero-trust architecture with OAuth device-flow authentication, domain allowlisting, and least-privilege scoping, ensuring robust security.
Audience & Benefit:
Ideal for developers seeking efficient workspace management, AI agents requiring direct interaction, and enterprise admins prioritizing secure access. Benefits include enhanced productivity through command-line efficiency, secure access mechanisms, and seamless integration with AI tools, all underpinned by a zero-trust security model.
This tool can be installed via winget, offering a straightforward setup process for users.
README
DingTalk Workspace CLI (dws)
dws — DingTalk Workspace on the command line, built for humans and AI agents.
> [!IMPORTANT]
> Co-creation Phase: This project accesses DingTalk enterprise data and requires enterprise admin authorization. Join the DingTalk DWS co-creation group for support and updates. See Getting Started below.
>
>
For humans — --help for usage, --dry-run to preview requests, -f table/json/raw for output formats.
For AI agents — structured JSON responses + built-in Agent Skills, ready out of the box.
For enterprise admins — zero-trust architecture: OAuth device-flow auth + domain allowlisting + least-privilege scoping. Not a single byte can bypass authentication and audit.
Installation
macOS / Linux:
curl -fsSL https://raw.githubusercontent.com/DingTalk-Real-AI/dingtalk-workspace-cli/main/scripts/install.sh | sh
> macOS users: If you see "cannot be opened because Apple cannot check it for malicious software", run:
> bash > xattr -d com.apple.quarantine /path/to/dws >
Build from source:
git clone https://github.com/DingTalk-Real-AI/dingtalk-workspace-cli.git
cd dingtalk-workspace-cli
go build -o dws ./cmd # build to current directory
cp dws ~/.local/bin/ # install to PATH
> Requires Go 1.25+. Use make package to cross-compile for all platforms (macOS / Linux / Windows x amd64 / arm64).
Upgrade
> Requires v1.0.7 or later. For earlier versions, please re-run the install script to upgrade.
dws has built-in self-upgrade capability. Updates are pulled directly from GitHub Releases with SHA256 integrity verification and automatic backup.
dws upgrade # interactive upgrade to latest version
dws upgrade --check # check for new versions without installing
dws upgrade --list # list all available versions
dws upgrade --version v1.0.7 # upgrade to a specific version
dws upgrade --rollback # rollback to the previous version
dws upgrade -y # skip confirmation prompt
How it works
The upgrade process follows a two-phase atomic flow to ensure consistency:
Prepare — downloads the platform-specific binary and skill packages to a temporary directory, verifies SHA256 checksums, and extracts/validates all files. If any step fails, the upgrade aborts without modifying the existing installation.
Apply — only after all preparations succeed, the binary is replaced and skill packages are installed to all detected agent directories (~/.agents/skills/dws, ~/.claude/skills/dws, ~/.cursor/skills/dws, etc.).
A backup of the current version is automatically created before each upgrade. Use dws upgrade --rollback to restore the previous version if needed.
Flag
Description
--check
Check for updates without installing
--list
List all available versions with changelogs
--version
Upgrade to a specific version (e.g. v1.0.7)
--rollback
Rollback to the previous backed-up version
--force
Force reinstall even if already on the latest version
Credentials are securely persisted after first login (Keychain). Subsequent runs auto-refresh tokens.
Quick Start
dws contact user search --query "engineering" # search contacts
dws calendar event list # list today's calendar events
dws doc search --query "quarterly" # search DingTalk Docs
dws minutes list mine # list AI meeting notes I created
dws drive list # list DingTalk drive files
dws todo task create --title "Quarterly report" --executors "" # create a todo (replace )
dws todo task list --dry-run # preview without executing
> Full command list: docs/command-index.md — all commands with descriptions and when-to-use guidance.
Using with Agents
dws is designed as an AI-native CLI. Complete Installation and Getting Started first, then configure your agent:
Agent Invocation Patterns
# Use --yes to skip confirmation prompts (required for agents)
dws todo task create --title "Review PR" --executors "" --yes
# Use --dry-run to preview operations (safe execution)
dws contact user search --query "engineering" --dry-run
# Use --jq to extract precisely (save tokens)
dws contact user get-self --jq '.result[0].orgEmployeeModel | {name: .orgUserName, dept: .depts[0].deptName, userId}'
Schema Discovery
Agents don't need pre-built knowledge of every command. Use dws schema to dynamically discover capabilities:
The repo ships a complete Agent Skill system (skills/). After installing, AI tools like Claude Code / Cursor can operate DingTalk directly through natural language:
# Install skills into current project
curl -fsSL https://raw.githubusercontent.com/DingTalk-Real-AI/dingtalk-workspace-cli/main/scripts/install-skills.sh | sh
> install.sh installs to $HOME/.agents/skills/dws (global); install-skills.sh installs to ./.agents/skills/dws (current project).
Per-product command reference (aitable, chat, calendar, etc.)
Intent guide
references/intent-guide.md
Disambiguation for confusing scenarios (e.g. report vs todo)
Global reference
references/global-reference.md
Auth, output formats, global flags
Error codes
references/error-codes.md
Error codes + debugging workflows
Recovery guide
references/recovery-guide.md
RECOVERY_EVENT_ID handling
Ready-made scripts
scripts/*.py
13 batch operation scripts (see below)
Ready-made scripts — 13 Python scripts for common multi-step workflows
Script
Description
calendar_schedule_meeting.py
Create event + add participants + find & book available meeting room
calendar_free_slot_finder.py
Find common free slots across multiple people, recommend best meeting time
calendar_today_agenda.py
View today/tomorrow/this week's schedule
import_records.py
Batch import records from CSV/JSON into AITable
bulk_add_fields.py
Batch add fields to an AITable data table
upload_attachment.py
Upload attachment to AITable attachment field
todo_batch_create.py
Batch create todos from JSON (with priority, due date, executors)
todo_daily_summary.py
Summarize today/this week's incomplete todos
todo_overdue_check.py
Scan overdue todos and output overdue list
contact_dept_members.py
Search department by name and list all members
attendance_my_record.py
View my attendance records for today/this week/specific date
attendance_team_shift.py
Query team shift schedules and attendance statistics
report_inbox_today.py
View today's received reports with details
ISV Integration: Author your own Agent Skills and orchestrate them with dws skills for cross-product workflows: ISV Skill → dws Skill → DingTalk Open Platform API (enforced auth + full audit).
Features
Raw API Access — call any DingTalk OpenAPI directly
dws api lets you call any DingTalk OpenAPI without an SDK. Tokens are automatically acquired and refreshed.
> Prerequisite: Must login with your own app credentials (see Custom App mode). Encrypted tokens from MCP default-credential login are not supported for raw API calls.
# Login (first time only)
dws auth login --client-id --client-secret
# === api.dingtalk.com ===
# List all enterprise apps
dws api GET /v1.0/microApp/allApps
# Search users (POST + JSON body)
dws api POST /v1.0/contact/users/search \
--data '{"queryWord":"engineering","offset":0,"size":10}'
# === oapi.dingtalk.com ===
# Get user details (use --base-url to specify domain)
dws api POST /topapi/v2/user/get \
--base-url https://oapi.dingtalk.com \
--data '{"userid":""}'
# Or use the full URL directly
dws api POST https://oapi.dingtalk.com/topapi/v2/user/get \
--data '{"userid":""}'
# === General ===
dws api GET /v1.0/microApp/allApps --page-all # auto-paginate
dws api GET /v1.0/microApp/allApps --dry-run # preview request
dws api GET /v1.0/microApp/allApps --jq '.agentId' # jq filtering
Feature
Details
Dual-form auto-detection
Automatically selects api.dingtalk.com (header auth) or oapi.dingtalk.com (query-param auth) based on URL
Automatic token management
App-level accessToken is fetched on first call, cached while valid, auto-refreshed on expiry
Domain allowlist
Only api.dingtalk.com and oapi.dingtalk.com permitted — prevents token leakage
Auto-pagination
--page-all iterates all pages. --page-limit caps the maximum (default 10, set to 0 for unlimited, hard cap at 500 to prevent infinite loops)
Smart Input Correction — auto-corrects common AI model parameter mistakes
Built-in pipeline engine that normalizes flag names, splits sticky arguments, and fuzzy-matches typos:
# Naming convention auto-conversion (camelCase / snake_case / UPPER -> kebab-case)
dws aitable record query --baseId BASE_ID --tableId TABLE_ID # auto-corrected to --base-id --table-id
# Sticky argument splitting
dws contact user search --query "engineering" --timeout30 # auto-split to --timeout 30
# Fuzzy flag name matching
dws aitable record query --base-id BASE_ID --tabel-id TABLE_ID # --tabel-id -> --table-id
# Value normalization (boolean / number / date / enum)
# "yes" -> true, "1,000" -> 1000, "2024/03/29" -> "2024-03-29", "ACTIVE" -> "active"
Agent Output
dws Auto-Corrects To
--userId
--user-id
--limit100
--limit 100
--tabel-id
--table-id
--USER-ID
--user-id
--user_name
--user-name
jq Filtering & Field Selection — fine-grained output control to reduce token consumption
# Built-in jq expressions
dws aitable record query --base-id BASE_ID --table-id TABLE_ID --jq '.invocation.params'
dws schema --jq '.products[] | {id, tools: (.tools | length)}'
# Return only specific fields
dws aitable record query --base-id BASE_ID --table-id TABLE_ID --fields invocation,response
Schema Introspection — query parameter schemas before making calls
dws schema # list all products and tools
dws schema aitable.query_records # view parameter schema
dws schema aitable.query_records --jq '.tool.required' # view required fields
dws schema --jq '.products[].id' # extract all product IDs
Pipe & File Input — read flag values from files or stdin
Online spreadsheet (contentType=ALIDOC, extension=axls): worksheet CRUD, range read/write/append, dimension ops, cell merge, find/replace, named filter views + sheet-level filters, image write, async export (submit_export_job + query_export_job — no consolidated export in v1.0.25)
Wiki
wiki
7
spacemember
Knowledge base management: space create / get / list / search + member add / list / update
DevDoc
devdoc
1
article
Search the DingTalk Open Platform documentation
Raw API
api
1
—
Call any DingTalk OpenAPI directly (api / oapi dual-form), with automatic app-level token management
> 204 commands across 16 products. Full listing with descriptions and usage scenarios: docs/command-index.md. Run dws --help for the top-level tree, or dws --help for subcommands.
> Note on chat bot: bot capabilities (send-by-bot / recall-by-bot / add-bot / send-by-webhook / bot search) are merged into the relevant chat subtrees (e.g. dws chat message send-by-bot, dws chat group members add-bot) so the agent-facing command surface stays flat and discoverable. There is no longer a separate top-level bot product.
Coming soon
conference (video) · aiapp (AI apps) · live (streaming)
Security by Design
dws treats security as a first-class architectural concern, not an afterthought. Credentials never touch disk, tokens never leave trusted domains, permissions never exceed grants, operations never escape audit — every API call must pass through DingTalk Open Platform's authentication and audit chain, no exceptions.
For Developers
Mechanism
Details
Encrypted token storage
PBKDF2 + AES-256-GCM encryption, keyed by device physical MAC address; cross-platform Keychain/DPAPI integration provides additional protection — tokens cannot be decrypted on another machine
Input security
Path traversal protection (symlink resolution + working directory containment), CRLF injection blocking, Unicode visual spoofing filtering — prevents AI Agents from being tricked by malicious instructions
Domain allowlist
DWS_TRUSTED_DOMAINS defaults to *.dingtalk.com; bearer tokens are never sent to non-allowlisted domains
HTTPS enforced
All requests require TLS; HTTP only permitted for loopback during development
Dry-run preview
--dry-run shows call parameters without executing, preventing accidental mutations
Zero credential persistence
Client ID / Secret used in memory only — never written to config files or logs
For Enterprise Admins
Mechanism
Details
OAuth device-flow auth
Users must authenticate through an admin-authorized DingTalk application
Least-privilege scoping
CLI can only invoke APIs granted to the application — no privilege escalation
Allowlist gating
Admin confirmation required during co-creation phase; self-service approval planned
Full-chain audit
Every data read/write passes through the DingTalk Open Platform API — enterprise admins can trace complete call logs in real time; no anomalous operation can hide
For ISVs
Mechanism
Details
Tenant data isolation
Operates under authorized app identity; cross-tenant access is impossible
Skill sandbox
Agent Skills are Markdown documents (SKILL.md) — prompt descriptions only, no arbitrary code execution
Zero blind spots
Every API call during ISV–dws skill orchestration is forced through DingTalk Open Platform authentication — full call chain is traceable with no bypass path