OpenTask:自托管 AI 任务与习惯管理器,单容器 SQLite 部署
trentmcnitt/opentask
OpenTask 是一款自托管、AI 驱动的任务与习惯管理器,以单个 Docker 容器加 SQLite 运行,数据存于服务器上的一个文件,支持 Web(PWA)、iPhone、Apple Watch 和 Mac 客户端。
A self-hosted, AI-powered task and habit manager for web, iPhone, Apple Watch, and Mac.
Single container. SQLite. Your data, your server.
Try the Demo · Documentation · API Reference · Roadmap
🌐 Web (PWA) · 📱 iOS (native, with widgets) · ⌚ Apple Watch · 💻 Mac · 🔌 REST API · OpenAPI 3.1
Note
Early release — Please bear with the rough edges. 👷 Expect occasional bugs and other issues as things get ironed out. Please open an issue if you run into any problems.
OpenTask is a self-hosted, AI-powered task and habit manager I built for personal use. I've been using it daily, and it's reached a point where I'm excited to open it up.
It runs as a single Docker container with SQLite — no Postgres, no Redis, no external services to manage. Your data lives in one file on your server.
✨ Features
📱 The apps (web, iPhone, Apple Watch, Mac)
- Mobile-first PWA — Installable on iOS and Android. Designed for phones first, looks great on desktop too.
- Snooze everything — Bulk snooze all overdue tasks in one tap. Individual snooze with presets, fine-grained adjustments, or custom times.
- Native Apple apps — An iPhone app with home-screen widgets and rich notifications (snooze grids and period checklists right from the lock screen), a full Apple Watch app with its own pages and Smart Stack widgets, and a Mac app with widgets. (Source included — not on the App Store.)
- Reminders and quotas — Recurring reminders grouped into periods of the day (morning, afternoon, evening — yours to edit), checked off as a list. Quotas track a count toward a target per day, week, month, or year ("read 5 times a week").
- Full undo/redo — Every action is logged and reversible.
- Trash & archive — Deleted tasks go to trash, completed tasks go to archive. Nothing is permanently lost until you say so.
🏠 Self-hosting
- Single container — SQLite with WAL mode. No external database, no message queue, no cache layer. Back up your data by copying one file.
- Reverse proxy auth — Works with Authelia, Authentik, and other auth proxies out of the box.
- Data export — JSON and CSV export of all your tasks, projects, and completions. Nothing is locked in.
🔧 Automation
- Full REST API — Every UI operation available over HTTP. Bearer token auth, interactive API docs, and curl-friendly. Script it, automate it, pipe it into Apple Shortcuts.
- Webhooks — HTTP callbacks on task events with HMAC-SHA256 signing. Integrate with n8n, Home Assistant, or anything that accepts webhooks.
🧠 AI-native task management (optional)
Every task gets AI-generated commentary and an attention score. AI sees your full task list and writes a one-liner — what it means, why it matters, what you might be forgetting.
- Natural language input — Type or dictate tasks in plain English. AI extracts the title, due date, recurrence, priority, project, and notes.
- Quick Take — A one-liner as you add a task, aware of the rest of your list.
- What's Next — Recommendations that surface overlooked or forgotten tasks.
- Insights — Each task gets a contextual one-liner and a 0–100 attention score. Filter by Stale, Act Soon, Quick Win, or Misprioritized.
- Tested, not hoped — A 150+ scenario eval suite checks every feature: schema and field checks first, then an LLM judge scoring each answer against a rubric.
- Entirely optional — Disabled by default. Turn it off and every trace of AI disappears from the UI. Works with Claude, GPT-4.1-mini, Grok, DeepSeek, Ollama, and others.
🚀 Quick Start (Docker)
# Create a directory for OpenTask mkdir opentask && cd opentask # Download the compose file curl -O https://raw.githubusercontent.com/trentmcnitt/opentask/main/docker-compose.yml # Generate a secret key and start the app cat > .env <<EOF AUTH_SECRET=$(openssl rand -base64 32) OPENTASK_INIT_USERNAME=admin OPENTASK_INIT_PASSWORD=changeme OPENTASK_INIT_TIMEZONE=America/New_York EOF docker compose up -d
Open http://localhost:3000 and log in with the username and password you set above. The initial user and database are created automatically on first start.
Tip
Run docker compose logs -f to see startup output and troubleshoot any issues.
Updating
docker compose pull docker compose up -d
Your data is stored in ./data/ and persists across updates. Store this directory on a local filesystem — network mounts (NFS, CIFS) are not compatible with SQLite's file locking.
Backup
SQLite makes backups simple — use the built-in .backup command for a safe, consistent copy:
# While running (recommended) docker compose exec opentask sqlite3 /app/data/tasks.db '.backup /app/data/backup.db' cp data/backup.db /path/to/your/backups/tasks-$(date +%F).db # Or stop first, then copy directly docker compose stop cp data/tasks.db /path/to/your/backups/ docker compose start
Tip
SQLite uses WAL (write-ahead logging), so tasks.db-wal and tasks.db-shm files may exist alongside the main database. A plain cp tasks.db while the app is running could produce an inconsistent backup. The sqlite3 .backup command handles this correctly.
Additional Users
Create more users from the command line:
# Docker docker compose exec opentask tsx scripts/create-user.ts <username> <password> # Bare metal npx tsx scripts/create-user.ts <username> <password> <email> <timezone>
API Tokens
Create a Bearer token for API access and automation:
# Docker docker compose exec opentask tsx scripts/create-token.ts <username> [token-name] # Bare metal npm run db:create-token -- <username> [token-name]
🛠️ Manual Installation
Requires Node.js 20+ and npm.
git clone https://github.com/trentmcnitt/opentask.git cd opentask npm install # Configure cp .env.example .env.local # Edit .env.local — at minimum, set AUTH_SECRET (openssl rand -base64 32) # Create your user npx tsx scripts/create-user.ts admin changeme admin@localhost America/New_York # Build and start npm run build npm run start
For development: npm run dev starts a hot-reloading server on port 3000.
⚙️ Configuration
See .env.example for all options. The essentials:
| Variable | Required | Description |
|---|---|---|
AUTH_SECRET |
Yes | Secret key for sessions (openssl rand -base64 32) |
AUTH_URL |
No | Public URL when behind a reverse proxy |
OPENTASK_DB_PATH |
No | SQLite database path (default: ./data/tasks.db) |
OPENTASK_AI_ENABLED |
No | Enable AI features (default: false) |
Login is username-based, not email-based.
Reverse Proxy
OpenTask runs on port 3000 by default. Set AUTH_URL to your public URL when using a reverse proxy.
Caddy
tasks.example.com {
reverse_proxy localhost:3000
}
Nginx
server { server_name tasks.example.com; location / { proxy_pass http://localhost:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # Required for Server-Sent Events (SSE) proxy_buffering off; proxy_cache off; } }
Note
OpenTask uses Server-Sent Events for real-time updates. Caddy handles this automatically. Nginx needs proxy_buffering off.
Reverse Proxy Header Auth
If you run an auth proxy like Authelia, Authentik, or Caddy's forward_auth, OpenTask can trust the authenticated username from a request header — no separate login required.
# docker-compose.yml environment: OPENTASK_PROXY_AUTH_HEADER: Remote-User
The header value must match an existing OpenTask username (case-insensitive). Users are not auto-created.
Warning
Your reverse proxy must strip this header from external requests. If external clients can set this header directly, they can authenticate as any user.
Push Notifications
- Web Push — Generate VAPID keys with
npx web-push generate-vapid-keysand set them in your environment. Works on all platforms including iOS Safari. - iOS Native (APNs) — Requires the iOS companion app and an Apple Developer Program membership. See
.env.examplefor configuration.
AI Features
AI is entirely optional — disabled by default. See AI-native task management above for what it provides. Add OPENTASK_AI_ENABLED=true and a provider key to your .env file — see .env.example for setup with Claude, GPT-4.1-mini, Grok, DeepSeek, and Ollama.
Three auth methods, checked in order: Bearer token → Proxy header → Session cookie
Key endpoints:
| Endpoint | Method | Description |
|---|---|---|
/api/tasks |
GET | List tasks with filters |
/api/tasks |
POST | Create a task |
/api/tasks/:id |
PATCH | Update task fields |
/api/tasks/:id |
DELETE | Soft delete to trash |
/api/tasks/:id/done |
POST | Mark done (advances recurring) |
/api/tasks/:id/snooze |
POST | Snooze to future time |
/api/tasks/bulk/snooze-overdue |
POST | One-tap snooze all overdue tasks |
/api/tasks/bulk/done |
POST | Bulk mark done |
/api/tasks/bulk/snooze |
POST | Bulk snooze by task IDs |
/api/undo |
POST | Undo last action |
/api/redo |
POST | Redo last undone action |
/api/projects |
GET/POST | List/create projects |
/api/export |
GET | Export data (JSON or CSV) |
/api/webhooks |
GET/POST | List/create webhooks |
/api/openapi |
GET | OpenAPI 3.1 spec (no auth) |
Full API reference with curl examples, webhook setup, and Apple Shortcuts integration: Documentation →
🧱 Tech Stack
| Layer | Technology |
|---|---|
| Runtime | Next.js 16 (App Router) + React 19 + TypeScript |
| Database | SQLite with WAL mode (better-sqlite3) |
| Auth | NextAuth/Auth.js (credentials, JWT sessions) |
| Styling | Tailwind CSS 4 + Shadcn UI |
| Testing | Vitest (behavioral + integration) + Playwright (E2E) |
📁 Project Structure
src/
├── app/ # Next.js pages and API routes
├── components/ # React components
├── core/ # Business logic (auth, db, tasks, recurrence, undo, ai)
├── hooks/ # Custom React hooks
├── lib/ # Utilities
└── types/ # TypeScript types
ios/ # Native iOS companion app (SwiftUI + WKWebView)
tests/ # Behavioral, integration, E2E, and AI quality tests
docs/ # Product spec, design rationale, API guide, roadmap
🤝 Contributing
Contributions are welcome! See CONTRIBUTING.md for the full guide.
git clone https://github.com/trentmcnitt/opentask.git cd opentask npm install cp .env.example .env.local echo 'AUTH_SECRET=dev-secret-change-me' >> .env.local npm run db:seed-dev npm run dev # Open http://localhost:3000 — login: dev / dev
CLAUDE.md has detailed development conventions for AI-assisted development.
👤 Author
Built by Trent McNitt — AI implementation consultant specializing in chatbots, workflow automation, and custom AI applications.
📄 License
来源:GitHub · github.com




