Skip to content

Repository files navigation

PyTM - Logo

PyTM - A CLI time tracker for projects with invoice generation

Goals

Project time management, billing, and invoice generation.

Preview

PyTM - Preview

Screenshots

PyTM - Screenshot PyTM - Invoice

Installing PyTM

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 pytm command on your PATH, 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

Basic commands

To see the available commands type:

pytm --help

Commands related to projects

  • 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

Commands related to Task

  • 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 digests

  • 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

Ambient tracking (shell hooks)

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 (~/.bashrc or ~/.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 unlink

  • See what a directory would resolve to without applying it: pytm hook resolve

Backup (git-based, local by default)

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.

Others

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

Running the tests

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 cd into 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 run finds the .venv created above automatically, so there's no need to manually activate it first.

Notes

About

A Python 🐍 3️⃣ CLI time tracker with invoice generation

Topics

Resources

Code of conduct

Contributing

Stars

17 stars

Watchers

0 watching

Forks

Releases

Used by

Contributors

Languages