A multiplatform task management monorepo organized with Dart/Flutter native pub workspaces. Task prioritization is driven by the Eisenhower Matrix (Urgent vs. Important).
The project contains three workspace members sharing a single dependency lockfile:
todo/
├── pubspec.yaml # Root workspace manifest
├── analysis_options.yaml # Monorepo static analysis rules
├── CHANGELOG.md # Project version history
├── tool/
│ └── dev.dart # Cross-platform developer task runner
├── packages/
│ ├── core/ # Core Dart library (todo_core)
│ │ ├── lib/
│ │ │ ├── todo_core.dart
│ │ │ └── src/models/ # TodoItem, TodoList, EisenhowerQuadrant
│ │ └── test/ # Core domain unit tests
│ ├── cli/ # Native Dart CLI (todo_cli)
│ │ ├── bin/todo.dart # CLI executable entrypoint
│ │ ├── lib/todo_cli.dart # CLI argument parsing & commands
│ │ ├── tool/smoke_cli.dart # Smoke tests against compiled binary
│ │ └── test/ # CLI unit tests
│ └── app/ # Flutter Android App (todo_app)
│ ├── android/ # Android platform project
│ ├── lib/main.dart # Flutter UI consuming todo_core
│ └── test/widget_test.dart# Flutter widget tests
└── .github/
├── dependabot.yml # Automated pub and actions updates
└── workflows/
├── dart.yml # Main CI pipeline (format, analyze, fix, test, build)
├── dart-beta.yml # Weekly beta SDK compatibility checks
└── release.yml # Multiplatform CLI & Android APK release pipeline
todo_core (packages/core): Pure Dart domain package holding task models, priority queues, and Eisenhower matrix logic. Has no Flutter dependency, enabling reuse across CLI, server, and client frontends.todo_cli (packages/cli): Native command-line interface for fast task capture and viewing from the terminal. Compiles to native AOT binaries across Linux, macOS, and Windows.todo_app (packages/app): Flutter Android application providing a rich Material 3 user interface on top of todo_core.tool/dev.dart)To avoid OS differences with make, a cross-platform Dart runner script is available at tool/dev.dart:
# Show all available commands
dart run tool/dev.dart help
# Formatting & static analysis
dart run tool/dev.dart format # Format all packages
dart run tool/dev.dart format --check # Check formatting without modifying
dart run tool/dev.dart analyze # Analyze with --fatal-infos
dart run tool/dev.dart fix # Apply automated fixes
dart run tool/dev.dart fix --check # Dry-run check for fixes
# Testing
dart run tool/dev.dart test # Run all tests (core, cli, app)
dart run tool/dev.dart test:core # Run core tests only
dart run tool/dev.dart test:cli # Run CLI tests only
dart run tool/dev.dart test:app # Run Flutter app tests only
# Building & Smoke Testing
dart run tool/dev.dart build:cli # Compile native CLI bundle
dart run tool/dev.dart smoke:cli # Smoke test compiled CLI binary
dart run tool/dev.dart build:app # Build Android debug APK
# Full Local CI Verification Suite (format, analyze, fix, test, build, smoke)
dart run tool/dev.dart verify
Install dependencies across all workspaces:
flutter pub get
Verify workspace membership:
dart pub workspace list
Check formatting and linting:
dart format --output=none --set-exit-if-changed .
dart analyze --fatal-infos
dart fix --dry-run
Run all tests:
# Core & CLI tests
dart test packages/core
dart test packages/cli
# Flutter app tests
flutter test packages/app
Build and smoke test the native CLI:
cd packages/cli
dart build cli
dart run tool/smoke_cli.dart
cd ../..
Run the Flutter Android app (with an emulator or device connected):
cd packages/app
flutter run
The GitHub Actions workflows mirror the established pattern from cards_with_dart and ascii_renderer:
.github/workflows/dart.yml):format: Verifies code formatting across all packages.analyze: Runs static analysis with fatal infos.fix: Asserts that dart fix --dry-run reports no pending automated fixes.test: Multi-OS test matrix (ubuntu-latest, windows-latest, macos-latest) with Linux coverage collection.build-cli: Multi-OS native CLI compilation and smoke testing.build-android: Compiles Android debug APK and uploads artifact..github/workflows/dart-beta.yml): Weekly non-blocking sanity check against the beta SDK channel..github/workflows/release.yml):v*.*.* or manual dispatch.pubspec.yaml version and CHANGELOG.md entry..tar.gz and .zip.SHA256SUMS and publishes draft GitHub Release with release notes..github/dependabot.yml): Weekly dependency update checks for Pub packages and GitHub Actions.This repository is ready to be marked as a GitHub Template Repository (Settings -> check Template repository, or gh repo edit --template). When generating a new project from this template, follow this customization checklist:
name: and description: in root pubspec.yaml.packages/core:name: in packages/core/pubspec.yaml (e.g., myproject_core).lib/todo_core.dart to lib/<new_name>.dart.packages/cli:name: in packages/cli/pubspec.yaml (e.g., myproject_cli).executables: map (e.g., mytool: mytool).bin/todo.dart to bin/mytool.dart and lib/todo_cli.dart to lib/mytool_cli.dart.todo_core to your new core package name.tool/smoke_cli.dart, update the binary name filter ('todo' -> 'mytool') and expected stdout checks.packages/app:name: in packages/app/pubspec.yaml.todo_core to your new core package name.lib/ and test/.In packages/app/android/app/build.gradle.kts:
namespace and applicationId from com.example.todo_app to your reverse-domain identifier (e.g. com.mycompany.myproject).packages/app/android/app/src/main/kotlin/.../MainActivity.kt directory and package statement to match.packages/app/android/app/src/main/res/mipmap-*..github/workflows/dart.yml, release.yml, dart-beta.yml):todo- -> myproject-).tool/dev.dart):CHANGELOG.md to ## 0.1.0 or ## 1.0.0 for your new project.flutter pub get
dart run tool/dev.dart verify
By default, all workspace packages are set to publish_to: none to prevent accidental public release of private code or name collisions.
If you want to publish todo_core as an open-source library and todo_cli as a globally activatable command-line tool, follow these steps:
publish_to: none:packages/core/pubspec.yaml and packages/cli/pubspec.yaml. (Keep it in root pubspec.yaml and packages/app/pubspec.yaml).description: >-
A concise description between 60 and 180 characters explaining what the package does.
repository: https://github.com/<user>/<repo>
issue_tracker: https://github.com/<user>/<repo>/issues
topics:
- cli
- productivity
# In packages/cli/pubspec.yaml:
dependencies:
myproject_core: ^0.1.0 # Must match the published version of core
LICENSEREADME.md (documenting the package's API or CLI usage)CHANGELOG.md (documenting versions for that package)Because cli depends on core, core must be published first:
# 1. Validate both packages with dry-run
cd packages/core && dart pub publish --dry-run
cd ../cli && dart pub publish --dry-run
# 2. Publish core
cd ../core && dart pub publish
# 3. Publish cli (after core is live on pub.dev)
cd ../cli && dart pub publish
Once published, end users can install your CLI globally:
dart pub global activate <cli_package_name>
<executable_name> --help
pub.dev supports Trusted Publishing using GitHub Actions OIDC (no stored tokens or secrets required):
.github/workflows/release.yml:publish-pub-dev:
name: Publish to pub.dev
needs: [verify, test]
runs-on: ubuntu-latest
permissions:
id-token: write # Required for pub.dev OIDC authentication
steps:
- uses: actions/checkout@v4
- uses: dart-lang/setup-dart@v1
- name: Publish Core
run: dart pub publish --force
working-directory: packages/core
- name: Publish CLI
run: dart pub publish --force
working-directory: packages/cli