# Todoist CLI
A command-line interface for Todoist.
## Installation
> ```bash
> npm install -g @doist/todoist-cli
> ```
### Agent Skills
Install skills for your coding agent:
```bash
td skill install claude-code
td skill install codex
td skill install copilot
td skill install cursor
td skill install gemini
td skill install pi
td skill install universal
```
Skills are installed to `~//skills/todoist-cli/SKILL.md` (e.g. `~/.claude/` for claude-code, `~/.agents/` for universal, etc.). When updating the CLI, installed skills are updated automatically. The `universal` agent is compatible with Amp, OpenCode, and other agents that read from `~/.agents/`.
The `gemini` agent installs to `~/.gemini/config/skills/todoist-cli/SKILL.md`, the global location read by Antigravity, Antigravity CLI and Antigravity IDE alike. For project-scoped Antigravity skills use `td skill install universal --local`, which writes to `.agents/skills/` — the workspace directory Antigravity reads.
```bash
td skill list
td skill uninstall
```
## Uninstallation
First, remove any installed agent skills:
```bash
td skill uninstall
```
Then uninstall the CLI:
```bash
npm uninstall -g @doist/todoist-cli
```
## Local Setup
```bash
git clone https://github.com/Doist/todoist-cli.git
cd todoist-cli
npm install
npm run build
npm link
```
This makes the `td` command available globally.
## Setup
```bash
td auth login
```
This opens your browser to authenticate with Todoist. Once approved, the token is stored in your OS credential manager:
- macOS: Keychain
- Windows: Credential Manager
- Linux: Secret Service/libsecret
Secure storage is required by default. If it is unavailable, login fails without writing a credential to disk. To explicitly use plaintext config-file storage, pass `--credential-store=plaintext`; the CLI always prints a warning when it writes a credential this way. Existing plaintext tokens are migrated automatically the next time the CLI reads them successfully from the config file.
For a read-only OAuth token (scope `data:read`), run:
```bash
td auth login --read-only
```
To explicitly store a credential in plaintext instead of the OS credential manager:
```bash
td auth login --credential-store=plaintext
```
In read-only mode, commands that change Todoist data (create/update/delete/complete/move/archive, etc.) are blocked by the CLI.
Some commands need opt-in OAuth scopes, requested via `--additional-scopes=` (comma-separated):
```bash
td auth login --additional-scopes=app-management # td apps ...
td auth login --additional-scopes=backups # td backup ...
td auth login --additional-scopes=billing # td billing ...
```
Run `td auth login --help` for the full list. When a command fails for lack of a scope, the error suggests a re-login command that preserves whichever flags were originally used.
### Alternative methods
**Manual token:** Get your API token from [Todoist Settings > Integrations > Developer](https://todoist.com/app/settings/integrations/developer):
```bash
td auth token "your-token"
```
Manual tokens use the system credential manager by default too. To explicitly store one
in plaintext, add `--credential-store=plaintext`; the CLI prints a warning after the write.
**Environment variable:**
```bash
export TODOIST_API_TOKEN="your-token"
```
`TODOIST_API_TOKEN` always takes priority over the stored token.
Note: externally provided tokens (`TODOIST_API_TOKEN` or `td auth token`) are treated as unknown scope and assumed write-capable. The CLI cannot currently auto-detect OAuth scope for these tokens.
### Auth commands
```bash
td auth status # check if authenticated + mode (read-only/read-write/unknown)
td auth logout # remove saved token and auth metadata
```
To switch back to normal write access, re-run:
```bash
td auth login
```
## Usage
```bash
td add "Buy milk tomorrow #Shopping" # quick add with natural language
td today # tasks due today + overdue
td inbox # inbox tasks
td task list # all tasks
td task list --project "Work" # tasks in project
td task list --project "Work" --ids-only # one task ID per line
td project list # all projects
td task view https://app.todoist.com/app/task/buy-milk-8Jx4mVr72kPn3QwB # paste a URL
```
Run `td --help` or `td --help` for more options.
Supported list commands accept `--ids-only` when each result has a stable ID. It prints one
ID per line and no human-readable empty-state text. When more pages exist, the pagination
notice goes to stderr so stdout remains safe for pipes. `--ids-only`, `--json`, and `--ndjson`
are mutually exclusive.
## Accessibility
For users who rely on screen readers or cannot distinguish colors, use the `--accessible` flag or set `TD_ACCESSIBLE=1` to add text labels to color-coded output:
```bash
td today --accessible
# or
export TD_ACCESSIBLE=1
td today
```
When active, due dates get a `due:` prefix, deadlines get a `deadline:` prefix, durations get a `~` prefix, and favorite items get a `★` suffix. Default output without the flag is unchanged.
## Extensions
Extensions add commands to `td`. An extension is an executable named `td-` that runs as `td `, and it can be written in any language:
```bash
td extension install owner/td-standup # from GitHub
td standup
td extension list
```
To write your own, start with `td extension create ` and see [docs/extensions.md](docs/extensions.md).
## Shell Completions
Tab completion is available for bash, zsh, fish, and PowerShell:
```bash
td completion install # prompts for shell
td completion install bash # or: zsh, fish, pwsh
```
Restart your shell or source your config file to activate. To remove:
```bash
td completion uninstall
```
## Development
```bash
npm install
npm run build # compile
npm run dev # watch mode
npm run type-check # type check
npm run fix # auto-fix lint + format
npm test # run tests
```