Skip to main content
The AI•Pkg server is built by forking NuGetGallery, stripping everything that doesn’t translate to the AI plugin registry use case, and building the AI•Pkg-specific surface on top. The migration is structured into four phases so that core infrastructure (Phases 0–1) can be verified independently before UI (Phase 3) and CLI (Phase 4) work begins.
The existing NuGetGallery.sln (139 projects) is not converted. A new AI•Pkg.slnx is created from scratch, pulling in only the source files and projects that are being retained.

Pre-Migration: Fork Setup

1

Fork the repo

Fork NuGet/NuGetGalleryAI•Pkg/AIpkgGallery on GitHub.
2

Create dev branch

Create a dev branch from main for migration work.
3

Protect main

Do not push breaking changes to main until Phase 1 is complete and tested.
4

Add specs

Add the src/AI•Pkg.Docs/ directory to the fork (already done).

Phase 0: Clean Solution Foundation

Goal: A buildable ASP.NET Core 10 SLNX solution with SQL Server DB Project and EasyAF scaffolding, no legacy code.

Step 0.1: Create AI•Pkg.slnx

Create a new Visual Studio SLNX solution file at the repo root. Add projects incrementally as they are created.

Step 0.2: Create Core Projects

ProjectTypeNotes
src/AI•Pkg.Core/.NET 10 class libraryNo NuGet output yet
src/AI•Pkg.Server/ASP.NET Core 10 web appMinimal APIs + Blazor
src/AI•Pkg.Server.Db/SQL Server DB Project (.sqlproj)Schema source of truth
src/AI•Pkg.Server.Data/.NET 10 class libraryEasyAF-generated; committed
tests/AI•Pkg.Core.Tests/xUnit .NET 10
tests/AI•Pkg.Server.Tests/xUnit .NET 10

Step 0.3: Set Up SQL Server Database Project

NuGetGallery sourceAI•Pkg tableChanges
PackagesPackagesRemove: RequiresLicenseAcceptance, DevelopmentDependency, IsSymbolsPackage. Add: Capabilities, Targets, Permissions (JSON columns)
PackageVersionsPackageVersionsSame as above; keep download count
PackageOwnersPackageOwnersNo change
UsersUsersKeep; remove legacy OpenID fields
CredentialsCredentialsKeep PBKDF2 API key structure
PackageDependenciesPackageDependenciesAdd Apms column (JSON) instead of TargetFramework
PackageTagsPackageTagsNo change
PackageHistoriesPackageHistoriesNo change
PackageRenames(drop)Not needed
SymbolPackages(drop)Not applicable

Step 0.4: EasyAF Code Generation

Run EasyAF CLI against AI•Pkg.Server.Db/ to generate:
  • EF Core 10 entity classes → AI•Pkg.Server.Data/Entities/
  • Repository classes → AI•Pkg.Server.Data/Repositories/
  • AIpkgDbContext.csAI•Pkg.Server.Data/
Generated files are committed to the repo and regenerated whenever the DB project changes.

Phase 0 Verification

  • dotnet build AI•Pkg.slnx succeeds with zero errors
  • dotnet test on AI•Pkg.Core.Tests and AI•Pkg.Server.Tests passes
  • DB project publishes successfully to a local SQL Server instance
  • EasyAF-generated entities compile against the DB project schema

Phase 1: Core Registry API + Auth + AI•Pkg.Core

Goal: Working push, download, registration, and authentication. Package round-trip: aipkg packaipkg pushaipkg install.

Source Files to Port

Source fileDestinationAction
src/NuGet.Services.Entities/Package.csAI•Pkg.Server.Data/Entities/Package.csGenerated by EasyAF; use as reference for field list
src/NuGetGallery.Core/Packaging/PackageMetadata.csAI•Pkg.Core/Packaging/ManifestReader.csPort pattern; replace XML with System.Text.Json
src/NuGetGallery.Core/Frameworks/FrameworkCompatibilityService.csAI•Pkg.Core/Platform/PlatformCompatibilityService.csPort architecture; replace TFM logic with APM fallback graph
src/NuGetGallery/Controllers/ApiController.cs (V3 parts)AI•Pkg.Server/Api/V3/Port push/delete/autocomplete as Minimal APIs
src/NuGet.Jobs.Catalog2Registration/Schema/EntityBuilder.csAI•Pkg.Server/Jobs/RegistrationBuilder.csPort; update JSON-LD schema for AI•Pkg fields
src/NuGetGallery/Services/PackageService.csAI•Pkg.Server/Services/PackageService.csPort; strip symbol/V2 logic
src/NuGetGallery/Services/UserService.csAI•Pkg.Server/Services/UserService.csPort PBKDF2 API key management
src/NuGetGallery/Authentication/AI•Pkg.Server/Auth/Port GitHub OAuth + API key auth
src/NuGetGallery.Core/Services/CorePackageFileService.csAI•Pkg.Server/Storage/PackageStorageService.csPort; rename .nupkg.aipkg

Step 1.1: AI•Pkg.Core Implementation Order

1

AipkgManifest model

Implement AipkgManifest model with System.Text.Json source-gen serialization.
2

AipkgReader

ZIP reading and manifest extraction.
3

AipkgWriter

ZIP creation.
4

PlatformCompatibilityService

APM fallback graph (hardcoded table for now).
5

AipkgValidator

Manifest validation + archive validation.
6

AipkgVersion

SemVer parsing and range checking.
Write unit tests for each in AI•Pkg.Core.Tests.

Step 1.2: Registry API Endpoints

Implement Minimal API endpoints in AI•Pkg.Server/Api/V3/:
GET  /v3/index.json
GET  /v3/registration/{id}/index.json
GET  /v3/registration/{id}/{version}.json
GET  /v3/flatcontainer/{id}/index.json
GET  /v3/flatcontainer/{id}/{version}/{id}.{version}.aipkg
GET  /v3/flatcontainer/{id}/{version}/{id}.{version}.aispec
PUT  /v3/package
DELETE /v3/package/{id}/{version}
GET  /v3/platforms
GET  /v3/registration/{id}/{version}/install/{apm}
Search and autocomplete endpoints are added in Phase 2 (they depend on Azure AI Search).

Phase 1 Verification

  • aipkg pack {id}.aispec produces a valid {id}.{version}.aipkg
  • aipkg push {package}.aipkg succeeds against a local server instance
  • GET /v3/flatcontainer/{id}/{version}/{id}.{version}.aipkg returns the uploaded package
  • GET /v3/registration/{id}/index.json returns valid registration data
  • aipkg verify {package}.aipkg exits 0 for a valid package, 1 for invalid
  • API key auth blocks unauthorized pushes with 401

Phase 2: Search + Catalog Pipeline

Goal: Functional search and autocomplete. Packages appear in search results after push.

Source Files to Port

SourceDestinationAction
src/NuGet.Services.AzureSearch/Models/BaseMetadataDocument.csAI•Pkg.Server.Search/AipkgSearchDocument.csPort structure; adapt fields
src/NuGet.Services.AzureSearch/ (indexing pipeline)AI•Pkg.Server.Search/Port; use AipkgSearchDocument
src/Stats.*src/AI•Pkg.Jobs/Stats/Port CDN stats parsing; adapt for .aipkg
src/GitHubVulnerabilities2Db/src/AI•Pkg.Jobs/Vulnerabilities/Port; adapt package ID resolution

Phase 2 Verification

  • Pushing a package makes it appear in GET /v3/search?q={id} within 60 seconds
  • GET /v3/search?apm=claude-code returns only claude-compatible packages
  • GET /v3/search?capability=mcp-server filters correctly
  • GET /v3/autocomplete?q={prefix} returns matching package IDs
  • Download count increments after each package download (within stats job cycle)

Phase 3: Blazor Web UI

Goal: Full public-facing web UI. Users can browse, search, view packages, upload, and manage accounts via browser. Build all Blazor components as defined in Registry UI spec. No porting of Razor views — build fresh. Implementation order:
  1. Layout components (NavBar, Footer, MainLayout)
  2. Package detail page (most important for discoverability)
  3. Search / browse pages
  4. Home page
  5. Upload wizard
  6. Account / API key management
  7. Admin panel

Phase 3 Verification

  • Home page loads and shows featured/new packages
  • Search returns results with correct filtering by APM and capability
  • Package detail page shows README, manifest, version history
  • Version selector switches versions without full page reload
  • Upload wizard accepts a valid .aipkg and publishes successfully
  • API key management allows create/revoke
  • All public SSR pages score ≥90 on Lighthouse SEO and Performance
  • WCAG 2.1 AA automated checks pass

Phase 4: aipkg CLI MVP

Goal: Functional install, restore, remove, list, search commands. Single-binary Native AOT release. Add remaining CLI commands (see SDK Interface spec): install, restore, remove, list, search, info, sources, new, login, logout Configure Native AOT publishing pipeline in GitHub Actions. Publish to GitHub Releases.

Phase 4 Verification

  • aipkg install git-helpers downloads, extracts, and installs to .claude/ (on claude-code)
  • aipkg restore installs all packages from aipkg.config.json
  • aipkg.lock.json is written with correct hashes and resolved versions
  • aipkg remove git-helpers cleans up installed files
  • aipkg search mcp returns results from aipkg.org
  • Native AOT binary runs on Windows, macOS, Linux without .NET runtime installed
  • Binary size < 30 MB per platform

What to Delete from NuGetGallery

Entire Projects / Directories

PathReason
src/NuGetGallery/ (old MVC app)Replaced by AI•Pkg.Server/
src/NuGetGallery.Core/Replaced by AI•Pkg.Core/ + AI•Pkg.Server.*
src/NuGet.Services.Entities/Replaced by EasyAF-generated entities
src/NuGet.Services.Odata/V2 OData — not used
src/NuGetGallery.WebUITests/Old Selenium tests — not used
src/NuGet.Jobs.Symbols*/Symbol package infrastructure — not applicable
src/NuGet.Services.Logging/Replace with Microsoft.Extensions.Logging directly
tests/NuGetGallery.Core.Facts/Recreate in AI•Pkg.Core.Tests/
tests/NuGetGallery.Facts/Recreate in AI•Pkg.Server.Tests/
NuGetGallery.FunctionalTests.slnNot migrated
tools/ (Python tooling)Python scripts — not used

Files Within Retained Projects

File/PatternReason
**/*.cshtmlAll Razor views — replaced by Blazor
**/_ViewImports.cshtmlRazor infrastructure
**/BundleConfig.jsjQuery bundling
**/Startup.cs (OWIN)OWIN startup — replaced by Program.cs
**/Global.asax*OWIN/System.Web
src/NuGetGallery/OData/V2 OData controllers
src/NuGetGallery/Controllers/ODataV*V2 OData controllers
**/AutofacRegistration*.csAutofac modules
**/ContainerBindings.csAutofac container setup
**/packages.configOld-style NuGet package references

Project Rename Reference

OriginalNew
NuGetGalleryAI•Pkg.Server
NuGetGallery.CoreAI•Pkg.Core
NuGet.Services.EntitiesAI•Pkg.Server.Data (generated)
NuGet.Services.AzureSearchAI•Pkg.Server.Search
NuGetGallery.Core.FactsAI•Pkg.Core.Tests
NuGetGallery.FactsAI•Pkg.Server.Tests
Stats.*AI•Pkg.Jobs (combined jobs project)
GitHubVulnerabilities2Dbpart of AI•Pkg.Jobs
NuGet.Packaging (client)AI•Pkg.Core (implements own reader/writer)
NuGetGallery.slnAI•Pkg.slnx

Critical Source Files to Reference

Read these NuGetGallery files before implementing the corresponding AI•Pkg components:
NuGetGallery sourceAI•Pkg componentWhat to learn
src/NuGet.Services.Entities/Package.csAI•Pkg.Server.Data/Entities/Package.csEntity field list, relationships
src/NuGetGallery.Core/Frameworks/FrameworkCompatibilityService.csAI•Pkg.Core/Platform/PlatformCompatibilityService.csFallback graph algorithm
src/NuGet.Services.AzureSearch/Models/BaseMetadataDocument.csAI•Pkg.Server.Search/AipkgSearchDocument.csSearch document field design
src/NuGet.Jobs.Catalog2Registration/Schema/EntityBuilder.csAI•Pkg.Server/Jobs/RegistrationBuilder.csRegistration blob construction
src/NuGetGallery.Core/Packaging/PackageMetadata.csAI•Pkg.Core/Packaging/ManifestReader.csManifest parsing patterns
src/Stats.*/AI•Pkg.Jobs/Stats/CDN log parsing
src/GitHubVulnerabilities2Db/AI•Pkg.Jobs/Vulnerabilities/Vulnerability job pattern

Open Items / Lower Priority

ItemNotes
License scanningEvaluate porting NuGet.Jobs.Validation.PackageSigning.*; lower priority
Package signingSpec defined in Code Signing spec; implement post-MVP
OIDC auth providerPost-MVP; add alongside GitHub OAuth
TypeScript SDK@aipkg/core etc.; post-MVP (see SDK Interface spec)
@aipkg/claude-code npm packagePost-MVP
DotNetDocs.com integrationBegin after AI•Pkg.Core 1.0.0 stabilizes
Package verified badgesNeed author verification system design
A/B testing frameworkPost-MVP