# install Scaffold the canonical Flutter consumer project structure and install the fast-CLI wrapper in a single step. Running `install` produces `bin/dispatcher.dart`, the two generated barrels, and `bin/fsa`, then injects `fluttersdk_artisan` into `pubspec.yaml` so every future `plugin:install` and `make:command` invocation resolves cleanly. --- ## Table of contents - [Basic Usage](#basic-usage) - [Synopsis](#synopsis) - [What It Writes](#what-it-writes) - [Pubspec Injection](#pubspec-injection) - [Idempotency](#idempotency) - [Fast-CLI Auto-Chain](#fast-cli-auto-chain) - [Examples](#examples) - [Related](#related) --- ## Basic Usage ```bash dart run fluttersdk_artisan install ``` Run once in a new Flutter project root. The command reads the project name from `pubspec.yaml`, writes the four artefacts listed below, and prints a summary. After this completes, use the consumer wrapper alias: ```bash dart run artisan ``` or, after the fast-CLI build finishes: ```bash ./bin/fsa ``` --- ## Synopsis Full signature as declared in `lib/src/commands/install_command.dart`: ``` install {--force : Overwrite files even when they already exist} ``` | Flag | Effect | |---|---| | `--force` | Overwrite `bin/dispatcher.dart`, the two generated barrels, and `bin/fsa` even when they are already present. Does not re-inject already-present pubspec entries. | --- ## What It Writes `install` produces four artefacts in this order: ### 1. `bin/dispatcher.dart` A generated CLI entry point that wires the consumer's own commands and plugin providers into the artisan runtime. The file is written from the `dispatcher.dart.stub` template with `{{ name }}` substituted to the `pubspec.yaml` project name. Header comment: `GENERATED by 'install' command; DO NOT EDIT. Regenerate via 'make:command' or 'plugins:refresh'.` Structure: - imports `package:/app/commands/_index.g.dart as consumer_commands` - imports `package:/app/_plugins.g.dart as plugins` - defines `_ConsumerCommandsProvider extends ArtisanServiceProvider` registering the consumer barrel - `main(List args)` calls `runArtisan(args, baseProviders: [_ConsumerCommandsProvider(), ...plugins.autoDiscoveredProviders()], delegateToConsumer: false)` ### 2. `lib/app/_plugins.g.dart` The plugins codegen barrel. Written as an empty-but-valid barrel on first install. `plugin:install` and `plugins:refresh` regenerate this file when plugins are added or removed. Never edit by hand: the source of truth is `.artisan/plugins.json`. ### 3. `lib/app/commands/_index.g.dart` The commands codegen barrel. Written as an empty-but-valid barrel on first install. `make:command` and `commands:refresh` regenerate this file as new command files appear under `lib/app/commands/`. Never edit by hand. ### 4. `bin/fsa` (via Fast-CLI Auto-Chain) A POSIX shell wrapper written by the `make:fast-cli` sub-command, which `install` calls in-process at the end of the scaffold phase. See [Fast-CLI Auto-Chain](#fast-cli-auto-chain) for details. --- ## Pubspec Injection `install` injects a `fluttersdk_artisan` dependency into `pubspec.yaml` after writing the four artefacts. Two injection modes: **Path-dep mode (monorepo)** When `.dart_tool/package_config.json` lists `fluttersdk_artisan` with a *relative* `rootUri` (sibling-package monorepo workflow), `install` resolves the path against the consumer root and writes a `path:` dependency: ```yaml dependencies: fluttersdk_artisan: path: ../fluttersdk_artisan ``` A `file://` absolute URI or any other absolute `rootUri` (the shape pub-cache produces) skips this branch and falls through to pub.dev mode. **Pub.dev mode** When no local relative-rootUri entry resolves, `install` injects the unconstrained version form so the next `dart pub get` (or `flutter pub get`) pulls the published package: ```yaml dependencies: fluttersdk_artisan: any ``` Run `dart pub get` (or `flutter pub get`) after `install` completes to resolve to a concrete version. Tighten the constraint by hand (e.g. `^0.0.1`) once the consumer has chosen a baseline. The injection is idempotent: if `pubspec.yaml` already contains a `fluttersdk_artisan:` key under `dependencies:`, neither form is written again (regardless of `--force`). --- ## Idempotency Re-running `install` without `--force` is a no-op when the artefacts already exist. Each file goes through a `_shouldWrite(path, force)` guard: if the file exists and `force` is false, the write is skipped and a `[skip]` line is printed for that artefact. The pubspec injection is always idempotent (key presence check, independent of `--force`). Pass `--force` to overwrite all four artefacts unconditionally. Useful after renaming the project or updating the stub template to a newer version: ```bash dart run fluttersdk_artisan install --force ``` `--force` is forwarded to the `make:fast-cli` auto-chain as well, so `bin/fsa` is rewritten and the AOT binary is recompiled from scratch. --- ## Fast-CLI Auto-Chain At the end of `scaffoldInto`, `install` calls `MakeFastCliCommand.scaffoldInto(root, force, ctx)` in-process. This produces `bin/fsa`, compiles the AOT binary under `.artisan/cli-bundle/`, and patches `.gitignore`. The call happens only after all scaffold writes and pubspec injection succeed, so a partial failure in the scaffold phase does not leave a compiled binary that references a missing dispatcher. The fast-CLI step is not separately gated: if `dart build cli` fails (e.g. the Dart SDK is too old to support it, the toolchain is missing, or the build itself errors), `make:fast-cli` returns a non-zero exit code and `install` propagates that failure. The scaffold artefacts written before the failure remain on disk so the project is still usable via `dart run fluttersdk_artisan ` (the slower fallback). Re-running `install --force` after fixing the underlying issue recompiles `bin/fsa` and the AOT cache. See [make:fast-cli](make-fast-cli.md) for the full performance profile, cache-hit behavior, and POSIX-only caveat. --- ## Examples ### 1. Fresh install in a new Flutter project ```bash flutter create my_app cd my_app dart run fluttersdk_artisan install ``` Output: ``` write bin/dispatcher.dart write lib/app/_plugins.g.dart write lib/app/commands/_index.g.dart inject pubspec.yaml (fluttersdk_artisan: ^0.0.1) write bin/fsa (Building artisan CLI, one-time ~8s...) Done. Run './bin/fsa status' to verify. ``` ### 2. Force-overwrite after project rename ```bash dart run fluttersdk_artisan install --force ``` Regenerates `bin/dispatcher.dart` with the updated project name and recompiles `bin/fsa`. ### 3. Native-asset hooks note `install` uses `dart build cli` (via the `make:fast-cli` auto-chain) to compile `bin/dispatcher.dart` into an AOT binary. This requires Dart 3.5 or later because transitive dependencies may declare `hook/build.dart` build hooks. On earlier SDKs, `bin/fsa` is not written but the rest of the scaffold completes normally. Use `dart run artisan ` as the fallback invocation form on those environments. ### 4. Monorepo path-dep install In a monorepo where `fluttersdk_artisan` lives at `../fluttersdk_artisan`, run `flutter pub get` once to populate `.dart_tool/package_config.json`, then: ```bash dart run fluttersdk_artisan install ``` The path-dep form is detected automatically and written to `pubspec.yaml`. No flag needed. --- ## Related - [make:command](make-command.md): scaffold a single `ArtisanCommand` subclass under `lib/app/commands/` and regenerate `_index.g.dart`. - [plugin:install](plugin-install.md): register a third-party plugin after `flutter pub add`; requires the `lib/app/_plugins.g.dart` barrel that `install` writes. - [make:fast-cli](make-fast-cli.md): the sub-command auto-chained by `install`; run it standalone to rebuild `bin/fsa` without touching the scaffold artefacts. - [Getting Started: Installation](../getting-started/installation.md): step-by-step walkthrough from `dart pub add` to first `./bin/fsa status` for both vanilla Flutter and magic-stack projects.