# src/commands

CLI command implementations, one module per top-level subcommand. Each module defines report structs, implements `OutputFormatter` (`format_text` / `format_pretty`), and exposes computation functions consumed directly by the service layer in `src/service/`. Top-level modules: `analyze`, `ci`, `context`, `daemon`, `edit`, `facts`, `find_references`, `generate`, `grammars`, `history`, `init`, `package`, `sessions`, `sync`, `syntax`, `text_search`, `tools`, `translate`, `update`, `view`. Note: trend commands (`complexity-trend`, `length-trend`, `density-trend`, `test-ratio-trend`, `trend`) have been moved out of `analyze` into `normalize trend` via `TrendService` — they continue to use the computation functions in `analyze/trend.rs` but are no longer mounted under `analyze`.

Notable modules: `context.rs` is the CLI wiring layer for the context command. Domain logic (frontmatter parsing, block matching, directory walk, `resolve_context`) lives in the `normalize-context` crate. `context.rs` re-exports `CallerContext`, `ContextBlock`, `ContextReport`, `ContextListReport`, `collect_new_context_files`, `resolve_context`, `yaml_to_json` from `normalize-context`; `OutputFormatter` impls for the report structs are in `normalize-context` behind its `cli` feature. `context.rs` itself contributes: CLI input helpers `parse_match_pairs` and `read_stdin_context` (+ private `flatten_json`), the legacy `.context.md`/`CONTEXT.md` walk (`collect_context_files`, `get_merged_context`) preserved for `service/view.rs` `--dir-context`, and a deprecation warning in `get_merged_context` prompting users to run `normalize context migrate`. `ContextKindReport`, `ContextMigrateReport`, and `ContextMigrateEntry` live in `service/context.rs` alongside `ContextService`.

`grammars.rs` exposes the grammar list/paths reports plus `ensure_grammars_first_use()` — a one-shot first-run hook called from `main.rs` and `init.rs`. It reads the `.installed-version` stamp in the user grammar dir and compares it to the running binary's `CARGO_PKG_VERSION`. If they match (or the stamp says `prebuilt`, a developer build), it short-circuits. If they differ (e.g. after `normalize update`), the stale stamp is deleted and grammars are re-downloaded for the current binary. If no stamp exists, it either marks an existing populated dir as pre-installed, auto-installs grammars via `GrammarService::install` in non-TTY sessions, or defers to the interactive `init` wizard.

`ci.rs` defines `CiReport` (wraps `DiagnosticsReport` with `engines_run` and `duration_ms`, with accessor methods `error_count`/`warning_count`/`info_count` computed on demand via a custom `Serialize` impl); `edit.rs` contains only shared type definitions (`Position`, `Operation`, `EditAction`, `EditChange`, `EditResult`) — all edit computation lives in `src/service/edit.rs`; `package.rs` exposes typed data-fetching functions (`get_info`, `get_list`, `get_tree`, `get_audit`, `show_outdated_data`) and formatting helpers (`print_human`, `print_tree`, `print_audit_human`, `find_dependency_paths`) consumed by `service/package.rs` — `get_list` returns a 3-tuple `(ecosystem, packages, all_detected_ecosystems)` so the service layer can surface multi-ecosystem advisory to callers — the old `PackageAction`/`run_package_action` print-and-return-i32 pattern has been replaced; `init.rs` includes an interactive rule setup wizard (`normalize init --setup`); `sync.rs` implements `normalize sync <dest>` for copying a project and its session metadata to a destination, with `--dry-run`, `--verbose`, `--force`, `--all`, `--active N`, `--repo`/`--exclude` filters, and post-copy index path rewriting via libsql (`SyncReport`, `SyncFileItem`). Incremental sync: `SyncManifest` records blake3 content hashes in `<dest>/.normalize/sync-manifest.json` and `copy_tree_incremental` skips unchanged files on subsequent syncs; `--force` bypasses the manifest. Session metadata is discovered via `normalize_chat_sessions::project_metadata_roots()` covering all registered AI agent formats (Claude Code, Codex, Gemini CLI, Normalize Agent); `session_metadata_roots()` is a thin wrapper that delegates to the registry; `sessions/` handles session-level analytics (`show`, `list`, `stats`, `analyze`, `messages`) — `analyze.rs` aggregates `SessionAnalysisReport` across multiple sessions including `largest_tool_results` (top-10 individual tool results by character count). Rule orchestration (`RulesService`, `run_rules_report()`, `apply_native_rules_config()`, syntax rule runner) lives in the `normalize-rules` crate, not here. The shared helper `build_filter()` constructs `Filter` values from `--exclude`/`--only` flags. `generate.rs` wires the `normalize generate types` command with `--dry-run` (preview without writing, prints `--- path ---\ncontent` for each file) and `--split` (emit one file per top-level IR type into the output directory, filename derived from type name via `type_name_to_filename`); `run_types_service` is the entry point for both modes.
