kasl-cli 1.8.1

Work activity tracker CLI: automatic workday and break detection, task management with Jira/GitLab integration, productivity reports and exports
Documentation

Your workday, recorded while you work: kasl watches activity in the background, turns it into intervals, pauses and tasks, and files the report for you.

Why

Time sheets get filled in from memory, at the end of the day, when the day is already gone. You reconstruct when you started, guess how long lunch was, and try to recall what that morning hour went into.

kasl records it as it happens. A background daemon watches keyboard and mouse activity, decides when the workday started, notices the breaks, and keeps the intervals. Tasks come from your own commits and issues rather than from memory. At the end you look at the day and send it, instead of inventing it.

A day in the life

Start the daemon once - or have it start itself at login - and forget about it:

$ kasl watch
Watcher started in the background (PID: 24180).

Later, note what you worked on. Candidates come from today's GitLab commits and resolved Jira issues, so most of this is picking from a list rather than typing:

$ kasl task find
Found: 1 incomplete, 2 jira, 4 gitlab
? Select tasks to import ›
❯ ◉ ↻ PROJ-419 Draft migration for protected pauses — 60%
  ◉ ◉ PROJ-412 Fix session timeout on the settings page
  ◯ ● Review PR #318: pause merging (a1c9f42)

Look at the day. The intervals, the breaks and the productivity figure were recorded while you worked:

$ kasl report
Report for August 8, 2026

+--------------+-------+-------+----------+
| ID           | START | END   | DURATION |
+--------------+-------+-------+----------+
| 1            | 09:12 | 13:30 | 04:18    |
| 2            | 14:18 | 16:02 | 01:44    |
| 3            | 16:29 | 18:04 | 01:35    |
|              |       |       |          |
| TOTAL        |       |       | 07:37    |
| PRODUCTIVITY |       |       | 96.1%    |
+--------------+-------+-------+----------+

Tasks:

+---+----+---------------------------------------------------+------------------+------+
| # | ID | NAME                                              | COMMENT          | DONE |
+---+----+---------------------------------------------------+------------------+------+
| 1 | 1  | PROJ-412 Fix session timeout on the settings page | stale cookie jar | 100% |
| 2 | 2  | Review PR #318: pause merging                     |                  | 100% |
| 3 | 3  | PROJ-419 Draft migration for protected pauses     | backfill pending | 60%  |
+---+----+---------------------------------------------------+------------------+------+

The monitor only sees the keyboard and the mouse, so an hour in a meeting room leaves no trace. Put it on the record yourself:

$ kasl pauses add --start 15:00 --minutes 40 --reason "offsite meeting"
Pause recorded: 15:00 - 15:40 (40 minutes)

Send the day when it is done:

$ kasl report --send
Your report dated August 8, 2026 has been successfully submitted
Wait for a message to your email address

And watch the month accumulate:

$ kasl sum
Working hours for August, 2026

+------------+-------+--------------+
| DATE       | HOURS | PRODUCTIVITY |
+------------+-------+--------------+
| 2026-08-07 | 08:04 | 94.7%        |
| 2026-08-08 | 07:37 | 96.1%        |
|            |       |              |
| TOTAL      | 15:41 |              |
| AVERAGE    | 07:50 |              |
+------------+-------+--------------+

Monthly work productivity: 95.4%

What you get

  • A workday that records itself. The daemon starts the day on sustained activity rather than the first stray keypress, and closes pauses when you come back. Brief interruptions and real absences count differently, so the productivity figure means something.

  • Tasks you do not have to remember. Today's GitLab commits and resolved Jira issues are offered as candidates and deduplicated against what you already logged. A Jira inbox polls assigned issues in the background, raises a desktop notification when something new lands on you or an issue changes, and drops issues that were closed or reassigned instead of letting the list go stale. Taking one into your tasks keeps the link: the task remembers the issue, and the issue shows as taken rather than vanishing.

  • Honest numbers. kasl records absences; it does not invent them. When a day falls below your reporting threshold it says so - and if the cause is a break the monitor missed, you add that break with its real time.

  • Reports where they need to go. One command submits the day, or the month, to your corporate API. Exports to CSV, JSON and Excel, including the hourly breakdown that time sheets tend to ask for.

  • Passwords in the OS keyring - Windows Credential Manager, macOS Keychain, Linux Secret Service. Nothing is encrypted with a key that ships inside the binary. API tokens, which are not prompted for, stay in the config file.

  • Nothing that hangs. Every prompt checks for a terminal first, so kasl under cron, under CI or under the daemon fails with a message naming the flag you needed instead of waiting forever for an answer nobody can give.

  • A team server, when there is one. kasl server connect points this machine at a self-hosted kasl-server with a token your administrator issues, and says whose token it is before storing anything - a token pasted from the wrong window would otherwise file your days under a colleague's name. kasl server push then sends a day whole, timestamps carrying this machine's UTC offset so days from different countries can be compared at all; the last upload wins, so re-sending a corrected day corrects it there and sending an unchanged one costs nothing. The token goes in the OS keyring; the config file records the address only. Connecting is optional and changes nothing locally.

  • A short alias. ka is installed alongside kasl by every channel as a link to the same binary, so both names answer with the same code and an update can never leave one behind. Completions are available for bash, zsh, fish, PowerShell and elvish.

Install

With npm:

npm i -g kasl-cli

With cargo:

cargo install kasl-cli

One-line installers. Windows (PowerShell):

irm https://raw.githubusercontent.com/lacodda/kasl/main/tools/install.ps1 | iex

macOS / Linux:

curl -fsSL https://raw.githubusercontent.com/lacodda/kasl/main/tools/install.sh | sh

On Windows use the PowerShell line above: install.sh carries the macOS and Linux builds only, and run from Git Bash it stops with a pointer back here.

Binary releases - grab the archive for your platform from Releases (Windows x86_64, Linux x86_64, macOS arm64), unpack and put kasl on your PATH. The archive carries one binary; ka is a link the installers create beside it, and you can make one yourself the same way.

Both installers take the newest release by default; set KASL_VERSION to a tag to pin one, KASL_INSTALL_DIR to choose where the binary lands, and KASL_NO_ALIAS=1 to skip the ka alias.

Quick start

kasl setup                # first-run wizard: monitor settings, integrations, credentials

kasl watch                # start monitoring in the background

kasl autostart enable     # and have it start at login

kasl task find            # pick up today's commits and issues

kasl report               # see the day

kasl report --send        # file it

Data lives in the platform user data directory: %LOCALAPPDATA%\lacodda\kasl on Windows, ~/Library/Application Support/lacodda/kasl on macOS, ~/.local/share/lacodda/kasl on Linux.

Full command reference and concepts: kasl.lacodda.com.

Status

Everything above works today, on Windows, macOS and Linux. What is next:

  • Finishing the inbox loop - triage in one pass, snooze with a return date, and toasts you can act on without opening a terminal
  • Scriptable output - --json and NO_COLOR/--plain, then kasl status for status bars and kasl standup for a markdown summary
  • Doctor and notifications - kasl doctor with --fix, a nudge when a break is due or the day is still open, quiet hours
  • Smarter time - overnight tracking and a configurable day boundary, so work past midnight belongs to the right day
  • A server you can be offline from - a queue that holds undelivered days through a week without a network and sends the backlog in one request when it returns
  • Beyond the terminal - a live TUI, a companion in the tray, and kasl-plugin-* subprocesses with Jira and GitLab behind the same interface

Released versions and what landed in each: CHANGELOG.

Documentation

The documentation site (Astro Starlight) lives in docs/; architecture decision records are in docs/adr/.

License

MIT (c) Kirill Lakhtachev