A modern Python-based Time Tracking TUI (Terminal User Interface) application built with Textual for Ubuntu Wayland systems.
- Real-time Task Tracking: Start and stop multiple tasks concurrently
- Daily Reset: All tracking resets at midnight (00:00)
- Manual Entry: Add work sessions with custom dates and durations
- Session Management: View, edit, and delete individual work sessions
- Weekly View: See your work distribution across the week at a glance
- Auto-save: Automatic data persistence every 60 seconds
- JSON Storage: Human-editable JSON format for work data
- API Key Validation: Requires a valid 16-character
APP_API_KEYin.env - No Root Required: Runs without sudo privileges
- Graceful Exit: Properly saves data before shutdown
- Automated Screenshots: Captures screen at random intervals (4-8 minutes)
- Wayland Compatible: Uses
grimcommand-line utility for Wayland - Smart Timing: Only takes screenshots when tasks are actively running
- Organized Storage: Screenshots saved as
DD-MM-YYYY/screenshot_HH-MM-SS.png
- Python 3.10+
- Ubuntu with Wayland display server
grimutility (for Wayland screenshot capture)
- Clone/Navigate to Project
cd /path/to/tt- Create Virtual Environment (if not already done)
python3 -m venv venv
source venv/bin/activate- Install Dependencies
pip install textual python-dotenv
apt install grim # For Wayland screenshot support- Configure API Key
Create or update
.envfile in the project root:
APP_API_KEY=YourExactly16CharacterKeyHere
The API key must be exactly 16 characters. If missing or invalid, the app will exit with "Unauthorized Access".
source venv/bin/activate
python main.py| Key | Action |
|---|---|
T |
Add a new task |
S |
Start/Stop task tracking |
A |
Manually add a work session |
D |
Delete a session |
← |
Navigate to previous week |
→ |
Navigate to next week |
Esc |
Close dialogs/cancel actions |
Enter |
Confirm selections in dialogs |
- Press
Tto open the new task dialog - Enter a task name (e.g., "Project Alpha", "Code Review")
- Press Enter or click "Add" to create the task
-
When no tasks are running: Shows a list of available tasks to start
- Default selection: Last used task (if available)
- Press Enter or click task name to start
-
When tasks are running: Shows active tasks to stop
- Select a task and press Enter to stop it
Add a work session retroactively:
- Press
Ato open the manual add dialog - Enter date (default: today, format DD-MM-YYYY)
- Enter hours and minutes worked
- Enter the task name
- Click "Add" to save
Example: Add 2.5 hours to "Research" for today
- Date: 23-12-2025
- Hours: 2
- Minutes: 30
- Task: Research
Remove a recorded session:
- Press
Dto view today's sessions - Select the session to delete
- Press Enter to confirm deletion
←: Move to the previous week→: Move to the next week- View displays all tasks and total hours per day
The application shows three main sections:
- Header Bar: Quick reference for available keybinds
- Weekly Table:
- Columns: Mon-Sun with dates
- Rows: All your tasks
- Cells: Total time spent on each task per day
- Footer: Daily and weekly totals
- Daily Breakdown:
- All sessions recorded today
- Shows task name, start time, end time, and duration
- Actively running tasks highlighted in green
All data is stored in work_data.json in the project root:
{
"tasks": {
"Project A": {
"sessions": [
{
"start": "2025-12-23T09:00:00",
"end": "2025-12-23T11:30:00",
"duration_seconds": 9000
}
]
}
},
"last_used_task": "Project A"
}- Thread-safe: Uses locks to prevent data corruption
- Auto-save: Saves every 60 seconds automatically
- Human-readable: JSON format allows manual editing
- Recovery-friendly: Can restart app and resume tracking
Screenshots are automatically captured while tasks are running:
screenshots/
├── 23-12-2025/
│ ├── screenshot_09-15-30.png
│ ├── screenshot_09-22-45.png
│ └── screenshot_09-31-12.png
├── 24-12-2025/
│ └── screenshot_14-05-22.png
- Interval: Random between 4-8 minutes
- Condition: Only when at least one task is active
- Frequency: Interval resets after each screenshot
Requires grim command-line utility:
sudo apt install grim # Debian/UbuntuIf grim is not available, screenshots silently fail (no data loss).
tt/
├── main.py # Application entry point
├── .env # Environment configuration (API key)
├── work_data.json # Work session data (auto-generated)
├── requirements.txt # Python dependencies
├── README.md # This file
├── src/
│ ├── config.py # Configuration and validation
│ ├── storage.py # JSON data persistence layer
│ ├── tracker.py # Core time tracking logic
│ ├── screenshots.py # Automated screenshot thread
│ └── ui.py # Textual TUI application
├── screenshots/ # Captured screenshots (auto-generated)
└── venv/ # Python virtual environment
- config.py: API key validation, file path management
- storage.py: Thread-safe JSON operations, data model
- tracker.py: High-level time tracking interface
- screenshots.py: Background screenshot thread with Wayland support
- ui.py: Textual widgets, screens, and event handlers
- main.py: App initialization, threading, lifecycle management
- Check
.envfile exists in project root - Verify
APP_API_KEYis exactly 16 characters - Ensure no extra spaces or newlines
- Verify
grimis installed:which grim - Check that at least one task is currently active
- Verify
screenshots/directory is writable
- Check file permissions on
work_data.json - Verify disk space is available
- Check that the app didn't crash unexpectedly
- Ensure terminal width is at least 80 characters
- Update Textual library:
pip install --upgrade textual - Try clearing terminal:
clearbefore running
- Main thread: Textual event loop
- Auto-save thread: Saves data every 60 seconds
- Screenshot thread: Runs independently every 4-8 minutes
- Thread safety: All data access protected with locks
- Sessions with both start and end times:
end - start - Active sessions (no end time): Shown as "ACTIVE" in display
- Manual sessions: User-specified hours + minutes
- All times stored in local system time
- No timezone conversion applied
- Midnight (00:00) local time = day reset
# Verify Python syntax
python -m py_compile main.py src/*.py
# Test API key validation
python -c "
import sys
sys.path.insert(0, 'src')
from config import validate_api_key
validate_api_key()
print('API key valid')
"
# Test tracker functionality
python -c "
import sys
sys.path.insert(0, 'src')
from tracker import TimeTracker
tracker = TimeTracker()
tracker.add_task('Test')
tracker.start_task('Test')
tracker.stop_task('Test')
print('Tracker working')
"- Python 3.10+ compatible
- Type hints for clarity
- Docstrings for all public methods
- Thread-safe operations with locks
[Add your license here]
For issues or questions:
- Check the Troubleshooting section above
- Review the project files for more details
- Examine
work_data.jsonfor data integrity
Potential improvements:
- Task categories/tags
- Time estimates and progress tracking
- Export to CSV/PDF reports
- Dark/light theme toggle
- Keyboard-driven UI refinements
- Database backend (SQLite) option
- Cloud sync capability