# pi-todo User Guide

## Concepts

### Todos

A todo has a short **subject**, a **description**, a **status** (`open`, `in_progress`, `completed`), and an integer **id**. Todos can reference each other via a `dependencies` array. All fields except `subject` and `description` have sensible defaults — see the [field reference](#todo-fields) below.

### IDs

Each todo gets a **sequential integer id** (`"1"`, `"2"`, `"3"`, …), assigned in creation order and scoped to the current project directory. IDs are **never reused** — even after a todo is deleted, its number is permanently retired (tracked by a high-water mark on disk).

In tool output, ids are shown with a `#` prefix (`#3`); pass the bare value (`"3"`) when calling a tool.

### Storage

Todos are stored as one JSON file per todo and persist across sessions. The save directory is `<agent dir>/todos/<list id>/`, where:

- `<agent dir>` is the pi agent config directory — `~/.pi/agent` by default,
  overridable via the `PI_CODING_AGENT_DIR` environment variable.
- `<list id>` defaults to a `--<encoded-cwd>--` form derived from the project
  cwd, giving each project its own list. Set the `PI_TODO_LIST_ID` environment
  variable to override this with a fixed list id (must match `[A-Za-z0-9_-]`,
  max 255 characters); when set, all sessions share that single list regardless
  of cwd.

For example, with the default agent dir, a session in
`/home/alice/projects/my-app` stores todos under:

    ~/.pi/agent/todos/--home-alice-projects-my-app--/

Each todo is its own file (`<id>.json`); the directory also contains a
`.high-water-mark` file recording the highest id ever assigned.

---

## Tools

### create_todo

Creates a new todo and saves it to disk.

```
Todo #3 created successfully: Fix auth bug
```

**Required:** `subject` (short title), `description` (full details).  
**Optional:** `status` (default `open`), `dependencies` (default `[]`), `metadata` (default `{}`).

---

### get_todo

Retrieves a single todo by id.

```
Todo #3: Fix auth bug
Status: in_progress
Description: <description>
Depends on: #1, #2
```

`Depends on:` is shown only when the todo has dependencies. Returns `Todo #<id> not found` if the id does not exist.

**Required:** `id`.

> **Note:** `metadata` is not shown in the output. It remains on the todo (visible in the structured `details` and the on-disk file) but is write-only from the tool text — see [metadata](#todo-fields).

---

### update_todo

Updates one or more fields of an existing todo. Only actually-changed fields are applied; a call that provides no changes (or values identical to the current state) is a no-op and does not touch the todo.

```
Updated todo #3 status, addDependencies
```

**Required:** `id`.  
**Optional:** `subject`, `description`, `status`, `addDependencies`, `metadata`.

- `subject` / `description` / `status` — set to the provided value.
- `addDependencies` — **idempotent union** into the todo's `dependencies`. Pass the ids you want to add; duplicates and already-present ids are ignored. (There is no `removeDependencies`.)
- `metadata` — **merged** into the existing metadata. Set a key to `null` to delete it; any other value overwrites or adds the key.

Returns `Todo #<id> not found` if the id does not exist, or `Todo #<id> no fields to update` if only `id` was provided.

---

### delete_todo

Permanently deletes a todo. The id is retired and never reused.

```
Deleted todo #3
```

Returns `Todo #<id> not found` if the id does not exist.

**Required:** `id`.

---

### list_todos

Lists all todos, optionally filtered by status. Results are **sorted by id ascending** (lowest first), so foundational/earlier tasks appear at the top.

```
#1 [completed] Set up project
#2 [in_progress] Fix auth bug [blocked by #4]
#3 [open] Write tests
```

The `[blocked by #…]` suffix is shown only when the todo has **open** (non-completed) dependencies; resolved blockers are filtered out to keep the list focused on actionable work. Output is truncated at 50 KB or 2000 lines.

**Optional:** `status`.

---

## Todo Fields

| Field | Type | Default | Description |
|---|---|---|---|
| `id` | string (integer) | auto-generated | Sequential id, scoped per project, never reused |
| `subject` | string | — | Short title |
| `description` | string | — | Full details |
| `status` | string | `open` | `open`, `in_progress`, or `completed` |
| `createdAt` | string (ISO 8601) | auto-set | Creation timestamp |
| `updatedAt` | string (ISO 8601) | auto-set | Last-updated timestamp |
| `dependencies` | string[] | `[]` | Ids of todos this todo depends on (the blockers) |
| `metadata` | object | `{}` | Arbitrary key-value pairs |

---
