User guide¶
Installation¶
To install Taxi, follow the steps below specific to your system.
OS X, Windows, generic Linux¶
Make sure you have Python at least 3.7 installed (by running python3
--version
), then use python3 -m pip
to install taxi in your user directory
(you should not use sudo or run this command as root):
$ python3 -m pip install --user taxi
You’ll probably want to install a backend too, that will allow you to push your timesheets. To install the Zebra backend for example (again, no sudo or root user needed):
$ python3 -m pip install --user taxi-zebra
To upgrade Taxi and the Zebra plugin, run python3 -m pip install --user --upgrade taxi taxi-zebra
Debian & Ubuntu¶
Run the following commands to add the Taxi repository and install it along with the Zebra backend:
sudo apt install apt-transport-https
wget 'https://taxi-packages.liip.ch/taxi-packages.liip.ch.key' -O - | sudo apt-key add
echo "deb [arch=amd64] https://taxi-packages.liip.ch/ unstable-ci main" | sudo tee /etc/apt/sources.list.d/taxi.list
sudo apt update
sudo apt install taxi taxi-backend-zebra
NixOS¶
If you’re running NixOS, you can then install it declaratively by adding it to
your /etc/nixos/configuration.nix
file and then running nixos-rebuild
switch
:
let
taxi = import <taxi>;
in
environment.systemPackages = [
# ...
taxi.taxi
]
Nix¶
Create a flake.nix
file in a directory with the following contents:
{
inputs.taxi.url = "github:sephii/taxi";
inputs.flake-utils.url = "github:numtide/flake-utils";
outputs = { self, nixpkgs, taxi, flake-utils }:
flake-utils.lib.eachDefaultSystem (system: {
packages.taxi = taxi.defaultPackage.${system}.withPlugins
(plugins: [ plugins.clockify plugins.zebra ]);
});
}
In this example, the clockify and zebra plugins are enabled. Feel free to adapt
this file with the plugins you want to enable. You’ll find a list of available
plugins in the ``availablePlugins` attribute of the pkgs.nix
file <https://github.com/sephii/taxi/blob/main/pkgs.nix#L121>`_.
Make sure your flake.nix
and flake.lock
files exist and are version controlled:
git init
git add flake.nix
nix flake lock
git add flake.lock
git commit -m "Init taxi"
Add the flake to your registry:
nix registry add taxi /path/to/your/flake/dir
Now you can finally install the package:
nix profile install taxi#taxi
Running the taxi
command should now work!
To upgrade taxi, cd
to the directory where you created the flake and run:
nix flake lock --update-input taxi
git add flake.nix flake.lock
git commit -m "Update taxi"
nix registry pin taxi
nix profile install taxi#taxi
NixOS¶
Use the overlay in taxi.overlay
:
{
inputs.taxi.url = "github:sephii/taxi";
outputs = attrs@{ nixpkgs, taxi, ... }: let
pkgs = import nixpkgs {
overlays = [ taxi.overlay ];
};
in {
nixosConfigurations.myConfig = nixpkgs.lib.nixosSystem {
modules = [
({ pkgs, ... }: { environment.systemPackages = [ pkgs.taxi-cli.withPlugins (plugins: [ plugins.clockify plugins.zebra ]) ]; })
];
}
}
}
Adapt the configuration depending on the plugins you need. You’ll find a list of
available plugins in the ``availablePlugins` attribute of the pkgs.nix
file <https://github.com/sephii/taxi/blob/main/pkgs.nix#L121>`_.
Common installation issues¶
taxi: command not found¶
This usually means the Python user binary path (where the taxi
binary is
installed) is not in your PATH
environment variable.
Run the following command to identify the Python user binary path:
$ python3 -c "import os, site; print(os.path.join(site.getuserbase(), 'bin'))"
/home/sephi/.local/bin
Add this directory to your PATH
environment variable, for example by
following this guide.
python3: command not found¶
Run the following command:
$ python --version
Python 3.8.5
Check that the version is at least 3.7. If that’s the case, replace python3
by python
when running commands. If that’s not the case, install Python 3.
First steps with Taxi¶
Once Taxi is installed, you’ll probably want to fetch the projects list from your backend:
taxi update
Since this is the first time you run Taxi, you’ll get asked a few questions:
Welcome to Taxi!
================
It looks like this is the first time you run Taxi. You will need a
configuration file (~/.config/taxi/taxirc) in order to proceed.
Please answer a few questions to create your configuration file.
Backend you want to use (choices are dummy, zebra): zebra
Username or token: b4b8123f4addb27ad0eb0b2b0a0ae81730af96b8
Password (leave empty if you're using a token) []:
Editor command to edit your timesheets [vim]:
Hostname of the backend (eg. timesheets.example.com): zebra.example.com
Taxi is now ready to use! Let’s start by recording the time we spent installing Taxi:
taxi edit
Note
If you didn’t choose the correct editor when running Taxi for the first time you might get into an editor called vim at this point. To exit it, type :q!. Then to manually set the editor Taxi should use, open your Taxi configuration file (by using the command taxi config), and change the value of the editor setting to the editor you want. If you’re using Linux, you might put gedit. If you’re using OS X, you might put open -a TextEdit.
Your editor will pop up and you’ll see the current date has been automatically added for you. Let’s add an entry so your file looks something like that:
09/05/2016
intro 10:15-10:30 Install Taxi
An entry consists of 3 parts:
- An alias (intro)
- A duration (10:15-10:30)
- A description (Install Taxi)
Aliases allow you to map meaningful names to activity ids. At that point you’ll probably don’t really know what alias to use, so let’s just try that for now and we’ll see what Taxi has to say about it.
Save the file and close your editor. You should see Taxi displaying a summary of what you did:
Staging changes :
Monday 09 may
intro (inexistent alias) 0.25 Install Taxi
Did you mean one of the following: _internal, _infra, _interview?
0.25
Total 0.25
Use `taxi ci` to commit staging changes to the server
Note
Depending on the editor you’re using you might not see anything happening when you close the file and you might need to run taxi status to get this output.
Whoops! It looks like the alias we used doesn’t exist. Taxi tried to help us by
suggesting similar matches among available aliases, and actually _internal
looks like the correct alias to use. We could have searched for aliases that
look like internal with the following command: taxi alias list internal
.
Note
This alias _internal exists because we ran taxi update before, which
synchronized the aliases database from the remote backend. You can also use
custom aliases that will not be shared with the remote backend. Refer to
the alias command help by running taxi alias --help
.
Let’s edit our file once again and fix that:
taxi edit
Replace the intro alias with _internal:
09/05/2016
_internal 10:15-10:30 Install Taxi
Close your editor and run taxi status if needed and check the output:
Staging changes :
Monday 09 may
_internal (7/16, liip) 0.25 Install Taxi
0.25
Total 0.25
Use `taxi ci` to commit staging changes to the server
You can now see the _internal alias has been recognized as mapped to project id 7, activity id 16 on the liip backend. If you’re satisfied with that, you can now push this to the remote server (ci is a shorthand for commit, which is equivalent):
taxi ci
Searching for aliases¶
The whole point of Taxi is to record your time spend on activities, but how do you know which activities you can use? As explained in the introduction, activities are fetched with the update command. To see the available aliases, use the alias list command:
$> taxi alias list
[dummy] my_alias -> 2000/11 (My project, my activity)
The part that appears in brackets is the backend that will be used to push the entries when using the commit command. The information on the right of the arrow is the “mapping”, that is a project id and an activity id, whose names are in parentheses.
You can search for a specific alias by adding a search string to the alias list command:
$> taxi alias list my_awesome_alias
You can also limit the results to aliases you have already used in your timesheets with the –used option:
$> taxi alias list --used
Filtering entries¶
The status and commit options support the –since, –until and –today/–not-today options that allow you to specify which entries should be included in the command. For example let’s say you entered entries for yesterday and today (Wednesday 21 june):
$> taxi status
Staging changes :
Tuesday 20 june
_internal 0.25 Install Taxi
0.25
Wednesday 21 june
_internal 1.00 First steps with Taxi
1.00
Total 1.25
Use `taxi ci` to commit staging changes to the server
And you only want to commit yesterday’s entry. You can use the –not-today option that will ignore today’s entries. Since you can use this option both with the status and commit command, you can review what you’re about to commit with the status command:
$> taxi status --not-today
Staging changes :
Tuesday 20 june
_internal 0.25 Install Taxi
0.25
Total 0.25
Use `taxi ci` to commit staging changes to the server
If you wanted to only include today’s entries, you could use the –since option. Both –since and –until support the following notations:
- Relative: 5 days ago, 2 weeks ago, 1 month ago, 1 year ago, today, yesterday
- Absolute: 21.05.2017
Back to our entries, let’s filter yesterday’s entry:
$> taxi status --since=today
Staging changes :
Wednesday 21 june
_internal 1.00 First steps with Taxi
1.00
Total 1.00
Use `taxi ci` to commit staging changes to the server
In fact, the –today option is just a shortcut for –since=today –until=today.
Ignored entries¶
You’ll sometimes have entries for which you’re not sure which alias you should
use and that shouldn’t be pushed until you have a confirmation from someone
else. Simply prefix the entry line with ? and the entry will be ignored. If we
run the edit
command and add a question mark to our pingpong
alias like
so:
23/02/2015
? pingpong 09:00-10:30 Play ping-pong
The output becomes:
Staging changes :
Monday 23 february
pingpong (ignored) 1.50 Play ping-pong
1.50
Total 1.50
Use `taxi ci` to commit staging changes to the server
Entry continuation¶
Having entries that follow each other, eg. 10:00-11:00, then 11:00-13:00, etc is a common pattern. That’s why you can skip the start time of an entry if the previous entry has an end time. The previous example would become (note that spaces don’t matter, you don’t need to align them):
23/02/2015
pingpong 09:00-10:30 Play ping-pong
taxi -12:00 Write documentation
You can also chain them:
23/02/2015
pingpong 09:00-10:30 Play ping-pong
taxi -12:00 Write documentation
internal -13:00 Debug coffee machine
Internal aliases¶
Some people like to timesheet everything they do: lunch, ping-pong games, going to the restroom… anyway, if you’re that kind of people you probably don’t want these entries to be pushed. To achieve that, start by adding a dummy backend to your configuration file (to open it, run taxi config):
[backends]
internal = dummy://
Then to add an internal alias, either add it in the corresponding section in your configuration file:
[internal_aliases]
_pingpong
_lunch
_shit
Or use the alias
command:
taxi alias add -b internal _pingpong ""
Getting help¶
Use taxi <command> --help
to get help on any Taxi command.
Upgrading Taxi¶
To upgrade Taxi, run python3 -m pip install --upgrade taxi
. If you have any plugins,
you’ll also need to manually upgrade them, by running for example python3 -m pip
install --upgrade taxi-zebra
.
Timesheet syntax¶
Taxi uses a simple syntax for timesheets, which are composed of dates and
entries. If you used the edit
command, you already saw the dates. A date is
a string that can have one of the following formats:
- dd/mm/yyyy
- dd/mm/yy
- yyyy/mm/dd
Actually the separator can be any special character. You can control the format Taxi uses when automatically inserting dates in your entries file with the date_format configuration option.
Timesheets also contain comments, which are denoted by the #
character.
Any line starting with #
will be ignored.
Entries are the entity that allow you to record the time spent an various activities. The basic syntax is:
alias duration description
alias
can be any string matching a mapping defined either by your
configuration, or a shared alias. If an alias is not found in the configured
aliases, a list of suggestions will be given and the alias will be ignored when
pushing entries.
duration
can either be a time range or a duration in hours. If it’s a time
range, it should be in the format start-end
, where start
can be left
blank if the previous entry also used a time range and had a time defined, and
end
can be ?
if the end time is not known yet, leading to the entry
being ignored. Each part of the range should have the format HH:mm
, or
HHmm
. If duration
is a duration, it should just be a number, eg. 2 for
2 hours, or 1.75 for 1 hour and 45 minutes.
description
can be any text but cannot be left blank.
Backends¶
Note
The plugin command is available starting from Taxi 4.2.
Backends are provided through Taxi plugins. To install (or upgrade) a plugin, use the plugin install command:
taxi plugin install zebra
This will fetch and install the backend plugin. Once installed, you’ll still need to tell Taxi to use it. This is explained in the next section.
You can also see which plugins are installed with plugin list:
$> taxi plugin list
zebra (1.2.0)
Note
This is only valid if you installed Taxi with the install script, that
transparently deals with installing Taxi in an isolated environment. If you
installed it differently (eg. by using a Debian package or by using pip),
either install the corresponding Debian package for the backend you want to
use or use pip (eg. pip install taxi-zebra
).
Configuration¶
You can open your configuration file using the command taxi config.
The configuration file uses the XDG user directories specification. This means the location is the following:
- Linux:
~/.config/taxi/taxirc
- OS X:
~/Library/Application Support/taxi/taxirc
- Windows:
%LOCALAPPDATA%\sephii\taxi\taxirc
orC:\Users\<User>\AppData\Local\sephii\taxi\taxirc
You can see the location of the configuration file used by running taxi in verbose mode, for example:
$ taxi -vvv status
DEBUG:root:Using configuration file in /home/sephi/.config/taxi/taxirc
...
The configuration file has a section named backends
that allows you to
define the active backends and the credentials you want to use. The syntax of
the backends part is:
[backends]
default = <backend_name>://<user>:<password>@<host>:<port><path><options>
Here a backend named default is defined. The backend_name
is the adapter
this backend will use. You’ll find this name in the specific backend package
documentation. The backend_name
is the only mandatory part, as some
backends won’t care about the user
, password
, or other configuration
options.
The name of each backend should be unique, and it will be used when defining
aliases. Each backend will have a section named [backend_name_aliases]
and
[backend_name_shared_aliases]
, where backend_name is the name of the
backend, each containing the user-defined aliases, and the automatic aliases
fetched with the update
command.
Note
If you have any special character in your password, make sure it is URL-encoded, as Taxi won’t be able to correctly parse the URI otherwise. You can use the following snippet to encode your password:
>>> import urllib
>>> urllib.quote('my_password', safe='')
On Python 3:
>>> from urllib import parse
>>> parse.quote('my_password', safe='')
Configuration options¶
auto_add¶
Default: auto
This specifies where the new entries will be inserted when you use start and edit commands. Possible values are auto (automatic detection based on your current entries), bottom (values are added to the end of the file), or top (values are added to the top of the file) or no (no auto add for the edit command).
auto_fill_days¶
Default: 0,1,2,3,4
When running the edit command, Taxi will add all the dates that are not
present in your entries file until the current date if they match any day
present in auto_fill_days
(0 is Monday, 6 is Sunday). You must have
auto_add set to something else than no for this option to take
effect.
date_format¶
Default: %d/%m/%Y
This is the format of the dates that’ll be automatically inserted in your entries file(s), for example when using the start and edit commands. You can use the same date placeholders as for the file option.
editor¶
When running the edit command, your editor command will be deducted from your environment but if you want to use a custom command you can set it here.
file¶
Default: ~/zebra/%Y/%m.tks
The path of your entries file. You’re free to use a single file to store all
your entries but you’re strongly encouraged to use date placeholders here. The
following will expand to ~/zebra/2011/11.tks
if you’re in November 2011.
You can use any datetime format code defined in the strftime documentation down to a resolution of a day (hours, minutes and seconds format codes are not supported because they make little sense).
regroup_entries¶
Default: true
If set to false, similar entries (ie. entries on the same date that are on the same alias and have the same description) won’t be regrouped.
Note
This setting is available starting from Taxi 4.1
nb_previous_files¶
Default: 1
Defines the number of previous timesheet files Taxi should try to parse. This allows you to make sure you don’t forget hours in files from previous months when starting a new month.
This option only makes sense if you’re using date placeholders in file.
round_entries¶
Default: 15
Number of minutes to round entries duration to when using the stop command. For example, if you start working on a task at 10:02 and you run taxi stop at 10:10 with the default round_entries setting you’ll get 10:02-10:17. Note that entries are always rounded up, never down.
Flags characters customization¶
By default Taxi uses the = character for pushed entries and ? for ignored entries. You can customize them in the [flags] section of the configuration file. Note that using # as a flag character will make any flagged entry interpreted as a comment and won’t be parsed by Taxi. Example of using custom characters for the ignored and pushed flags:
[flags]
ignored = !
pushed = @