Web Interface for Task Warrior
A simple web interface that wraps the taskwarrior CLI, allowing you to manage your tasks through a browser while maintaining full CLI syntax compatibility.
- ✅ Taskwarrior Backend: Secure command endpoint plus filter, settings, completion, and taskrc APIs
- ✅ Vue.js Frontend: Modern reactive UI with CQRS architecture
- ✅ CQRS Pattern: Separate query (read) and command (write) services
- ✅ Add tasks with CLI syntax: Full support for taskwarrior's powerful command syntax
- ✅ Edit tasks with CLI syntax: Modify tasks using the same syntax as the command line
- ✅ Custom report commands: Execute any taskwarrior report command (list, next, pending, all, etc.)
- ✅ Task management: View, add, edit, complete, and delete tasks
- ✅ Execute custom commands: Advanced users can execute any taskwarrior command directly
- Command Endpoint:
POST /api/taskaccepts Taskwarrior command arguments - Direct CLI Execution: Uses
execFile()for secure command execution - Taskwarrior as Source of Truth: Tasks remain managed by the Taskwarrior CLI and taskrc
- TaskQueryService: Handles read operations (queries)
- TaskCommandService: Handles write operations (commands)
- TaskApiClient: Single point of communication with backend
- Reactive UI: Vue.js 3 Composition API
- Docker
- Docker Compose
- Taskwarrior installed on your system
- Bun (v1.3 or higher)
Ubuntu/Debian:
sudo apt-get install taskwarriormacOS:
brew install taskOther systems: See Taskwarrior installation guide
- Clone the repository:
git clone https://github.com/Eckii24/taskwarrior-web.git
cd taskwarrior-web- Start with Docker Compose:
docker compose up -d- Access the application:
- Web Interface: http://localhost:3000
- Sync Server: http://localhost:8080
- Clone the repository:
git clone https://github.com/Eckii24/taskwarrior-web.git
cd taskwarrior-web- Install dependencies:
bun install# Start services
docker compose up -d
# View logs
docker compose logs -f
# Stop services
docker compose down- Start the server:
bun run start- Open your browser and navigate to:
http://localhost:3000
Use the "Add Task" section with full taskwarrior CLI syntax:
Buy milk project:groceries +shopping due:tomorrow
Write report project:work priority:H due:friday
Call dentist +phone +urgent
Select a view/report to view your tasks:
- next: Next tasks (Taskwarrior report)
- today: Tasks due today (Taskwarrior report)
- all: All tasks (Taskwarrior report)
Or enter a filter/report expression.
Rules:
- If the last token matches a Taskwarrior report name (from
/api/reports), it runs:task <filters...> export <report> - Otherwise it runs:
task <filter> export(ortask exportwhen empty)
Click the "Edit" button on any task and use CLI syntax:
priority:H- Set high priorityproject:work due:tomorrow- Change project and due date+urgent- Add tag-shopping- Remove tagNew description text- Change description
For advanced operations, use the "Execute Custom Command" section:
1 modify priority:H- Modify task 12 annotate 'Important note'- Add annotation to task 2project:work done- Mark all work tasks as done
The backend provides this primary command endpoint:
Execute any taskwarrior command by passing arguments.
Request Body:
{
"args": "add Buy milk project:groceries +shopping"
}Response:
{
"success": true,
"output": "Created task 1.\n",
"error": ""
}Examples:
# Add a task
curl -X POST http://localhost:3000/api/task \
-H "Content-Type: application/json" \
-d '{"args": "add Buy milk project:groceries +shopping"}'
# List tasks (export as JSON)
curl -X POST http://localhost:3000/api/task \
-H "Content-Type: application/json" \
-d '{"args": "status:pending export"}'
# Modify a task
curl -X POST http://localhost:3000/api/task \
-H "Content-Type: application/json" \
-d '{"args": "1 modify priority:H"}'
# Mark task as done
curl -X POST http://localhost:3000/api/task \
-H "Content-Type: application/json" \
-d '{"args": "1 done"}'The frontend implements Command Query Responsibility Segregation:
class TaskQueryService {
async getTasks(filterOrReport) {
// If last token is a known report: task <filters...> export <report>
// Otherwise: task <filter> export (or task export)
// Returns parsed JSON array of tasks
}
}class TaskCommandService {
async addTask(description) { }
async modifyTask(taskId, modifications) { }
async completeTask(taskId) { }
async deleteTask(taskId) { }
async executeCustom(command) { }
}class TaskApiClient {
async execute(args) {
// Calls POST /api/task with args
}
}- Command Endpoint:
POST /api/taskexecutes Taskwarrior commands - Security: Uses
execFile()to prevent command injection - No Business Logic: Frontend controls all task operations
- Vue.js 3: Reactive UI with Composition API
- CQRS Pattern: Separated read/write operations
- Service Layer: TaskQueryService, TaskCommandService, TaskApiClient
- Responsive Design: Works on desktop and mobile
- CLI Syntax First: Maintains taskwarrior's command syntax
The app has no built-in authentication and can modify tasks and taskrc settings. Keep it on a trusted network, behind a VPN, or behind an authenticated reverse proxy. Do not expose port 3000 directly to the public internet.
The application uses your existing taskwarrior configuration (~/.taskrc). Any custom reports, filters, or settings defined in your taskwarrior configuration will be available in the web interface.
Run Bun backend and UI tests (jsdom + mocked backend):
bun test --preload ./tests/setup.jsTo modify the application:
- Backend: Edit
backend/server.js - Frontend HTML: Edit
public/index.html - Frontend JavaScript: Edit
public/app.js - Frontend Styles: Edit
public/styles.css
ISC
Contributions are welcome! Please feel free to submit a Pull Request.