Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,31 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.1.6] - 2025-07-26

### Added

- **Stale Session Cleanup**: Automatic detection and cleanup of sessions running longer than a configurable threshold (default: 8 hours). Prevents forgotten sessions from accumulating hundreds of hours.
- **Configurable Stale Session Threshold**: Set custom threshold via `~/.config/flow/config.yml` with `stale_session_threshold` setting.

### Removed

- **Watch Command**: Removed `flow watch` command and associated watcher functionality.
- **Doctor Command**: Removed `flow doctor` diagnostic command.
- **Goal Command**: Removed `flow goal` daily goal tracking command.

### Changed

- **Simplified Configuration**: Removed watch and goal-related configuration options. Old config files are gracefully ignored.
- **Enhanced Start Command**: Now automatically cleans up stale sessions before starting new ones.
- **Enhanced Status Command**: Warns about stale sessions using the configurable threshold.
- **Code Reduction**: Removed 577 lines of code while adding 251 lines, for a net reduction of 326 lines.

### Fixed

- **Linting Issues**: Fixed all `errcheck` issues in configuration tests.
- **Test Isolation**: Improved test isolation to prevent interference between configuration tests.

## [1.1.5] - 2025-07-26

### Added
Expand Down
6 changes: 2 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,11 @@ For other installation methods (Go, manual), see the [Installation Guide](docs/I
| `resume` | Resume a paused session. |
| `end` | Complete the session and log it. |
| `delete` | Interactively delete a session from your log. |
| `watch` | Run a watcher to get gentle, timely reminders. |

> **💡 Tip**: After ending a session, if you made a mistake, you can immediately run `flow delete` to remove it!

> **🛡️ Stale Session Protection**: If you forget to end a session and it runs for over 8 hours (configurable), Flow will automatically detect and clean it up when you start a new session. The abandoned session will be logged with an [ABANDONED] tag for your records.

### Data & Analysis Commands

| Command | Description |
Expand All @@ -127,16 +128,13 @@ For other installation methods (Go, manual), see the [Installation Guide](docs/I

| Command | Description |
| ------------------------ | ------------------------------------------------------ |
| `goal [--set ""]` | Set or view your daily focus goal. |
| `doctor` | Run a diagnostic check on your Flow setup. |
| `completion [bash\|zsh]` | Generate shell completion scripts. |

## Customization

You can extend Flow to fit your unique workflow using hooks and environment variables.

- **Automation Hooks**: Trigger custom scripts on session events.
- **Watcher Timings**: Customize reminder intervals for the `watch` command.
- **Configuration**: Customize storage paths using environment variables.

For detailed information, see the [Customization Guide](docs/CUSTOMIZATION.md).
Expand Down
90 changes: 0 additions & 90 deletions cmd/doctor.go

This file was deleted.

116 changes: 0 additions & 116 deletions cmd/goal.go

This file was deleted.

33 changes: 32 additions & 1 deletion cmd/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,41 @@ A session is a single, uninterrupted period of focus.
You can add a descriptive tag to your session to remember what you worked on.
If a session is already active, 'start' will show you the status instead.`,
Run: func(cmd *cobra.Command, args []string) {
// Load configuration
config, err := core.LoadConfig()
if err != nil {
fmt.Fprintf(os.Stderr, "Error loading configuration: %v\n", err)
os.Exit(1)
}

// Check if session already exists
if core.SessionExists() {
session, err := core.LoadSession()
if err == nil {
if err != nil {
fmt.Fprintf(os.Stderr, "Error reading existing session: %v\n", err)
os.Exit(1)
}

// Check if the session is stale (running for too long)
if core.IsSessionStale(session, config.ParsedStaleSessionThreshold()) {
duration := time.Since(session.StartTime) - session.TotalPaused
if session.IsPaused {
duration = session.PausedAt.Sub(session.StartTime) - session.TotalPaused
}

// Automatically clean up the stale session
if err := core.CleanupStaleSession(session, true); err != nil {
fmt.Fprintf(os.Stderr, "Error cleaning up stale session: %v\n", err)
os.Exit(1)
}

thresholdStr := core.FormatDuration(config.ParsedStaleSessionThreshold())
fmt.Printf("⚠️ Found and cleaned up a stale session: %s\n", session.Tag)
fmt.Printf(" Duration: %s (logged as abandoned)\n", core.FormatDuration(duration))
fmt.Printf(" Threshold: %s\n", thresholdStr)
fmt.Printf(" Starting fresh session...\n\n")
} else {
// Normal existing session (not stale)
if session.IsPaused {
fmt.Printf("🌊 You have a paused session: %s\n", session.Tag)
fmt.Printf("Use 'flow resume' to continue or 'flow end' to finish.\n")
Expand Down
23 changes: 22 additions & 1 deletion cmd/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ The --raw flag can be used to output only the session tag for scripting purposes
return
}

// Load configuration
config, err := core.LoadConfig()
if err != nil {
fmt.Fprintf(os.Stderr, "Error loading configuration: %v\n", err)
os.Exit(1)
}

session, err := core.LoadSession()
if err != nil {
fmt.Fprintf(os.Stderr, "Error reading session: %v\n", err)
Expand All @@ -39,6 +46,20 @@ The --raw flag can be used to output only the session tag for scripting purposes
return
}

// Check if session is stale and warn the user
if core.IsSessionStale(session, config.ParsedStaleSessionThreshold()) {
duration := time.Since(session.StartTime) - session.TotalPaused
if session.IsPaused {
duration = session.PausedAt.Sub(session.StartTime) - session.TotalPaused
}

thresholdStr := core.FormatDuration(config.ParsedStaleSessionThreshold())
fmt.Printf("⚠️ WARNING: This session has been running for over %s!\n", thresholdStr)
fmt.Printf(" Duration: %s\n", core.FormatDuration(duration))
fmt.Printf(" You likely forgot to end the previous session.\n")
fmt.Printf(" Run 'flow start' to automatically clean up and start fresh.\n\n")
}

if session.IsPaused {
pausedDuration := time.Since(session.PausedAt)
fmt.Printf("⏸️ Session paused: %s\n", session.Tag)
Expand All @@ -52,7 +73,7 @@ The --raw flag can be used to output only the session tag for scripting purposes
fmt.Printf("Worked for %s • Paused for %s\n",
core.FormatDuration(workingTime),
core.FormatDuration(pausedDuration))
fmt.Printf("Use 'flow resume' to continue or 'flow stop' to end.\n")
fmt.Printf("Use 'flow resume' to continue or 'flow end' to finish.\n")
} else {
duration := time.Since(session.StartTime) - session.TotalPaused
baseMsg := fmt.Sprintf("🌊 Deep work: %s (Active for %s)", session.Tag, core.FormatDuration(duration))
Expand Down
Loading
Loading