This is a repo template for building a cross-platform native command line executable using .NET. It includes a sample CLI plus reusable infrastructure for self-updating, GitHub Releases integration, provenance verification, structured logging, and more.
- A minimal
System.CommandLineCLI insrc\templatecli - Source-generated JSON serialization for persisted update state
- Structured console and file logging
- Cross-platform app-home and runtime-context helpers
- GitHub Releases integration for self-update
- Provenance verification:
- GitHub artifact attestations on Linux/macOS
- Windows Authenticode verification via an embedded PowerShell verifier
- Staged self-update flow in
UpdateService - Install scripts for Windows and Linux/macOS
- Release/build workflows plus composite GitHub Actions
- Windows signing and issuer verification support
This first iteration uses a concrete placeholder app identity instead of tokenized replacements:
| Setting | Value |
|---|---|
| Command name | templatecli |
| Project/assembly name | templatecli |
| Namespace root | TemplateCli |
| Default repository | example/templatecli |
| App home env var | TEMPLATECLI_HOME |
The main source of truth for the app identity is src\templatecli\Infrastructure\AppIdentity.cs.
The sample CLI intentionally keeps only the reusable maintenance command shape:
templatecli completions scripttemplatecli configtemplatecli logstemplatecli update
shutdown-instance is retained as a hidden internal helper for Windows self-update shutdown behavior.
templatecli stores user-managed global configuration in its home folder:
- default path:
~/.templatecli/config.jsonon Linux/macOS,~\.templatecli\config.jsonon Windows - overridden path:
%TEMPLATECLI_HOME%\config.jsonor$TEMPLATECLI_HOME/config.json
View the current config:
templatecli configUpdate a value:
templatecli config --set default_log_level=debug
templatecli config --set include_prerelease_updates=trueSupported keys:
default_log_levelinclude_prerelease_updates
This template includes a built-in completions script command that emits shell completion scripts with no external dependency. The generated shell hooks call the CLI's own System.CommandLine [suggest:<cursor>] support, so users do not need dotnet-suggest or any other helper tool.
templatecli completions script [<bash|fish|pwsh|zsh>] [--command-name <name>]...
If no shell is specified, the command uses the detected current shell, defaulting to pwsh on Windows.
If no --command-name values are supplied, the generated script registers completion for templatecli. Use --command-name to target alternate entry points such as local convenience run scripts.
The install scripts automatically:
- generate a
templatecli-completions.<ext>script next to the installed binary - add a profile entry that sources that script for future shells
If you want to enable it manually later, generate a script and source it from your shell profile:
- Bash:
templatecli completions script bash > ~/.templatecli/bin/templatecli-completions.bashecho '[ -f ~/.templatecli/bin/templatecli-completions.bash ] && . ~/.templatecli/bin/templatecli-completions.bash' >> ~/.bashrc
- Zsh:
templatecli completions script zsh > ~/.templatecli/bin/templatecli-completions.zshecho '[ -f ~/.templatecli/bin/templatecli-completions.zsh ] && . ~/.templatecli/bin/templatecli-completions.zsh' >> ~/.zshrc
- Fish:
templatecli completions script fish > ~/.config/fish/completions/templatecli.fish
- PowerShell:
templatecli completions script pwsh > $HOME\\.templatecli\\bin\\templatecli-completions.ps1Add-Content -Path $PROFILE.CurrentUserAllHosts -Value ". '$HOME\\.templatecli\\bin\\templatecli-completions.ps1'"
cmd.exe does not support this integration.
src\templatecli- sample CLI plus reusable infrastructurescripts\install- Windows and Linux/macOS installersscripts- publish, bundle, provenance, validation, and C# file-based workflow helpers.github\actions- reusable composite actions for build/publish.github\workflows- CI, PR, versioning, release, and installer publication workflows
If you turn this into a real repository, start here:
- Rename the app identity in
AppIdentity.cs. - Update
Directory.Build.propsmetadata, especiallyRepositoryUrl. - Replace the sample commands in
Program.csandCommands\. - Review installer defaults in
scripts\install\install-templatecli.ps1andinstall-templatecli.sh. - Configure the
productionenvironment and installer branch/tag rulesets before first install-script publication. - Update README examples and any remaining placeholder strings like
example/templatecli. - If you change persisted models, register them in
Models\JsonContext.cs.
All of the release-channel mechanics, signing configuration, install-script publication flow, and provenance behavior live in docs/release-and-provenance.md.
Build from the repo root:
.\build.ps1The repo-root build scripts also refresh shell-completion registration for the local source runners. build.ps1 updates the current PowerShell session and persists the sourced completion file for future sessions. build.sh refreshes the sourced completion file under .templatecli-home/completions and ensures your shell profile loads it.
Or directly:
dotnet build .\src\templatecli\templatecli.csproj -nologoRun the sample CLI from source:
.\templatecli.ps1 logsValidate the script assets:
.\scripts\Verify-PowerShellSyntax.ps1./scripts/verify-shell-syntax.sh- The template intentionally preserves working release/update logic rather than abstracting everything behind a more complicated token engine.
- This is an extraction baseline, not a finished productized template. Expect to make a second pass for your final app identity, branding, and command surface.