---
name: dothings-cli
description: Manage dothings.fyi tasks from the terminal with the `justdothings` CLI — list/search/create/update/move/delete tasks, read & add comments, manage labels, create typed task links, link GitHub issues/PRs to tasks, manage pages/docs, and manage workspace membership & invites. Use whenever the user wants to view or change their dothings tasks or board, mark tasks done/finished, triage a backlog, assign people, attach a GitHub item to a task, manage pages/docs, or manage workspace members/invites from the command line. Triggers on "my dothings tasks", "mark this task done", "what's on my board", "add a dothings task", "link this PR to a task", "justdothings", "dt tasks".
---

# dothings CLI (`justdothings`)

A CLI for **dothings.fyi**, a task/board app. Same binary also serves the MCP server (`justdothings mcp`). Talks to the REST API at `https://api.dothings.fyi` by default.

## Install & invoke

Published on npm: `npm i -g justdothings`. Bins: `justdothings`, `dt`, `dothings` (all identical).

**Every command accepts `--json`** for machine-readable output — always pass it when you need to parse the result (ids, status, etc.).

## Auth (do this first if commands 401)

- `justdothings login` — prompts for a token (create one at `https://dothings.fyi/settings/tokens`, format `dt_live_…`), verifies it, and saves to the config file.
- `justdothings whoami` — current user + workspace + accessible projects. Good connectivity check.
- `justdothings auth status` — show configured base URL + token presence.
- `justdothings logout` — clear the saved token.

Config: token from `DOTHINGS_TOKEN` env or `~/.config/dothings/config.json`.

## Enums (the API rejects others)

- **status:** `think_about` · `todo` · `doing` · `finished`  ("done" = `finished`)
- **priority:** `none` · `low` · `medium` · `high` · `urgent`
- **link types:** `blocks` · `relates` · `duplicates` · `implements` · `parent`
- **workspace roles:** `owner` · `admin` · `member`
- **project roles:** `admin` · `member`

Projects, members, labels are **project-scoped** — pass `--project <idOrSlug>` (slug like `dothings-fyi` works).

## Command reference

- `justdothings login` — save an API token (verifies it first)
- `justdothings logout` — remove the stored API token
- `justdothings whoami` — current user + accessible projects
- `justdothings auth status` — show the configured base URL + whether a token is set
- `justdothings auth keys` — list your active personal access tokens
- `justdothings profile set [--display-name --github-username]` — update your own profile
- `justdothings notifications read <id>` — mark one notification read
- `justdothings notifications read-all` — mark all your notifications read
- `justdothings notifications read-messages [--comment <id>…]` — mark mention/reply messages read
- `justdothings projects list` — list projects
- `justdothings projects create --name <n> [--description --color --member <id>…]` — create a project (admin)
- `justdothings projects rename <idOrSlug> <name>` — rename a project (admin)
- `justdothings projects set-description <idOrSlug> <description>` — set a project's description (admin)
- `justdothings projects archive <idOrSlug>` — archive a project (admin)
- `justdothings projects unarchive <idOrSlug>` — unarchive a project (admin)
- `justdothings members list --project <slug>` — list assignable people
- `justdothings members add <projectIdOrSlug> <userId>` — add a member (admin)
- `justdothings members remove <projectIdOrSlug> <userId>` — remove a member (admin)
- `justdothings members set-role <projectIdOrSlug> <userId> <role>` — set a project member's role (admin)
- `justdothings teammates list` — list everyone in the workspace (admin)
- `justdothings labels list --project <slug>` — list labels
- `justdothings labels create --project <slug> --name <n> [--color <hex>]` — create a label
- `justdothings tasks list [--project --status --priority --assignee --me --label --search --all]` — list/search tasks (hides finished by default)
- `justdothings tasks mine [--project --status --all]` — tasks assigned to you
- `justdothings tasks get <id>` — show a task in full (id or share link)
- `justdothings tasks create --project <slug> --title <t> [--body|--body-file --status --priority --assignee… --label… --due]` — create a task
- `justdothings tasks update <id> [--status --priority --abandoned --add-assignee --remove-label …]` — update a task
- `justdothings tasks move <id> <status>` — move between columns
- `justdothings tasks start <id>` — move a task to doing
- `justdothings tasks done <id>` — move a task to finished
- `justdothings tasks open <id>` — open the task in your browser
- `justdothings tasks delete <id> --yes` — delete a task
- `justdothings comments list <taskId>` — read a comment thread
- `justdothings comments add <taskId> "<body>" [--reply-to <id>]` — add a comment
- `justdothings comments edit <commentId> "<body>"` — edit a comment (author/admin)
- `justdothings comments delete <commentId>` — delete a comment (author/admin)
- `justdothings link <src> <tgt> --type <type>` — link two tasks
- `justdothings unlink <linkId>` — remove a task link
- `justdothings relink <linkId> <type>` — change a task link's type
- `justdothings github items <projectIdOrSlug>` — list a project's synced GitHub issues & PRs
- `justdothings github link <taskId> <githubItemId>` — link a GitHub issue/PR to a task
- `justdothings github link-pr <taskId> <number>` — sync + link a repo PR/issue #number to a task
- `justdothings github unlink <taskId> <githubItemId>` — remove a GitHub item link from a task
- `justdothings github connect <projectIdOrSlug> <repo>` — connect a repo + initial sync (admin)
- `justdothings github disconnect <projectIdOrSlug>` — disconnect the repo + drop items (admin)
- `justdothings github sync <projectIdOrSlug>` — re-pull a project's GitHub items (member)
- `justdothings github repos list` — list repos the workspace can connect (admin)
- `justdothings pages list --project <slug>` — list a project's pages
- `justdothings pages get <id>` — show a page with its full content
- `justdothings pages create --project <slug> --type <doc|sheet|tweet> [--title --content|--content-file]` — create a page
- `justdothings pages update <id> [--title --content|--content-file --archive --unarchive]` — update a page
- `justdothings pages delete <id> --yes` — delete a page
- `justdothings pages link <pageId> <taskId>` — link a page to a task
- `justdothings pages unlink <pageId> <taskId>` — remove a page ↔ task link
- `justdothings workspace rename <name>` — rename the workspace (owner)
- `justdothings workspace members list` — list workspace members (member)
- `justdothings workspace members set-role <userId> <role>` — set a workspace member's role (admin)
- `justdothings workspace members remove <userId>` — remove a workspace member (admin)
- `justdothings workspace invites send <email> [--role]` — invite someone to the workspace (admin)
- `justdothings workspace invites resend <id>` — resend a workspace invite (admin)
- `justdothings workspace invites revoke <id>` — revoke a workspace invite (admin)
- `justdothings mcp` — run the stdio MCP server
- `justdothings install-mcp [--client claude-code|claude-desktop|cursor]` — print the MCP config snippet
- `justdothings docs` — open the documentation in your browser

## Always include share links

When referencing any task or comment in conversation, always append the share link inline — don't just mention the title or ID:
- Task: `https://dothings.fyi/t/<taskId>`
- Comment: `https://dothings.fyi/t/<taskId>?c=<commentId>`

## Gotchas

- **`--body` interprets `\n` as a newline** (v0.1.8+) — write multiline bodies inline with `\n` (or `\t`), or use `--body-file <path>` for verbatim / complex content. On older CLI versions `--body` stored a literal `\n`, so update with `npm i -g justdothings@latest`.
- **Moving a task to `finished` closes any linked GitHub issues.** To discard a `think_about` idea instead, use `tasks update <id> --abandoned true`.
- `github link`/`unlink` take the **item UUID**, not the PR/issue number — get it from `github items <project>` or `tasks get <id>`.
- Labels must already exist before assigning; create with `labels create` first.
- `workspace` commands require a **workspace-scoped token**. An unscoped legacy token will get a 400.
- Prefer `--json` + parse over scraping the table when scripting or chaining.

## Conventions

## Status (the workflow column)
- think_about — a rough idea or "maybe"; not committed yet.
- todo — committed and ready to be picked up (the right default for "add a task").
- doing — actively in progress now.
- finished — done (or, for a think_about idea, discarded).

## Finishing vs. discarding
Moving a task to finished marks it done AND closes any linked GitHub issues. To drop a
think_about idea rather than complete it, set abandoned: true (update_task) so it isn't
counted as a real completion.

## Priority
none, low, medium, high, urgent — set it to reflect real urgency.

## Writing a task body (markdown)
A one-line summary, then "## Context" and an "## Acceptance criteria" checklist (- [ ]).

## Assignees & labels
Assignees are referenced by username (resolve via list_members). Labels are
project-scoped and must exist before use (create with create_label). A task created
directly into (or moved to) doing should always have an assignee — default to the
current user, or the person doing the work. Work in progress needs an owner.

## Linking tasks
blocks, relates, duplicates, implements, parent — pick the type matching the real dependency.

## Resolving a project
Tasks belong to exactly one project. Resolve the user's words to a project via
list_projects; if several could match, ask which one.

## GitHub & task links
get_task returns linked github_items (issues AND pull requests) and task links
(typed relationships to other tasks) — read them to see what a task references.
Every task also carries attachments: image URLs parsed out of its markdown body
(the inline ![](url) images the web composer uploads).

## Pages (in-project docs, sheets & tweet drafts)
A project can hold pages — list_pages/get_page to read, create_page/update_page to write,
link_page to attach one to a task. A page's content shape is keyed by its type:
- doc — a TipTap/ProseMirror node: { type: "doc", content: [ … ] }.
- sheet — a table: { columns: [{ id, name, type, options?, width? }], rows: [{ "<columnId>": cell }] };
  a column type is text | number | date | due | updated | checkbox | select | member.
- tweet — a draft thread: { tweets: [{ id, text, images? }] }.
update_page REPLACES content, so get_page first and send back the full value. The anchored,
Google-Docs-style comment threads on a doc page are web-only (no REST/CLI/MCP surface).

## Notifications & attribution
You act AS the token's user; tasks/comments/completions are attributed to them.
Assigning, @-mentioning, or replying notifies that person (in-app + push) — don't
bulk-assign or mention more people than intended.
