A lightweight, table-based project tracking system with automated token usage and time tracking from git history.
This project is inspired by artist Tom Sachs' studio practice of knolling — the act of arranging objects at 90-degree angles and tidying all surfaces after finishing work. In his seminal video Ten Bullets, Sachs outlines his studio's operating principles, with Bullet #8 being "Always Be Knolling" (ABK).
Just as knolling resets a physical workspace to be shipshape and ready for the next session, this tool "knolls" your digital project state — logging time, tracking costs, organizing metadata, and preparing your workspace for the next work session. It's the practice of tidying up your project tracking at the end of each session so you can start fresh next time.
"Knolling is the process of arranging like objects in parallel or 90-degree angles as a method of organizing." — Tom Sachs
- 📊 Table-based tracking - TSV format opens in any spreadsheet app
- 💰 Token tracking - Auto-aggregate Claude Code usage by project
- ⏱️ Activity-based time tracking - Precise session hours from Claude Code logs
- 🔍 Status filtering - View active/paused/completed projects
- ⚡ Quick updates - CLI tools for rapid field updates
- 📱 Cross-platform - Works on terminal and spreadsheet apps
All files are automatically installed in:
- Data:
$PROJECTS_DIR/.project-tracker.tsv - Tools:
~/.local/bin/project-{view,update,tokens,time},session-hours - Docs:
$PROJECTS_DIR/.project-tracker-README.md
Ensure ~/.local/bin is in your PATH:
# Add to ~/.zshrc if not present
export PATH="$HOME/.local/bin:$PATH"project-view # Show all projects
project-view active # Filter by statusproject-update gmail-integration status Active
project-update gmail-integration priority High
project-update gmail-integration started 2026-01-20
project-update gmail-integration hours 8.5session-hours gmail-integration --update # Bill current session hours (recommended)
project-tokens --update # Aggregate Claude Code tokensDisplay projects as a formatted table.
project-view [active|paused|completed|planned]Examples:
project-view # All projects
project-view active # Only active projectsUpdate project fields.
project-update <project> <field> <value>Fields:
status- Active, Paused, Completed, Planned, Archivedpriority- High, Medium, Lowstarted- YYYY-MM-DDdeadline- YYYY-MM-DDprogress- 0-100%tags- comma,separated,tagshours- Number (float)notes- "Text in quotes"
Special Commands:
touch- Set Last_Active to todayadd-hours <N>- Add hours to existing total
Examples:
project-update my-project status Active
project-update my-project deadline 2026-03-15
project-update my-project tags work,backend,urgent
project-update my-project touch
project-update my-project add-hours 2.5Track billable hours from Claude Code session activity (recommended method).
session-hours # Show current session duration
session-hours <project> # Preview billing to project
session-hours <project> --update # Bill hours to project trackerHow it works:
- Reads start timestamp from current session's
.jsonllog file - Calculates elapsed time to the minute
- Rounds up to nearest 0.25 hour increment (15-minute billing blocks)
- Provides precise, activity-based tracking
Examples:
session-hours # Check current session time
session-hours gmail-integration # Preview before billing
session-hours gmail-integration --update # Bill to project (end of session)Recommended workflow: Run session-hours <project> --update at the end of each work session for accurate time tracking.
Aggregate Claude Code token usage from session logs.
project-tokens [--update] [--quiet]Options:
--update/-u- Update tracker file with token counts--quiet/-q- Suppress display output
What it tracks:
- Input tokens (prompt + context)
- Output tokens (generated text)
- Cache tokens (for cost awareness)
- Estimated cost (based on Sonnet 4.5 pricing)
Data source: ~/.claude/projects/ session logs
Examples:
project-tokens # Show token usage
project-tokens --update # Update tracker
project-tokens -u -q # Silent updateEstimate project time from git commit history (fallback method).
project-time [--update] [--quiet]Heuristic: Commits within 2 hours = one 1-hour session
Use case: For projects without Claude Code sessions, provides baseline time estimates from git history.
Options:
--update/-u- Update tracker (only fills empty fields)--quiet/-q- Suppress display output
Examples:
project-time # Show estimates
project-time --update # Update trackerNote: For Claude Code projects, prefer session-hours for more accurate tracking.
The tracker is a tab-separated file (.project-tracker.tsv) with these columns:
| Column | Description | Example |
|---|---|---|
| Project | Folder name | gmail-integration |
| Status | Current state | Active, Paused, Completed |
| Priority | Importance | High, Medium, Low |
| Started | Start date | 2026-01-20 |
| Deadline | Due date | 2026-03-15 |
| Progress | Completion % | 60% |
| Tags | Categories | work,backend |
| Input_Tokens | Claude input | 45200 |
| Output_Tokens | Claude output | 12300 |
| Hours | Time spent | 12.5 |
| Last_Active | Last worked | 2026-02-07 |
| Notes | Free text | Blocked on API approval |
Terminal (read-only):
project-viewSpreadsheet (full edit):
open "$PROJECTS_DIR/.project-tracker.tsv"CLI (field updates):
project-update <project> <field> <value>project-update my-new-project status Active
project-update my-new-project priority High
project-update my-new-project started $(date +%Y-%m-%d)
project-update my-new-project tags personal,learningproject-view active
project-update current-project touchsession-hours current-project --update # Bill precise session time
project-tokens --update # Sync token costsproject-update current-project progress 75%
project-update current-project notes "Completed OAuth flow"project-tokens --update # Refresh all token counts
project-view active # Review active workproject-update finished-project status Completed
project-update finished-project progress 100%
project-update finished-project notes "Deployed to production"Activity-based tracking from Claude Code session logs:
- Finds most recently modified
.jsonlfile in~/.claude/projects/ - Extracts start timestamp from first message
- Calculates elapsed time to current moment
- Rounds up to nearest 0.25 hour increment (15-minute billing blocks)
Advantages over git-based estimation:
- Tracks actual AI-assisted work time, not just git commits
- Accounts for research, debugging, and planning time
- Precise to the minute, not session-based estimates
- Works for all projects using Claude Code
Parses Claude Code session logs (~/.claude/projects/*/...*.jsonl) to extract:
- Token usage from assistant messages
- Working directory (
cwd) to map to project - Aggregates all sessions for each project
Only tracks sessions where cwd is inside $PROJECTS_DIR.
For projects without Claude Code sessions, uses git commit timestamps:
- Commits within 2 hours = one continuous work session
- Each session = 1 hour (configurable in script)
- Provides baseline estimate (actual time may vary)
Manual override if needed:
project-update my-project hours 12.5- Shell: Works with bash 3.2+ (macOS default)
- Python: Requires Python 3 for token/time scripts
- Git: Required for time tracking feature
- Platform: macOS, Linux (untested on Windows)
Add to ~/.zshrc for convenience:
alias pv='project-view'
alias pu='project-update'
alias pt='project-tokens'
alias sh='session-hours' # Quick session time check
alias ptime='project-time'
alias pa='project-view active'Claude Code token costs (Sonnet 4.5 pricing):
- Input tokens: $3.00 per 1M
- Output tokens: $15.00 per 1M
- Cache reads: $0.30 per 1M
Run project-tokens periodically to monitor spending:
project-tokens
# Shows total cost estimate across all projectsThe tracker file lives in iCloud ($PROJECTS_DIR/.project-tracker.tsv), so it's:
- ✅ Automatically backed up
- ✅ Synced across devices
- ✅ Version controlled (if
$PROJECTS_DIRis a git repo)
Consider also committing it to git:
cd "$PROJECTS_DIR"
git add .project-tracker.tsv
git commit -m "docs: update project tracker"# Verify ~/.local/bin is in PATH
echo $PATH | grep .local/bin
# If missing, add to ~/.zshrc:
export PATH="$HOME/.local/bin:$PATH"
source ~/.zshrc- Run Claude Code from within project directories
- Verify
$PROJECTS_DIRis set correctly - Check session logs exist:
ls ~/.claude/projects/*/
- Make sure you're running
session-hoursduring or after a Claude Code session - Session logs are stored in
~/.claude/projects/ - The script finds the most recently modified
.jsonlfile across all sessions
- Project must be a git repository
- Verify git is installed:
git --version - Check commits exist:
cd <project> && git log - Note: For Claude Code projects, use
session-hoursinstead
MIT - Free to use, modify, and distribute.
This is a personal tool, but feel free to fork and adapt for your needs!
Built with: Claude Sonnet 4.5 Last Updated: 2026-02-09 (v2.0 - Activity-based time tracking)