||5 days ago|
|cl||2 weeks ago|
|doc||3 months ago|
|elisp||1 month ago|
|features||2 years ago|
|tests||4 months ago|
|.dir-locals.el||3 months ago|
|.gitignore||3 years ago|
|CHANGELOG.md||3 months ago|
|Makefile||2 months ago|
|README.org||3 months ago|
|TODO.org||3 weeks ago|
|UNLICENSE||2 years ago|
|WTFPL||2 years ago|
|manual.org||5 days ago|
|org-doom-molokai.css||12 months ago|
- How-to Guides
- How to display a prompt when exiting with an active task
- How to load the program using literate-elisp
- How to attach tags to time intervals
- How to attach key-values to time intervals
- How to skip running hooks/attaching tags and key values
- How to open certain files when you start a task
- How to warn yourself about uncommitted changes
- How to display the current time interval in the activity indicator
- How to back up your Chronometrist data
- How to configure Vertico for use with Chronometrist
- User's reference
Chronometrist is a friendly and powerful personal time tracker and analyzer. It has frontends for Emacs and CLIM.
- Made for personal use - by default, your data is stored on your machine and is only accessible to you
- Extremely simple and efficient to use
- Displays useful information about your time usage (including fancy graphs with the
- Support for both mouse and keyboard
- Human errors in tracking can be easily fixed by editing a plain text file
- Hooks to integrate time tracking into your workflow
- No support for concurrent tasks (planned)
timeclock.el (Emacs built-in)
Compared to timeclock.el, Chronometrist
- stores data in an s-expression format rather than a line-based one
- supports attaching tags and arbitrary key-values to time intervals
- has commands to shows useful summaries
- has more hooks
Org time tracking
Chronometrist and Org time tracking seem to be equivalent in terms of capabilities, approaching the same ends through different means.
- Chronometrist doesn't have a mode line indicator at the moment. (planned)
- Chronometrist doesn't have Org's sophisticated querying facilities. (an SQLite backend is planned)
- Org does so many things that keybindings seem to necessarily get longer. Chronometrist has far fewer commands than Org, so most of the keybindings are single keys, without modifiers.
- Chronometrist's UI is cleaner, since the storage is separate from the display. It doesn't show tasks as trees like Org, but it uses tags and key-values to achieve that. Additionally, navigating a flat list takes fewer user operations than navigating a tree.
- Chronometrist data is just s-expressions (plists), and may be easier to parse than a complex text format with numerous use-cases.
Common Lisp port
In March 2022, work began on the long-awaited Common Lisp port of Chronometrist, which aims to create -
- a greater variety of backends (e.g. SQLite)
- a common reusable library for frontends to use,
a greater variety of frontends, such as -
The port was also driven by the desire to have access to Common Lisp's better performance, and features such as namespaces, a de facto standard build system, multithreading, SQLite bindings, a more fully-featured implementation of CLOS and MOP, and type annotations, checking, and inference.
The literate sources for the Common Lisp port may be found in cl/chronometrist.org. Currently, this port can -
import from a plist-group file and export to an SQLite database
(chronometrist:to-file (chronometrist:to-hash-table (make-instance 'chronometrist.plist-group:plist-group-backend :file "/path/to/file.plg")) (make-instance 'chronometrist.sqlite:sqlite-backend) "/path/to/file.sqlite")
- display a (WIP) CLIM GUI -
The Emacs Lisp codebase will probably become an Emacs frontend to a future Common Lisp CLI client.
Chronometrist is written as an Org literate program, which makes it easy to obtain different views of the program source, thanks to tree- and source-block folding, tags, properties, and the
The Org literate program can also be loaded directly using the literate-elisp package, so that all source links (e.g.
describe-function) lead to the Org file. See How to load the program using literate-elisp.
Source code overview
The plist and plist-group backends (collectively known as the s-expression backends)
read a text file containing s-expressions into a hash table, and query that. When the file is changed—whether by the program or the user—they update the hash table and the buffer. The s-expression backends also make use of a plist pretty-printer of their own.
There are also some migration commands.
Extensions exist for -
Contributions and contact
Feedback and MRs are very welcome. 🙂
- /contrapunctus/chronometrist/src/branch/dev/TODO.org has a long list of tasks
- /contrapunctus/chronometrist/src/branch/dev/elisp/chronometrist.org contains all developer-oriented documentation
If you have tried using Chronometrist, I'd love to hear your experiences! Get in touch with the author and other Emacs users in the Emacs channel on the Jabber network - xmpp:email@example.com?join (web chat)
(For help in getting started with Jabber, click here)
I'd like for all software to be liberated - transparent, trustable, and accessible for anyone to use, study, or improve.
I'd like anyone using my software to credit me for the work.
I'd like to receive financial support for my efforts, so I can spend all my time doing what I find meaningful.
But I don't want to make demands or threats (e.g. via legal conditions) to accomplish all that, nor restrict my services to only those who can pay.
The main buffer and the report buffer are copied from the Android application, A Time Tracker
wasamasa, bpalmer, aidalgol, pjb and the rest of #emacs for their tireless help and support
timeclock.el, which we used as a backend in earlier versions
blandest for helping me with the name
fiete and wu-lee for testing and bug reports
- Set up MELPA - https://melpa.org/#/getting-started
M-x package-install RET chronometrist RET
M-x chronometrist to see your projects, the time you spent on them today, which one is active, and the total time clocked today.
Click or hit
chronometrist-toggle-task) on a project to start tracking time for it. If it's already clocked in, it will be clocked out.
You can also hit
<numeric prefix> RET anywhere in the buffer to toggle the corresponding project, e.g.
C-1 RET will toggle the project with index 1.
r to see a weekly report (see
M-x chronometrist-report (or
chronometrist with a prefix argument of 1, or press
r in the
chronometrist buffer) to see a weekly report.
b to look at past weeks, and
f for future weeks.
M-x chronometrist-statistics (or
chronometrist with a prefix argument of 2) to view statistics.
b to look at past time ranges, and
f for future ones.
In the buffers created by the previous three commands, you can press
chronometrist-open-log) to view/edit your
chronometrist-file, which by default is
All of these commands will kill their buffer when run again with the buffer visible, so the keys you bind them to behave as a toggle.
All buffers keep themselves updated via an idle timer - no need to frequently press
g to update.
If you wish you could define time goals for some tasks, and have Chronometrist notify you when you're approaching the goal, completing it, or exceeding it, check out the extension chronometrist-goal.el.
See the Customize groups
chronometrist-report for variables intended to be user-customizable.
How to display a prompt when exiting with an active task
Evaluate or add to your init.el the following -
(add-hook 'kill-emacs-query-functions 'chronometrist-query-stop)
How to load the program using literate-elisp
The literate Org document will automatically
literate-elisp-load itself when opened, if
literate-elisp is installed via
If you want it to be loaded with
literate-elisp-load on Emacs startup, add the following to your init.el -
(add-to-list 'load-path "<directory containing chronometrist.org>") (require 'literate-elisp) ;; or autoload, use-package, ... (literate-elisp-load "chronometrist.org")
How to attach key-values to time intervals
chronometrist-kv-addto one or more of these hooks 3 -
(add-to-list 'chronometrist-after-in-functions 'chronometrist-kv-add) (add-to-list 'chronometrist-before-out-functions 'chronometrist-kv-add) (add-to-list 'chronometrist-after-out-functions 'chronometrist-kv-add)
To exit the prompt, press the key it indicates for quitting - you can then edit the resulting key-values by hand if required. Press
C-c C-c to accept the key-values, or
C-c C-k to cancel.
How to open certain files when you start a task
An idea from the author's own init -
(defun my-start-project (project) (pcase project ("Guitar" (find-file-other-window "~/repertoire.org")) ;; ... )) (add-hook 'chronometrist-before-in-functions 'my-start-project)
How to warn yourself about uncommitted changes
Another one, prompting the user if they have uncommitted changes in a git repository (assuming they use Magit) -
(autoload 'magit-anything-modified-p "magit") (defun my-commit-prompt () "Prompt user if `default-directory' is a dirty Git repository. Return t if the user answers yes, if the repository is clean, or if there is no Git repository. Return nil (and run `magit-status') if the user answers no." (cond ((not (magit-anything-modified-p)) t) ((yes-or-no-p (format "You have uncommitted changes in %S. Really clock out? " default-directory)) t) (t (magit-status) nil))) (add-hook 'chronometrist-before-out-functions 'my-commit-prompt)
How to display the current time interval in the activity indicator
(defun my-activity-indicator () (--> (chronometrist-latest-record (chronometrist-active-backend)) (plist-put it :stop (chronometrist-format-time-iso8601)) (list it) (chronometrist-events-to-durations it) (-reduce #'+ it) (truncate it) (chronometrist-format-duration it))) (setq chronometrist-activity-indicator #'my-activity-indicator)
How to back up your Chronometrist data
Add the following to your init.
Open your Chronometrist file and add
async-backupto a buffer-local
M-x chronometrist-open-log M-x add-file-local-variable-prop-line RET eval RET (add-hook 'after-save-hook #'async-backup nil t) RET
async-backup-locationto set a specific directory for the backups -
(setq async-backup-location "/path/to/backup/dir/")
How to configure Vertico for use with Chronometrist
By default, Vertico uses its own sorting function - for some commands (such as
chronometrist-key-values-unified-prompt) this results in worse suggestions, since Chronometrist sorts suggestions in most-recent-first order.
You can either disable Vertico's sorting entirely -
(setq vertico-sort-function nil)
vertico-multiform to disable sorting for only specific commands -
(use-package vertico-multiform :init (vertico-multiform-mode) :config (setq vertico-multiform-commands '((chronometrist-toggle-task (vertico-sort-function . nil)) (chronometrist-toggle-task-no-hooks (vertico-sort-function . nil)) (chronometrist-key-values-unified-prompt (vertico-sort-function . nil)))))
All variables intended for user customization are listed here. They serve as the public API for this project for the purpose of semantic versioning. Any changes to these which require a user to modify their configuration are considered breaking changes.
McCLIM also has an incomplete ncurses backend - when completed, a CLIM frontend could provide a TUI "for free".
the literate source is also included in MELPA installs, although not loaded through
literate-elisp-load by default, since doing so would interfere with automatic generation of autoloads.
It is possible to use Emacs' built-in backup system to do it, but since it is synchronous, doing so will greatly slow down saving of the Chronometrist file.