|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Repository Overview |
| 6 | + |
| 7 | +This is a CLI client for Todoist written in Go. It provides command-line access to Todoist's task management features with support for filtering, projects, labels, and offline caching. |
| 8 | + |
| 9 | +## Common Commands |
| 10 | + |
| 11 | +### Building and Testing |
| 12 | +```bash |
| 13 | +# Install the binary to $GOPATH/bin |
| 14 | +make install |
| 15 | + |
| 16 | +# Build the binary in the current directory |
| 17 | +make build |
| 18 | + |
| 19 | +# Run all tests |
| 20 | +make test |
| 21 | + |
| 22 | +# Generate the filter parser (required before building if filter_parser.y is modified) |
| 23 | +make prepare |
| 24 | +``` |
| 25 | + |
| 26 | +### Running Single Tests |
| 27 | +```bash |
| 28 | +# Run a specific test function |
| 29 | +go test -v -run TestFilterParser |
| 30 | + |
| 31 | +# Run tests in a specific file |
| 32 | +go test -v ./filter_parser_test.go ./filter_parser.go ./filter_eval.go |
| 33 | +``` |
| 34 | + |
| 35 | +### Development Workflow |
| 36 | +```bash |
| 37 | +# Generate filter parser from yacc grammar (automatically done by prepare target) |
| 38 | +goyacc -o filter_parser.go filter_parser.y |
| 39 | + |
| 40 | +# Build for multiple platforms (for releases) |
| 41 | +make release VERSION=x.y.z |
| 42 | +``` |
| 43 | + |
| 44 | +## Architecture |
| 45 | + |
| 46 | +### Core Structure |
| 47 | + |
| 48 | +The codebase is organized into two main layers: |
| 49 | + |
| 50 | +1. **CLI Layer (root directory)**: Command handlers, formatting, and user-facing logic |
| 51 | + - `main.go` - CLI setup using urfave/cli/v2 framework |
| 52 | + - `list.go`, `add.go`, `close.go`, etc. - Command implementations |
| 53 | + - `format.go` - Output formatting (TSV/CSV writers) |
| 54 | + - `cache.go` - Local cache management for offline access |
| 55 | + |
| 56 | +2. **Library Layer (`lib/` directory)**: Core Todoist API client and data models |
| 57 | + - `lib/todoist.go` - HTTP client and API communication |
| 58 | + - `lib/sync.go` - Store structure and tree construction |
| 59 | + - `lib/item.go`, `lib/project.go`, `lib/label.go` - Data models |
| 60 | + - `lib/command.go` - Command serialization for Todoist Sync API |
| 61 | + - `lib/interface.go` - Common interfaces and helper functions |
| 62 | + |
| 63 | +### Data Model |
| 64 | + |
| 65 | +The application uses a **tree-based data structure** for both items and projects: |
| 66 | + |
| 67 | +- **Store** (`lib/sync.go`): Central data structure containing all synced data |
| 68 | + - Maintains maps (`ItemMap`, `ProjectMap`, `LabelMap`, `SectionMap`) for fast lookups |
| 69 | + - Constructs linked tree structures with `ChildItem`/`BrotherItem` and `ChildProject`/`BrotherProject` pointers |
| 70 | + - `RootItem` and `RootProject` serve as entry points to traverse hierarchies |
| 71 | + |
| 72 | +- **Tree Construction**: `ConstructItemTree()` builds parent-child and sibling relationships from flat API responses |
| 73 | + |
| 74 | +### Filter System |
| 75 | + |
| 76 | +The filter implementation uses a **yacc-based parser** for Todoist's filter syntax: |
| 77 | + |
| 78 | +- `filter_parser.y` - Yacc grammar definition (generates `filter_parser.go`) |
| 79 | +- `filter_eval.go` - Expression evaluation logic |
| 80 | +- Supports date expressions, project/label filters, boolean operators (`&`, `|`, `!`) |
| 81 | +- Filter syntax examples: `(overdue | today) & p1`, `#ProjectName`, `@LabelName` |
| 82 | + |
| 83 | +### Configuration and Caching |
| 84 | + |
| 85 | +- **Config**: Stored in `$HOME/.config/todoist/config.json` (XDG Base Directory compliant) |
| 86 | + - Contains API token, color preferences, date formats |
| 87 | + - Permissions enforced to 0600 for security |
| 88 | + |
| 89 | +- **Cache**: Stored in `$HOME/.cache/todoist/cache.json` |
| 90 | + - Full sync from Todoist API using sync token |
| 91 | + - Enables offline browsing and faster startup |
| 92 | + |
| 93 | +### API Communication |
| 94 | + |
| 95 | +The client uses Todoist's **Sync API** (not the REST API): |
| 96 | + |
| 97 | +- Commands are batched and sent to `/sync` endpoint |
| 98 | +- Uses bearer token authentication |
| 99 | +- Operations (add, update, close, delete) are queued as commands |
| 100 | +- `ExecCommands()` executes command batches atomically |
| 101 | + |
| 102 | +### Integration Points |
| 103 | + |
| 104 | +- **peco/fzf integration**: Shell functions in `todoist_functions.sh` provide interactive task selection |
| 105 | +- **Shell completion**: Supports bash/zsh autocomplete via urfave/cli |
| 106 | +- **Browser integration**: Can open URLs embedded in task content (markdown links) |
| 107 | + |
| 108 | +## Important Notes |
| 109 | + |
| 110 | +- The `filter_parser.go` file is **auto-generated** from `filter_parser.y` - never edit it directly |
| 111 | +- When modifying the filter grammar, run `make prepare` to regenerate the parser |
| 112 | +- The application automatically syncs on first run if token differs from cached token |
| 113 | +- Item and project hierarchies use **in-memory linked structures** rather than recursive lookups |
| 114 | +- Priority values in Todoist API are 1-4, where 1 is highest priority (p1) |
| 115 | +- Date handling supports multiple formats: RFC3339, natural language (via Todoist API), and custom filter syntax |
0 commit comments