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 + static Localization service |
| AI Config | CLAUDE.md + .cursorrules + /localize Claude command |
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.15
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 directly in lib/features/profile/ 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.
To interactively pick from existing role directories:
codeable_cli feature home --pick-role
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, Localization service)
│ └── 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> | --pick-role]
| Option | Description |
|---|---|
--role, -r |
Role prefix (e.g., customer, admin). Places the feature under features/<role>/ and prefixes all file names, class names, and routes with the role. |
--pick-role, -R |
Interactively pick a role from existing role directories under lib/features/. |
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
.claude/commands/localize.md—/localize— auto-localizes an entire feature directory (scans for hardcoded strings, adds ARB keys, updates theLocalizationservice, replaces strings, and verifies).claude/commands/fix-rtl.md—/fix-rtl— migratesEdgeInsetstoEdgeInsetsDirectionalfor proper RTL/LTR support.claude/commands/add-api.md—/add-api— wires up a new API endpoint end-to-end (endpoint constant, repository, cubit, state).claude/commands/add-cubit-state.md—/add-cubit-state— adds new state fields and cubit methods to an existing feature
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.
Libraries
- codeable_cli
- codeable_cli, A CLI tool that scaffolds production-ready Flutter projects.