<samp>pncat</samp>
A unified cli tool that enhances package managers catalog: feature
pnpm add -D pncat<samp>pnpm</samp> · <samp>yarn</samp> · <samp>bun</samp> · <samp>vlt</samp>
- <samp>🚀 Init</samp> - Initialize configuration with optimized rules
- <samp>🔍 Detect</samp> - Scan workspace to identify catalogable dependencies
- <samp>📦 Migrate</samp> - Automatically group dependencies by rules
- <samp>➕ Add</samp> - Install dependencies with catalog and workspace support
- <samp>➖ Remove</samp> - Safely remove dependencies and worksspace catalogs
- <samp>🧹 Clean</samp> - Find and remove unused catalog entries
- <samp>↩️ Revert</samp> - Revert cataloged dependencies to package.json
Usage
Init
pncat initInitialize your workspace with an optimized configuration file. Analyzes your current workspace dependencies and generates tailored rules for better project visibility.
Detect
pncat detectScans your workspace to identify dependencies that could be moved to catalogs.
Migrate
pncat migrate[!NOTE] To update catalog groups according to rules, run
pncat migrate -f, or do a clean migration withpncat revert→pncat migrate.
Automatically groups dependencies by rules (e.g., lint, test, utils), updating both workspace catalog configuration and relevant package.json.
Default rules can be found in src/rules.ts. To customize rules, create a pncat.config.ts file in the root directory.
Add
pncat add dep
pncat install dep
pncat i depAdd dependencies with prompts and catalogs support (credit to @antfu/nip). It also supports adding monorepo workspace packages using the workspace: protocol.
You can specify a catalog name using --catalog name. When no catalog is specified, dependencies are automatically assigned based on your catalog rules configuration.
Remove
pncat remove dep
pncat rm dep
pncat uninstall dep
pncat un dep
pncat u depDisplay which catalog group is using the dependency. If confirmed, it will remove the dependency from both workspace catalog configuration and package.json.
To remove a dependency from all packages in the monorepo, you can use pnpm remove dep -r or pnpm remove dep --recursive to recursively remove the dependency from all workspace packages.
Clean
pncat cleanFind unused catalog dependencies and remove them from workspace catalog configuration.
Revert
pncat revertReverts cataloged dependencies to package.json. Useful for monorepo restructuring or migration.
You can also revert specific dependencies using:
pncat revert dep
Configuration
You can use pncat init to initialize a configuration file with optimized rules based on your current workspace, or create a pncat.config.ts file manually to customize catalog rules:
import { defineConfig, mergeCatalogRules } from 'pncat'
export default defineConfig({
  // To extend default rules instead, use: catalogRules: mergeCatalogRules([...])
  catalogRules: [
    {
      name: 'vue',
      match: ['vue', 'vue-router', 'pinia'],
      // smaller numbers represent higher priority
      priority: 15,
      // Advanced: version-specific rules
      specifierRules: [
        { specifier: '<3.0.0', suffix: 'legacy', match: ['vue'] }
      ]
    }
  ],
  // Control how version ranges are processed
  specifierOptions: {
    skipComplexRanges: true,
    allowPreReleases: true,
    allowWildcards: false
  },
  // Hook to run after command completion (supports string commands, functions, or arrays)
  postRun: 'eslint --fix "**/package.json" "**/pnpm-workspace.yaml"'
})<samp>Catalog Rules:</samp>
- name: catalog name (required)
- match: packages to include, supports RegExp (required)
- priority: smaller numbers represent higher priority (optional)
- specifierRules: version-specific rules (optional)- specifier: semver range like ">=3.0.0", "<2.0.0" (required)
- match: specific packages this rule applies to (optional, defaults to parent match)
- name: complete catalog name (takes priority over suffix)
- suffix: catalog suffix (e.g., "legacy", "modern")
 
<samp>Specifier Options (optional):</samp>
- skipComplexRanges: Skip complex ranges like "||", "-", ">=" (default: true)
- skipRangeTypes: Specific range types to skip (overrides skipComplexRanges)- '||': Logical OR (e.g., "^3.0.0 || ^4.0.0")
- '-': Hyphen range (e.g., "1.2.3 - 2.3.4")
- '>=',- '<=',- '>',- '<': Comparison ranges
- 'x': Wildcard (e.g., "3.x")
- '*': Any version
- 'pre-release': Beta/alpha/rc versions
 
- allowPreReleases: Allow beta/alpha/rc versions (default: true)
- allowWildcards: Allow wildcard versions like "3.x", "*" (default: false)
Why pncat?
For monorepo repositories, maintaining consistent dependency versions across multiple packages is crucial. Grouping dependencies can significantly improve project understanding, making it easier to collaborate within teams or keep track of the project's structure.
Currently, pnpm's catalog support is limited. For example, there is no built-in feature for adding or migrating dependencies into specific groups. Managing the catalog manually across the entire project can be time-consuming and error-prone. To address this, pncat was developed.
Additionally, when migrating a specific package in a monorepo that uses catalogs, it's important to also migrate the workspace catalog configuration. This requires manually comparing which catalogs need to be removed. To streamline this process, the clean and revert commands were introduced to automate this task.
Inspiration
This project is inspired by and builds upon the excellent work of the following projects:
- taze - provided essential monorepo I/O utilities for reading and parsing workspace configuration and package.jsonfiles across workspace packages
- @antfu/nip - inspired the interactive prompts and user experience design for dependency management workflows
Special thanks to @antfu for his article Categorizing Dependencies which provided great inspiration and guidance during the development of this tool.
Related Projects
- eslint-plugin-pnpm-catalog by @onmax - ESLint plugin that enforces the use of named catalogs in pnpm workspaces
Contributors
License
MIT License © jinghaihan
 jinghaihan
jinghaihan