Un único store de NuGet, builds byte-idénticos, sin formato de manifiesto nuevo.
PCPM es un gestor de paquetes direccionable por contenido para .NET, construido sobre Central Package Management. Recorta entre un 70-90% la huella de NuGet en disco, fija cada transitivo a un hash de contenido, e incluye de serie un doctor del workspace y auditoría de seguridad.
$ # From an empty directory…
$ pcpm init
✓ Created pcpm.json
✓ Created Directory.Packages.props
$ pcpm add Newtonsoft.Json
→ Resolved Newtonsoft.Json@13.0.3
✓ Wrote Directory.Packages.props
✓ Hardlinked to ~/.nuget/packages
$ pcpm install
→ Resolving 12 packages…
→ 11 served from store (0 KB)
→ 1 new package (387 KB) written to store
✓ dotnet restore completed in 1.4s
$ pcpm doctor
✓ CPM enabled, no floating versions
✓ Lockfile in sync, no known CVEs
✓ Workspace is clean Qué hace por ti, concretamente
No es pitch comercial — son las cuatro cosas por las que la gente se pasa a PCPM.
-
70-90% menos de disco en la caché de NuGet
Cada .nupkg distinto se almacena una sola vez en un store direccionable por contenido y se enlaza con hardlinks a ~/.nuget/packages. El store no crece con el número de proyectos — añadir un trigésimo primer proyecto que usa los mismos 200 paquetes suma cero bytes.
-
Builds reproducibles, de verdad
pcpm.lock registra la versión resuelta y el sha256 del .nupkg de cada entrada. pcpm ci rechaza continuar si el lockfile está obsoleto, falta o tiene hashes que no coinciden con el store — un run limpio de CI que resuelva un transitivo nuevo se convierte en fallo de build, no en regresión silenciosa.
-
Restauraciones limpias en CI que no son lentas
La primera install descarga el mundo. Cada install posterior — incluso en un runner limpio con caché caliente — solo trae los deltas. El paso del hardlink es solo metadatos, y dotnet restore ve un layout estándar de ~/.nuget/packages.
-
Te dice quién metió qué
pcpm why <paquete> recorre el lockfile y muestra la cadena completa de dependientes que trajo un transitivo a tu build. Cuando un bump sorpresa aparece en CI, sabes exactamente con qué dependencia directa negociar.
Salud del workspace, antes de que CI lo haga por ti
PCPM trae dos herramientas de diagnóstico reales: un doctor para la higiene de CPM y una auditoría para seguridad y licencias.
pcpm doctor
exit 1/2/0Ejecuta una batería de comprobaciones contra el workspace actual y sale con código distinto de cero ante problemas reales. Conéctalo a la puerta de calidad de tu build.
- ManagePackageVersionsCentrally está definido
- Sin versiones flotantes (1.0.*, *) en Directory.Packages.props
- Sin <PackageReference Version=…> heredado de una era pre-CPM
- Sin entradas CPM huérfanas (declaradas, sin uso)
- Sin entradas CPM faltantes (referenciadas, sin declarar)
- Lockfile sincronizado con el workspace
- CVEs conocidos desde el feed de NuGet (se salta con --no-cve)
Exit 1 = errores, 2 = warnings, 0 = limpio.
pcpm audit
SBOMEscanea el grafo resuelto contra avisos de vulnerabilidades y metadatos de licencia. --output <dir> escribe un SBOM CycloneDX y un informe de licencias.
- Escaneo de vulnerabilidades contra el feed de advisories de NuGet
- Detección de licencia e informe (identificadores SPDX)
- Salida SBOM CycloneDX (--no-sbom para saltarla)
- Modo de salida JSON para pipe en CI
¿Ya tienes una solución .NET? Migra con un solo comando.
pcpm convert recorre tu solución y la reescribe in-place: sube cada Version= por proyecto a <PackageVersion />, adopta un Directory.Packages.props existente, escribe pcpm.json y pcpm.lock.
- Adopta el Directory.Packages.props existente — nunca lo sobrescribe
- Quita Version= de <PackageReference /> en cada .csproj
- --dry-run previsualiza el diff antes de tocar nada
- --revert deshace un convert anterior
- --workspace cubre todos los proyectos del monorepo
$ pcpm convert --dry-run
→ Will write Directory.Packages.props (new)
→ Will strip Version= from 14 .csproj files
→ Will write pcpm.json + pcpm-workspace.yaml
$ pcpm convert
✓ Created Directory.Packages.props
✓ Stripped 14 Version= attributes
✓ Wrote pcpm.json
✓ pcpm install completed in 3.1s
→ Done. Roll back with: pcpm convert --revert Todo lo que necesitas, nada que sobre
Doce verbos. Sin 80 flags, sin maraña de plugins.
| Command | Qué hace |
|---|---|
| pcpm init | Inicializa un workspace (pcpm.json, Directory.Packages.props, pcpm-workspace.yaml para monorepos). |
| pcpm add <pkg> | Añade una dependencia directa. --version <v> para fijar, --project <path> para un csproj, --no-install para saltar la instalación implícita. |
| pcpm install | Resuelve el grafo transitivo, materializa los paquetes en el store, hardlink a ~/.nuget/packages, ejecuta dotnet restore. |
| pcpm remove <pkg> | Elimina de CPM y de todos los .csproj que lo referencien. |
| pcpm list | Imprime pcpm.lock formateado como tabla. |
| pcpm why <pkg> | Muestra las cadenas de dependientes que traen <pkg> al lockfile. |
| pcpm outdated | Consulta el feed por versiones más nuevas, informa del tipo de bump (major / minor / patch). |
| pcpm doctor | Higiene de CPM, versiones flotantes, Version= hardcodeado, huérfanos, entradas faltantes, sync del lockfile, feed de CVEs. |
| pcpm audit | Escaneo de vulnerabilidades, informe de licencias, SBOM CycloneDX (--output <dir>, --no-sbom). |
| pcpm convert | Migra una solución existente a CPM + pcpm. --dry-run, --revert, --workspace. |
| pcpm store status | Uso de disco del almacén global direccionable por contenido. |
| pcpm ci | Instalación estricta y fail-fast para CI — rechaza si pcpm.lock está obsoleto o los hashes no coinciden. |
Una arquitectura sobre la que puedes razonar
Tres capas, cada una con una única responsabilidad, conectadas por inyección de dependencias. Cero I/O en el core, así que las reglas de dominio se prueban en aislamiento.
pcpm.Cli
Comandos de Spectre.Console.Cli (uno por verbo) — solo orquestación fina, sin lógica de negocio.
pcpm.Core
Modelos de dominio, abstracciones, lógica pura — DependencyResolver, parseo de versiones, detección de conflictos. Sin I/O.
pcpm.Infrastructure
Implementaciones: NuGetFeed (HTTP crudo), PackageStore (direccionable por contenido), HardlinkCreator (P/Invoke Win32), CpmFileService, LockfileService, ConvertService, …
¿Listo para probar PCPM?
MIT, abierto a contribuciones. El repo se compila con un único dotnet build; la documentación cubre instalación, migración, integración con CI y la referencia completa de comandos.