Connect dothings to your terminal & Claude

do things is a team task workspace. The justdothings package gives you a CLI and an MCP server, so you — or a Claude agent — can manage tasks, projects, and team membership without leaving your editor.

Quickstart

Three steps, then ask Claude to add a task.

npm i -g justdothings
justdothings login          # paste a token from /settings/tokens
justdothings install-mcp    # add the MCP server to Claude

Then in Claude: “add a todo to the website project: fix the footer links, high priority.”

Install the CLI

npm i -g justdothings
justdothings --version

Requires Node 18+. The same package ships the CLI (justdothings, dt) and the MCP server (justdothings mcp).

Create an API token

Generate a personal access token at /settings/tokens. It's shown once — copy it. A token acts as you: it carries your workspace membership and project access, and anything it creates is attributed to you. Workspace-scoped tokens are fenced to a single workspace — useful for CI or per-environment automation.

justdothings login            # paste it when prompted
# …or, statelessly:
export DOTHINGS_TOKEN=dt_live_…

Configure the MCP server

justdothings install-mcpprints this with your token inlined. Paste it into your client's MCP config:

Project .mcp.json, or run claude mcp add.

{
  "mcpServers": {
    "dothings": {
      "command": "justdothings",
      "args": ["mcp"],
      "env": { "DOTHINGS_TOKEN": "dt_live_…" }
    }
  }
}

Claude Code skill

Using Claude Code? Drop this file into your repo at .claude/skills/dothings-cli/SKILL.md and Claude will automatically know how to use the CLI — commands, share link format, gotchas and all. Or fetch it directly: /docs/skill.md.

---
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.

The data model

Everything lives inside a workspace. A workspace contains projects, and projects contain tasks. Members join the workspace first, then get added to individual projects. Workspace roles (owner › admin › member) control what each person can manage; project roles (admin · member) control task-level access within a project.

A task belongs to one project and sits in one status column. Both the CLI and the MCP tools understand these semantics — the agent gets them in every tool description.

StatusMeaning
think_aboutThink abouta rough idea or maybe; not committed yet
todoTo docommitted and ready to be picked up
doingDoingactively in progress now
finishedFinisheddone (or, for a think_about idea, discarded)

Priority: nonelowmediumhighurgent

Link types:
  • blockssource must be done before the target can proceed
  • relatesloosely related
  • duplicatessource duplicates the target
  • implementssource implements the target
  • parentsource is the parent of the target (subtask hierarchy)

Task bodies are markdown — a one-line summary, then ## Context and an ## Acceptance criteria checklist works well. Inline images (![](url)) are also surfaced separately on every task as an attachments array of image URLs.

Workspace & team management

Workspace admins can manage membership and projects programmatically — useful for onboarding automation, CI pipelines, or Claude agents that maintain the board.

Projects (admin)
  • Create, rename, set description, archive / unarchive
  • Add or remove members; set per-project role (admin · member)
  • Connect a GitHub repo for issue & PR sync
Workspace membership (admin)
  • List all members with their workspace roles
  • Invite by email; resend or revoke pending invites
  • Promote or demote members (admin · member); owners can also grant owner
  • Remove members from the workspace

All workspace commands require a workspace-scoped token. Rename requires the owner role; all other membership ops require admin.

GitHub integration

Connect a repo to a project and its issues & pull requests sync in — link them to tasks, and finishing a task can close its linked issue. Your workspace installs the dothings GitHub App on your own org or account, and it reads only the repos you grant — everything else stays invisible.

To connect one: open a project → Settings Connect GitHub / add repos. That opens GitHub's repo picker to install the app on your org; pick the repos you want, then choose one back in Settings to start syncing. A fresh signup owns their workspace, so they can do this themselves — workspace admins and project admins can connect repos too.

CLI reference

CommandDescription
justdothings loginsave an API token (verifies it first)
justdothings logoutremove the stored API token
justdothings whoamicurrent user + accessible projects
justdothings auth statusshow the configured base URL + whether a token is set
justdothings auth keyslist 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-allmark all your notifications read
justdothings notifications read-messages [--comment <id>…]mark mention/reply messages read
justdothings projects listlist 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 listlist 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> --yesdelete 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 listlist 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> --yesdelete 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 listlist 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 mcprun the stdio MCP server
justdothings install-mcp [--client claude-code|claude-desktop|cursor]print the MCP config snippet
justdothings docsopen the documentation in your browser

Every command takes --json.

MCP tools

ToolWhat it does
whoamithe authenticated user + accessible projects
update_profileupdate your own display name / GitHub handle
list_api_keysyour active personal access tokens (self)
mark_notification_readmark one of your notifications read
mark_all_notifications_readmark all your notifications read
mark_messages_readmark mention/reply messages read
list_projectslist/resolve projects (by name or slug)
create_projectcreate a project (admin)
update_projectrename / set description (admin)
list_teammateseveryone in the workspace (admin); ids feed add_member
add_memberadd a teammate to a project (admin)
remove_memberremove a teammate from a project (admin)
list_taskslist/search tasks with filters
get_taskone task in full (body, assignees, labels, linked GitHub issues/PRs, task links, image attachments)
create_taskcreate a task in a project
update_taskpatch a task; assignees/labels replace the set
move_taskmove a task to a status column
delete_taskpermanently delete a task
add_commentadd a markdown comment (supports @mentions, replies)
edit_commentedit a comment (author or admin)
delete_commentdelete a comment (author or admin)
list_commentsread a task's comment thread
list_labelslabels in a project
create_labelcreate a project label
list_memberspeople assignable in a project
link_taskscreate a typed link between two tasks
unlink_tasksremove a task link by id
update_task_linkchange a task link's type
list_github_itemslist a project's synced GitHub issues & PRs
link_githublink a GitHub issue/PR to a task
unlink_githubremove a GitHub item link from a task
list_pageslist a project's pages (docs, sheets, tweet drafts)
get_pageone page in full, incl. its typed content
create_pagecreate a page (doc|sheet|tweet) in a project
update_pageupdate a page's title / content / archived flag
delete_pagepermanently delete a page
link_pagelink a page to a task (same project)
unlink_pageremove a page ↔ task link
connect_github_repoconnect a repo "owner/repo" + initial sync (admin)
disconnect_github_repodisconnect the repo + drop synced items (admin)
sync_githubre-pull a project's GitHub issues & PRs (member)
archive_projectarchive or unarchive a project (admin)
set_project_member_roleset a member's per-project role: "admin" or "member"
rename_workspacerename the token's workspace (owner)
list_workspace_memberslist workspace members with roles (member)
set_workspace_member_roleset a member's workspace role (admin)
remove_workspace_memberremove a member from the workspace (admin)
invite_workspace_memberinvite someone to the workspace by email (admin)
resend_workspace_inviteresend a pending invite email, refresh expiry (admin)
revoke_workspace_invitecancel a pending workspace invite (admin)
list_installable_reposrepos the workspace can connect via GitHub App (admin)

REST API

Base https://api.dothings.fyi — endpoints are under /v1. Authenticate with Authorization: Bearer dt_live_….

curl -H "Authorization: Bearer dt_live_…" \
  https://api.dothings.fyi/v1/whoami
MethodPath
GET/v1/whoami
current user + accessible projects
PATCH/v1/whoami
update your own profile { display_name?, github_username? }
GET/v1/api-keys
your active personal access tokens (self)
GET/v1/teammates
everyone in the workspace (admin)
POST/v1/notifications/:id/read
mark one notification read (self)
POST/v1/notifications/read-all
mark all notifications read (self)
POST/v1/messages/read
mark mention/reply messages read { comment_ids? }
GET/v1/projects?q=
list projects
POST/v1/projects
create a project (admin) { name, description?, color?, member_ids? }
GET/v1/projects/:id
one project (id or slug)
PATCH/v1/projects/:id
rename / set description / archive (admin) { name?, description?, archived? }
GET/v1/projects/:id/members
assignable people
POST/v1/projects/:id/members
add a member (admin) { user_id }
DELETE/v1/projects/:id/members?user_id=
remove a member (admin)
PATCH/v1/projects/:id/members/:userId
set a member's project role (admin) { role }
GET/v1/projects/:id/labels
labels
POST/v1/projects/:id/labels
create a label { name, color? }
POST/v1/projects/:id/github
connect a repo (admin) { repo }
DELETE/v1/projects/:id/github
disconnect the repo (admin)
POST/v1/projects/:id/github/sync
re-pull GitHub items (member)
GET/v1/tasks?project=&status=&priority=&assignee=&label=&q=&limit=&offset=
list/search tasks (paginated: total/has_more/limit/offset; limit ≤ 500, default 200)
POST/v1/tasks
create a task
GET/v1/tasks/:id
one task, fully hydrated
PATCH/v1/tasks/:id
update fields; assignees/labels replace
POST/v1/tasks/:id/move
move to a status column { status, position? }
PUT/v1/tasks/:id/assignees
replace assignees { assignees[] }
PUT/v1/tasks/:id/labels
replace labels { labels[] }
DELETE/v1/tasks/:id
delete a task
GET/v1/tasks/:id/comments
comment thread
POST/v1/tasks/:id/comments
add a comment { body, reply_to_id? }
PATCH/v1/comments/:id
edit a comment (author/admin) { body }
DELETE/v1/comments/:id
delete a comment (author/admin)
POST/v1/task-links
link tasks { source_task_id, target_task_id, type }
PATCH/v1/task-links/:id
change a link's type { type }
DELETE/v1/task-links/:id
remove a link
GET/v1/projects/:id/github-items
list synced GitHub issues & PRs
POST/v1/github-links
link a GitHub item to a task { task_id, github_item_id }
DELETE/v1/github-links?task_id=&github_item_id=
remove a GitHub item link
GET/v1/pages?project_id=
list a project's pages (summaries)
POST/v1/pages
create a page { project_id, type, title?, content? }
GET/v1/pages/:id
one page with full content
PATCH/v1/pages/:id
update a page { title?, content?, archived? }
DELETE/v1/pages/:id
delete a page
POST/v1/page-links
link a page to a task { page_id, task_id }
DELETE/v1/page-links?page_id=&task_id=
remove a page ↔ task link
PATCH/v1/workspace
rename the workspace (owner) { name }
GET/v1/workspace/members
list workspace members (member)
PATCH/v1/workspace/members/:userId
set a member's workspace role (admin) { role }
DELETE/v1/workspace/members/:userId
remove a workspace member (admin)
POST/v1/workspace/invites
invite a member by email (admin) { email, role? }
POST/v1/workspace/invites/:id/resend
resend a pending invite (admin)
DELETE/v1/workspace/invites/:id
revoke a pending invite (admin)
GET/v1/workspace/github
list repos the workspace can connect (admin)

Pointing an LLM at dothings? Give it /docs/llms.txt — the whole API, CLI, and MCP surface in one plain-text file.