/rem

A fast Rust-core CLI program to manage Apple Reminders.

Primary LanguageRustMIT LicenseMIT

Rem - Apple Reminders TUI

A fast, beautiful Terminal User Interface (TUI) for Apple Reminders built with a modern Swift wrapper + Rust core architecture. Rem provides a keyboard-driven interface to view, navigate, and manage your Apple Reminders directly from the terminal with native macOS integration.

CI

โœจ Features

  • ๐Ÿš€ Lightning Fast: Native EventKit integration eliminates AppleScript delays (18+ seconds โ†’ <1 second)
  • ๐Ÿ“ฑ Real Apple Reminders Data: Direct integration with macOS Reminders app
  • โŒจ๏ธ Vim-style Navigation: Intuitive keyboard shortcuts (j/k, arrow keys)
  • ๐ŸŽจ Beautiful UI: Modern terminal interface with colors, emojis, and rounded borders
  • โœ… Full Management: Create, toggle, delete reminders with comprehensive form interface
  • ๐Ÿ” Live Data: Real-time access to your actual reminders and lists
  • ๐Ÿ›ก๏ธ Native Permissions: Automatic permission handling with native macOS dialogs
  • ๐Ÿ—๏ธ Modern Architecture: Type-safe Swift-Rust communication via UniFFI
  • ๐Ÿ“ Rich Creation: Create reminders with title, notes, due dates, lists, and priorities

๐Ÿ–ผ๏ธ Screenshots

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ ๐Ÿ“ Your Reminder Lists โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                                                              โ”‚
โ”‚  โ–ถ โ—  Today                                                  โ”‚
โ”‚      9306 reminders                                          โ”‚
โ”‚                                                              โ”‚
โ”‚    โ—  House                                                  โ”‚
โ”‚      51 reminders                                            โ”‚
โ”‚                                                              โ”‚
โ”‚    โ—  Our Things                                             โ”‚
โ”‚      12 reminders                                            โ”‚
โ”‚                                                              โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Controls โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  โ†‘โ†“ or j/k navigate  โŽ select  c create  q quit         โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

๐Ÿ—๏ธ Architecture Overview

Rem uses a modern Swift wrapper + Rust core architecture that separates system integration from TUI logic:

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                    Swift Wrapper                       โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”‚
โ”‚  โ”‚ RemindersServiceโ”‚  โ”‚   PermissionManager         โ”‚   โ”‚
โ”‚  โ”‚  (EventKit)     โ”‚  โ”‚  (Native Dialogs)           โ”‚   โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                   UniFFI Bridge                         โ”‚
โ”‚             (Type-Safe Rust โ†” Swift)                    โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                    Rust Core                            โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚
โ”‚  โ”‚              Ratatui TUI Engine                     โ”‚ โ”‚
โ”‚  โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”‚ โ”‚
โ”‚  โ”‚   โ”‚   Lists   โ”‚ โ”‚Reminders โ”‚ โ”‚   Navigation    โ”‚    โ”‚ โ”‚
โ”‚  โ”‚   โ”‚Component  โ”‚ โ”‚Component โ”‚ โ”‚    & Events     โ”‚    โ”‚ โ”‚
โ”‚  โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ”‚ โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                 Apple Reminders                         โ”‚
โ”‚                   (macOS App)                           โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

๐Ÿ”„ Data Flow

  1. Swift Entry Point: Handles permissions and loads data via native EventKit
  2. Native Integration: Fast, reliable access to Reminders data
  3. UniFFI Bridge: Type-safe data conversion between Swift and Rust
  4. Rust TUI: High-performance terminal interface and user interaction
  5. Action Processing: Swift receives actions and updates data accordingly

๐Ÿ“ Project Structure

RemTUI/                           # New Architecture
โ”œโ”€โ”€ RemTUIKit/                    # Swift Package (System Integration)
โ”‚   โ”œโ”€โ”€ Package.swift
โ”‚   โ”œโ”€โ”€ Sources/RemTUIKit/
โ”‚   โ”‚   โ”œโ”€โ”€ RemindersService.swift    # Native EventKit wrapper
โ”‚   โ”‚   โ”œโ”€โ”€ PermissionManager.swift   # Native permission handling
โ”‚   โ”‚   โ””โ”€โ”€ [Generated UniFFI files]  # Rust bindings
โ”‚   โ””โ”€โ”€ Tests/RemTUIKitTests/
โ”œโ”€โ”€ rust-core/                   # Rust Library (TUI Core)
โ”‚   โ”œโ”€โ”€ Cargo.toml
โ”‚   โ”œโ”€โ”€ src/
โ”‚   โ”‚   โ”œโ”€โ”€ lib.rs              # UniFFI exports
โ”‚   โ”‚   โ”œโ”€โ”€ rem_core.udl        # Interface definition
โ”‚   โ”‚   โ””โ”€โ”€ tui/               # Ratatui implementation
โ”‚   โ”‚       โ”œโ”€โ”€ app.rs         # Main TUI application
โ”‚   โ”‚       โ”œโ”€โ”€ components.rs  # UI components
โ”‚   โ”‚       โ””โ”€โ”€ events.rs      # Event handling
โ”œโ”€โ”€ RemTUI/                     # Swift Executable
โ”‚   โ”œโ”€โ”€ Package.swift
โ”‚   โ”œโ”€โ”€ Sources/main.swift      # Application entry point
โ”‚   โ””โ”€โ”€ Info.plist             # Permissions & metadata
โ”œโ”€โ”€ build.sh                    # Build coordination script
โ”œโ”€โ”€ test-migration.sh           # Validation script
โ”œโ”€โ”€ Makefile                    # Development workflow
โ”œโ”€โ”€ MIGRATION.md               # Architecture migration guide
โ”œโ”€โ”€ DEVELOPMENT.md             # Feature development guide
โ””โ”€โ”€ ARCHITECTURE.md            # Detailed architecture documentation

๐Ÿš€ Installation

Prerequisites

  • macOS 14.0+ (required for full EventKit access)
  • Rust 1.70+ with Cargo
  • Swift 5.9+ with Package Manager
  • Xcode Command Line Tools

Quick Start

# Clone the repository
git clone https://github.com/yourusername/rem.git
cd rem

# Build everything with UniFFI bindings
make build

# Run the application
make run

Development Installation

# Install with development tools
make install-dev

# Run tests
make test

# Run with debug logging
make debug

๐ŸŽฎ Usage

Basic Commands

# Start the application (full build + run)
make run

# Run without rebuilding (preserves UniFFI checksums - recommended)
make run-direct

# Run directly:
cd RemTUI && .build/release/RemTUI

# Run with debug output
make debug

# Run development version
make dev

Note: Use make run-direct to avoid UniFFI checksum issues when the TUI integration is already built. This builds only the Swift executable without regenerating Rust bindings.

Navigation & Controls

Lists View:

  • j/k or โ†‘/โ†“ - Navigate between lists
  • Enter - Open selected list
  • c - Create new reminder
  • q - Quit application

Reminders View:

  • j/k or โ†‘/โ†“ - Navigate between reminders
  • Space or Enter - Toggle reminder completion
  • dd or Delete - Delete selected reminder (vim-style)
  • c - Create new reminder
  • q or Esc - Go back to lists

Create Reminder Form:

  • Tab - Navigate between form fields
  • โ†‘/โ†“ - Change list/priority selections
  • Ctrl+S - Save and create reminder
  • q or Esc - Cancel and return

Form Fields:

  • Title - Text input for reminder title (required)
  • Notes - Multi-line text input for notes
  • Date - Due date in ISO8601 format (e.g., 2024-12-31T23:59:59Z)
  • List - Select target reminder list
  • Priority - Set priority level (0-9, where 0 = none)

Permissions

On first run, Rem will automatically request permission to access your Reminders using native macOS dialogs. No manual setup required!

๐Ÿ› ๏ธ Development

Development Workflow

# Setup development environment
make setup

# Build components individually
make build-rust      # Build Rust core only
make build-uniffi    # Build Rust + generate UniFFI bindings
make build-swift     # Build Swift package only
make build          # Build everything

# Running
make run            # Full build + run
make run-direct     # Run without rebuilding (preserves checksums)
make run-debug      # Run in debug mode

# Development
make dev-swift      # Watch Swift files only (preserves checksums)
make fix-checksums  # Fix UniFFI checksums after rebuild

# Development and testing
make dev            # Run in development mode
make test           # Run all tests
make test-rust      # Test Rust core only
make test-swift     # Test Swift package only

# Code quality
make fmt            # Format all code
make lint           # Run linters
make check          # Check compilation without building

# Debugging
make debug          # Run with debug logging
make debug-rust     # Debug Rust components
make debug-swift    # Debug Swift components

# Cleanup
make clean          # Clean build artifacts
make clean-all      # Clean everything including dependencies

Architecture Details

Swift Layer (System Integration)

RemindersService.swift

  • Native EventKit integration for fast data access
  • Concurrent list and reminder loading
  • Real-time permission status monitoring
  • Error handling with detailed context

PermissionManager.swift

  • Native permission request dialogs
  • Status checking and guidance
  • Automatic permission flow handling

Rust Layer (TUI Core)

lib.rs - UniFFI exports and main interface tui/app.rs - Core TUI application logic with Ratatui rem_core.udl - UniFFI interface definition for type safety

Build System

build.sh - Coordinates Rust compilation and UniFFI binding generation Makefile - Complete development workflow automation test-migration.sh - Validates architecture and compilation

Performance Improvements

Metric Before (AppleScript) After (Native EventKit)
Cold Start 18+ seconds <1 second
List Loading 2-3 seconds <500ms
Reminder Fetch 1-2 seconds/list <200ms/list
Permission Setup Manual guidance Automatic native dialogs

๐Ÿงช Testing

# Run all tests
make test

# Test individual components
make test-rust          # Rust core tests
make test-swift         # Swift package tests
make test-integration   # Integration tests

# Validate migration
make test-migration     # Architecture validation

# Performance benchmarks
make benchmark          # Performance comparison tests

๐Ÿ”ง Troubleshooting

UniFFI Checksum Issues

The most common issue is "UniFFI API checksum mismatch" when rebuilding:

# Use run-direct to avoid regenerating bindings
make run-direct

# If checksums are out of sync, clean rebuild:
make clean-all
make build
# Then manually update checksums in RemCore.swift if needed

Why this happens: UniFFI generates checksums to ensure the Rust library matches the Swift bindings. When rebuilding, the checksums may change, requiring manual updates in the generated Swift file.

Permission Issues

The new architecture handles permissions automatically, but if you encounter issues:

# Check permission status
make check-permissions

# Reset permissions (if needed)
tccutil reset Reminders

# Debug permission flow
make debug-permissions

Build Issues

# Clean and rebuild everything
make clean-all
make build

# Check individual components
make check-rust         # Rust compilation check
make check-swift        # Swift compilation check

# Debug build process
make debug-build

Performance Issues

# Profile the application
make profile

# Debug with detailed logging
make debug

# Check system requirements
make check-system

๐Ÿš€ Future Enhancements

The new architecture enables exciting possibilities:

  • ๐Ÿ“… Calendar Integration: Events alongside reminders
  • ๐Ÿ”„ Real-time Sync: Live updates with iCloud synchronization
  • ๐Ÿท๏ธ Advanced Filtering: Tag-based and smart list filtering
  • ๐Ÿ“ Rich Editing: In-place reminder editing and creation
  • ๐ŸŽฏ Bulk Operations: Multi-select actions and batch operations
  • ๐Ÿ“Š Analytics: Productivity insights and completion tracking

๐Ÿค Contributing

We welcome contributions! The new architecture makes it easy to contribute to specific layers:

Contributing Areas

  • Swift Layer: EventKit integration, native macOS features, permissions
  • Rust Core: TUI components, user experience, performance optimizations
  • Documentation: Guides, examples, architecture explanations

Getting Started

# Fork and clone
git clone https://github.com/yourusername/rem.git
cd rem

# Setup development environment
make setup

# Run tests to ensure everything works
make test

# Create feature branch
git checkout -b feature/amazing-feature

# Make changes and test
make dev
make test

# Submit pull request

Adding New Features

See DEVELOPMENT.md for a comprehensive guide on adding functionality through all layers of the architecture, including:

  • Step-by-step feature implementation
  • UniFFI integration patterns
  • Key handling and TUI updates
  • Swift backend services
  • Testing strategies

The development guide uses the delete functionality (dd command) as a complete example of implementing features from Rust TUI to Swift EventKit integration.

Code Style

  • Swift: Follow Swift API Design Guidelines
  • Rust: Use cargo fmt and pass cargo clippy
  • Documentation: Update relevant docs in docs/
  • Tests: Add tests for new functionality

๐Ÿ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

๐Ÿ™ Acknowledgments

  • Ratatui - Excellent TUI framework for Rust
  • UniFFI - Type-safe FFI between Rust and Swift
  • Apple EventKit - Native Reminders integration
  • Rust Community - Amazing ecosystem and documentation
  • Swift Package Manager - Modern dependency management

Migration Note: This version represents a complete architectural upgrade from the previous Rust-only implementation. See MIGRATION.md for detailed migration information and performance comparisons.