New
Apps 1,382Makers 1,380This week 1,382
Promote your app−30%
meghnaad screenshot 1
0views in
the last 30 days

Meghnaad

Meghnaad

Taskwarrior 3 in your browser and on your phone. The Rust engine runs in the page (and natively in the Android app), a small Worker on Cloudflare keeps the secret, your existing S3 or R2 bucket is the sync store, Cloudflare Access is the login.

Deploy to Cloudflare   Get the Android app (APK)


Meghnaad is another replica of your Taskwarrior data. The task CLI keeps syncing to R2 as it does today; this app reads and writes the same bucket. A task added here shows up on your laptop after task sync, and the other way round. It is console-first (type task commands) with tables, forms and charts beside it. Both use the same command engine. It comes as a web app you deploy to Cloudflare and as an Android app with home-screen widgets that keeps the tasks on the phone and syncs straight with your bucket.

Philosophy

  • It complements Taskwarrior, it does not replace it. Same bucket, same data, same rules: your task CLI keeps working beside it.
  • It behaves exactly like task. Where it doesn't, that is a bug: please file an issue.
  • Power tools for advanced users, usable by everyone. A console as capable as the CLI, with tables, forms and buttons for anyone who would rather click.
  • Basic features run on Cloudflare's free tier. Workers, R2 and Access each have a free plan that is enough (limits).

What you get

  • Uses your existing bucket. Same R2 bucket, same encryption secret. No migration, no new server, nothing changes for the CLI.
  • Taskwarrior's behaviour, not an imitation. Filters, virtual tags, urgency, reports, recurrence, regexes, the calendar, summary, burndown, history, timesheet, stats, export, import, purge, duplicate, context, calc and the confirmations are ported from the source and checked against the real task 3.5.0. Settings removed before 3.5.0 are not supported.
  • Your taskrc, safely. Paste it, upload it, import a whole folder of files or import it from a link (your dotfiles repository). It is kept as you wrote it, include works, and the files are listed in Settings to add, edit, delete and include. UDAs, reports, contexts, holidays and settings are read; a line the app can't use is commented out, and sync settings and credentials are removed (what is read).
  • tasksh's review. Walk the tasks you have not looked at lately and mark each reviewed, skip, edit, change, finish or delete it, from the top bar's Review button (a card) or the Console (review), with keys as in tasksh. It sets up the reviewed attribute and _reviewed report itself.
  • Your own commands. A word for a whole command line, such as fail for done outcome:fail, with an icon from Lucide. It works typed (3 fail, project:Home fail) and from a ⋯ menu on a task and on the selected tasks. Kept in the app's own settings.json.
  • Colours as on the desktop. color.* rules, precedence and themes, drawn softly, plus a default theme of its own.
  • Boards. Pages of your own made of numbers, tables and charts (bars, stacked or side by side, lines, areas, pies, donuts, radar: a sum of estimates by project, what you finish per week, split by outcome), each with its own filter, laid out on a 12-column grid that you drag and resize, and on 4 or 6 columns on a phone (several numbers to a row, resizable there too). Kept in the app's own settings.json (Boards).
  • Hooks, as Lua. on-add, on-modify, on-launch and on-exit become functions in a script you edit in Settings, kept in your bucket and run on the Worker, or on the phone in the Android app (Hooks).
  • Works on a phone. The layout adapts (a menu for the pages, tasks as cards with their marks, time tracking, reminders, a console with completion), and there is a native Android app.
  • An Android app and widgets. The engine runs on the phone, so it works offline, syncs straight with any S3-compatible bucket or a TaskChampion sync server (no Worker, no Cloudflare Access), and has four home-screen widgets: a task list for any report, a burndown, a calendar and a card of a board (the Android app), and boards you can make and change on the phone, with a link to every page.

Status. Verified against the released task 3.5.0 on a local S3-compatible server, in both directions (tasks, UDAs, reports, recurring series, snapshots, purge, import), and in use on a real R2 bucket.

The Android app's three widgets: a task list, a calendar with the tasks of the selected day, and a burndown
The Android app's widgets: tasks (any report, the fields you choose), a calendar (tap a day to see its tasks) and a burndown

The Tasks view: the next report as a table, with the prompt underneath

Summary: progress of each project Calendar: what is due on which day
Summary: how far along each project is Calendar: click a day to see what is due
Burndown: pending, started and done by day A task's detail drawer with tracked time and history
Burndown, drawn the way task burndown counts Task detail: time tracking, annotations, history
The console: a report, a calculation, and a question as a table of ticks The phone layout
The console. Taskwarrior's yes/no/all/quit becomes a table of ticks On a phone
Settings, Commands: words that stand for a command line, each with a Lucide icon The menu under the ellipsis on a task lists those commands
Settings: your own commands, with any Lucide icon They are on the ⋯ menu of a task, and of the selected tasks
Settings, tasksh: what review needs in the taskrc, and the lines that would be written Settings, Urgency: every coefficient next to its default
Settings: the tasksh setup, with the exact lines it writes Settings: urgency coefficients next to their defaults
tasksh's review in the console: the question to define what it needs, then the first task and the review prompt The review card: the task, and Reviewed, Skip, Edit, Modify, Complete, Delete and Quit
tasksh's review in the console: press a key, as in tasksh The same review as a card, with the same keys

Documentation

Using Meghnaad Pages, console, confirmations, hooks, recurrence, urgency, time tracking
Deploying Setup, GitHub Actions deploy, Access, connecting task, troubleshooting
The Android app Install, connect (a bucket or a TaskChampion sync server, or neither), the four widgets, sharing settings and hooks, building it
Architecture The engine, sync, platform limits, how correctness is kept
taskrc support Every taskrc option: done, partial, not done

How it works

flowchart TB
  subgraph desktop["Desktop: Taskwarrior 3"]
    direction TB
    sh["shell aliases<br/>alias fail='task done outcome:fail'"]
    tsh["tasksh<br/>review"]
    cli["task CLI (C++)"]
    tcd["TaskChampion (Rust)"]
    db[("SQLite replica<br/>~/.task")]
    rc["~/.taskrc"]
    sh -.-> cli
    tsh -.-> cli
    cli --> tcd --> db
    rc -.-> cli
  end

  subgraph web["Your browser: Meghnaad"]
    direction TB
    cmds["task commands<br/>(settings.json)"]
    rev["tasksh review"]
    spa["Svelte app<br/>(draws results)"]
    eng["Engine in a Web Worker (Rust → WASM)<br/>command engine in tc-core"]
    tcw["TaskChampion (Rust)"]
    mem[("Replica in memory<br/>saved copy in IndexedDB")]
    cmds -.-> spa
    rev -.-> spa
    spa -- "what you type or click" --> eng --> tcw --> mem
  end

  subgraph phone["Your phone: Meghnaad for Android"]
    direction TB
    wg["Widgets<br/>tasks · burndown · calendar"]
    app["The app<br/>Kotlin and Compose"]
    nat["Engine (Rust, native)<br/>tc-core, hooks (Lua)"]
    rep[("Replica in a file<br/>settings and keys on the phone")]
    wg --> nat
    app --> nat --> rep
  end

  subgraph edge["Cloudflare"]
    direction TB
    access{{"Cloudflare Access<br/>sign-in and token check"}}
    assets["Static assets<br/>the app and the engine (.wasm)"]
    wk["Worker (Rust → WASM)<br/>opens and seals versions<br/>runs your hooks (Lua)<br/>key in a Worker secret"]
    access --> assets
    access --> wk
  end

  bucket[("R2 bucket<br/>salt · latest<br/>v-parent-child · s-version<br/>web/config.json · web/settings.json")]

  tcd <-- "task sync (when you run it)<br/>S3 API, key on your machine" --> bucket
  nat <-- "S3 API, signed on the phone<br/>any S3-compatible store" --> bucket
  tcw <-- "after every write, when you return,<br/>every 30 s: /api/tc/*, plain versions" --> access
  spa -. "taskrc settings, settings.json<br/>/api/config, /api/settings" .-> access
  eng -. "a hook call: /api/run" .-> access
  wk <-- "R2 binding" --> bucket
  assets -. "loaded once, then cached" .-> spa

  sh <-. "counterpart" .-> cmds
  tsh <-. "counterpart" .-> rev

  classDef ext fill:transparent,stroke:#999,color:#999,stroke-dasharray:4 3
  class sh,tsh,cmds,rev ext
  • Dashed grey boxes are not Taskwarrior: your own words for command lines (shell aliases on the desktop, task commands here) and tasksh's review (tasksh there, built in here). They only ever send ordinary commands.
  • The engine runs in your browser. Taskwarrior's rules live in one place, tc-core, compiled to WebAssembly and run in a Web Worker in the page. It holds your tasks in memory, so a command costs no round trip and uses none of the Worker's CPU. Only your hooks run elsewhere, on the Worker (below). The Svelte app only draws.
  • The bucket holds TaskChampion's standard cloud layout, encrypted client-side. The browser's replica and your CLI are interchangeable replicas of it.
  • The Worker keeps the secret. It checks Cloudflare Access, and opens and seals the versions that pass between the bucket and your browser (/api/tc/*), so the encryption secret never leaves it. It parses no tasks. It also runs your hooks: the engine sends it a task and gets the task back (/api/run).
  • The browser keeps a copy in IndexedDB, so a visit starts from where the last one ended and only pulls what is new. It syncs after every write, when you come back to the tab, and every 30 seconds while you look at it; other tabs are told when one pushes.
  • Imported taskrc files are stored in the bucket (as written, less sync and credential lines), so they survive restarts and follow you between devices. The app's own settings.json (task commands, so far) is stored beside them; the Worker keeps its text as it is and only the browser reads it.
Desktop Taskwarrior Meghnaad
Local state Persistent SQLite In the page, with a saved copy in the browser (IndexedDB)
Sync When you run task sync After every write, when you return to the tab, every 30 s while you look at it
Offline Works Changes work and are kept; they go up when the connection is back. The page itself needs a connection to load
Encryption key Only on your machine In a Worker secret; the Worker opens and seals what passes through it
Task ids Local to that replica Computed separately, so they differ
Hooks Scripts in ~/.task/hooks Lua functions in a script kept in the bucket, edited in Settings; they run on the Worker (or with task, through meghnaad-hook)

More in Architecture.

Quick start (local)

Runs without a Cloudflare account; wrangler simulates R2. You need Rust 1.91+ and Node.js 20+.

git clone <this repo> && cd Meghnaad
npm install
cp .dev.vars.example .dev.vars   # local-only secret + Access bypass
npm run dev                      # builds the engine, then serves the app (hot reload) and the Worker

The first build takes a few minutes (it installs the wasm-bindgen tool once). Open http://127.0.0.1:5273: the app with hot reload, and the Worker behind it on 8787. The engine is rebuilt when the Rust under crates/tc-core or crates/browser changes, and the Worker when its own does. For demo data run ./scripts/seed-dev.sh. Local R2 data lives in .wrangler/state (delete it to start over), or somewhere else with npm run dev -- --persist-to DIR; the ports are --api-port and --web-port.

Deploy to Cloudflare

You need Workers, R2 and Access; each has a free plan.

No Rust needed: CI publishes a prebuilt release. Use the button,

Deploy to Cloudflare

or from a terminal with only Node.js 20+:

git clone --branch release --depth 1 https://github.com/uroybd/Meghnaad.git meghnaad && cd meghnaad
npm install
npm run setup        # guided: bucket, domain, secret, Access; safe to repeat
npm run deploy       # whenever you update (after pulling the release branch)

From a clone of the source (Rust needed), the same two commands build it first.

Setup asks for your sync bucket and encryption secret, deploys, and tells you what to click to connect Access. Until then the app shows a setup page and nothing is reachable. Pointing your task CLI at R2 is in Deploying. To deploy from GitHub instead, run the manual Deploy workflow (setup).

Android app

The same app on your phone, with the engine on the phone. It works offline, keeps your keys in the Android Keystore, and syncs straight with your bucket over S3 (R2, AWS S3, MinIO, ...), so it needs no Worker and no Cloudflare Access.

  1. Download meghnaad-<version>.apk from the latest release and open it (allow installing from your browser or files app when asked). It is about 4.5 MB, for 64-bit ARM phones, and later releases update it in place.
  2. Enter your bucket's S3 endpoint, bucket, region, access key and secret, and the encryption secret (the same as your taskrc's sync.encryption_secret), or press Use on this phone only to start without syncing and connect later in Settings → Sync.
  3. Long-press the home screen, Widgets → Meghnaad: Tasks (any report, a filter, the fields you tick; tick a task done, tap one to open it, + to add), Burndown and Calendar.

Settings and hooks can be kept in step with the web app's through the bucket (two switches under Settings → Sync); the secrets for hooks never are. Everything about it, including building it yourself, is in the Android app.

Using it

The header has Tasks, Projects, Tags, Summary, Calendar, Burndown, Boards and Console, and Settings (the taskrc, tasksh, your own commands, hooks and urgency). Anything you can click you can type:

project:Home +errand due.before:eow list
add Pay rent project:Home due:eom +bills
3 modify due:2026-12-25T08:30 priority:H
3 done            3 delete            undo
calc 2 days + 3 hours
history.monthly   ghistory.monthly   timesheet   export   (Console only; export downloads a file)
show weekstart     config weekstart monday   (Console only)
3 done && add Next step ; list   (Console, and task commands: && after a success, || after a failure, ; always)

A report typed in the Console prints there; elsewhere it opens in Tasks. Taskwarrior's confirmations arrive as a table of ticks. &&, || and ; chain commands as in a shell: the page runs them one after the other. More in Using Meghnaad.

Hooks

Taskwarrior's four hooks are functions in a *

Description taken from the repository README.

Ratings

–
0 ratings
5 0
4 0
3 0
2 0
1 0

Rate this app

Sign in to rate

Comments 0

Sign in to comment

No comments yet.

Related apps

#productivity · #taskwarrior · #cloudflare