Skip to main content
Glama
README.md
# TaskPad

A Windows system-tray task manager and reminder engine with deep AI and automation integration.

- **System tray icon** — colour-coded badge (blue / green / amber / red) with a task count
- **Floating overlay** — always-on-top compact task list; drag it anywhere on screen
- **Reminder engine** — fires desktop alerts and system sounds at the scheduled time
- **MCP server** — Claude Code, Claude Desktop, and claude.ai can all read and write your tasks
- **REST API** — JSON API on `localhost:8765` for n8n, Home Assistant, or any HTTP client
- **Outbound webhooks** — push `task.created`, `task.completed`, `reminder.fired`, etc. to any URL

---

## Table of contents

1. [Requirements](#requirements)
2. [Installation](#installation)
3. [Running from source](#running-from-source)
4. [Tray icon guide](#tray-icon-guide)
5. [Cloudflare tunnel setup](#cloudflare-tunnel-setup)
6. [Claude Desktop setup](#claude-desktop-setup)
7. [Claude Code setup](#claude-code-setup)
8. [claude.ai browser setup](#claudeai-browser-setup)
9. [n8n integration](#n8n-integration)
10. [REST API reference](#rest-api-reference)
11. [Outbound webhook events](#outbound-webhook-events)
12. [Configuration file](#configuration-file)
13. [Building the installer](#building-the-installer)

---

## Requirements

| Requirement | Version |
|---|---|
| Windows | 10 / 11 (64-bit) |
| Python | 3.10 or later |
| Pip packages | see `requirements.txt` |

TaskPad stores its data in `%APPDATA%\TaskPad\` (i.e. `C:\Users\<you>\AppData\Roaming\TaskPad\`).

---

## Installation

Run the installer — `TaskPad-Setup-1.0.0.exe` — and follow the wizard.

The wizard will:

1. Copy all source files to `C:\Program Files\TaskPad\` (or your chosen path).
2. Optionally add a desktop shortcut and a Windows autostart entry.
3. Run `pip install -r requirements.txt` with the detected Python interpreter.
4. Ask for an optional **Cloudflare tunnel URL** (for Claude AI) and **n8n webhook URL** — you can skip these and configure them later from the tray menu.

After the installer completes, tick **"Launch TaskPad now"** on the final page or start it from the Start menu / desktop shortcut.

> **Note:** If Python was not detected, install it from [python.org/downloads](https://www.python.org/downloads/), then open a terminal in the install folder and run:
> ```
> pip install -r requirements.txt
> ```

---

## Running from source

```powershell
# Clone / copy the source, then:
pip install -r requirements.txt
python main.py
```

**MCP stdio mode** (for Claude Code / Claude Desktop):
```powershell
python main.py --mcp
```

---

## Tray icon guide

The tray icon colour tells you your task state at a glance:

| Colour | Meaning |
|---|---|
| Blue | No pending tasks |
| Green | Tasks exist, none due / reminded today |
| Amber | At least one reminder is scheduled for today |
| Red | Urgent task or a reminder is due within the hour |

A number badge in the top-right corner shows the count of incomplete tasks (up to 99).

**Right-click menu:**

| Menu item | Action |
|---|---|
| Open TaskPad | Show/hide the floating overlay |
| Add Task… | Quick-add dialog |
| Start on Boot / Stop at Boot | Toggle Windows autostart |
| Sound Settings… | Choose system sound or custom WAV |
| MCP Settings… | Set your static Cloudflare tunnel URL |
| Integration Settings… | View API key, API URL, set n8n webhook |
| MCP URL | Shows the active public MCP URL |
| Copy MCP URL | Copies it to clipboard |
| Quit | Exit the tray app |

---

## Cloudflare tunnel setup

TaskPad exposes the MCP server on port **8766** (HTTP/SSE). To make it reachable from claude.ai or n8n on another machine you need to expose that port via a Cloudflare tunnel.

### Option A — Permanent named tunnel (recommended)

This gives you a stable URL that survives restarts.

1. **Create the tunnel in the Cloudflare dashboard:**
   - Cloudflare Zero Trust → Access → Tunnels → **Create a tunnel**
   - Name it (e.g. `taskpad`).
   - Under **Public hostname**, add a subdomain pointing to `http://localhost:8766`
     e.g. `taskpad.yourdomain.com`
   - Install / authenticate `cloudflared` on this machine (the dashboard shows the command).

2. **Tell TaskPad the stable URL:**
   - Right-click tray icon → **MCP Settings…**
   - Enter `https://taskpad.yourdomain.com` and save.
   - TaskPad will use this URL immediately (no cloudflared management needed — you run `cloudflared` separately as a service).

3. **Expose the REST API too** (for n8n on another server):
   - Add a second public hostname in the same tunnel:
     `taskpad-api.yourdomain.com` → `http://localhost:8765`
   - Use this URL as the base URL in n8n.

### Option B — Quick ephemeral tunnel (development / testing)

If `cloudflared` is on your PATH or in `%APPDATA%\TaskPad\cloudflared.exe`, TaskPad will start a quick tunnel automatically on launch and show a tray notification with the URL. The URL changes every restart.

TaskPad will download `cloudflared.exe` automatically from GitHub if it is not found.

---

## Claude Desktop setup

1. Open Claude Desktop → Settings → Developer → Edit Config (`claude_desktop_config.json`).
2. Add under `"mcpServers"`:

```json
{
  "mcpServers": {
    "taskpad": {
      "command": "python",
      "args": ["C:\\Program Files\\TaskPad\\main.py", "--mcp"]
    }
  }
}
```

3. Restart Claude Desktop. TaskPad should appear in the tool list.

> Use `pythonw` instead of `python` if you want to suppress the console window.

---

## Claude Code setup

Run once in a terminal:

```bash
claude mcp add taskpad -s user -- python "C:\Program Files\TaskPad\main.py" --mcp
```

Verify it is registered:

```bash
claude mcp list
```

Claude Code will now have access to all TaskPad tools in every project.

---

## claude.ai browser setup

claude.ai connects over HTTP/SSE (not stdio), so it needs the tunnel URL.

1. Complete the [Cloudflare tunnel setup](#cloudflare-tunnel-setup) to get a stable public URL.
2. In claude.ai → Settings → Integrations → Add MCP server:
   - **URL:** `https://taskpad.yourdomain.com/sse`
3. Save. The TaskPad tools will appear in your claude.ai conversations.

---

## n8n integration

TaskPad acts as both an **inbound** HTTP server (n8n calls it) and an **outbound** webhook sender (TaskPad calls n8n).

### Inbound — n8n creates tasks in TaskPad

Use an **HTTP Request** node in n8n:

| Field | Value |
|---|---|
| Method | `POST` |
| URL | `https://taskpad-api.yourdomain.com/webhook` |
| Header | `X-API-Key: <your-api-key>` |
| Body | JSON (see below) |

Example body (email flagged → task with link back):
```json
{
  "title": "Follow up on invoice from Acme",
  "category": "work",
  "priority": "high",
  "remind_at": "2026-08-01T09:00:00",
  "notes": "Flagged in Outlook — needs reply by EOD",
  "source_url": "https://outlook.office.com/mail/deeplink/..."
}
```

Find your API key: right-click tray → **Integration Settings…** → copy the key shown.

### Outbound — TaskPad notifies n8n

1. In n8n, create a **Webhook** node. Copy its URL.
2. In TaskPad: right-click tray → **Integration Settings…** → paste the URL in *n8n webhook URL* and save.

TaskPad will POST a JSON payload to that URL for each enabled event.

---

## REST API reference

Base URL (local): `http://127.0.0.1:8765`
Base URL (remote): `https://taskpad-api.yourdomain.com`

All endpoints except `/health` require the header:
```
X-API-Key: <your-api-key>
```

Interactive docs are available at `http://127.0.0.1:8765/docs` while TaskPad is running.

### Endpoints

| Method | Path | Description |
|---|---|---|
| GET | `/health` | Health check (no auth) |
| GET | `/tasks` | List tasks. Query params: `category`, `completed` |
| POST | `/tasks` | Create a task |
| GET | `/tasks/{id}` | Get a single task |
| PATCH | `/tasks/{id}` | Update task fields |
| DELETE | `/tasks/{id}` | Delete a task |
| POST | `/tasks/{id}/complete` | Mark complete/incomplete. Query param: `done=true/false` |
| POST | `/webhook` | Simplified create endpoint (same as POST /tasks, shorter schema) |

### Task schema

```json
{
  "title":               "string (required)",
  "category":            "work | personal | shared",
  "task_type":           "todo | reminder | both",
  "priority":            "urgent | high | normal | none",
  "notes":               "string",
  "tags":                ["string"],
  "due_date":            "YYYY-MM-DD or null",
  "remind_at":           "ISO datetime or null",
  "repeat":              "none | daily | weekdays | weekly | monthly | every_n_days",
  "repeat_n":            1,
  "repeat_days":         [0,1,2,3,4],
  "repeat_day_of_month": 1,
  "enabled":             true,
  "source_url":          "https://... or null"
}
```

### Example — create a task with curl

```bash
curl -X POST https://taskpad-api.yourdomain.com/tasks \
  -H "X-API-Key: YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Review PR #42",
    "category": "work",
    "priority": "high",
    "remind_at": "2026-08-01T10:00:00",
    "source_url": "https://github.com/your-org/your-repo/pull/42"
  }'
```

---

## Outbound webhook events

When a webhook URL is configured, TaskPad POSTs a JSON body to it for each event.

| Event | When it fires |
|---|---|
| `task.created` | Task added (via tray, MCP, or API) |
| `task.updated` | Task fields changed |
| `task.completed` | Task marked complete |
| `task.uncompleted` | Task marked incomplete |
| `task.deleted` | Task removed |
| `reminder.fired` | Reminder alert shown |
| `task.overdue` | Overdue check triggered |

Payload shape:
```json
{
  "event":      "task.created",
  "task_id":    "abc123",
  "title":      "Review PR #42",
  "category":   "work",
  "priority":   "high",
  "task_type":  "todo",
  "remind_at":  "2026-08-01T10:00:00",
  "due_date":   null,
  "completed":  false,
  "source_url": "https://github.com/...",
  "created_at": "2026-07-28T08:00:00",
  "updated_at": "2026-07-28T08:00:00"
}
```

---

## Configuration file

`%APPDATA%\TaskPad\config.json` — created automatically on first run.

```json
{
  "api_key":       "auto-generated 48-char hex key",
  "mcp_public_url": "https://taskpad.yourdomain.com",
  "webhook_url":   "https://n8n.yourdomain.com/webhook/taskpad",
  "webhook_events": [
    "task.created", "task.completed", "reminder.fired", "task.overdue"
  ],
  "sound_type":    "system",
  "system_sound":  "SystemExclamation"
}
```

All settings are editable from the tray menu — direct JSON editing is not normally required.

---

## Releasing a new version

`release.ps1` handles the full release cycle in one command:

```powershell
.\release.ps1              # bump patch (1.0.0 → 1.0.1), build, commit, tag, push
.\release.ps1 -Bump minor  # bump minor (1.0.0 → 1.1.0)
.\release.ps1 -Bump major  # bump major (1.0.0 → 2.0.0)
.\release.ps1 -Version 1.5.0  # explicit version
.\release.ps1 -NoBuild     # commit + tag only, skip installer build
.\release.ps1 -NoPush      # build + tag locally, do not push to remote
```

What it does, in order:
1. Reads the current version from `version.py`
2. Calculates the new version (or uses `-Version`)
3. Asks for confirmation before doing anything
4. Writes the new version back to `version.py`
5. Builds the installer via `build.ps1` (unless `-NoBuild`)
6. `git commit` — `chore: release v1.0.1`
7. `git tag -a v1.0.1`
8. `git push` + `git push --tags` (unless `-NoPush` or no remote)

If the project has not been initialised as a git repo yet, the script will run `git init` and do an initial commit automatically.

---

## Building the installer

**Prerequisites:**
- Python 3.10+ with Pillow (`pip install Pillow`)
- [Inno Setup 6](https://jrsoftware.org/isdl.php) installed

**To release a new version**, edit `version.py`:
```python
__version__ = "1.1.0"
```

Then run from the project root:

```powershell
.\build.ps1
```

Or override the version without editing the file:
```powershell
.\build.ps1 -Version 1.1.0
```

The build script will:
1. Read `version.py` (or use `-Version` override).
2. Generate `assets/icon.ico` (all sizes from 16 to 256 px).
3. Compile `installer/taskpad.iss` with ISCC, injecting the version.
4. Output `installer/output/TaskPad-Setup-<version>.exe`.

The version string also appears in the tray icon tooltip (`TaskPad v1.1.0`).

---

## File layout

```
TaskPad/
├── main.py               # Entry point — tray app or --mcp mode
├── models.py             # Task dataclass
├── store.py              # SQLite storage + config helpers
├── scheduler.py          # Reminder / overdue scheduler
├── requirements.txt
├── LICENSE.txt
├── build.ps1             # Build script (icon + Inno Setup)
├── api/
│   ├── server.py         # FastAPI REST server on :8765
│   └── webhooks.py       # Outbound webhook sender
├── mcp_server/
│   ├── server.py         # MCP stdio server (--mcp flag)
│   ├── http_server.py    # MCP HTTP/SSE server on :8766
│   └── tunnel.py         # Cloudflare tunnel manager
├── ui/
│   ├── overlay.py        # Floating task overlay
│   ├── alert.py          # Reminder alert dialog
│   └── widgets.py        # Custom PIL-based widgets
├── assets/
│   └── icon.ico          # Generated by build.ps1
└── installer/
    ├── taskpad.iss        # Inno Setup script
    ├── launcher.vbs       # No-console launcher (wscript.exe)
    ├── generate_icon.py   # PIL icon generator
    └── write_config.py    # Post-install config writer
```

---

## License

MIT — see `LICENSE.txt`.

Maintenance

ActivitySlowing
ResponsivenessNo issues