Fuso

A dead-simple terminal time tracker.
One key to start. One key to switch. One key to stop.

Install · Usage · Reports · Contributing


Most time tracking tools are either clunky web apps that demand your attention, or over-engineered CLIs with a dozen subcommands and flags. You just want to press one key when you sit down, and another key when you switch tasks. That's it.

Fuso is a terminal-native time tracker that lives in your terminal and gets out of your way. No accounts. No cloud. No config files to learn. You open it, press s, and you're tracking. Press 3 to switch to "Meeting." Press s again to stop. Done.

Your data is yours - plain JSON files in ~/.fuso/.

Screenshots

Fuso — active tracking

Tracking time with live category breakdown and per-category totals.

Fuso — weekly report

Weekly and monthly reports with CSV export.

Features

  • One-key workflows to start/stop, 19 to switch categories, p to switch projects
  • Minimalist TUI — only what matters is on screen, nothing else
  • Offline & private — all data stored locally in ~/.fuso/ as plain JSON
  • Suspend-safe — if your laptop sleeps or hibernates, the timer stops automatically at the last known time (works in WSL too)
  • CSV export — weekly and monthly reports, ready for timesheets or invoicing
  • Zero config — sensible defaults on first run, customize via the built-in settings screen

Installation

Requirements

  • Ruby 3.2+ (Ruby 4.0+ recommended)
  • A terminal with 256-color support

From RubyGems

gem install fuso

That's it. Now run fuso from anywhere.

From source

git clone https://github.com/AfonsoNeto/fuso-tui.git
cd fuso-tui
bundle install
bundle exec exe/fuso

Usage

Quick Start

  1. Launch fuso
  2. Press s to start tracking
  3. Press 19 to switch between categories
  4. Press s to stop
  5. Press r to view reports

That's it. No flags, no subcommands, no YAML.

Typical Workflow

Imagine you're a developer working on two projects. You open Fuso in the morning:

→ Press s to start tracking "Development" on "Project Alpha"
→ A meeting starts — press 3 to switch to "Meeting"
  (Development time is saved automatically)
→ Meeting ends — press 1 to switch back to "Development"
→ Need to help a colleague — press 4 for "Support"
→ End of day — press s to stop
→ Press r then e to export your timesheet as CSV

Every category switch is a single keypress. No interruptions. No context switching away from your terminal.

Use Cases

Scenario How Fuso Helps
Freelancer billing Track hours per project/category, export CSV for invoicing
Team standups Glance at yesterday's breakdown before standup
Focus tracking See where your time actually goes vs. where you think it goes
Contractor timesheets Monthly reports with weekly breakdown, ready for submission

Keyboard Shortcuts

Main Screen

Key Action
s / Space Start or stop the timer
19 Switch to category by number
p Cycle through projects
m Open settings (manage projects & categories)
r Open reports
q / Ctrl+C Quit (active session is saved automatically)

Settings Screen

Key Action
/ Navigate list
Tab Switch between projects and categories
a Add new item
d Set selected item as default
x Delete selected item
Esc Back to main screen

Reports Screen

Key Action
Tab Toggle between weekly and monthly view
/ Navigate between weeks or months
e Export current view as CSV
Esc Back to main screen

Reports

In-App Reports

Press r to open the report view. Use Tab to switch between weekly and monthly breakdowns. Navigate with / .

CSV Export

Press e on the report screen to export. Files are saved to ~/.fuso/exports/:

~/.fuso/exports/fuso_weekly_2026-W25.csv
~/.fuso/exports/fuso_monthly_2026-06.csv

The monthly CSV includes a weekly breakdown with columns for each week-ending date, matching a standard timesheet format.

CLI Reports

You can also view reports without the TUI:

fuso report weekly   # Current week summary
fuso report monthly  # Current month summary

Data Storage

All data lives in ~/.fuso/:

~/.fuso/
├── config.json     # Projects, categories, defaults
├── sessions.json   # All time entries, keyed by date
├── heartbeat       # Active tracking timestamp (auto-cleaned)
└── exports/        # Exported CSV files

Everything is plain JSON. You can read it, edit it, back it up, or sync it however you want.

How Suspend Recovery Works

If your laptop goes to sleep, hibernates, or suspends — or if you close the lid and come back later — Fuso won't count the sleep time as work.

While the timer is running, Fuso writes a heartbeat timestamp to ~/.fuso/heartbeat every 10 seconds. When it wakes up and notices the gap is too large (>60s), it saves the session at the last known heartbeat time and stops the timer.

This works everywhere: native Linux, WSL, macOS — no D-Bus, no systemd, no OS-specific APIs needed.

Built With

  • Ruby — simple, readable, gets the job done
  • Charm Rubybubbletea (Elm Architecture TUI), lipgloss (styling), bubbles (components)

Contributing

Contributions are welcome! Whether it's bug fixes, new features, documentation improvements, or just ideas — all are appreciated.

Getting Started

# Clone the repo
git clone https://github.com/AfonsoNeto/fuso-tui.git
cd fuso-tui

# Install dependencies
bundle install

# Run the test suite
bundle exec rake test

# Launch the app
bundle exec exe/fuso

Running Tests

The project uses Minitest. All tests run in an isolated temporary directory so your actual ~/.fuso/ data is never touched.

bundle exec rake test

Project Structure

lib/fuso/
├── app.rb           # Main Bubbletea model (Elm Architecture)
├── config.rb        # Config loading & persistence
├── session.rb       # Time entry recording & queries
├── heartbeat.rb     # Suspend detection via heartbeat file
├── styles.rb        # Lipgloss style definitions
└── views/
    ├── main_view.rb      # Timer screen (idle + tracking)
    ├── settings_view.rb  # Project/category management
    └── report_view.rb    # Weekly & monthly reports + CSV export

Guidelines

  • Keep it minimal. Every feature should earn its screen space.
  • Follow the Elm Architecture pattern (initupdateview).
  • Add tests for new functionality.
  • No external services, no network calls, no accounts.

License

This project is licensed under the MIT License.