# SAIF.Platform.CLI

## Description

The SAIF CLI is a console app that is published to a Nuget Feed and is installed using the dotnet cli.  This CLI is used to automate processes that a developer might do manually like dotnet new, creating Azure DevOps Pipeline, creating Azure DevOps Repo, and many other automation processes.

## Why we use it

We use it to give a single interface to do multiple operations across multiple cloud services.  It will be used create all project in CIAM, so that every project is created with standard setup and naming.

## Command model

The CLI nouns are layered deliberately. Understanding the layers explains why `app` and `service` look similar but are **not** redundant.

| Layer | Commands | Returns | Question it answers |
|-------|----------|---------|---------------------|
| **Facet** (raw lookups) | `app`, `repo`, `pipeline`, `docs` | One row per underlying resource (e.g. one Entra app registration, one repo) | "Show me this specific registration / repo / build." |
| **Aggregate** (one domain, consolidated) | `service` | A `Service` that groups app registrations by environment and correlates its repository | "Show me everything about this service across its environments." |
| **Federation** (cross-domain) | `search` | Merged hits from multiple domains (services + docs) | "Find anything matching this term." |

Key points:

- **`app` and `service` share the same catalog (`IServiceCatalog`), not the same shape.** `app` returns raw `CatalogService` rows (the facet tier); `service` returns the consolidated `Service` aggregate built by `ServiceGrouper` + repository correlation. The overlap is intentional reuse, not duplication.
- **`app` is symmetric with `repo`.** Both are facet-level lookups that the `service` aggregate draws from. Just as `service` correlates a repository while `repo search` does the raw repo lookup, `service` consolidates registrations while `app search` does the raw registration lookup.
- **`app` is not a strict subset of `service`.** It powers the auth/token path (`app search --audience`/`--app-id`, used when resolving a JWT `aud`) and can surface registrations that are deliberately excluded from `service` (vendor/COTS/free-text apps without a known environment suffix). Those are only reachable through `app`.
- **Aggregate ≠ federation.** `service` consolidates *one domain across environments*; `search` federates *across domains*. They are different aggregation axes, so `service` is not "a smaller `search`".
- **Pipelines are keyed by repo, not service.** `service describe` reports a pipeline count and a hint (`saif pipeline list --repo <name>`); there is no direct service→pipeline data coupling.

Practical guidance: use `service describe <name>` for the full topology of a known service, the facet commands (`app`, `repo`, `pipeline`) for targeted raw lookups, and `search` to discover across domains.

<a id="prerequisites"></a>
<a id="setup"></a>

## Installation and updates

Follow [Install the SAIF CLI](https://github.com/saif-corp/forge/blob/main/docs/learn/install-saif-cli.md) for prerequisites, NuGet feed authentication, installation, verification, and updates. That guide owns the setup instructions rather than duplicating them in this package README.

Use [CLI workflows](https://github.com/saif-corp/forge/blob/main/docs/reference/cli-workflows.md) for token, publishing, repair, service-discovery, and documentation-retrieval behavior. The documentation build generates the [command reference](https://docs.saif.com/forge/reference/dotnet/SAIF.Platform.CLI/commands/) from the source-backed CLI manifest.


[Generated command reference](commands.md)

---

[View source on GitHub](https://github.com/saif-corp/forge/blob/main/src/dotnet/SAIF.Platform.CLI/README.md)
