Skip to content

Features

An overview of what kasl does and how its pieces fit together. Command-level detail lives in Reference; this page is the map.

A background daemon (kasl watch) watches keyboard and mouse input and turns it into workdays, work intervals and pauses - nothing to start or stop by hand.

  • Workday start: begins once continuous activity reaches activity_threshold.
  • Pause detection: an inactivity gap of pause_threshold or more opens a pause; it closes and is kept if it lasted at least min_pause_duration.
  • Background operation: runs as a daemon; kasl watch --foreground runs it in the current terminal with live output instead.
config.json
{
"monitor": {
"min_pause_duration": 20,
"pause_threshold": 60,
"poll_interval": 500,
"activity_threshold": 30,
"min_work_interval": 10
}
}

Minutes for the shortest break that gets recorded and the shortest interval kept in reports; seconds of inactivity before a pause opens and of activity before a workday starts; milliseconds between activity checks. kasl config set monitor.pause_threshold 90 changes one of them - see Configuration for the full reference.

The monitor only sees keyboard and mouse, so an absence spent away from the machine leaves no trace. kasl pauses add puts it on the record:

  • Explicit times: you state when the absence began and how long it lasted - nothing is inferred.
  • --keep: exempts an entry from the duration filter and from being merged into an adjacent detected pause.
  • Conflict prevention: an entry overlapping a pause already on record is rejected rather than silently merged.
Terminal window
kasl pauses add --start 13:00 --minutes 60 --reason "lunch"
kasl pauses add --start 16:20 --minutes 10 --keep
Available Work Time = Workday Length - Long Pauses
Net Work Time = Available Work Time - Short Pauses
Productivity = Net Work Time / Available Work Time * 100

Long pauses - detected absences at or above min_pause_duration, plus every manual pause - leave the denominator entirely; short pauses lower the numerator only. kasl report --send refuses to submit a day when productivity falls below min_productivity_threshold, and kasl report warns once enough of the expected workday (min_workday_fraction_before_suggest) has passed while productivity is still low.

config.json
{
"productivity": {
"min_productivity_threshold": 75.0,
"workday_hours": 8.0,
"min_workday_fraction_before_suggest": 0.5
}
}

Full task lifecycle, tags, and templates:

Terminal window
kasl task add --name "Review PR" --comment "Security review" --completeness 0 --tags "urgent,backend"
kasl task list --tag "urgent"
kasl task edit 1
kasl task remove --today
kasl template add --name "daily-standup"
kasl task add --template "daily-standup"
kasl tag add "urgent" --color "red"

Completeness is a 0-100 percentage: 0 means not started, 100 means done, anything between is in progress.

Terminal window
kasl report # today
kasl report --last # yesterday
kasl report --send # submit to the configured reporting API
kasl sum # this month's totals and daily breakdown
kasl report --month # submit the monthly summary

A report shows work intervals, pauses, tasks, and productivity for one day; sum aggregates the current month - daily hours, an average, and rest-day integration from the company calendar. Both filter out intervals shorter than min_work_interval before display and before submission, so a few minutes of stray activity around a break does not clutter the numbers - and a day’s hours in the month are exactly its report’s total.

Terminal window
kasl export report --format csv
kasl export tasks --format json
kasl export summary --format excel
kasl export all --format json # report + tasks + summary

Formats: CSV, pretty-printed JSON, or Excel (one worksheet per export, with headers and autofit).

Exports are files; --json is the same data on stdout, for a status bar or a script that asks a question and goes on:

Terminal window
kasl report --json | jq '.work_seconds'
kasl inbox list --json | jq -r '.issues[0].key'

Every command that prints data takes it, and every document keeps the same conventions - an object at the top, every key present, local moments, durations in seconds. --plain keeps the human output but drops colour, emoji and table frames, for logs and grep. See kasl in scripts and CI.

Both feed kasl task find, which imports Jira issues resolved today and, from the GitLab plugin, the commits you pushed today. Jira is configured through kasl setup; GitLab is a plugin that ships with kasl and is set up with kasl plugin setup gitlab.

  • GitLab: the kasl-plugin-gitlab plugin. It authenticates with a personal access token kept in the OS keyring, offers your pushed commits to task find, and feeds your assigned issues and merge requests to the inbox. See Working with the GitLab inbox.
  • Jira: authenticates with a session cookie obtained from login credentials; supports custom fields (inbox.custom_fields) so extra Jira fields can be pulled into the inbox view and used for sorting (sort_by_field).

kasl inbox keeps a separate, persistent list of assigned open Jira issues - synced, ranked, and actionable independently of task find:

Terminal window
kasl inbox sync
kasl inbox list
kasl inbox take ISSUE-123

kasl setup configures the corporate reporting endpoint - the si block - used by kasl report --send for the day and kasl report --month for the month. Its password goes to the OS keyring, like Jira’s; the config file holds only the login and the addresses.

What a submission contains is readable before it is made: kasl report --send --show prints the multipart form field by field and posts nothing. For the other channel, kasl server manifest reads what the team server stores about you from the server itself.

Terminal window
kasl autostart enable
kasl autostart status
kasl autostart disable
  • Windows: Task Scheduler, falling back to a HKCU\...\Run registry entry if that fails.
  • macOS: a LaunchAgent (~/Library/LaunchAgents/com.lacodda.kasl.plist).
  • Linux: a systemd user unit.
Terminal window
kasl watch # start the daemon
kasl watch --foreground
kasl watch --stop

kasl keeps no log file; diagnostics go through tracing to stderr, off by default:

Terminal window
KASL_DEBUG=1 kasl watch --foreground # shorthand for RUST_LOG=kasl=debug
RUST_LOG=kasl=trace kasl watch --foreground

See Troubleshooting for how to use this when something goes wrong.

  • Jira and SiServer passwords live in the OS keyring - Credential Manager on Windows, Keychain on macOS, Secret Service on Linux - under the service name lacodda.kasl. Nothing is encrypted with a key compiled into the binary; that scheme was removed in 1.0 (see ADR 0001).
  • The GitLab plugin’s token lives in the OS keyring as plugin.gitlab.token. The reporting server’s auth_token is stored as plain text in config.json, because it is read by the unattended background daemon and has no interactive prompt to fall back to. Keep the data directory private.

kasl builds and runs on Windows 10+, macOS, and Linux, with no runtime dependencies beyond the OS keyring backend. Official release binaries target:

  • x86_64-pc-windows-msvc
  • x86_64-unknown-linux-gnu
  • aarch64-apple-darwin (Apple Silicon)

Other platforms and architectures build from source via cargo install kasl-cli.