ag_cli
The Flutter GetX CLI that developers actually love.
Scaffold production-ready modules in seconds — not hours.
Angular CLI for Flutter.
ag_clidoes for GetX what Angular CLI does for Angular — one command wires up every layer of your architecture, tested and ready to ship.
Why ag_cli?
Every Flutter GetX developer knows the grind: copy-paste a controller, wire up the binding, register the route, create the service, write the repo… for every single feature. It's repetitive, error-prone, and eats hours.
ag_cli eliminates all of it.
One command generates a complete, production-grade module — controller with debounced search, paginated repo, Dio service, typed binding with fenix: true, animated app bar, filter chips, and auto-injected routes. Every file is wired together, every import correct, on the first try.
What the best alternatives give you:
| Feature | get_cli |
mason (templates) |
ag_cli |
|---|---|---|---|
| Interactive arrow-key prompts | ❌ | ❌ | ✅ |
| Auto-injects routes into existing files | ❌ | ❌ | ✅ |
| Debounced search + history baked in | ❌ | ❌ | ✅ |
| Smart Refresh (no redundant API calls) | ❌ | ❌ | ✅ |
| Background JSON parsing (Isolate) | ❌ | ❌ | ✅ |
flutter pub add on init |
❌ | ❌ | ✅ |
Rewrites main.dart to GetMaterialApp |
❌ | ❌ | ✅ |
ag doctor environment checks |
❌ | ❌ | ✅ |
ag upgrade self-update |
❌ | ❌ | ✅ |
| Spinner + color-coded output | ❌ | ✅ | ✅ |
| 160/160 pub.dev score | — | — | ✅ |
Installation
dart pub global activate ag_cli
Make sure ~/.pub-cache/bin is on your PATH. Then verify your setup:
ag doctor
Quick Start
# 1. Create a fresh Flutter project
flutter create my_app && cd my_app
# 2. Scaffold the full GetX architecture
ag init
# 3. Generate your first feature module
ag g module orders --full
That's it. You now have a fully wired orders module with:
- paginated repo + Dio service
- controller with search, debounce, filter chips, and history
- animated app bar that switches between title and search field
- binding with
fenix: trueon every dependency - page using
GetBuilder,CustomRefreshIndicator, andSearchHistoryPanel - routes automatically injected into
app_routes.dart,app_pages.dart, androute_management.dart
Commands
ag g — Generate
The core command. Run it interactively with no arguments:
ag g
Arrow-key menus guide you through type → name → mode. Or skip the prompts entirely:
ag g module <name> [--full | --minimal | --search]
ag g component <name>
ag g model <name>
ag g repo <name>
ag g controller <name> [--minimal]
ag g binding <name>
ag g page <name> [--full | --minimal | --search]
Shortcuts:
ag g m orders --full # module
ag g c OrderCard # component
ag g r orders # repo
ag g ctrl orders --minimal # controller
ag g b orders # binding
ag g p orders --full # page
Flags:
| Flag | Description |
|---|---|
--full / -f |
Search + filter chips + history + smart refresh |
--minimal / -m |
Clean controller, no search |
--search / -s |
Search + history, no filter chips |
--dry-run / -d |
Preview files without writing them |
--force |
Overwrite existing files |
--module |
Target module for individual generators |
--package |
Override package name (auto-detected from pubspec.yaml) |
--output |
Override lib/ directory |
ag init — Scaffold Project
Run once in a fresh Flutter project. Creates the full GetX folder structure, installs get, dio, logger, shared_preferences, and flutter_screenutil, then rewrites main.dart to use GetMaterialApp and ScreenUtilInit.
ag init
ag init --dry-run # preview what would be created
ag init --force # overwrite existing files
What gets created:
lib/
├── apis/providers/api_provider.dart ← Dio + interceptors + error handling
├── bindings/initial_binding.dart ← Global GetX dependencies
├── constants/enums.dart ← LoadingStatus enum
├── core/
│ ├── guards/
│ │ └── auth_guard.dart ← Token validation & redirect
│ ├── isolate_handler.dart ← Background JSON parsing
│ └── services/
│ ├── theme_service.dart ← Persistent dark/light mode
│ └── search_history_service.dart ← Search history persistence
├── extensions/response_extension.dart
├── helpers/query_helper.dart
├── model/common/state_model.dart ← Filter chip model
├── modules/ ← Your feature modules go here
├── resources/app_string.dart
├── routes/
│ ├── app_pages.dart
│ ├── app_routes.dart
│ └── route_management.dart
├── utils/
│ ├── dimens.dart ← ScreenUtil-powered spacing
│ ├── utility.dart
│ └── theme/
│ ├── app_colors.dart
│ └── app_theme.dart
└── widgets/
├── common/
│ ├── app_error_widget.dart
│ ├── empty_state_page_new.dart
│ ├── item_card.dart
│ ├── list_shimmer.dart
│ └── search_history_panel.dart
└── custom/
├── custom_refresh_indicator.dart
└── custom_scrollview_with_sliverappbar.dart
ag doctor — Check Your Environment
ag doctor
Checks Dart SDK version (≥ 3.0.0), Flutter installation, pubspec.yaml, required packages, and whether ag init has been run.
ag list / ag ls — List Generators
ag list
ag upgrade — Self-Update
ag upgrade
Example App & Best Practices
Check out the example/ folder in the repository! We've scaffolded a reference application using only ag_cli commands.
cd example
flutter run
The example highlights:
- Centralized
StorageService: A robust, type-safe wrapper overSharedPreferencesinjected duringag init. - Pre-built
AuthGuard: AGetMiddlewareimplementation protecting private routes instantly. - Generated Modules: Full
AuthLogin,Home,Profile,Settings, andProductsDetailsmodules with automatic routing. - Nested Architecture: Showcases how
components/details/stay cleanly separated while logic stays flat.
Generated Module Structure
Running ag g module orders --full produces:
lib/modules/orders/
├── repos/
│ └── orders_repo.dart ← Abstract interface + IsolateHandler impl
├── services/
│ └── orders_service.dart ← Dio endpoints, typed, documented
├── controllers/
│ └── orders_controller.dart ← Search, debounce, filters, pagination, history
├── bindings/
│ └── orders_binding.dart ← lazyPut + fenix: true
├── pages/
│ └── orders_page.dart ← Stack + SearchHistoryPanel + PopScope
├── components/
│ ├── orders_app_bar.dart ← AnimatedSwitcher: normal ↔ live search bar
│ ├── orders_appbar_filter.dart ← Horizontal filter chip row
│ └── orders_card.dart ← Clean list item card
└── models/
├── orders_model.dart ← fromJson / toJson stub
└── orders_response_model.dart ← Paginated wrapper
Plus, routes are automatically injected into your existing route files. No manual wiring.
Nested Submodules
You can easily generate submodules (e.g. an item details page that belongs to the parent orders module).
ag g m orders/details --full
ag_cli intelligently separates your UI and Logic:
- Logic (
orders_details_controller.dart,orders_details_repo.dart, etc.) is cleanly merged into the parentlib/modules/orders/folder, maintaining a flat MVC architecture. - UI Components (
orders_details_card.dart,orders_details_app_bar.dart) are isolated into their own subfolder:lib/modules/orders/components/details/.
The Smart Refresh Pattern
The generated controller implements a debounced search + smart refresh strategy that eliminates unnecessary API calls:
| User Action | API Call? | Why |
|---|---|---|
| Open search, type locally, press back | ❌ | Nothing was fetched |
| Submit a search query | ✅ | Fetches filtered results |
| Submit the same query again | ❌ | Duplicate guard |
| Clear search (✕) after submitting | ✅ | Restores full list |
| Press back after submitting | ✅ | Restores full list |
| Pull-to-refresh while search is open | ✅ | Closes search and refreshes |
The debouncer fires at 700ms — fast enough to feel responsive, slow enough to not hammer your API on every keystroke.
Overwrite Protection
By default, ag_cli skips files that already exist:
⚠ lib/modules/orders/controllers/orders_controller.dart already exists (skipped, use --force to overwrite)
Use --force to overwrite, or --dry-run to preview without touching anything.
Architecture Overview
ag_cli uses args + CommandRunner (same pattern as the Dart SDK CLI itself)
Logger: mason_logger (same library used internally by the Flutter team)
Templates: pure Dart string functions — zero external dependencies at runtime
The architecture maps directly to what Angular CLI, Flutter CLI, and Dart CLI use. Each command is an isolated Command<int> class. run() returns an exit code. Errors are caught and exit with code 1.
Contributing
PRs are welcome. Run tests with:
dart test
dart analyze
dart format .
Made with ❤️ by Kripadevg — built for Flutter developers who ship fast.
Libraries
- ag_cli
- ag_cli — Flutter GetX module generator.