| name | dida-cli |
| description | Use DidaCLI to operate Dida365/TickTick from agents. Trigger whenever the user asks to read, create, update, complete, delete, move, organize, or audit Dida365 tasks, projects, folders, tags, completed history, trash, or kanban columns. Prefer this skill over browser automation because DidaCLI provides stable JSON, auth checks, dry-run writes, and explicit destructive confirmations. |
DidaCLI Agent Skill
Use the dida command for Dida365/TickTick operations. It is built for agents: every --json response has a stable envelope, writes support --dry-run, and destructive actions require --yes.
First Checks
Run these before doing useful work:
dida doctor --json
dida account verify --json
dida schema list --compact --json
dida channel list --json
dida agent context --outline --json
dida auth status --verify --json
If auth is missing or expired, tell the operator to run:
dida auth cookie set --token-stdin --json
Never ask the user to paste cookies, browser tokens, or raw t= values into chat. If manual cookie import is unavoidable, tell the operator to run dida auth cookie set --token-stdin locally.
Safety Rules
You MUST follow these rules when operating DidaCLI:
- Always preview writes first — Run
--dry-run before any write command. Show the user the generated payload. Only remove --dry-run after the user confirms.
- Never skip
--yes on deletes — Destructive operations (delete, merge) require --yes. Never add --yes without the user's explicit instruction.
- You are an operator, not an owner — You do not own the Dida365 account. Any data loss, modification, or account issue caused by your actions is the user's responsibility. Make this clear by always previewing before executing.
- Do not chain destructive writes — Never batch-delete or batch-modify without individual confirmation. One mistake in a batch write is hard to undo.
- Treat tokens as secrets — Never log, echo, or display cookie/token values. DidaCLI automatically redacts them; do not circumvent this.
Use the local schema command when selecting a command or checking safety flags:
dida schema show task.create --json
dida schema show comment.delete --json
Check authRequired, dryRun, and confirmationRequired in schema output
before choosing a command. If authRequired is true, verify the matching
channel auth first; do not assume a Web API cookie can satisfy official MCP or
OpenAPI commands.
Pick The Channel
Choose the channel by job, not by habit:
| Job | Prefer | Notes |
|---|
| First account read for an Agent | dida agent context --outline --json | Web API one-call context pack; lowest repeated-token cost. |
| Normal task/project/folder/tag/comment work | Web API first-class commands | Broadest web-app coverage, compact reads, dry-run writes, --yes deletes. |
| Official task/project validation with token auth | dida official ... | Uses Official MCP; DIDA365_TOKEN or saved official token config only. |
| Habit/focus resource work | Official MCP or dida openapi ... | Prefer official surfaces; current live smokes may need disposable habit/focus records. |
| Public OAuth REST validation | dida openapi ... | Requires saved OAuth client config and access token; MCP tokens do not apply. |
| Web-app-only metadata | Web API reads | Settings, comments, sharing, calendar, templates, stats, trash, closed history, and search. |
| Unknown private write flow | No command yet | Document evidence first; do not tunnel writes through raw calls. |
Read Context
Prefer the one-call context pack. Use outline mode first when IDs and compact
task fields are enough:
dida agent context --outline --json
dida agent context --json
Use separate bounded JSON commands when you need a narrower response:
dida project list --json
dida folder list --json
dida tag list --json
dida filter list --json
dida column list <project-id> --json
dida comment list --project <project-id> --task <task-id> --json
dida +today --compact --json
dida task upcoming --days 14 --limit 50 --compact --json
dida task due-counts --json
dida quadrant list --json
dida completed today --compact --json
dida trash list --cursor 20 --compact --json
dida pomo list --limit 10 --json
dida pomo task --project <project-id> --task <task-id> --json
dida habit list --json
dida habit checkins --habit <habit-id> --json
dida attachment quota --json
dida reminder daily --json
dida share project shares <project-id> --json
dida calendar subscriptions --json
dida stats general --json
dida pomo timeline --limit 10 --json
dida template project list --limit 10 --json
dida search all --query <text> --limit 20 --json
dida attachment download --project <project-id> --task <task-id> --attachment <attachment-id> --output <file> --json
Use exact IDs from read commands for writes. Do not guess project IDs, folder IDs, or task IDs from names if the command output is available.
Use --compact or --brief on broad task reads to reduce agent context. Compact task output keeps operational fields and drops large text, checklist, reminder, and raw fields. Use agent context --outline when repeated task objects would waste tokens; it returns today/upcoming/quadrants as task id references plus a deduplicated taskIndex. Fetch full task JSON only when those larger fields are needed.
Task Writes
Preview generated task writes first:
dida task create --project <project-id> --title "Example" --dry-run --json
dida task update <task-id> --project <project-id> --title "New title" --dry-run --json
dida task move <task-id> --from <project-id> --to <project-id> --dry-run --json
dida task parent <task-id> --parent <parent-task-id> --project <project-id> --dry-run --json
Use first-class task field flags instead of raw payloads: --content, --desc, --start, --due, --timezone, --tag, --tags, --item, --column, --reminder, --repeat, --repeat-from, --repeat-flag, --all-day, and --floating.
Time inputs accept RFC3339, YYYY-MM-DD[ HH:MM], or Dida wire UTC and are normalized before write. Reminder inputs accept human forms (30m, 15min, 1h, at-start) or TRIGGER:-PT30M.
Timed tasks with reminders
Web /batch/task rejects reminders (HTTP 500). The CLI coordinates:
dida account verify --json → require identity_match: true when both channels are configured
dida task create ... --reminder 30m --reminder 15m --dry-run --json → two-step preview
- same command without
--dry-run → Web body, then OpenAPI reminders only
Do not invent cross-account fallback. Identity mismatch is a hard error unless emergency DIDA_ALLOW_CROSS_ACCOUNT=1.
Execute narrow writes only after the preview matches intent:
dida task create --project <project-id> --title "Example" --json
dida task create --project <project-id> --title "Grab code" --start "2026-07-18T20:00:00+08:00" --timezone Asia/Shanghai --reminder 30m --reminder 15m --json
dida task update <task-id> --project <project-id> --title "New title" --json
dida task complete <task-id> --project <project-id> --json
Deletes require explicit confirmation:
dida task delete <task-id> --project <project-id> --dry-run --json
dida task delete <task-id> --project <project-id> --yes --json
Resource Writes
Use high-level resource commands before raw API probes:
dida project create --name "Inbox review" --dry-run --json
dida project update <project-id> --name "New name" --dry-run --json
dida project delete <project-id> --dry-run --json
dida project delete <project-id> --yes --json
dida folder create --name "Work" --dry-run --json
dida folder update <folder-id> --name "Work archive" --dry-run --json
dida folder delete <folder-id> --dry-run --json
dida folder delete <folder-id> --yes --json
dida tag create planning --color "#147d4f" --dry-run --json
dida tag rename planning planning-next --dry-run --json
dida tag merge old-tag new-tag --dry-run --json
dida tag merge old-tag new-tag --yes --json
dida tag delete old-tag --dry-run --json
dida tag delete old-tag --yes --json
After tag merge, list tags again if the goal is to retire the source tag. The observed private endpoint can leave the source tag object present, so explicit tag delete may still be needed.
Column support is intentionally conservative:
dida column list <project-id> --json
dida column create --project <project-id> --name "Doing" --dry-run --json
Do not claim column update/delete support unless the CLI exposes those commands.
Comments
Use comment commands for task discussion. Preview writes before execution:
dida comment list --project <project-id> --task <task-id> --json
dida comment create --project <project-id> --task <task-id> --text "Example" --dry-run --json
dida comment create --project <project-id> --task <task-id> --text "Example" --file ./image.png --dry-run --json
dida comment update --project <project-id> --task <task-id> --comment <comment-id> --text "Updated" --dry-run --json
dida comment delete --project <project-id> --task <task-id> --comment <comment-id> --dry-run --json
Deletes require explicit confirmation:
dida comment delete --project <project-id> --task <task-id> --comment <comment-id> --yes --json
For comment attachments, use the real project id from dida agent context --json, not the logical inbox alias. Always preview generated writes with
--dry-run before uploading local files. Existing task attachments can be
downloaded with dida attachment download --project <project-id> --task <task-id> --attachment <attachment-id> --output <file> --json; the command
refuses to overwrite local files unless --force is provided. Task-level
attachment upload, preview, mutation, and delete are not exposed yet. If upload
fails, check dida attachment quota --json.
Official MCP And OpenAPI
Keep official channels separate from browser-cookie Web API commands.
Use official MCP when the operator has configured DIDA365_TOKEN or saved a
local official token:
dida official doctor --json
dida official token status --json
dida official show get_focuses_by_time --json
dida official project list --json
dida official project data <project-id> --json
dida official task get <task-id> --project <project-id> --json
dida official task search --query "today" --json
dida official task query --query "today" --json
dida official task filter --project <project-id> --status 0 --json
dida official task batch-add --args-json "{\"tasks\":[{\"title\":\"Example\"}]}" --dry-run --json
dida official task complete-project --project <project-id> --task <task-id> --dry-run --json
dida official habit list --json
dida official habit sections --json
dida official habit get <habit-id> --json
dida official habit checkin <habit-id> --date 2026-05-09 --value 1 --dry-run --json
dida official focus list --from-time 2026-05-01T00:00:00+08:00 --to-time 2026-05-09T23:59:59+08:00 --type 1 --json
Use dida official token clear --json only when the operator explicitly wants
to remove the saved local official MCP token.
Treat dida official call as a read-oriented exploration escape hatch. It has
no dry-run layer, so do not use it for write-capable MCP tools unless the
operator explicitly approves that specific tool and payload.
Use official OpenAPI only through dida openapi .... It is OAuth-based and
does not accept MCP dp_... tokens or Web API cookies as bearer tokens.
dida openapi doctor --json
dida openapi status --json
dida openapi client status --json
dida openapi logout --json
dida openapi project list --json
dida openapi project create --args-json "{\"name\":\"Project\",\"viewMode\":\"list\",\"kind\":\"TASK\"}" --dry-run --json
dida openapi focus list --from 2026-04-01T00:00:00+0800 --to 2026-04-02T00:00:00+0800 --type 1 --json
dida openapi habit list --json
dida openapi habit checkin <habit-id> --args-json "{\"stamp\":20260407,\"value\":1}" --dry-run --json
If OpenAPI client config is missing, ask the operator to run this locally:
dida openapi client set --id <client-id> --secret-stdin --json
Preview official habit writes and focus deletes with --dry-run first. Do not
create live disposable habits only to validate the wrapper unless the operator
has approved a cleanup or archive procedure; the official MCP surface exposes
habit create/update/check-in but no habit delete tool. Do not delete focus
records unless the operator has identified a disposable record; live
dida official focus delete and dida openapi focus delete require --yes.
Account Metadata
Use these read-only commands for operational context around uploads, reminders,
sharing, and calendar integrations:
dida attachment quota --json
dida attachment download --project <project-id> --task <task-id> --attachment <attachment-id> --output <file> --json
dida reminder daily --json
dida share contacts --json
dida share recent-users --json
dida share project shares <project-id> --json
dida share project quota <project-id> --json
dida share project invite-url <project-id> --json
dida calendar subscriptions --json
Do not create invite links, delete invite links, invite users, or change
sharing permissions unless the CLI exposes a first-class command with dry-run or
confirmation behavior.
Error Handling
If a JSON command returns ok: false, surface error.message and error.hint to the operator. Do not retry destructive operations automatically.
Example error shape:
{
"ok": false,
"command": "task delete",
"error": {
"type": "confirmation_required",
"message": "task delete requires --yes",
"hint": "preview first with: dida task delete <task-id> --project <project-id> --dry-run"
}
}
Raw Escape Hatch
Use raw reads only when a high-level command is missing:
dida raw get /path --api-version v1|v2 --json
dida raw get /batch/check/0 --json
dida raw get /user/preferences/settings --json
dida raw get /attachment/isUnderQuota --api-version v1 --json
Raw writes are intentionally unavailable. Add a first-class command with tests instead of tunneling writes through raw calls.
When dida raw get ... --json fails, inspect error.details.statusCode,
error.details.path, and error.details.bodySnippet. Treat the snippet as API
evidence only; do not paste it into public docs if it contains user data.