Background
PR #16927 landed Phase 1 of the git-based template system: spec, gitTemplatesEnabled feature flag, and four stub subcommands behind it (aspire template list, search, refresh, new). This issue tracks the remaining phases needed to make the feature actually usable.
This work resumes the spike from PR #14763, but with a key architectural change: template discovery is delegated to a single aspire.dev HTTP endpoint instead of a federated walk of aspire-template-index.json files. That removes per-repo index files, includes federation, gh-based personal/org auto-discovery, and the aspire template new-index command. CLI configuration collapses to templates.serviceUrl + templates.cacheTtlMinutes.
The full architecture is in docs/specs/git-templates.md. The phased plan is in §15 of that spec.
Current state (shipped in #16927)
KnownFeatures.GitTemplatesEnabled (default false).
aspire template command group wired into RootCommand behind the flag.
- 4 stub subcommands that print "not yet implemented" and return
Success.
- 15 parse / feature-flag-gating tests, all passing.
- No real implementation behind any of the commands yet.
Enable for local smoke testing:
aspire config set features.gitTemplatesEnabled true
aspire template --help
Remaining phases
Each phase below should ship as its own PR so reviews stay focused.
Phase 2: Catalog client + caching primitives
- HTTP client for
GET {templates.serviceUrl}/templates/index.json?q=&language=&limit=&cursor= with response shape per spec §3.
- Disk cache layout under
~/.aspire/templates/:
index/ — HTTP-cached catalog responses keyed by full URL, honoring templates.cacheTtlMinutes (default TBD; see §13).
repos/<repo-hash>/<sha>/ — content-addressed git checkouts (no writes after phase 2).
templates.serviceUrl + templates.cacheTtlMinutes config keys with sensible defaults.
- Decide cache size budget and eviction policy (open question in spec §13).
- Tests: catalog client (with a fake
HttpMessageHandler), TTL behavior, malformed payload handling, cursor pagination.
Phase 3: aspire template list + aspire template search <keyword>
- Wire the catalog client into the
list and search stubs.
- Render results as a Spectre table (name, description, language, tags, publisher, verified badge).
- Honor
--language, --limit, paging via --cursor or auto-page-on-demand (decide which).
- Tests: end-to-end with a faked catalog response; verify rendering, filtering, and pagination.
Phase 4: aspire template refresh
- Force-refresh both the index cache and (optionally) any pre-fetched repo checkouts.
- Decide whether refresh is global or accepts a
--template <name> filter.
- Tests: confirm cache invalidation observable in subsequent
list calls.
Phase 5: aspire template new <name> [path] (single-template, .NET only)
- Resolve
<name> against the catalog → (repo, ref, path).
- Clone or fetch into the content-addressed
repos/ cache; checkout the resolved sha.
- Apply the template via the existing dotnet template engine path (per-template manifest in spec §4 and §7).
- Stay .NET-only for this phase; defer polyglot to phase 6.
- Tests: full flow against a local fake git server (or git file:// remote in a temp dir); verify content lands on disk and engine variables are wired.
Phase 6: Polyglot engine support
- Implement the language-agnostic template engine described in spec §11 (token replacement, file renaming, conditional inclusion).
- Honor per-template manifest opting into the polyglot engine instead of the dotnet template engine.
- Tests: end-to-end with a representative non-.NET template (Node, Python, etc.).
Cross-cutting open questions (spec §13)
These need answers before / alongside the phases above:
- Final shape of the
aspire.dev/templates/index.json response. Current schema in spec §3 is a placeholder.
- Catalog governance: who decides what gets listed, how malicious entries are removed, signing strategy (security review TBD; spec §10 currently has a
TODO).
- Cache size budget + eviction policy.
- Whether the catalog host is literally
aspire.dev or some other domain.
- Telemetry: what events to emit on list/search/new for catalog feedback.
References
Background
PR #16927 landed Phase 1 of the git-based template system: spec,
gitTemplatesEnabledfeature flag, and four stub subcommands behind it (aspire template list,search,refresh,new). This issue tracks the remaining phases needed to make the feature actually usable.This work resumes the spike from PR #14763, but with a key architectural change: template discovery is delegated to a single
aspire.devHTTP endpoint instead of a federated walk ofaspire-template-index.jsonfiles. That removes per-repo index files,includesfederation,gh-based personal/org auto-discovery, and theaspire template new-indexcommand. CLI configuration collapses totemplates.serviceUrl+templates.cacheTtlMinutes.The full architecture is in
docs/specs/git-templates.md. The phased plan is in §15 of that spec.Current state (shipped in #16927)
KnownFeatures.GitTemplatesEnabled(defaultfalse).aspire templatecommand group wired intoRootCommandbehind the flag.Success.Enable for local smoke testing:
Remaining phases
Each phase below should ship as its own PR so reviews stay focused.
Phase 2: Catalog client + caching primitives
GET {templates.serviceUrl}/templates/index.json?q=&language=&limit=&cursor=with response shape per spec §3.~/.aspire/templates/:index/— HTTP-cached catalog responses keyed by full URL, honoringtemplates.cacheTtlMinutes(default TBD; see §13).repos/<repo-hash>/<sha>/— content-addressed git checkouts (no writes after phase 2).templates.serviceUrl+templates.cacheTtlMinutesconfig keys with sensible defaults.HttpMessageHandler), TTL behavior, malformed payload handling, cursor pagination.Phase 3:
aspire template list+aspire template search <keyword>listandsearchstubs.--language,--limit, paging via--cursoror auto-page-on-demand (decide which).Phase 4:
aspire template refresh--template <name>filter.listcalls.Phase 5:
aspire template new <name> [path](single-template, .NET only)<name>against the catalog →(repo, ref, path).repos/cache; checkout the resolved sha.Phase 6: Polyglot engine support
Cross-cutting open questions (spec §13)
These need answers before / alongside the phases above:
aspire.dev/templates/index.jsonresponse. Current schema in spec §3 is a placeholder.TODO).aspire.devor some other domain.References
docs/specs/git-templates.md