Deepstaging CLI¶
The deepstaging CLI generates all non-C# output from your compilation. It queries the same Deepstaging.Projection layer that source generators use — no intermediate formats, no staleness detection, just direct projection queries against your code.
Installation¶
The CLI is bundled inside the Deepstaging NuGet package. When a project sets <IsDeepstagingApp>true</IsDeepstagingApp>, MSBuild targets automatically:
- On restore — emit a
./deepstagingwrapper script in the project directory - After build — run
deepstaging syncto keep non-C# output current
The wrapper script always points to the CLI DLL from the currently-referenced package version — no separate tool install needed, no version to pin.
# In your Monolith project directory
./deepstaging sync # one-shot sync
./deepstaging sync --dry-run # preview changes
./deepstaging watch # continuous sync in a terminal
The wrapper is auto-added to .gitignore (it contains a local NuGet cache path).
Global tool install
For use outside a project directory, the CLI is also available as a global dotnet tool:
Commands¶
deepstaging watch — Continuous Sync¶
Holds the compilation warm and syncs on every file change. Run in a terminal alongside your dev server.
- Opens your project via
MSBuildWorkspaceonce (warm start) - Watches source files with 200ms debounce
- On change: incremental recompilation + all syncers run
- Output updates within milliseconds of save
deepstaging sync — CI / One-Shot¶
Explicit one-shot sync for CI pipelines or manual runs.
| Option | Description |
|---|---|
[PROJECT] |
Path to .csproj (defaults to first .csproj in current directory) |
--dry-run |
Show what would change without writing |
--skip <TYPES> |
Skip specific syncers (comma-separated) |
Skip types: wire-manifest, config, typescript, docs, ef-tooling, bruno
# Sync everything
deepstaging sync
# Sync only config and wire manifest
deepstaging sync --skip typescript,docs,ef-tooling,bruno
# Preview changes
deepstaging sync --dry-run
What Gets Generated¶
The CLI runs a set of syncers — each produces specific output files from the compilation:
Wire Manifest¶
File: wire-manifest.json
Tracks all [IntegrationEvent] wire names across the system. Append-only — new wire names are added automatically, existing entries are never removed. The DSEQ11 analyzer reads this manifest and flags removals or changes as errors.
[
{ "wireName": "ordering.order-placed", "clrType": "OrderPlaced", "registered": "2026-03-15", "status": "active" },
{ "wireName": "catalog.item-created", "clrType": "ItemCreated", "registered": "2026-03-16", "status": "active" }
]
Configuration¶
Files:
| File | Ownership | Purpose |
|---|---|---|
deepstaging.schema.json |
Machine-owned (always overwritten) | JSON Schema for appsettings.json |
deepstaging.secrets.schema.json |
Machine-owned | JSON Schema for secrets (if any [Secret] properties exist) |
deepstaging.settings.json |
Human-owned (intelligent merge) | Settings template — new keys added, existing values preserved |
deepstaging.secrets.json |
Human-owned (intelligent merge) | Secrets template (if applicable) |
Discovered from all [ConfigSection] types visible to the composition root.
TypeScript Client¶
Files: api-types.ts, api-client.ts
Auto-generated TypeScript types and client from [RestApi] projection models. Keeps your frontend type-safe against the C# API.
EF Tooling¶
File: ef.sh
Shell script wrapper for Entity Framework migrations across all discovered [DataStore] bounded contexts. Handles the --project, --context, and --output-dir flags automatically.
Documentation¶
Files: docs/{context}/index.md, docs/{context}/{entity}.md, docs/{context}/events.md, docs/{context}/api.md
Auto-generated documentation pages from [DocsModule] types — entity schemas, API routes, published/consumed events.
Bruno Collection¶
Files: bruno/opencollection.yml, bruno/environments/*.yml, bruno/{entity}/*.yml
Auto-generated Bruno API collection in OpenCollection YAML format. Per-route request definitions with environment-specific base URLs.
How It Works¶
deepstaging sync / watch
↓
CompilationProvider opens .csproj via MSBuildWorkspace
↓
Checks for [assembly: DeepstagingApp]
↓
Syncers walk the compilation
├── Per-type syncers: WalkAllNamedTypes()
└── Compilation-wide syncers: run once
↓
Each syncer calls Deepstaging.Projection queries
(same queries the source generators use)
↓
FileSync.WriteIfChanged() — only touches files that differ
↓
SyncSummaryRenderer shows results table
The CLI targets the composition root project — the one with [assembly: DeepstagingApp]. It discovers all [Runtime], [DataStore], [RestApi], [ConfigSection], and [IntegrationEvent] types across all referenced assemblies, exactly as the source generators do.
CI Integration¶
Add to your CI pipeline after build:
- name: Sync non-C# artifacts
run: dotnet deepstaging sync --dry-run # Verify nothing is stale
- name: Check wire manifest
run: |
dotnet deepstaging sync
git diff --exit-code wire-manifest.json # Fail if manifest changed
Relationship to Source Generators¶
Source generators produce C# code (store implementations, DbContexts, dispatch handlers, etc.). The CLI produces everything else (JSON schemas, TypeScript, shell scripts, docs, API collections). Both consume Deepstaging.Projection — the single source of truth for attribute interpretation.
| Output | Producer | Runs When |
|---|---|---|
| C# code | Roslyn source generators | Every compilation |
| Wire manifest, config, TypeScript, docs, ef.sh, Bruno | deepstaging CLI |
watch daemon or sync command |