Skip to main content

cctodo

The command line tool and Python client for ccToDo, made by CloudCircus.

pip install cctodo
cctodo login          # paste a token from Settings → API tokens
cctodo mytasks
cctodo new -group "work group" "my task"
cctodo done 123

It uses only the Python standard library and needs Python 3.9 or newer.

Commands

Tasks are shown with their id (#123), and the commands take that id. Where a command takes a group, you can give its id, its title, or the start of the title (case-insensitive). Without -g, commands use your My Tasks.

A milestone is a goal with a target date that tasks in the same group can belong to (one milestone per task). It's reached when it has no pending tasks and every milestone before it is reached. Give a milestone by its id, or by its title (or the start of it) together with -g GROUP.

Command What it does
cctodo mytasks (my) Your pending My Tasks. -c shows completed tasks instead.
cctodo list [GROUP] (ls) A group's pending tasks. --all lists every group, -c shows completed tasks.
cctodo assigned Pending tasks assigned to you, in all groups.
cctodo groups Your groups, with their pending counts.
cctodo new TITLE… [-g GROUP] [-a WHO] [-b BODY] [-e] (add) Adds a task at the bottom of the list. -b - reads the details from stdin; -e writes the title and details in $EDITOR.
cctodo show ID A task with its details (markdown) and comments.
cctodo done ID… / start ID… / reopen ID… Sets the state to done, in progress, or to do.
cctodo edit ID [-t TITLE] [-b BODY] Edits a task. With no options it opens $EDITOR: the first line is the title and the rest is the details. It refuses to overwrite someone else's newer edit.
cctodo assign ID WHO Assigns to me, a member's email, or none.
cctodo mv ID -g GROUP / mv ID --before ID2 / --after ID2 Moves a task to another group, or reorders it.
cctodo rm ID… [-y] Deletes tasks after asking you to confirm.
cctodo comment ID TEXT… [-r COMMENT_ID] Adds a comment, or a reply with -r.
cctodo milestones [GROUP] (ms) A group's milestones in order of target date: reached [x], next [>], overdue [!], with task counts.
cctodo milestone new TITLE… -d YYYY-MM-DD [-g GROUP] [-b DESCRIPTION] Adds a milestone.
cctodo milestone show/edit/rm MILESTONE Shows a milestone with its tasks, changes it (-t, -d, -b, or $EDITOR), or deletes it (its tasks stay).
cctodo milestone link MILESTONE TASK_ID… / unlink TASK_ID… Puts tasks in a milestone, or takes them out. new -m MILESTONE and edit ID -m MILESTONE (or -m none) do the same for one task.
cctodo group new/rename/members/leave/rm Manages groups.
cctodo invite GROUP EMAIL [-m MESSAGE] Invites someone. If you're a member rather than an owner, an owner approves the invite first.
cctodo invites / accept ID / decline ID Lists and answers invites addressed to you.
cctodo whoami / logout Shows the account you're logged in as, or forgets the saved token.

Add --json to any command for the raw API output. NO_COLOR turns colours off.

Exit codes:

  • 0: the command succeeded.
  • 1: an error occurred.
  • 3: you're not logged in, or your token was revoked.

Configuration

cctodo login saves the token in ~/.config/cctodo/config.json, readable only by you (%APPDATA%\cctodo\config.json on Windows). You can set these environment variables instead:

  • CCTODO_TOKEN: the API token.
  • CCTODO_API_URL: the API address. It defaults to https://api.cctodo.com.
  • CCTODO_CONFIG: a different config file.

To revoke a token, go to Settings → API tokens on www.cctodo.com.

Python

from cctodo import Client, Conflict

todo = Client()                                  # the same token as the CLI (or Client(token="cct_..."))
work = todo.find_group("work group")
task = todo.create_task(work.id, "Write the report", body="Due **Friday**")
todo.assign(task.id, todo.me().id)
todo.start(task.id)

for t in todo.tasks(work.id):                    # pending tasks, in order
    print(t.id, t.state, t.title)                # attribute or t["title"] access

roof = todo.create_milestone(work.id, "Roof on", "2026-11-01", description="Tiles **and** gutters")
todo.set_milestone(task.id, roof.id)             # or None to take it out
for m in todo.milestones(work.id):               # in order of target date
    print(m.title, m.target_date, "reached" if m.reached else f"{m.pending_count} to go")

try:
    todo.update_task(task.id, body="…", expected_updated_at=task.updated_at)
except Conflict:
    print("Someone else changed it first")

Return values: results are the API's JSON as Record objects (dicts with attribute access).

Errors: errors raise cctodo.NotFound (404; this also covers groups you're not in), NotAllowed (403), Invalid (400), Conflict (409), RateLimited (429) or Unauthorized (401). All of them subclass cctodo.CctodoError.

Development

pip install -e .
python -m unittest discover -s . -t .
CCTODO_API_URL=http://api.localhost:8000 cctodo whoami      # against a local cctodo_web

Licence

MIT. See LICENSE.

Metadata

Release files for cctodo 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cctodo 0.2.0
File Size Uploaded
cctodo-0.2.0.tar.gz 24.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for cctodo 0.2.0
File Interpreter ABI Platform
cctodo-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 45.1 kB

Release files / cctodo-0.2.0.tar.gz

Download URL cctodo-0.2.0.tar.gz
Size 24.5 kB
Tags Source
SHA-256 checksum
How to use checksums
409342b554dd12364807cc8ce3b19c496fc2e01ec1981219601f17696d0fdf75
BLAKE2b-256 checksum
How to use checksums
3ccf585bf14cdb97638e86332747153e6f3c8614a02d7b8116e27a3be51ada51
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 30, 2026.

Transparency log

Release files / cctodo-0.2.0-py3-none-any.whl

Download URL cctodo-0.2.0-py3-none-any.whl
Size 20.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2de279f55e3fe71f5ba92fad16935b43fd109eaaecf52e58b8f3b8c6fb23ec2c
BLAKE2b-256 checksum
How to use checksums
6749ab62503b3cb471706ee212755e50eed51d3007f4693ab5fdf4c0527cf5c5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 30, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page