Agent-native CLI for TickTick task management — full API coverage via V1 + V2
Project description
ticktick-cli
Agent-native command-line interface for TickTick
Full API coverage · JSON-first · Built for AI agents and humans alike
I was frustrated that no proper TickTick CLI existed. The official API covers only tasks and projects, third-party SDKs are incomplete, MCP servers add unnecessary context overhead, and none of these approaches are designed for the way modern AI agents actually work. So I built ticktick-cli -- a CLI that covers 100% of TickTick's API surface (including the unofficial V2 endpoints), outputs structured JSON by default, and works equally well when invoked by a human or by Claude Code via Bash.
Why CLI, not MCP or SDK?
The emerging consensus from practitioners like Peter Steinberger and Armin Ronacher is clear: CLI-first, MCP only when necessary. AI coding agents (Claude Code, Codex, Cursor) already invoke tools via shell -- that's their native interface. Adding an MCP server is an extra process, an extra protocol, and extra context pollution that doesn't add value when a CLI already outputs structured JSON. Benchmarks show CLI achieves higher task completion at equivalent token cost. The Unix philosophy was accidentally designed for AI agents decades before they existed.
Highlights
- JSON output by default -- structured
{"ok": true, "data": [...]}responses, parseable by any agent or script --humanflag -- switch to rich terminal tables with a single flag- 100% API coverage -- tasks, subtasks, projects, folders, tags, kanban columns, habits, focus/pomodoro (including live timer), filters, templates, user profile
- Dual API support -- V1 (official OAuth 2.0) + V2 (unofficial session-based) for full feature access
- Focus timer control -- start, stop, log, and delete pomodoro sessions directly from CLI
- Multiple output formats -- JSON (default), CSV, YAML, or rich terminal tables (
--human) - Natural language dates --
--due tomorrow,--start "next monday",--due "in 3 days" - Agent-friendly design -- no interactive prompts,
--yesflags,--dry-run, deterministic exit codes (0/1/2) - Field selection --
--fields id,title,priorityto return only what you need - Multiple profiles --
--profile work/--profile personalfor separate accounts - Security-first -- OAuth CSRF protection, encrypted credential storage (600 permissions), env var support for secrets
- Shell completions -- bash, zsh, fish auto-complete out of the box
- Retry with backoff -- automatic retries for transient API errors, V1 token auto-refresh
Table of Contents
- Installation
- Quick Start
- Commands
- Output Format
- Agent Integration
- Authentication
- Configuration
- Security
- Contributing
- License
Installation
From source (recommended for now)
git clone https://github.com/MakotoUwu/ticktick-cli.git
cd ticktick-cli
python -m venv .venv && source .venv/bin/activate
pip install -e .
pip
pip install ticktick-agent-cli
pipx (isolated install)
pipx install ticktick-agent-cli
The published package name is ticktick-agent-cli; the installed command remains ticktick.
Quick Start
1. Authenticate
# V2 session (recommended -- unlocks all features)
ticktick auth login-v2 --username you@email.com
# Password is prompted securely (or set TICKTICK_PASSWORD env var)
# V1 OAuth (official API -- tasks & projects only)
export TICKTICK_CLIENT_ID="your_client_id"
export TICKTICK_CLIENT_SECRET="your_client_secret"
ticktick auth login --client-id "$TICKTICK_CLIENT_ID" --client-secret "$TICKTICK_CLIENT_SECRET"
2. Start using it
# List your tasks (JSON)
ticktick task list
# Same thing, but as a rich table
ticktick --human task list
# Add a task (natural language dates!)
ticktick task add "Review pull request" --priority high --due tomorrow
# Complete it
ticktick task done TASK_ID
# What's overdue?
ticktick task overdue
# Check your habits
ticktick --human habit list
# Start a 25-minute focus session
ticktick focus start --duration 25
# Inspect linked calendar accounts
ticktick calendar account list
# Inspect upcoming linked calendar events
ticktick calendar event list --limit 10
# Distinguish TickTick-owned entries from external mirrors
ticktick --fields title,sourceType,linkedTaskId,calendarName calendar event list --limit 10
# Resolve a TickTick-owned calendar entry to its backing task
ticktick calendar event task EVENT_ID
# Check focus timer status
ticktick focus status
# Focus stats for the last 30 days
ticktick focus heatmap --days 30
# Output as CSV or YAML
ticktick task list --output csv
ticktick habit list --output yaml
# Select specific fields
ticktick task list --fields id,title,priority
# Full account sync
ticktick sync
JSON output (default)
{
"ok": true,
"data": [
{
"id": "abc123",
"title": "Review pull request",
"priority": "high",
"status": "active",
"dueDate": "2026-03-11T00:00:00.000+0000"
}
],
"count": 1
}
Rich table output (--human)
Tasks
┏━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━┓
┃ id ┃ title ┃ priority ┃ dueDate ┃
┡━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━┩
│ abc123 │ Review pull request │ high │ 2026-03-11 │
│ def456 │ Buy groceries │ none │ 2026-03-12 │
└──────────┴────────────────────────┴──────────┴──────────────┘
Commands
| Domain | Commands | API |
|---|---|---|
| Tasks | add list show edit done abandon delete move search today overdue completed trash pin unpin batch-add duplicate convert activity comment list comment add comment delete |
V1+V2 |
| Subtasks | set unset list |
V2 |
| Projects | list create show edit delete |
V1+V2 |
| Folders | list create rename delete |
V2 |
| Tags | list create edit rename merge delete |
V2 |
| Kanban | column list create edit delete |
V2 |
| Habits | list show create edit delete checkin history archive unarchive |
V2 |
| Focus | start stop status log delete stats heatmap by-tag |
V2 |
| Filters | list show create edit delete |
V2 |
| Templates | list show create delete |
V2 |
| User | profile status stats preferences |
V2 |
| Config | set get list path |
-- |
| Auth | login login-v2 logout status refresh |
-- |
| Utilities | sync schema completion version |
V2 |
Global Options
| Flag | Description |
|---|---|
--human |
Rich table output instead of JSON |
--output FORMAT |
Output format: json (default), csv, yaml |
--fields FIELDS |
Comma-separated list of fields to include |
--dry-run |
Preview what would happen without making changes |
--verbose |
Enable debug output |
--profile NAME |
Auth profile to use (default: default) |
--version |
Show version |
--help |
Show help for any command |
Output Format
Every command returns a consistent JSON envelope:
Success: {"ok": true, "data": <result>, "count": <n>}
Message: {"ok": true, "message": "Task created."}
Error: {"ok": false, "error": "description"}
Exit Codes
| Code | Meaning |
|---|---|
0 |
Success |
1 |
General error (API error, invalid input) |
2 |
Authentication error (not logged in, expired token) |
Agent Integration
ticktick-cli follows the agent-native CLI design pattern -- the same approach used by gh, git, and docker with Claude Code, Codex, and Cursor. An AGENTS.md file is included for agent discovery (compatible with the AGENTS.md standard adopted by 60,000+ repositories).
No ANSI escape codes in JSON mode -- output is always clean, parseable JSON.
No interactive prompts -- use --yes to skip confirmations for destructive actions:
ticktick task delete TASK_ID --yes
ticktick project delete PROJECT_ID --yes
Deterministic exit codes -- agents can check $? to determine success/failure without parsing output.
Pipe-friendly -- combine with jq for complex queries:
# Get titles of all high-priority tasks
ticktick task list --priority high | jq -r '.data[].title'
# Count overdue tasks
ticktick task overdue | jq '.count'
# Get habit names and streaks
ticktick habit list | jq '.data[] | {name, currentStreak}'
Environment variables for auth -- no secrets in command args:
export TICKTICK_USERNAME="you@email.com"
export TICKTICK_PASSWORD="secret"
export TICKTICK_CLIENT_ID="your_id"
export TICKTICK_CLIENT_SECRET="your_secret"
Why not MCP? MCP servers add a separate process, a custom protocol, and consume thousands of tokens just from tool descriptions being loaded. A CLI that outputs JSON is already a perfect tool interface -- Claude Code calls it via Bash, parses the JSON, and moves on. Zero overhead, universal compatibility, and it works with any agent that has shell access.
Authentication
V1: Official OAuth 2.0
The official API supports tasks and projects. Requires a developer app:
- Go to developer.ticktick.com and create an app
- Set redirect URI to
http://localhost:8080/callback - Run:
ticktick auth login --client-id YOUR_ID --client-secret YOUR_SECRET
This opens your browser for OAuth authorization and stores the token locally.
V2: Session-based (recommended)
The unofficial V2 API unlocks everything: habits, tags, focus stats, kanban, folders, subtasks, and more.
ticktick auth login-v2 --username you@email.com
# Password is prompted securely
Note: V2 uses the same API the TickTick web app uses. It sends your password over HTTPS to TickTick's servers. If you're uncomfortable with this, use V1 OAuth for the subset of features it supports.
Multiple profiles
ticktick --profile work auth login-v2 --username work@company.com
ticktick --profile personal auth login-v2 --username me@gmail.com
ticktick --profile work task list
ticktick --profile personal habit list
Check auth status
ticktick auth status
Configuration
Config files live at ~/.config/ticktick-cli/<profile>/ (XDG-compliant).
# See where config is stored
ticktick config path
# List all settings
ticktick config list
# Set a value
ticktick config set default_project "Work"
# Get a value
ticktick config get default_project
Security
- Credentials stored with
600permissions -- only your user can readauth.json - Atomic file writes -- no TOCTOU race condition where credentials are briefly world-readable
- OAuth CSRF protection --
stateparameter validated on callback - No secrets in process args -- password is prompted interactively or read from env vars
- Error messages sanitized -- API responses truncated to prevent token/credential leakage
- Profile name validation -- prevents directory traversal attacks
Contributing
# Clone and set up
git clone https://github.com/MakotoUwu/ticktick-cli.git
cd ticktick-cli
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
# Run tests
pytest -v
# Build release artifacts
uv build
# All 439 tests should pass
Releasing
- Update
versioninpyproject.toml. - Move the relevant notes from
CHANGELOG.mdinto a dated release section. - Run local release checks:
ruff check src/ tests/
pytest -v --tb=short
uv build
uvx twine check dist/*
- Push
main. - For a staging publish, run the
Publish Python PackageGitHub Actions workflow with thetestpypitarget. - For a production publish, create and publish a GitHub Release (or manually dispatch the workflow with the
pypitarget).
The repository includes a trusted-publishing-ready workflow in .github/workflows/publish.yml. One-time setup is still required in GitHub environments and in the PyPI/TestPyPI Trusted Publisher settings.
Project Structure
src/ticktick_cli/
api/
base.py # Shared HTTP transport with retry & backoff
v1.py # Official OAuth2 API client
v2.py # Unofficial session API client (incl. focus timer)
client.py # Unified TickTickClient
models/
task.py # Task, TaskPriority, TaskStatus
project.py # Project, ProjectKind, ProjectViewMode
tag.py # Tag
habit.py # Habit, HabitCheckin
pomodoro.py # Pomodoro, FocusOperation, PomodoroStatus
comment.py # Comment, Activity, UserProfile
filter.py # Filter, FilterRule, FilterCondition
template.py # TaskTemplate
commands/
auth_cmd.py # login, login-v2, logout, status, refresh
task_cmd.py # 22 task commands + comments + convert
project_cmd.py # CRUD for projects
folder_cmd.py # CRUD for folders
tag_cmd.py # tag management + merge
kanban_cmd.py # kanban columns
subtask_cmd.py # subtask parent/child
habit_cmd.py # habit tracking + checkins
focus_cmd.py # pomodoro timer + stats
filter_cmd.py # saved filters (smart lists) CRUD
template_cmd.py # task templates CRUD
user_cmd.py # profile, stats, preferences
config_cmd.py # CLI config management
schema_cmd.py # CLI structure discovery for agents
auth.py # OAuth2 + V2 auth flows
config.py # XDG config management
output.py # JSON/CSV/YAML/Rich table output
dates.py # Natural language date parsing
exceptions.py # Custom exception hierarchy
cli.py # Main entry point
Why This Over the Official CLI?
This is an unofficial, community-built CLI. TickTick released their own @ticktick/ticktick-cli in March 2025, and various MCP servers exist on the LobeHub registry. Here's how they compare:
| Feature | ticktick-cli (this) | Official CLI | MCP Servers |
|---|---|---|---|
| Commands | 70+ | ~12 | 5-15 |
| API coverage | V1 + V2 (100%) | V1 only | V1 only |
| Habits, Focus, Kanban | Yes | No | No |
| Filters, Templates | Yes | No | No |
| Comments, Activity feed | Yes | No | No |
| JSON-first output | {"ok": true, "data": ...} |
--json flag |
JSON-RPC |
| CSV / YAML / Rich tables | Yes | No | No |
--dry-run |
All mutating commands | No | No |
--fields selection |
Yes | No | No |
schema introspection |
Yes | No | Partial |
| Natural language dates | Yes | No | No |
| Retry with backoff | Yes | No | No |
| Shell completions | bash, zsh, fish | No | N/A |
| Works without runtime | Yes (just Python) | Yes (Node.js) | Needs MCP host |
| Agent-native design | Built for it | Afterthought | Agent-only |
| Human-friendly | --human tables |
Basic | No |
TL;DR: The official CLI covers basic task/project CRUD. MCP servers are agent-only with limited coverage. This CLI covers the entire API surface, works for both humans and agents, and includes features like focus timers, habits, and kanban that no other tool provides.
Roadmap
Done
- Shell completions (bash, zsh, fish)
- V1 token auto-refresh
- CI/CD with GitHub Actions
- CSV and YAML output formats
- Natural language date parsing
- Field selection (
--fields) - Dry-run mode (
--dry-run) - Retry with exponential backoff
- Focus/Pomodoro live timer control
- Pydantic models for all entities
-
schemacommand for agent discovery - Task comments (list, add, delete)
- Activity feed / change history
- Task duplicate
- Smart lists / saved filters
- Task templates (save/reuse)
- Task ↔ Note conversion
Next
- Publish package to PyPI
- Configure Trusted Publishing for repeatable PyPI/TestPyPI releases
- Package and submit a Claude Code plugin directory entry
- Publish native skill distribution for OpenClaw / ClawHub
- Homebrew formula
- Read-only calendar discovery commands (
calendar account list,calendar subscription list,calendar event list) - Advanced productivity reports
- Focus session ↔ task linking
Disclaimer
This project is an unofficial CLI for TickTick and is not affiliated with, endorsed by, or associated with TickTick or Appest Inc. in any way. Use at your own risk.
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ticktick_agent_cli-0.1.1.tar.gz.
File metadata
- Download URL: ticktick_agent_cli-0.1.1.tar.gz
- Upload date:
- Size: 112.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7a9c3b20b577f6516906205ff4353b551e65726566f255a7be285cb4e0e91d8b
|
|
| MD5 |
e5c0d45d00497d08d4f88d3fdacb1df8
|
|
| BLAKE2b-256 |
b4cec9aca906aad54885a1d72f0bae5f89ffc9478fbbdd2c76958bd4ea26455d
|
Provenance
The following attestation bundles were made for ticktick_agent_cli-0.1.1.tar.gz:
Publisher:
publish.yml on MakotoUwu/ticktick-cli
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ticktick_agent_cli-0.1.1.tar.gz -
Subject digest:
7a9c3b20b577f6516906205ff4353b551e65726566f255a7be285cb4e0e91d8b - Sigstore transparency entry: 1194140027
- Sigstore integration time:
-
Permalink:
MakotoUwu/ticktick-cli@814722b284b3cc3c7c40959a48db8dcbbfb42fbe -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/MakotoUwu
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@814722b284b3cc3c7c40959a48db8dcbbfb42fbe -
Trigger Event:
release
-
Statement type:
File details
Details for the file ticktick_agent_cli-0.1.1-py3-none-any.whl.
File metadata
- Download URL: ticktick_agent_cli-0.1.1-py3-none-any.whl
- Upload date:
- Size: 67.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
20ea085ebab0f4e11118cdb2dff9e339a7b0b45958b8f3776a79f37b11ca51b9
|
|
| MD5 |
f5ff3853512fb00ab40f813608da4a6f
|
|
| BLAKE2b-256 |
dad63a428a17f2af061587b7ee43de31626d6743fe7ec031117ed528218381cc
|
Provenance
The following attestation bundles were made for ticktick_agent_cli-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on MakotoUwu/ticktick-cli
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ticktick_agent_cli-0.1.1-py3-none-any.whl -
Subject digest:
20ea085ebab0f4e11118cdb2dff9e339a7b0b45958b8f3776a79f37b11ca51b9 - Sigstore transparency entry: 1194140029
- Sigstore integration time:
-
Permalink:
MakotoUwu/ticktick-cli@814722b284b3cc3c7c40959a48db8dcbbfb42fbe -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/MakotoUwu
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@814722b284b3cc3c7c40959a48db8dcbbfb42fbe -
Trigger Event:
release
-
Statement type: