{"id":32968486,"url":"https://github.com/h-sifat/productivity-timer","last_synced_at":"2026-02-10T16:40:41.815Z","repository":{"id":38410791,"uuid":"504250945","full_name":"h-sifat/productivity-timer","owner":"h-sifat","description":"A CLI/TUI Pomodoro timer and todo (coming soon) application for keyboard addicts and terminal fans that makes you more productive. ","archived":false,"fork":false,"pushed_at":"2023-05-07T11:41:41.000Z","size":1809,"stargazers_count":29,"open_issues_count":2,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-04-22T04:51:03.528Z","etag":null,"topics":["cli","nodejs","pomodoro-timer","timer","tui"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/h-sifat.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-06-16T17:43:10.000Z","updated_at":"2024-04-20T12:48:35.000Z","dependencies_parsed_at":"2022-08-25T02:50:30.608Z","dependency_job_id":null,"html_url":"https://github.com/h-sifat/productivity-timer","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/h-sifat/productivity-timer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/h-sifat%2Fproductivity-timer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/h-sifat%2Fproductivity-timer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/h-sifat%2Fproductivity-timer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/h-sifat%2Fproductivity-timer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/h-sifat","download_url":"https://codeload.github.com/h-sifat/productivity-timer/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/h-sifat%2Fproductivity-timer/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29307926,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-10T16:09:25.305Z","status":"ssl_error","status_checked_at":"2026-02-10T16:08:52.170Z","response_time":65,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","nodejs","pomodoro-timer","timer","tui"],"created_at":"2025-11-13T03:01:38.370Z","updated_at":"2026-02-10T16:40:41.801Z","avatar_url":"https://github.com/h-sifat.png","language":"TypeScript","funding_links":["https://www.buymeacoffee.com/sifathossain"],"categories":["\u003ca name=\"time-tracker\"\u003e\u003c/a\u003eTime trackers","Table of Contents"],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://user-images.githubusercontent.com/80267830/227173633-15b85265-29ea-4942-a565-07dcc6b5e906.svg\" width=\"200px\" align=\"center\" alt=\"Productivity Timer Logo\" /\u003e\n  \u003ch1 align=\"center\"\u003eProductivity Timer\u003c/h1\u003e\n  \u003cp align=\"center\"\u003e\n    A CLI/TUI Pomodoro timer and todo (coming soon) application for keyboard addicts\n    and terminal fans that makes you more productive.\n  \u003c/p\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n\u003ca href=\"https://github.com/h-sifat\" rel=\"nofollow\"\u003e\u003cimg src=\"https://img.shields.io/badge/created--by-h--sifat-green\" alt=\"Created by Muhammad Sifat Hossain\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opensource.org/licenses/MIT\" rel=\"nofollow\"\u003e\u003cimg src=\"https://img.shields.io/github/license/h-sifat/productivity-timer\" alt=\"License\"\u003e\u003c/a\u003e\n\u003ca href=\"https://www.npmjs.com/package/productivity-timer\" rel=\"nofollow\"\u003e\u003cimg src=\"https://img.shields.io/npm/dw/productivity-timer.svg\" alt=\"npm\"\u003e\u003c/a\u003e\n\u003ca href=\"https://www.npmjs.com/package/productivity-timer\" rel=\"nofollow\"\u003e\u003cimg src=\"https://img.shields.io/github/stars/h-sifat/productivity-timer\" alt=\"stars\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n![productivity_timer demo](https://user-images.githubusercontent.com/80267830/223765835-e02cc6d0-bb17-492f-9cd6-f25776bf1653.gif)\n\n## Table of Contents\n\n- [Features](#features)\n- [Installing](#installing)\n- [Usages](#usages)\n  - [CLI](#cli)\n  - [TUI](#tui)\n- [Configuration](#configuration)\n  - [Timer](#timer)\n  - [Speaker](#speaker)\n  - [Database](#database)\n  - [TUI](#tui-1)\n- [Integrating with other apps](#integrating-in-other-apps)\n- [Privacy Policy](#privacy-policy)\n- [Known Issues](#known-issues)\n- [Tech Stack](#tech-stack)\n- [Todo](#todo)\n- [Development](#development)\n- [Conclusion](#conclusion)\n\n## Features\n\nThis application is **20k+** lines of code (including tests) terminal madness\nand packed with features. It\n\n- can be be used entirely from the CLI (you don't have to switch to another\n  window to interact with a Pomodoro app anymore)\n- has a sleek and (almost) responsive TUI\n- plays alarm beep after every non-break timer ends\n- can show notifications\n- can show comprehensive stats (in the TUI)\n- has automatic database backup system\n- is reactive to changes. Changes from any TUI instance or CLI is reflected\n  everywhere.\n\n[Go to TOC](#table-of-contents)\n\n## Installing\n\nIf you don't have Node.js installed then go ahead and install an LTS version\nfrom [here](https://nodejs.org/) and run the following command in your terminal\nor command prompt.\n\n```bash\nnpm i -g productivity-timer\n```\n\nAfter installing run `pt -v` to verify, it should print the current version of\nthe app.\n\n#### Updating\n\nTo update the app run the following command:\n\n```bash\nnpm i -g productivity-timer@latest\n```\n\n#### Uninstalling\n\nTo uninstall the app run:\n\n```bash\nnpm un -g productivity-timer\n```\n\n**Note:** You have to remove the config file `~/ptrc.json` and the data\ndirectories specified in the config manually.\n\n### Installing `mplayer`\n\nProductivity Timer depends on the **mplayer** CLI for playing audio. It\nshould be accessible globally in your shell as the `mplayer` command. If it's\nnot globally available in the shell then you can manually provide the `mplayer`\nbinary path in the config.\n\n**On Arch based systems**\n\n```bash\nsudo pacman -S mplayer\n```\n\n**On Debian based systems:**\n\n```bash\nsudo apt install mplayer\n```\n\n**On MacOS with homebrew:**\n\n```bash\nbrew install mplayer\n```\n\n**On Windows and other OSs:** Please refer to the [official mplayer\nwebsite](http://www.mplayerhq.hu) or your package manager for installation\ninstructions.\n\n[Go to TOC](#table-of-contents)\n\n## Usages\n\nProductivity Timer doesn’t enforce a strict Pomodoro sequence (work -\u003e break -\u003e\nwork). It’s entirely up to you when you want to start a timer, though you can\nconfigure the app to automatically start a break after each work session.\n\nIf a timer has a reference to a task category or project, it’ll be saved and\nshow up in your stats. Otherwise, it’ll be considered a break timer and not be\nlogged. It is only your hard work that counts!\n\n[Go to TOC](#table-of-contents)\n\n### CLI\n\nKindly read the **help** page (with `pt --help`) to learn about all the\ncommands.\n\n**Note:** In the help page of the CLI you'll see commands like `pause|p`. Here\n`|p` means an alias named `p`.\n\n```bash\n# boot up the server\npt bootup\n\n# create a category or project\npt create category --name Study # or use alias: pt c c -n Study\n\n# start a 25m timer for the \"Study\" category\npt start --category --name study -d 25m # or: pt start -cn study -d 20m\n\n# see the current status\npt info # or: pt i\n\n# after the above timer times up start a short break (5m)\npt break -s # or: pt b -s\n\n# shortcut to start the study timer again\npt start --last # or: pt s -l\n```\n\n**Tip:**\n\n1. When the timer is beeping you can mute it by issuing the mute command. e.g.,\n   `pt mute`.\n1. Don't worry about writing long commands. Almost every command has a\n   single-character alias.\n\n[Go to TOC](#table-of-contents)\n\n### TUI\n\n```bash\n# before starting the TUI start the server\npt bootup\n\n# start the TUI\npt tui\n```\n\nWhen in the TUI press \u003ckbd\u003eF1\u003c/kbd\u003e to see the help page.\n\n[Go to TOC](#table-of-contents)\n\n## Configuration\n\nThis app depends on a config file named `~/.ptrc.json`.\n\n**Tip:**\n\n1. Here `~/` means your **home** directory/folder. If you're not sure what is\n   your home directory then run `node -p 'os.homedir()'` in your\n   terminal/command prompt.\n1. The config JSON file supports comments and trailing commas thanks to JSON5.\n\n**Example Configuration:**\n\n```json\n{\n  // timer\n  \"BEEP_DURATION_MS\": \"10s\",\n  \"DEFAULT_TIMER_DURATION_MS\": \"10m\",\n  \"SHOW_TIMER_NOTIFICATIONS\": true,\n  \"AUTO_START_BREAK\": false,\n  \"AUTO_START_BREAK_DURATION\": 300000,\n\n  // speaker\n  \"SPEAKER_VOLUME\": 40,\n  \"MPLAYER_PATH\": \"mplayer\",\n  \"MPLAYER_AUDIO_PATH\": \"/home/muhammad/alarm.mp3\",\n\n  // database\n  \"DB_BACKUP_INTERVAL_MS\": 3600000,\n  \"DATA_DIR\": \"/home/muhammad/.p-timer\",\n  \"DB_BACKUP_DIR\": \"/home/muhammad/.p-timer-bak\",\n\n  // tui\n  \"FIRST_DAY_OF_WEEK\": \"Mon\",\n\n  // other\n  \"CHECK_UPDATE\": true\n}\n```\n\n**Descriptions:**\n\n[Go to TOC](#table-of-contents)\n\n#### Timer\n\n1. `BEEP_DURATION_MS`: for how long the beep should be played when a timer times\n   up.\n\n1. `DEFAULT_TIMER_DURATION_MS`: this value will be used to start a timer when no\n   explicit duration is provided.\n\n1. `SHOW_TIMER_NOTIFICATIONS`: whether the app should show a notification when a\n   timer ends.\n\n1. `AUTO_START_BREAK`: whether the app should automatically start the break\n   timer.\n\n1. `AUTO_START_BREAK_DURATION`: the timer duration of automatically started\n   breaks.\n\n[Go to TOC](#table-of-contents)\n\n#### Speaker\n\n1. `MPLAYER_PATH`: this app uses the `mplayer` audio player to play the alarm.\n   If the `mplayer` command is not available in your shell then you can manually\n   specify the `mplayer` binary path in this field.\n\n1. `MPLAYER_AUDIO_PATH`: path to a custom audio file.\n\n1. `SPEAKER_VOLUME`: An integer value for the speaker volume. **0** for mute and\n   **100** for maximum.\n\n**Note:** All path must be absolute, i.e. should start from your root directory.\nExample: `/home/muhammad/alarm.mp3`\n\n[Go to TOC](#table-of-contents)\n\n#### Database\n\n1. `DATA_DIR`: the directory where the sqlite database and error logs should be\n   stored.\n\n1. `DB_BACKUP_DIR`: the database backup directory.\n\n1. `DB_BACKUP_INTERVAL_MS`: database backup interval timer. I recommend setting\n   this to `1h` to be on the safe side.\n\n[Go to TOC](#table-of-contents)\n\n#### TUI\n\n1. `FIRST_DAY_OF_WEEK`: The TUI depends on this field to render calendar.\n   Example day names: `\"Saturday\"`, `\"Sat\"` or `\"Sa\"`.\n\n#### Other\n\n1. `CHECK_UPDATE`: Whether the app should check for updates and show\n   notification.\n\n**Tip:** All the duration fields can either take a milliseconds number value or\na descriptive duration string value (e.g., `\"20m\"`, `\"1h30m\"` etc.).\n\n[Go to TOC](#table-of-contents)\n\n## Integrating in other apps\n\n### With the `pt_plugin` CLI\n\nThe `pt_plugin` is a lightweight CLI provided by Productivity Timer for easy\nintegration with other applications that can show status by invoking shell\ncommands (e.g., Polybar). Right now, it has only one command named `info` that\ncan either take a template to format status message or output raw JSON.\n\nRun `pt_plugin info --help` to see the command structure.\n\n#### Status Template\n\n**Example**\n\n```bash\npt_plugin info -t \"[ref] | [ed]/[td] | [state]\"\n# will print something like: 'p(2)/Timer | 00:00:06/01:00:00 | RUNNING'\n```\n\n**Syntax**\n\nYou can write anything in the template and to interpolate a variable, write it\ninside `[]`. To escape the `[` and `]` characters use `%` and to write a single\n`%` write `%%`.\n\n**Examples**\n\n```bash\npt_plugin info -t \"Elapsed time: [ed]\"\n# example output: 'Elapsed time: 01:23'\n\npt_plugin info -t \"Elapsed time%% %[[ed]%]\"\n# example output: 'Elapsed time% [01:23]'\n```\n\n**Available Variables**\n\n1. `ref`: the timer reference. It will be formatted as `[pc](id)/name`. Here `c`\n   and `p` means task category and project respectively. If ref is `null` i.e.\n   it's a break timer then it'll be set to the string `\"Break\"`. Also the `name`\n   field is truncated to **15** characters.\n\n1. `state`: timer states: `ENDED`, `PAUSED`, `RUNNING`, `TIMED_UP`, and\n   `NOT_STARTED`.\n\n1. `td`: target duration.\n1. `ed`: elapsed duration.\n1. `rd`: remaining duration.\n\n**Tip:** Checkout [executor](https://github.com/raujonas/executor) if you're\nusing Gnome. It can show the output of any shell command in your top panel.\n\n#### JSON\n\nIf the template doesn't suit your needs then you can provide the `--json` flag\nto get the raw JSON data.\n\n```bash\npt_plugin info --json\n```\n\nThe response data has the following interface:\n\n```ts\ntype InfoCommandResponse =\n  | { error: null; data: any }\n  | { error: { message: string; code: string }; data: null };\n```\n\n### With Node.js\n\nYou can programmatically communication with Productivity Timer through IPC\nsocket.\n\n1. Install [express-ipc](https://github.com/h-sifat/express-ipc)\n1. Copy the config from `src/config/other.ts` module and the client services\n   from `src/client/services` directory.\n\n**Example:** see the `docs/api-integration.ts` file.\n\n[Go to TOC](#table-of-contents)\n\n## Privacy Policy\n\nI have the utmost respect for your privacy and zero interest in your personal\ndata. Whatever data you generate with this app lives in your own machine and it\ndoesn't make any network requests except for update check (you can turn it off).\nBut the sqlite database is unencrypted though and is accessible to every\napplication running on your system!\n\n[Go to TOC](#table-of-contents)\n\n## Known Issues\n\n**1.** The app shows the background color of my terminal!\n\nThe library I'm using to build the TUI is called **blessed**. It's a\nvery old library and it hasn't been updated in the last **seven years.** It\ndoesn't support inheritance for background color styling. So to fix this I've to\nmanually assign a background color to every element. Even if I assign a value of\n\"#000\" it doesn't become as black as my terminal background. So yeah, it's a\nfeature!\n\n**2.** The line-chart in the stats page of TUI is not responsive.\n\nIt's probably intended by **blessed-contrib** as drawing that line is\nprobably expensive. Not sure if I should create a new line-chart element after\nevery resize event.\n\n**3.** The key bindings doesn't work or app is not responding to key press.\n\nYou probably clicked somewhere in the app that removed the focus from the\nselected element. Try pressing \u003ckbd\u003ectrl-j\u003c/kbd\u003e or \u003ckbd\u003ectrl-k\u003c/kbd\u003e to bring\nback the focus or move to another tab and come back to the current one.\n\n[Go to TOC](#table-of-contents)\n\n## Tech stack\n\nThis project has been made possible with help of following open source libraries\nand frameworks. I'm just a lousy developer who have stitched together all this\ntechnologies. Long live open source!\n\n- Backend Service\n\n  - Database: better-sqlite3\n  - Validation: zod and handy-types\n  - IPC Server: express-ipc\n  - Notification: node-notifier\n\n- CLI (commander)\n\n  - IPC Client: express-ipc\n  - Text formatting: ansi-colors\n  - Table: cli-table\n  - Box: boxen\n\n- TUI (blessed + blessed-contrib)\n\n  - Pie chart: cli-pie\n  - Fuzzy search: fuse.js\n  - State management: redux\n  - Terminal Canvas: drawille-canvas\n  - Tree printing: flexible-tree-printer\n\n- Other\n  - Utils: lodash\n  - Date utilities: date-fns\n\n[Go to TOC](#table-of-contents)\n\n## Todo\n\nThis app is far from being complete. I still have to implement so many features.\nIf you think you can help me to implement some features then please do so. It's\nbecoming very tiresome for me to do everything singlehandedly.\n\n- [ ] Add todo feature.\n- [ ] Write code documentation.\n- [ ] Replace nasty validation logic with zod schemas.\n- [x] Remove the overengineered sub-process database layer.\n- [x] Don't refresh stats in the TUI for unrelated changes. Use `redux-watch` to\n      selectively update stats.\n\n[Go to TOC](#table-of-contents)\n\n## Development\n\n```bash\n# running tests\nnpm test\nnpm run test:watch # in watch mode\nnpm run test:coverage # to see test coverage\n\n# building\nnpm run build:dev:watch # run build in watch mode\nnpm run build:dev\nnpm run build:prod # the debug log won't be visible in the TUI\n\n# formatting\nnpm run format\n```\n\n[Go to TOC](#table-of-contents)\n\n## Conclusion\n\nMy main inspiration in building this app was that, I didn't like to move my\nhands from the keyboard to start a Pomodoro timer. Now I can be more productive\nand never leave VIM and my terminal. Though, ironically I've spent more than\nfive months building this app. I guess that's productivity at the peak 😅. But\nthat's not the point. I actually learned a lot (sqlite, child process\nmanagement, blessed, redux ...) while building this app and also built an entire\nIPC server framework ([express-ipc](https://github.com/h-sifat/express-ipc))\nfrom scratch.\n\nIf you like this app, give it a ⭐ on Github and share it with others. You can\nalso buy me a coffee if you want, I would really appreciate that 💝.\n\n\u003ca href=\"https://www.buymeacoffee.com/sifathossain\" target=\"_blank\"\u003e\n  \u003cimg src=\"https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png\" alt=\"Buy Me A Coffee\" style=\"height: 60px !important;width: 217px !important;\" width=\"217\" \u003e\n\u003c/a\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fh-sifat%2Fproductivity-timer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fh-sifat%2Fproductivity-timer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fh-sifat%2Fproductivity-timer/lists"}