Project time management, billing, and invoice generation.
PyTM is installed with uv, a fast, single-binary Python package manager. It takes care of getting a suitable Python version for you too, so there's nothing else to install first.
Install uv (skip this if you already have it):
curl -LsSf https://astral.sh/uv/install.sh | sh
Windows, and other install options, are covered in the uv installation docs.
Install PyTM as a standalone command-line tool:
uv tool install python-pytm
This puts a
pytmcommand on yourPATH, isolated in its own environment, without touching any other Python project on your machine.Prefer not to install anything permanently? Try it in one shot instead:
uvx python-pytm --help
Check the version by typing the following in your terminal.:
pytm --version
To see the available commands type:
pytm --help
- Start a new project with a default name:
pytm project start - Start a new project with the given name or, start an existing project:
pytm project start PROJECT_NAME - Rename a project:
pytm project rename OLD_PROJECT_NAME NEW_NAME - Remove a project:
pytm project remove PROJECT_NAME - Check the status of a project:
pytm project status PROJECT_NAME - Check the list of tasks and duration of a project:
pytm project summary PROJECT_NAME - Finish active project:
pytm project finish - Pause active project:
pytm project pause - Abort active project:
pytm project abort
- Start a new task with a default name in the current active project:
pytm task start - Start a new task with the given name or existing task in the current active project:
pytm task start TASK_NAME - Rename a task of the active project:
pytm task rename OLD_TASK_NAME NEW_NAME - Remove a task:
pytm task remove TASK_NAME - current task's status:
pytm task status - Finish active task:
pytm task finish - Pause active task:
pytm task pause - Abort active task:
pytm task abort - Atomically pause the active task and start/resume another:
pytm task switch TASK_NAME - Correct a task's recorded duration by hand:
pytm task edit TASK_NAME --duration HOURS
- Time logged today, across all projects:
pytm today - Time logged this week, across all projects:
pytm week - The week's start day (default Saturday) is configurable:
pytm config user --week-start monday
Automatically start/switch tasks based on the directory you cd into and the git branch you're on — opt-in, per directory, no auto-detection.
Link a directory (and its subdirectories) to a project:
cd ~/code/my-client-project pytm hook link my-client-project
Enable the hook in your shell rc file (
~/.bashrcor~/.zshrc):eval "$(pytm hook init bash)" # or: pytm hook init zsh
From then on, cd-ing into a linked directory (or any of its subdirectories) starts/resumes its project, and switching git branch there switches to a task named after the branch. Directories that were never linked are left untouched — nothing is inferred automatically.
Manage links:
pytm hook list,pytm hook unlinkSee what a directory would resolve to without applying it:
pytm hook resolve
Turns ~/.pytm into its own git repo and commits every write
automatically. Opt-in and commit-only by default — no remote is
configured or pushed to unless you explicitly ask.
Turn it on:
pytm backup enable
Check status (enabled/disabled, working-tree clean/dirty, last commit, configured remote):
pytm backup status
Point it at a remote you control (a private GitHub/GitLab repo, or any git host, including self-hosted) — this only configures the remote, it doesn't push:
pytm backup remote set git@github.com:you/pytm-backup.git
Push manually when you want an off-site copy. Auto-backup never pushes on its own — it only commits locally:
pytm backup push
Manually flush any pending changes (works whether auto-backup is on or off):
pytm backup commit
Turn it off (history and any configured remote are left untouched):
pytm backup disable
Restoring on a new machine (after a lost/stolen laptop, say) is a
plain git clone — there's no separate pytm backup restore command,
because none is needed:
git clone git@github.com:you/pytm-backup.git ~/.pytm
If you never configured a remote, commit-only backup protects against a
corrupted write or an accidental rm, but not against losing the
machine itself — run pytm backup remote set and pytm backup push
if you want that guarantee too.
Configure project, user and invoice info:
pytm config project PROJECT_NAME pytm config user pytm config invoice
Generate Invoice:
pytm invoice auto PROJECT_NAME pytm invoice manual
Check version:
pytm --version pytm -v
Check summary of all the projects:
pytm summary
For a list of all the available commands try:
pytm --help
This is for working on PyTM itself, not for just using it — if you only want
the pytm command, see Installing PyTM above instead.
Clone this repository and
cdinto it:git clone https://github.com/wasi0013/PyTM.git cd PyTM
Create a virtual environment (uv downloads a matching Python for you if needed) and install dependencies into it:
uv venv uv pip install -r requirements.txt
Run the tests:
uv run pytest
uv runfinds the.venvcreated above automatically, so there's no need to manually activate it first.
- Author - Wasi - (wasi0013).
- License - see the LICENSE file.
- Contributing - see CONTRIBUTING.rst for detail. You can also help by creating issues.
- Version - see the tags on this repository.
- Acknowledgments - bootstrapped using this cookiecutter package.
- Built With ❤️ using Python.




