Build workflows for both humans and LLM/AI agents—without SaaS limits.
Modern teams (and their coding agents or LLMs) need a task platform that’s open, and agent-friendly.
Tired of apps that lock you in and don’t talk to your automations or agents? This system gives you:
- A developer-first CLI—ideal for scripts, automations, and LLM agents
- A human-friendly Kanban web UI for drag-and-drop workflow
- A robust API for LLM agents and bots to create, search, assign, and complete tasks automatically
- Full data ownership, privacy by default, and no vendor lock-in
- Machine-readable outputs and clear error handling—built for agent resilience
Let your team—and your AI agents—manage work together in the terminal, browser, or with code. Get started below!
A cross-platform task management system with a robust CLI client (API-only), REST API backend, and persistent storage for advanced task management.
Check out a demo of the Task Management System in action:
The project is structured around a clear separation of concerns for usability, automation, and scalability. Here is a high-level architecture:
+------------------------+
| User/Developer |
| (CLI & Browser) |
+-----------+------------+
|
+------------------+-------------------+
| |
+-------v--------+ +-------v---------+
| CLI | | Web UI |
| (Task.Cli) | | (Kanban Razor) |
+-------+--------+ +-------+---------+
| |
(API mode: HTTP via API—CLI requires remote API) |
| [Server-side, accesses]
+-------v--------+ +---------+-------------+
| API |<----------------+ Task.Api (Razor) |
| (Task.Api) | [shared logic & direct DB access] |
+-------+--------+ +---------+-------------+
| |
+------------------v-------------------+
SQLite DB
(tasks, tags, FTS, etc)
Legend:
- CLI: Command-line tool (
Task.Cli) — connects exclusively to the API with HTTP (API mode). - Web UI: Kanban board (Razor pages) — accesses data directly using Task.Core logic (no HTTP/REST).
- API: REST backend (
Task.Api) — serves the CLI in API mode and remote services; also hosts Razor pages. - SQLite DB: The backend (Task.Api) stores data in SQLite. The CLI communicates with the API and does not access SQLite directly.
The system consists of three main components:
- CLI Client (
Task.Cli/): A command-line interface for managing tasks - REST API Backend (
Task.Api/): A web API server providing REST endpoints and Kanban Board Web UI - Storage: The backend uses an SQLite database with full-text search and vector search capabilities
-
Add, list, edit, delete, and complete tasks
-
Assign tasks to users/assignees
-
Search tasks (full-text and semantic search)
-
Import tasks
-
JSON output for scripting and integration
-
Plain text output option
-
API integration mode (--api-url)
- RESTful endpoints for task management
- Scalar/OpenAPI documentation
- CORS support for web integrations
- Advanced filtering and sorting
- Tag management
- JSON serialization with custom converters
- The backend database (SQLite) includes schema for FTS5 and vector search
- Automatic schema migration
- Optimized indexes for performance
- Support for tags, priorities, due dates, assignees
- Full-text search on title, description, and tags
- Vector search for semantic similarity (requires sqlite-vss extension)
The Telegram provider sends a notification when there are no active tasks in
todo or in_progress. Configuration is read from the Telegram section in
appsettings.json, appsettings.{Environment}.json, or environment variables.
Environment variables override JSON values (use __ instead of : for nested
keys).
{
"Telegram": {
"Enabled": false,
"BotToken": "",
"ChatId": "",
"DefaultMessage": "No tasks are currently in todo or in_progress."
}
}Telegram:Enabled: Enables or disables sending notifications. Whenfalse, the provider logs and skips sends.Telegram:BotToken: Telegram bot token used to call the Telegram API.Telegram:ChatId: Target chat ID for the message.Telegram:DefaultMessage: Message body for notifications. Blank or whitespace falls back to the default string shown above.
If Telegram:Enabled is true but BotToken or ChatId are missing, the
provider throws an error to surface misconfiguration.
TasksController.GetTasks calls the Telegram notification service after
fetching tasks. The notification triggers only when there are zero tasks whose
status is todo or in_progress. If any active task exists, the service logs
that the notification was skipped.
Download the appropriate single executable for your platform from the releases page. Each executable is self-contained, including the .NET runtime and all dependencies, making it easy to distribute and run without additional setup.
- Linux x64:
Task.Cli(single executable file, ~17MB) - macOS Intel:
Task.Cli(single executable file) - macOS ARM64:
Task.Cli(single executable file) - Windows x64:
Task.Cli.exe(single executable file)
-
Download: Download the executable for your platform from the releases page.
-
Make Executable (Linux/macOS only): After downloading, make the file executable:
chmod +x Task.Cli
-
Install to PATH (Recommended): To use the
taskcommand from anywhere, move the executable to a directory in your system's PATH:- On Linux/macOS: Move to
/usr/local/bin/(requires sudo) or~/bin/(create if needed):sudo mv Task.Cli /usr/local/bin/task # or mkdir -p ~/bin && mv Task.Cli ~/bin/task
Ensure
~/binis in your PATH by adding to your shell profile (e.g.,~/.bashrcor~/.zshrc):PATH="$HOME/bin:$PATH"- On Windows: Move
Task.exeto a directory in your PATH, such asC:\Windows\System32\or create a custom directory and add it to PATH via System Properties > Environment Variables.
- On Linux/macOS: Move to
-
Verify Installation: Open a new terminal and run:
task --help
To run without installing to PATH, simply execute the file from its download location.
The output below shows all available global options and commands for the CLI:
USAGE:
task [OPTIONS] <COMMAND>
EXAMPLES:
task add Buy groceries
task add --title Refactor code --priority high --tags code,refactor
task add --title Upload report --due-date 2024-04-01
task add --title Team meeting --project work --status in_progress
task add --title "Blocked by API" --status blocked --block-reason "Waiting on API access"
task add Buy groceries --priority high --assignee john.doe --tags errands
--due-date 2026-03-01
task start
task status
task stop
task server run --urls http://localhost:8080
OPTIONS:
-h, --help Prints help information
-v, --version Prints version information
COMMANDS:
add Create a new task with optional properties like priority,
due date, tags, and project assignment
list Display tasks with advanced filtering by status, priority,
assignee, project, tags, and due date
edit <ids> Modify existing task properties including title,
description, priority, due date, and assignee
delete Permanently remove one or more tasks (supports bulk
deletion with confirmation)
complete Mark tasks as completed (supports bulk completion)
reset <id> Reset a completed task back to pending status
search <query> Perform full-text or semantic similarity search across
task titles and descriptions
import Import tasks from JSON or CSV files, merging with existing
data
config Manage CLI configuration settings
server run Run the API server in the foreground
server start Start the background API server daemon
server status Check the status of the background API server
server stop Stop the background API server
help Show detailed help information
Requirements:
- .NET 10.0 SDK
Clone the repository and build:
git clone <repository-url>
cd Task
dotnet build Task.Cli/Task.Cli.csproj -c ReleaseTo publish single-file executables:
cd Task.Cli
# Linux
dotnet publish -c Release -r linux-x64 --self-contained -p:PublishSingleFile=true -p:PublishTrimmed=true
# macOS Intel
dotnet publish -c Release -r osx-x64 --self-contained -p:PublishSingleFile=true -p:PublishTrimmed=true
# macOS ARM64
dotnet publish -c Release -r osx-arm64 --self-contained -p:PublishSingleFile=true -p:PublishTrimmed=true
# Windows
dotnet publish -c Release -r win-x64 --self-contained -p:PublishSingleFile=true -p:PublishTrimmed=trueRun the CLI application:
./Task.Cli --helpThe easiest way to run the API backend is using Docker Compose:
-
Ensure Docker and Docker Compose are installed on your system.
-
From the project root directory, run:
docker-compose up -d
This will:
- Build the API Docker image
- Start the API server on port 8080
- Mount a
./datadirectory for persistent SQLite database storage
-
Verify the API is running:
- API endpoints: http://localhost:8080/api/tasks
- Scalar UI: http://localhost:8080/scalar
-
To stop the services:
docker-compose down
Requirements:
- .NET 10.0 SDK
-
Navigate to the API directory:
cd Task.Api -
Restore dependencies and run:
dotnet run
The API will start on http://localhost:5000 (development) or https://localhost:5001 (with SSL).
For production deployment, configure the ASPNETCORE_ENVIRONMENT and DatabasePath settings.
The CLI requires a remote Task API server and operates in API mode only. All commands communicate with the backend API via the --api-url option. The CLI configuration is stored at the canonical config path ~/.config/task/config.json.
You can configure Telegram notification settings for the API server within your CLI config file. These settings are automatically passed to the API when you start the server from the CLI (task server run, task server start).
Example ~/.config/task/config.json:
{
"apiUrl": "http://localhost:8080",
"defaultOutput": "plain",
"telegram": {
"botToken": "<your-telegram-bot-token>",
"chatId": "<your-telegram-chat-id>"
}
}When the CLI starts the API server, it sets these as environment variables (Telegram__BotToken, Telegram__ChatId). The API will pick them up automatically.
The CLI can manage its own background API server directly.
Start the background server:
task server start
When the server starts successfully, it outputs Task.Ready to indicate readiness. This is particularly useful for agents and automations that need to wait for the server.
Check server status:
task server status
Stop the background server:
task server stop
Alternatively, run the server in the foreground:
task server run --urls http://localhost:8080
When --database-path is omitted, the API stores its SQLite database in the same config directory used for CLI configuration: ~/.config/task/tasks.db (or the equivalent resolved config directory path, such as $XDG_CONFIG_HOME/task/tasks.db).
To override the database location explicitly:
task server run --database-path ./data/tasks.db
Add a task:
task add "Buy groceries" --api-url http://localhost:8080
# or set the API URL once with:
task config set api-url http://localhost:8080
# Set Telegram notification config (CLI convenience):
task config set telegram.botToken <your-telegram-bot-token>
# Automatically discover and set your chatId:
task telegram discover-chat-id
# (Alternatively set manually if you know your chatId)
task config set telegram.chatId <your-telegram-chat-id>
# Get a value:
task config get telegram.botToken
# Unset Telegram chat ID:
task config unset telegram.chatId
# then use:
task add "Review code" --assignee john.doe --priority highList tasks:
task list
task list --assignee john.doe --status todoComplete a task:
task complete a2b3k9Edit a task:
task edit 1 "Buy groceries and milk"
task edit 1 --assignee jane.smithDelete a task:
task delete 1Search tasks:
task search "groceries"--json: Output in JSON format--plain: Plain text output--api-url <url>: Base URL of the Task API (required)
List tasks in JSON:
task list --jsonConnect to API backend:
task --api-url http://localhost:8080 listThe API provides REST endpoints for task management. When running locally, access:
- Scalar UI: http://localhost:8080/scalar (when using Docker) or http://localhost:5000/scalar (development)
- API Base URL: http://localhost:8080/api (Docker) or http://localhost:5000/api (development)
GET /api/tasks- List all tasks with optional filteringGET /api/tasks/{uid}- Get a specific task by UIDPOST /api/tasks- Create a new taskPUT /api/tasks/{uid}- Update a taskDELETE /api/tasks/{uid}- Delete a taskPATCH /api/tasks/{uid}/complete- Mark task as completedGET /api/tasks/search?q={query}&type={fts|semantic}- Search tasksGET /api/tags- Get all unique tags
Create a task:
curl -X POST http://localhost:8080/api/tasks \
-H "Content-Type: application/json" \
-d '{"title": "New Task", "priority": "high"}'List tasks:
curl http://localhost:8080/api/tasksThe backend application uses SQLite for data storage with an advanced schema supporting:
- Tasks Table: Core task data with priorities, due dates, tags, and status
- FTS5 Virtual Table: Full-text search across title, description, and tags
- VSS Virtual Table: Vector search for semantic similarity (requires sqlite-vss extension)
- Triggers: Automatic synchronization between tables
- Indexes: Optimized for common query patterns
The SQLite database file is created automatically on the backend. In Docker deployments, it's stored in the ./data directory for persistence.
See SCHEMA.sql (in the backend source) for the complete database schema definition.
Check out a demo of the Task Management System in action:
Most browsers will play the video in-page or download it directly.



