codeable_cli 1.0.14
codeable_cli: ^1.0.14 copied to clipboard
A CLI tool that scaffolds production-ready Flutter projects with Clean Architecture, BLoC/Cubit, Dio, Hive, GoRouter, multi-flavor builds, and Firebase integration.
Codeable CLI #
A production-ready Flutter project scaffolding tool.
Instantly generate Flutter projects with Clean Architecture, BLoC/Cubit state management, Dio networking, Hive storage, GoRouter navigation, multi-flavor builds (Android + iOS), Firebase integration, and 30+ reusable UI components — all wired together and ready to go.
Table of Contents #
- Overview
- Prerequisites
- Installation
- Quick Start
- Commands
- Generated Architecture
- Included UI Components
- Multi-Flavor Builds
- Platform Configuration
- AI-Assisted Development
- FAQ
- Contributing
- Contributors
- License
Overview #
Starting a new Flutter project means hours of boilerplate — setting up architecture, configuring flavors, wiring DI, adding interceptors, building reusable widgets, and configuring platform files. Codeable CLI does all of that in seconds.
| Metric | Detail |
|---|---|
| Architecture | Clean Architecture (feature-first) |
| State Management | BLoC/Cubit with DataState |
| Networking | Dio with auth, logging, Chucker interceptors |
| Storage | Hive-based local storage |
| Navigation | GoRouter with named routes |
| UI Components | 30+ production-ready widgets |
| Build Flavors | Development, Staging, Production |
| Platforms | Android & iOS pre-configured |
| Firebase | Multi-environment directory structure |
| Localization | ARB files with context.l10n |
| AI Config | CLAUDE.md + .cursorrules |
Prerequisites #
Before installing Codeable CLI, make sure you have:
- Dart SDK >= 3.0
- Flutter SDK >= 3.0
- Java/JDK >= 17 (required for Android keystore generation)
Installation #
Activate from pub.dev #
dart pub global activate codeable_cli
Activate a specific version #
dart pub global activate codeable_cli 1.0.14
Or run without activating #
If you prefer not to globally activate (e.g., in CI), you can run commands directly:
dart pub global run codeable_cli:codeable_cli <command> <args>
Update to the latest version #
codeable_cli update
Verify installation #
codeable_cli --help
Note: If
codeable_cliis not found after activation, make sure~/.pub-cache/binis in your system PATH:# macOS / Linux — add to ~/.zshrc or ~/.bashrc export PATH="$PATH":"$HOME/.pub-cache/bin" # Windows — add to your system environment variables # %LOCALAPPDATA%\Pub\Cache\binAfter adding, restart your terminal or run
source ~/.zshrc.
Quick Start #
Create a new project:
codeable_cli create --name my_app --app-name "My App" --org com.example.myapp
Navigate into the project:
cd my_app
Run it:
flutter run --flavor development -t lib/main_development.dart
That's it. Your project is ready with the full architecture, all dependencies installed, and the keystore generated.
Generate a new feature #
codeable_cli feature profile
This creates the full feature module and auto-wires everything:
- Cubit registered in
app_page.dart's MultiBlocProvider - Route added to
go_routerwith named route constants - Navigate with
context.goNamed(AppRouteNames.profileScreen)
Role-based features #
Organize features by user role (e.g., customer, admin):
codeable_cli feature home --role customer
This creates lib/features/customer/home/ with all files and classes prefixed — CustomerHomeScreen, CustomerHomeCubit, route /customer-home.
Verify everything works #
flutter analyze # Should show zero errors
flutter test # Run tests
Commands #
create — Scaffold a new project #
codeable_cli create [options]
| Option | Description | Default |
|---|---|---|
-n, --name |
Project name (snake_case) | Prompted interactively |
-a, --app-name |
Display name of the app (e.g., My App) |
Prompted interactively |
-o, --org |
Organization identifier (e.g., com.example.app) |
Prompted interactively |
-d, --description |
Project description | A new Flutter project |
--output |
Output directory | . (current directory) |
--roles |
Comma-separated role directories under features/ (e.g., customer,admin) |
None |
What it generates:
my_app/
├── lib/
│ ├── main_development.dart # Dev entry point (with DevicePreview)
│ ├── main_staging.dart # Staging entry point
│ ├── main_production.dart # Production entry point
│ ├── bootstrap.dart # App initialization & DI setup
│ ├── exports.dart # Global barrel exports
│ ├── app/view/ # App root (MaterialApp.router, theme, splash)
│ ├── config/ # Flavor config, API environment, remote config
│ ├── constants/ # Colors, text styles, asset paths, constants
│ ├── core/
│ │ ├── api_service/ # Dio client + auth/log interceptors
│ │ ├── app_preferences/ # Hive-based local storage
│ │ ├── di/ # GetIt dependency injection
│ │ ├── endpoints/ # API endpoint definitions
│ │ ├── locale/ # Locale cubit for i18n
│ │ ├── models/ # API response & auth models
│ │ ├── notifications/ # Firebase & local notifications
│ │ ├── permissions/ # Permission manager
│ │ └── field_validators.dart # Form validation (email, phone, etc.)
│ ├── features/
│ │ └── onboarding/ # Sample feature (login screen)
│ ├── go_router/ # GoRouter config, routes, named routes
│ ├── l10n/ # Localization (ARB files, context.l10n)
│ └── utils/
│ ├── extensions/ # Dart extensions
│ ├── helpers/ # Toast, layout, decorations, logger, etc.
│ ├── response_data_model/ # Response parsing utilities
│ └── widgets/core_widgets/ # 30+ reusable UI components
├── .run/ # Android Studio run configurations (Dev/Staging/Prod)
├── assets/ # images, vectors, animation, fonts
├── firebase/ # Per-flavor Firebase config directories
├── android/ # Configured with flavors, signing, ProGuard
├── ios/ # Configured with Podfile, Info.plist, entitlements
├── CLAUDE.md # AI assistant context (Claude Code)
├── .cursorrules # AI assistant context (Cursor)
└── README.md # Project documentation
feature — Generate a feature module #
Must be run from inside an existing Codeable project.
codeable_cli feature <feature_name> [--role <role>]
| Option | Description |
|---|---|
--role, -r |
Optional role prefix (e.g., customer, admin). Places the feature under features/<role>/ and prefixes all file names, class names, and routes with the role. |
Basic example:
codeable_cli feature profile
lib/features/profile/
├── data/
│ ├── models/profile_model.dart
│ └── repository/profile_repository_impl.dart
├── domain/
│ └── repository/profile_repository.dart
└── presentation/
├── cubit/
│ ├── cubit.dart
│ └── state.dart
├── views/profile_screen.dart
└── widgets/
Role-based example:
codeable_cli feature home --role customer
lib/features/customer/home/
├── data/
│ ├── models/customer_home_model.dart
│ └── repository/customer_home_repository_impl.dart
├── domain/
│ └── repository/customer_home_repository.dart
└── presentation/
├── cubit/
│ ├── cubit.dart
│ └── state.dart
├── views/customer_home_screen.dart
└── widgets/
With --role, all class names are prefixed (e.g., CustomerHomeScreen, CustomerHomeCubit) and the route becomes /customer-home. Without --role, behavior is identical to before.
Each generated file comes with boilerplate — the repository interface, implementation wired to ApiService and AppPreferences (cache), cubit with DataState, and a screen scaffold with customAppBar and BlocBuilder.
Auto-wired out of the box:
- Cubit registered in
app_page.dart'sMultiBlocProvider - Route added to
go_router/router.dart - Route constants added to
AppRoutesandAppRouteNames - Screen import added to
go_router/exports.dart - Navigate with
context.goNamed(AppRouteNames.customerHomeScreen)
rename — Rename a project #
codeable_cli rename --name <new_name>
Updates the package name in pubspec.yaml, renames all package:old_name/ imports across the codebase, renames the project folder, and runs flutter pub get.
change-app-name — Change app display name #
codeable_cli change-app-name --name "New App Name"
| Option | Description |
|---|---|
-n, --name |
The new display name (e.g., "My App") |
Updates the app display name across the entire project:
android/app/build.gradle.kts(flavormanifestPlaceholders)ios/Runner.xcodeproj/project.pbxproj(FLAVOR_APP_NAME)lib/constants/app_constants.dart(AppConstants.appName)lib/l10n/app_*.arb(localizationappNamekey)
Staging and development flavors are automatically suffixed with [STG] and [DEV].
change-id — Change bundle identifier #
codeable_cli change-id --id <new_id>
Updates the application/bundle identifier in:
android/app/build.gradle.kts(namespace + applicationId)android/app/src/main/AndroidManifest.xml(package attribute)ios/Runner.xcodeproj/project.pbxproj(PRODUCT_BUNDLE_IDENTIFIER)
Generated Architecture #
Clean Architecture #
Every feature follows a strict three-layer structure:
UI (Screen/Widget)
↓ triggers
Cubit (State Management)
↓ calls
Repository Interface (Domain)
↓ implemented by
Repository Implementation (Data)
↓ uses
ApiService (Dio) + AppPreferences (Cache)
State Management #
Uses Cubit (not full BLoC with events) for simplicity. States use a DataState<T> wrapper:
// cubit.dart
class ProfileCubit extends Cubit<ProfileState> {
ProfileCubit(this._repository) : super(const ProfileState());
final ProfileRepository _repository;
Future<void> getProfile() async {
emit(state.copyWith(profileState: DataState.loading));
final response = await _repository.getProfile();
if (response.isSuccess) {
emit(state.copyWith(profileState: DataState.loaded, profile: response.data));
} else {
emit(state.copyWith(profileState: DataState.failure));
}
}
}
Styling System #
Text styles via context extension with modifier chains:
Text('Title', style: context.h1) // Header 32px bold
Text('Body', style: context.b1) // Body 14px medium
Text('Label', style: context.l2.secondary) // Label 12px, white
Text('Caption', style: context.b3.tertiary) // Body 12px, gray
Colors via AppColors constants:
AppColors.blackPrimary // Primary text/foreground
AppColors.white // White
AppColors.textSecondary // Secondary text (gray)
AppColors.backgroundTertiary // Light background
AppColors.error // Error red
AppColors.success // Success green
API Layer #
Pre-configured Dio client with:
- Auth interceptor — automatically attaches bearer token from local storage
- Log interceptor — request/response logging for development
- Chucker interceptor — in-app network inspector (development only)
- 60s timeout with centralized error handling via
AppApiException
Dependency Injection #
GetIt-based via Injector wrapper:
// Register in app_modules.dart
Injector.resolve<ApiService>();
// Resolve anywhere
final apiService = Injector.resolve<ApiService>();
Included UI Components #
The generated project includes 30+ production-ready widgets in lib/utils/widgets/core_widgets/:
| Widget | Description |
|---|---|
CustomAppBar |
App bar with back button, title, actions |
CustomButton |
Primary filled button with loading state |
CustomOutlineButton |
Outlined variant |
CustomTextButton |
Text-only button |
CustomIconButton |
Icon button with optional badge |
CustomTextField |
Text field with validation, prefix/suffix, formatters |
CustomSearchField |
Search input with debounce |
CustomDropdown |
Dropdown selector with cubit |
SearchableDropdown |
Dropdown with search/filter |
CustomSlidingTab |
Animated sliding tab bar |
CustomSectionTitle |
Section header with optional "See All" |
PaginatedListView |
List with built-in pagination |
CustomConfirmationDialog |
Confirmation dialog |
CustomBottomSheet |
Bottom sheet wrapper |
CustomShimmerWidget |
Shimmer loading placeholder |
CustomLoadingWidget |
Loading indicator |
CustomEmptyStateWidget |
Empty state with icon and message |
CustomRetryWidget |
Error state with retry button |
CustomStarRatingWidget |
Star rating display/input |
CustomSocialAuthButton |
Google/Apple sign-in buttons |
CachedNetworkImageWidget |
Cached network image with placeholder |
CustomDatePicker |
Date picker |
CustomTimePicker |
Time picker |
CustomCheckbox |
Checkbox with label |
CustomSwitch |
Toggle switch |
CustomSlider |
Range slider |
CustomChips |
Chip selection widget |
CustomProgressDashes |
Step progress indicator |
CustomRichText |
Rich text with tappable spans |
CustomBulletPointItem |
Bullet point list item |
StackedImagesWidget |
Overlapping avatar stack |
BlurOverlay |
Blurred background overlay |
ImagePickerWidget |
Camera/gallery image picker |
ReusableCalendarWidget |
Calendar date selector |
All widgets follow the Custom<WidgetName> naming convention and use the project's AppColors and text style system.
Multi-Flavor Builds #
Three flavors are configured out of the box with separate entry points:
| Flavor | Entry Point | Bundle ID Suffix | Display Name | App Icon |
|---|---|---|---|---|
production |
lib/main_production.dart |
(none) | MyApp |
AppIcon |
staging |
lib/main_staging.dart |
.stg |
MyApp [STG] |
AppIcon-stg |
development |
lib/main_development.dart |
.dev |
MyApp [DEV] |
AppIcon-dev |
flutter run --flavor development -t lib/main_development.dart
flutter run --flavor production -t lib/main_production.dart
What's configured per flavor #
Android:
productFlavorsinbuild.gradle.kts(development, staging, production)- Per-flavor launcher icons in
android/app/src/{development,staging}/res/mipmap-* - Production icons in
android/app/src/main/res/mipmap-*
iOS:
- Xcode schemes for each flavor (
development.xcscheme,staging.xcscheme,production.xcscheme) - 27 build configurations (3 build types × 3 flavors × 3 targets) in
project.pbxproj - Per-flavor
PRODUCT_BUNDLE_IDENTIFIER(e.g.,com.example.app,com.example.app.stg,com.example.app.dev) - Per-flavor
FLAVOR_APP_NAMEfor display name (resolved via$(FLAVOR_APP_NAME)in Info.plist) - Per-flavor app icon sets in
ios/Runner/Assets.xcassets/(AppIcon,AppIcon-stg,AppIcon-dev)
Customizing per-flavor icons #
All three icon sets start with the same default icons. To differentiate:
- Replace icons in
ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/(development) - Replace icons in
ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/(staging) - Replace icons in
android/app/src/development/res/mipmap-*/(Android dev) - Replace icons in
android/app/src/staging/res/mipmap-*/(Android staging)
Platform Configuration #
Android (pre-configured) #
build.gradle.ktswith flavor dimensions, signing config, ProGuard, desugaring- Per-flavor source sets with launcher icons (
src/development/res/,src/staging/res/) - Auto-generated keystore at
android/app/<project_name>-keystore.jks - Signing credentials in
android/key.properties - Internet, camera, location, notification permissions in AndroidManifest.xml
iOS (pre-configured) #
- Xcode schemes for each flavor (development, staging, production)
- 27 build configurations with per-flavor bundle IDs, display names, and app icons
- Per-flavor app icon sets in
Assets.xcassets(AppIcon, AppIcon-dev, AppIcon-stg) - Podfile with iOS 15.6 minimum, permission handler pods
- Info.plist with camera, photo library, location usage descriptions
- Entitlements for push notifications and Sign in with Apple
- Google Service copy script for per-flavor Firebase config
Firebase #
- Directory structure at
firebase/{development,staging,production}/ - Drop in your
google-services.jsonandGoogleService-Info.plistper flavor - Build scripts auto-copy the correct config for the active flavor
AI-Assisted Development #
Generated projects include configuration files for AI coding assistants:
- CLAUDE.md — Project structure, patterns, and conventions for Claude Code
- .cursorrules — Architecture rules and coding guidelines for Cursor
These files give AI assistants full context about your project's architecture, so they generate code that follows your patterns.
FAQ #
Do I need Flutter installed before using Codeable CLI?
Yes. Codeable CLI runs flutter create under the hood and then overlays the architecture on top. You need both Dart SDK (>= 3.0) and Flutter SDK (>= 3.0) installed.
Can I use this with an existing Flutter project?
The create command is designed for new projects. However, the feature command works inside any Codeable-structured project. If your existing project follows a similar architecture, you can use the feature command to generate new modules.
How do I add Firebase to a generated project?
The directory structure is already in place at firebase/{development,staging,production}/. Simply drop your google-services.json (Android) and GoogleService-Info.plist (iOS) into the appropriate flavor directory.
Can I customize the generated code after scaffolding?
Absolutely. The generated code is plain Dart/Flutter — no code generation or build_runner dependencies for the architecture itself. Modify anything you need.
Does the feature command require manual wiring?
No. As of v1.0.1, the feature command auto-wires everything: it registers the cubit in app_page.dart, adds routes to go_router, and creates route constants. You just need to start building your UI.
Contributing #
Contributions, issues, and feature requests are welcome!
# Fork the repo, then:
git clone https://github.com/<your-username>/codeable_cli.git
cd codeable_cli
dart pub get
# Make your changes, then:
dart test
dart analyze
# Submit a pull request
See the issues page for open tasks.
Contributors #
Syed Arham Imran |
Abdullah Zeb |
Muhammad Anas Akhtar |
Muhammad Shoaib Irfan |
Shahab Arif |
License #
This project is licensed under the MIT License — see the LICENSE file for details.