npm package: @matthamlin/dodo
Description: A task management CLI with web UI
Latest version: 0.1.0

# `dodo`

A local task management CLI with a web UI. Tasks are stored as JSONL in a `.dodo/` directory, making them easy to track in version control.

## Getting Started

Install dodo:

```bash
bun add --exact @matthamlin/dodo
```

Initialize a new task store in your project:

```bash
dodo init
```

This creates a `.dodo/` directory with a `tasks.jsonl` file.

> **Note:** Most commands auto-initialize if `.dodo/` doesn't exist yet, so you can skip `init` and jump straight to `dodo add`.

## Commands

### `dodo init`

Initialize a `.dodo/` directory in the current working directory.

```bash
dodo init
```

### `dodo add <title>`

Create a new task. Aliases: `create`.

```bash
dodo add "Fix login bug"
dodo add "Setup database" --description "Configure PostgreSQL" --tags "setup,backend"
dodo add "Write tests" --parent <parent-id> --blocked-by <id1>,<id2>
```

| Flag                     | Short | Description                      |
| ------------------------ | ----- | -------------------------------- |
| `--description <text>`   | `-d`  | Task description                 |
| `--parent <id>`          | `-p`  | Parent task ID                   |
| `--tags <tag1,tag2>`     | `-t`  | Comma-separated tags             |
| `--blocked-by <id1,id2>` | `-b`  | Comma-separated blocker task IDs |

### `dodo list`

List tasks in a tree view (hides done tasks by default). Aliases: `ls`.

```bash
dodo list
dodo list --status open --tag important
dodo list --all
```

| Flag                | Short | Description                                                 |
| ------------------- | ----- | ----------------------------------------------------------- |
| `--status <status>` | `-s`  | Filter by status (`open`, `in-progress`, `blocked`, `done`) |
| `--tag <tag>`       | `-t`  | Filter by tag                                               |
| `--parent <id>`     | `-p`  | Filter by parent task                                       |
| `--all`             | `-a`  | Include done tasks                                          |

### `dodo show <id>`

Display detailed information about a task, including its relationships, tags, and timestamps.

```bash
dodo show abc12345
dodo show abc12345 --prompt          # render prompt template
dodo show abc12345 --prompt | pbcopy # pipe to clipboard
```

| Flag       | Description                                              |
| ---------- | -------------------------------------------------------- |
| `--prompt` | Render the task as an agent prompt and copy to clipboard |

> **Tip:** Use `--prompt` to quickly copy a task as a ready-made prompt for an AI coding agent. See [Prompt Templates](#prompt-templates) for customization.

### `dodo update <id>`

Update task properties. Aliases: `edit`.

```bash
dodo update abc12345 --title "New title" --description "Updated description"
dodo update abc12345 --status in-progress
dodo update abc12345 --add-tag urgent --remove-tag backlog
dodo update abc12345 --add-blocker xyz99999
dodo update abc12345 --parent def67890   # set parent
dodo update abc12345 --parent ""          # remove parent
```

| Flag                    | Short | Description                  |
| ----------------------- | ----- | ---------------------------- |
| `--title <text>`        |       | New title                    |
| `--description <text>`  | `-d`  | New description              |
| `--status <status>`     | `-s`  | Set status                   |
| `--parent <id>`         | `-p`  | Set or remove (`""`) parent  |
| `--add-tag <tag>`       |       | Add a tag                    |
| `--remove-tag <tag>`    |       | Remove a tag                 |
| `--add-blocker <id>`    |       | Add a blocking dependency    |
| `--remove-blocker <id>` |       | Remove a blocking dependency |

### `dodo complete <id>`

Mark a task as done. Any tasks that were blocked by this task will have their status automatically re-evaluated. Aliases: `done`.

```bash
dodo complete abc12345
```

### `dodo delete <id>`

Delete a task and clean up all references (parent/child links, blocking dependencies). Aliases: `rm`.

```bash
dodo delete abc12345
```

### `dodo query <text>`

Fuzzy search across task titles, descriptions, and tags. Powered by MiniSearch with prefix matching and fuzzy tolerance. Aliases: `search`.

```bash
dodo query "login"
dodo query "db" --status open --limit 10
dodo query "setup" --all
```

| Flag                | Short | Description               |
| ------------------- | ----- | ------------------------- |
| `--status <status>` | `-s`  | Filter by status          |
| `--all`             | `-a`  | Include done tasks        |
| `--limit <count>`   | `-n`  | Max results (default: 20) |

### `dodo api [method] <path>`

Call REST API endpoints directly without a running server. Useful for scripting and automation.

```bash
dodo api tasks                                  # GET /api/tasks
dodo api get tasks                              # explicit GET
dodo api post tasks -d '{"title": "My task"}'   # create a task
dodo api patch tasks/abc123 -d '{"status": "done"}'
dodo api delete tasks/abc123
dodo api prompt-template                        # get the prompt template
```

| Flag            | Short | Description                |
| --------------- | ----- | -------------------------- |
| `--body <json>` | `-d`  | Request body (JSON string) |

### `dodo serve`

Start the web UI.

```bash
dodo serve
dodo serve --port 8080
```

| Flag            | Short | Description                 |
| --------------- | ----- | --------------------------- |
| `--port <port>` | `-p`  | Port number (default: 3456) |

## Task Statuses

| Status        | Description                          |
| ------------- | ------------------------------------ |
| `open`        | Default status for new tasks         |
| `in-progress` | Currently being worked on            |
| `blocked`     | Has incomplete blocking dependencies |
| `done`        | Completed                            |

## Task Relationships

Dodo supports two kinds of relationships between tasks:

**Parent-child** - Organize tasks hierarchically. A task can have one parent and many children. The `list` command renders these as a tree.

**Blocking dependencies** - Model task dependencies. When a task has blockers, its status automatically becomes `blocked` until all blockers are marked done. Dodo validates against cycles in both relationship types.

## Storage

Tasks are stored in `.dodo/tasks.jsonl` as one JSON object per line. This format is human-readable and works well with version control. Writes are atomic (temp file + rename) to prevent corruption.

## Web UI

Run `dodo serve` to open a browser-based interface for managing tasks. The web UI supports:

- **List view** with hierarchical tree layout
- **Kanban view** with columns for each status
- **Task detail page** with full markdown rendering, relationships, and timestamps
- **Copy agent prompt** button on the task detail page — copies a ready-made prompt to your clipboard
- Adding and deleting tasks
- Cycling task status by clicking the status badge
- Filtering by status and tag
- Fuzzy search

## REST API

The web server exposes a JSON API at `/api/`. You can also call these endpoints directly from the CLI with `dodo api`.

| Method   | Path                   | Description                                         |
| -------- | ---------------------- | --------------------------------------------------- |
| `GET`    | `/api/tasks`           | List tasks (filter: `status`, `tag`, `parent`)      |
| `POST`   | `/api/tasks`           | Create a task                                       |
| `GET`    | `/api/tasks/search`    | Fuzzy search (`q`, `status`, `tag`, `all`, `limit`) |
| `GET`    | `/api/tasks/:id`       | Get a task by ID                                    |
| `PATCH`  | `/api/tasks/:id`       | Update a task                                       |
| `DELETE` | `/api/tasks/:id`       | Delete a task                                       |
| `GET`    | `/api/prompt-template` | Get the prompt template and variables               |
| `PUT`    | `/api/prompt-template` | Save a custom prompt template                       |
| `GET`    | `/api/__introspect`    | List all API endpoints                              |

## Prompt Templates

Dodo can render any task as a prompt for AI coding agents. Use this from the CLI with `dodo show <id> --prompt` or from the web UI with the **Copy agent prompt** button on any task detail page.

The default template produces a structured prompt with the task title, description, status, relationships, and a completion command. To customize it, create a `.dodo/prompt-template.txt` file with your own template.

### Available variables

| Variable          | Description                           |
| ----------------- | ------------------------------------- |
| `{{id}}`          | Task ID                               |
| `{{title}}`       | Task title                            |
| `{{description}}` | Task description                      |
| `{{status}}`      | Task status (open, in-progress, etc.) |
| `{{tags}}`        | Comma-separated tags                  |
| `{{parent}}`      | Parent task title and ID              |
| `{{children}}`    | List of subtask titles and IDs        |
| `{{blocked_by}}`  | List of blocking task titles and IDs  |
| `{{blocks}}`      | List of tasks this one blocks         |
| `{{created_at}}`  | Creation timestamp                    |
| `{{updated_at}}`  | Last update timestamp                 |

### Custom template example

Create `.dodo/prompt-template.txt`:

```
Complete the following task: {{title}}

{{description}}

Related context:
- Blocked by: {{blocked_by}}
- Subtasks: {{children}}

When finished, run: `dodo complete {{id}}`
```

## Environment Variables

| Variable   | Description                    |
| ---------- | ------------------------------ |
| `NO_COLOR` | Set to disable terminal colors |

## Contributing

### Building

This package uses [`hohoro`](https://github.com/hazelcast/hohoro) and [TypeScript](https://www.typescriptlang.org/docs/) to build the source code and generate types. The web UI is bundled separately with Bun.

To build, run `bun run build` from the root or from this workspace.

### Code Quality

**Type Checking** - Uses TypeScript via `tsgo`. Run `bun run type-check`.

**Linting** - Uses [oxlint](https://oxc.rs/docs/guide/usage/linter.html) with type-aware rules. Run `bun run lint`.

**Tests** - Uses Bun's built-in test runner. Run `bun run test`.

### Publishing

To publish, run `bun run pub` from the workspace root. This will prompt you to login to npm and publish the package.