⚠️ UNDER CONSTRUCTION: This project is currently in active development and is not ready for production use. APIs may change without notice. Use at your own risk.
A headless REST API server for Taskwarrior, providing a clean HTTP interface to interact with your tasks programmatically.
This server acts as a bridge between Taskwarrior's powerful CLI and modern applications, allowing you to:
- Build web, mobile, or desktop UIs for Taskwarrior
- Integrate Taskwarrior with other tools and services
- Access your tasks from anywhere via HTTP
- Keep Taskwarrior as the single source of truth (no database duplication)
- CLI-Only Integration: Uses Taskwarrior CLI exclusively - no direct file manipulation
- RESTful API: Clean, predictable HTTP endpoints
- Token Authentication: Simple bearer token authentication
- Sync-Friendly: Compatible with Taskwarrior sync or file syncing (Syncthing, etc.)
- No State Duplication: All data lives in Taskwarrior
- Go 1.21 or higher
- Taskwarrior installed and configured (
taskcommand available)
# Clone the repository
git clone https://github.com/dotbinio/taskwarrior-api.git
cd taskwarrior-api
# Install dependencies
make install
# Set required environment variable
export TW_API_TOKENS="your-secret-token"
# Build and run
make build
./bin/taskwarrior-apiThe server will start on http://localhost:8080
Access Swagger UI: Open http://localhost:8080/swagger/index.html in your browser
A read-only web UI is available for viewing tasks and reports. This is intended as an example/development tool and is enabled by default.
Simply start the server and open http://localhost:8080/ in your browser.
If you want to disable the UI (e.g., for production):
export TW_API_ENABLE_UI=false
./bin/taskwarrior-api- Read-only interface for viewing tasks
- Dynamic report viewer using Taskwarrior's report configurations
- Displays tasks using each report's configured columns and labels
- Clean, minimal styling with Pico CSS
- No build step required (all dependencies via CDN)
- Enabled by default - Can be disabled via
TW_API_ENABLE_UI=false - Requires valid API token (stored in browser session only)
- Read-only - cannot create, modify, or delete tasks
- Recommended for development and internal use
- Consider using a reverse proxy with additional authentication for external access
# Clone the repository
git clone https://github.com/dotbinio/taskwarrior-api.git
cd taskwarrior-api
# Install dependencies
make install
# Build the binary
make build
# The binary will be available at ./bin/taskwarrior-api# Run directly with Go
make run
# Or run the built binary
./bin/taskwarrior-api# Build
docker build -t taskwarrior-api:latest .
# Tag for your registry
docker tag taskwarrior-api:latest your-registry/taskwarrior-api:latest
# Push
docker push your-registry/taskwarrior-api:latestOr use the Makefile:
make docker-build
make docker-push # Shows push instructionsComplete Kubernetes manifests are provided in k8s/deployment.yaml.
# 1. Create secret with your tokens
kubectl create secret generic taskwarrior-api-secret \
--from-literal=tokens="your-token-1,token-2" \
-n taskwarrior
# 2. Update image in k8s/deployment.yaml
# 3. Deploy
kubectl apply -f k8s/deployment.yaml
# 4. Port forward to test
kubectl port-forward -n taskwarrior svc/taskwarrior-api 8080:8080Or use the Makefile:
make k8s-deploy
make k8s-port-forwardSee KUBERNETES.md for complete deployment guide including:
- Image registry setup
- Ingress configuration
- Monitoring and scaling
- Data persistence options
- Troubleshooting
The server is configured entirely through environment variables.
| Variable | Description | Example |
|---|---|---|
TW_API_TOKENS |
Comma-separated list of valid auth tokens | token1,token2,token3 |
| Variable | Description | Default |
|---|---|---|
TW_API_HOST |
Server host address | 0.0.0.0 |
TW_API_PORT |
Server port | 8080 |
TW_API_ENABLE_UI |
Enable embedded example UI | true |
TW_DATA_LOCATION |
Path to Taskwarrior data directory | ~/.task |
TW_API_LOG_LEVEL |
Log level (debug, info, warn, error) | info |
TW_API_CORS_ENABLED |
Enable CORS | true |
TW_API_CORS_ORIGINS |
Comma-separated list of allowed origins | http://localhost:3000 |
export TW_API_TOKENS="my-secret-token-123,another-token-456"
export TW_API_PORT=8080
export TW_DATA_LOCATION="~/.task"
export TW_API_LOG_LEVEL="info"
export TW_API_CORS_ORIGINS="http://localhost:3000,https://mytasks.example.com"
./bin/taskwarrior-apiOr create a .env file (see env.example for template) and source it:
cp env.example .env
# Edit .env with your values
source .env
./bin/taskwarrior-apiAll API endpoints require authentication via Bearer token.
Once the server is running, you can access the interactive Swagger UI at:
http://localhost:8080/swagger/index.html
This provides a web interface to:
- Browse all available endpoints
- View request/response schemas
- Test API calls directly from your browser
- See example requests and responses
Include the token in the Authorization header:
curl -H "Authorization: Bearer your-token-here" http://localhost:8080/api/v1/tasksNo authentication required
GET /health
Response:
{
"status": "ok",
"service": "taskwarrior-api"
}GET /api/v1/tasks
Query parameters:
status(default:pending) - Filter by status (pending, completed, deleted, waiting)project- Filter by project nametags- Filter by tags (can be specified multiple times)
Example:
curl -H "Authorization: Bearer token" \
"http://localhost:8080/api/v1/tasks?status=pending&project=work"Response:
{
"tasks": [
{
"uuid": "a360fc44-315c-4366-b70c-ea7e7520b749",
"description": "Complete project documentation",
"status": "pending",
"project": "work",
"tags": ["documentation"],
"urgency": 8.9,
"entry": "2026-01-01T10:00:00Z"
}
],
"count": 1
}GET /api/v1/tasks/:uuid
Example:
curl -H "Authorization: Bearer token" \
http://localhost:8080/api/v1/tasks/a360fc44-315c-4366-b70c-ea7e7520b749POST /api/v1/tasks
Request body:
{
"description": "New task",
"project": "work",
"tags": ["important", "urgent"],
"priority": "H",
"due": "2026-01-15T00:00:00Z"
}Required fields:
description(string)
Optional fields:
project(string)tags(array of strings)priority(string: H, M, L)due(ISO 8601 datetime)wait(ISO 8601 datetime)scheduled(ISO 8601 datetime)depends(array of UUIDs)recur(string: daily, weekly, monthly, etc.)
Example:
curl -X POST -H "Authorization: Bearer token" \
-H "Content-Type: application/json" \
-d '{"description":"Write API documentation","project":"docs","tags":["writing"]}' \
http://localhost:8080/api/v1/tasksPATCH /api/v1/tasks/:uuid
Request body (all fields optional):
{
"description": "Updated description",
"project": "work",
"priority": "H",
"due": "2026-01-20T00:00:00Z"
}Example:
curl -X PATCH -H "Authorization: Bearer token" \
-H "Content-Type: application/json" \
-d '{"priority":"H","project":"urgent"}' \
http://localhost:8080/api/v1/tasks/a360fc44-315c-4366-b70c-ea7e7520b749DELETE /api/v1/tasks/:uuid
Example:
curl -X DELETE -H "Authorization: Bearer token" \
http://localhost:8080/api/v1/tasks/a360fc44-315c-4366-b70c-ea7e7520b749POST /api/v1/tasks/:uuid/done
Example:
curl -X POST -H "Authorization: Bearer token" \
http://localhost:8080/api/v1/tasks/a360fc44-315c-4366-b70c-ea7e7520b749/donePOST /api/v1/tasks/:uuid/start
Example:
curl -X POST -H "Authorization: Bearer token" \
http://localhost:8080/api/v1/tasks/a360fc44-315c-4366-b70c-ea7e7520b749/startPOST /api/v1/tasks/:uuid/stop
Example:
curl -X POST -H "Authorization: Bearer token" \
http://localhost:8080/api/v1/tasks/a360fc44-315c-4366-b70c-ea7e7520b749/stopGet pending tasks sorted by urgency.
GET /api/v1/reports/next
Get currently active (started) tasks.
GET /api/v1/reports/active
Get completed tasks.
GET /api/v1/reports/completed
Get tasks in waiting state.
GET /api/v1/reports/waiting
Get all tasks regardless of status.
GET /api/v1/reports/all
Example:
curl -H "Authorization: Bearer token" \
http://localhost:8080/api/v1/reports/nextGet all projects with task counts.
GET /api/v1/projects
Response:
{
"projects": [
{
"name": "work",
"count": 5
},
{
"name": "personal",
"count": 3
}
],
"count": 2
}Get all tasks for a specific project.
GET /api/v1/projects/:name/tasks
Example:
curl -H "Authorization: Bearer token" \
http://localhost:8080/api/v1/projects/work/tasksAll errors follow a consistent format:
{
"error": "Human readable error message",
"code": "ERROR_CODE"
}Common error codes:
MISSING_AUTH_HEADER- No Authorization header providedINVALID_AUTH_FORMAT- Authorization header format is incorrectINVALID_TOKEN- Token is not validINVALID_UUID- Task UUID format is invalidTASK_NOT_FOUND- Task with given UUID doesn't existINVALID_REQUEST- Request body is malformed
HTTP status codes:
200- Success201- Created400- Bad Request401- Unauthorized404- Not Found500- Internal Server Error
make testInstall air:
go install github.com/air-verse/air@latestThen run:
make devmake fmt┌─────────────┐
│ Client │
│ (Web/Mobile)│
└──────┬──────┘
│ HTTP/REST
│
┌──────▼──────────────┐
│ API Server (Go) │
│ - Auth Middleware │
│ - Route Handlers │
└──────┬──────────────┘
│ CLI Commands
│
┌──────▼──────────────┐
│ Taskwarrior CLI │
│ - task export │
│ - task add │
│ - task modify │
└──────┬──────────────┘
│ File I/O
│
┌──────▼──────────────┐
│ .task/ Files │
│ (Single Source of │
│ Truth) │
└─────────────────────┘
- Taskwarrior is the backend - No database, no state duplication
- CLI-only integration - Never touch
.task/files directly - Strict separation - Server and UI are completely independent
- Safe by default - No arbitrary command execution
- Local-first - Works with existing Taskwarrior + sync setups
- Token Security: Use strong, randomly generated tokens. Keep them secret.
- HTTPS: Always use HTTPS in production to protect tokens in transit.
- Network Access: Consider running behind a reverse proxy (nginx, Caddy) with additional security layers.
- Local Use: For maximum security, bind to
127.0.0.1and use SSH tunneling for remote access.
- Web UI: Build a modern web interface for Taskwarrior
- Mobile Apps: Create native mobile apps with offline sync
- Automation: Integrate with tools like Zapier, IFTTT, or custom scripts
- Team Dashboards: Display team tasks on shared screens
- Voice Assistants: Add tasks via Alexa, Google Home, etc.
This project includes production-ready deployment configurations:
- Docker: Multi-stage build with security best practices
- Docker Compose: Ready-to-use orchestration
- CI/CD: GitHub Actions workflows for testing and releases
- Systemd: Service configuration for Linux servers
- Reverse Proxy: Examples for Nginx and Caddy
See DEPLOYMENT.md for detailed deployment guides, security considerations, monitoring, and troubleshooting.
export TW_API_TOKENS="$(openssl rand -hex 32)"
docker-compose up -dAccess at: http://localhost:8080/swagger/index.html
Contributions are welcome! Please feel free to submit issues or pull requests.
MIT License - see LICENSE file for details.
- Taskwarrior - The amazing task management tool this API wraps