Native macOS app for tracking projects, reusable tasks, and timed work sessions.
Checkpoint keeps elapsed time derived from timestamps (not a counting timer), recovers active sessions after relaunch, and exports history as CSV.
- Project management with active, completed, and archived lists
- Reusable project tasks with status, estimates, search, filter, and reorder
- One active work session at a time, with task activities and ad hoc tasks
- Live session and task timers based on
startedAt/endedAt - History with filters, session timelines, and historical edits
- Analytics dashboard (totals, streaks, charts)
- CSV export of projects, tasks, sessions, and activities
- Idle detection prompts and sleep/wake handling
- Suspicious/orphaned session recovery on relaunch
- Settings for idle, recovery, confirmations, timers, analytics defaults, and export
SwiftUI + SwiftData + Swift Charts.
| Layer | Responsibility |
|---|---|
App/ |
App entry, navigation state, settings |
Models/ |
SwiftData entities and domain enums |
Services/ |
Session engine, analytics, export, history/task/project ops, idle detection |
Views/ |
macOS NavigationSplitView UI |
Utilities/ |
Date/duration formatting, project appearance |
CheckpointTests/ |
Swift Testing unit tests for business logic |
Session transitions go through SessionManager. Views should not mutate session/activity entities directly.
Project
├── ProjectTask[] (cascade delete)
└── WorkSession[] (cascade delete)
└── TaskActivity[] (cascade delete)
ProjectTask ← TaskActivity (nullify; title snapshot retained)
Project — name, description, status, optional target date, appearance, sort order
ProjectTask — title, status, estimate, sort order, optional ad hoc flag
WorkSession — start/end, notes, status (active / completed / cancelled)
TaskActivity — taskTitleSnapshot, start/end, outcome, notes; optional task link
Rules:
- Only one active session and one active activity at a time
- Durations are always computed from timestamps
- Historical activity keeps
taskTitleSnapshoteven if the task is renamed or deleted
Checkpoint/
├── App/ # CheckpointApp, AppState, AppSettings
├── Models/ # Project, ProjectTask, WorkSession, TaskActivity, enums
├── Services/ # SessionManager, Analytics, Export, Idle, ops
├── Views/
│ ├── Main/
│ ├── Projects/
│ ├── Session/
│ ├── History/
│ ├── Analytics/
│ ├── Settings/
│ └── Shared/
├── Utilities/
└── PreviewContent/
CheckpointTests/
CheckpointUITests/
Checkpoint.xcodeproj/
- macOS 14.0 (Sonoma) or later (deployment target)
- Xcode with Swift 5 / SwiftUI / SwiftData support
- No third-party dependencies
- Open
Checkpoint.xcodeprojin Xcode. - Select the Checkpoint scheme.
- Run on My Mac (⌘R).
Settings: Checkpoint → Settings… (or ⌘,).
In Xcode: Product → Test (⌘U), or:
xcodebuild \
-project Checkpoint.xcodeproj \
-scheme Checkpoint \
-destination 'platform=macOS,arch=arm64' \
test -only-testing:CheckpointTestsUnit tests cover SessionManager, AnalyticsService, ExportService, idle detection, and settings.
On launch, SessionManager.recoverActiveSession() restores any persisted active session.
- Standard recovery — continue tracking from the original start time.
- Suspicious recovery — if elapsed time exceeds the settings threshold, choose Continue, Stop at now, or Correct end time.
- Orphaned recovery — if the project is missing, stop/correct/cancel; data is never discarded silently.
Closing the window does not stop an active session. Sleep/wake and idle prompts never rewrite history without confirmation.
AnalyticsService builds a report from completed/cancelled historical sessions (active sessions excluded).
- Tracked time — overlap of session intervals with the selected date range
- Daily / weekly / project grouping — summed durations
- Completed / skipped counts — from task activities in range
- Streaks — consecutive calendar days with completed sessions of positive duration
- Estimate vs actual — completed activities that have an estimated duration on the linked task
Default range comes from Settings; the dashboard can override it (including Custom).
File → Export CSV… (⇧⌘E) writes four UTF-8 files into a user-chosen folder:
projects.csvtasks.csvsessions.csvtask_activities.csv
Dates use ISO 8601. Relationships use ID columns. Optional Settings:
- Include cancelled sessions
- Reveal export folder in Finder after success
The app is sandboxed with User Selected Files: Read/Write so export works to Documents, Desktop, and other chosen folders.
- Single Mac, single-user; no iCloud sync or multi-device sharing
- Idle detection uses system input idle time; accuracy depends on macOS event state
- Large histories load via SwiftData
@Query; very large datasets may need future pagination - No notifications, calendar sync, attachments, or team collaboration
- JSON export was removed; CSV only
- Project/task totals on list rows are computed from related sessions (fine for MVP scale)
- iCloud synchronization
- Menu bar mode / quick start
- Pomodoro mode and notifications
- Recurring tasks
- Calendar and GitHub integration
- Nested subtasks and attachments
- iPhone/iPad companion apps
- Team collaboration
| Shortcut | Action |
|---|---|
| ⌘N | New Project |
| ⇧⌘N | New Task |
| ⌘↩ | Start / Show Session |
| ⇧⌘↩ | Complete current task |
| ⇧⌘P | Pause current task |
| ⇧⌘K | Skip current task |
| ⌥⌘S | Stop session |
| ⇧⌘E | Export CSV |
| ⇧⌘H | Show History |
| ⇧⌘A | Show Analytics |
| ⇧⌘F | Toggle History filters |
| ⌘, | Settings |