Packed CLI 📦

Pub Version License: MIT

A powerful CLI tool to rapidly generate Flutter feature structures following Clean Architecture and the BLoC/Cubit pattern. Stop wasting time on boilerplate and focus on building features.


🚀 Features

  • 🏗️ Clean Architecture: Automatically generates Data, Domain, and Presentation layers.
  • 📦 Auto-Dependencies: Automatically installs flutter_bloc, get_it, equatable, dartz, and internet_connection_checker if they are missing.
  • 💉 Dependency Injection: Automatic get_it registration for all layers (Datasources, Repositories, Usecases, and Cubits).
  • 🧩 Modular Structure: Each feature is self-contained with its own DI file for better maintainability.
  • Standalone Usecases: Generate new usecases for existing features with automatic DI registration.
  • 📏 Smart Naming: Automatically handles snake_case for files and PascalCase for classes.

📥 Installation

# From pub.dev
dart pub global activate packed

🛠️ Usage

Note: All commands must be run from the root directory of your Flutter project.

1. Initialize Project

Sets up the core folder structure (lib/core/), base classes (Failures, UseCases), and a global Dependency Injection container.

packed generate init

This command will create:

  • lib/core/error/failures.dart
  • lib/core/usecases/usecase.dart
  • lib/core/network/network_info.dart
  • lib/injection_container.dart

!IMPORTANT > CRITICAL: After running init or feature <feature_name>, you must manually call the initialization function in your main.dart file. Otherwise, dependency injection will not work and your app will crash.

import 'injection_container.dart' as di;

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await di.init(); // Initialize dependencies
  runApp(const MyApp());
}

2. Generate a New Feature

Generates a complete Clean Architecture folder structure with all necessary boilerplate code. You will be prompted to choose between Cubit or Bloc for state management.

packed generate feature <feature_name>

Example:

packed generate feature Home

Generated Structure:

lib/features/home/
├── data/
│   ├── datasources/home_remote_datasource.dart
│   ├── models/home_model.dart
│   └── repositories/home_repository_impl.dart
├── domain/
│   ├── entities/home_entity.dart
│   ├── repositories/home_repository.dart
│   └── usecases/get_home_usecase.dart
├── presentation/
│   ├── cubit/ (or bloc/)
│   │   ├── home_cubit.dart & home_state.dart
│   │   └── (or home_bloc.dart, home_event.dart & home_state.dart)
│   ├── pages/home_page.dart & home_view.dart
│   └── widgets/
└── di/
    └── home_di.dart (Dependency Injection)

3. Generate a Standalone Usecase

Adds a new usecase to an existing feature and automatically registers it in the feature's DI file.

packed generate usecase <usecase_name> <feature_name>

Example:

packed generate usecase UpdateProfile Home

This command will:

  1. Create update_profile_usecase.dart in lib/features/home/domain/usecases/.
  2. Add the necessary import to lib/features/home/di/home_di.dart.
  3. Register UpdateProfileUseCase in the GetIt container within the DI file.

🏛️ Architecture Overview

🎨 Presentation Layer

  • Cubit / Bloc: Handles state management using the Cubit or Bloc pattern.
  • Page: The entry point widget that provides the Cubit/Bloc using GetIt.
  • View: The actual UI layout, separated from the Page for better testing and readability.

🌐 Domain Layer

  • Entities: Simple business objects extending Equatable.
  • Repositories: Abstract interfaces defining the contract for data operations.
  • Usecases: Single-responsibility classes containing business logic.

💾 Data Layer

  • Models: Data Transfer Objects (DTOs) with JSON serialization (extends Entities).
  • Datasources: Remote and Local data handling logic.
  • Repository Impl: Concrete implementation of domain repositories.

📄 License

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