javascript-package-delegator (jpd) is a powerful and intuitive Command Line Interface (CLI) tool designed to streamline your workflow across various JavaScript package managers. Inspired by the simplicity of @antfu/ni, jpd automatically detects the package manager used in your project (npm, Yarn, pnpm, Bun, or Deno) based on existing lock files and configuration, then transparently delegates your commands to the appropriate tool.
This eliminates the need to remember different commands or continuously switch between package managers when collaborating in diverse teams or managing multiple projects. jpd provides a unified experience, allowing you to focus on development rather than toolchain nuances.
jpd offers a comprehensive set of features to simplify your JavaScript development experience:
-
Automatic Package Manager Detection: Intelligently identifies the active package manager by checking for
package-lock.json,yarn.lock,pnpm-lock.yaml,bun.lockb,deno.json,deno.jsonc, ordeno.lock. -
Unified Command Set: Provides a consistent API for common package management tasks, regardless of the underlying tool:
-
jpd install(i,add):** Installs project dependencies. -
jpd run(r):** Executes scripts defined inpackage.jsonor tasks indeno.json. -
jpd exec(x):** Executes packages (e.g.,npx,yarn dlx,pnpm dlx,bunx). -
jpd create(c):** Scaffolds new projects using create runners (supports package names for npm/pnpm/yarn/bun and URLs for deno). -
jpd update(u,up,upgrade):** Updates installed packages to their latest compatible versions. -
jpd uninstall(un,remove,rm):** Removes specified packages from your project. -
jpd clean-install(ci):** Performs a clean installation with a frozen lockfile, ideal for CI/CD environments and production builds. -
jpd agent(a):** Displays the detected package manager for the current project.
-
-
Intelligent Yarn Version Handling: Differentiates between Yarn v1 and Yarn v2+ for
clean-installandexeccommands, applying the correct flags (--frozen-lockfilevs.--immutable/yarnvs.yarn dlx). -
Interactive Package Installation (
-s,--search): Provides an interactive interface for users to search for packages on the npm registry and select which ones to install. -
Interactive Script/Task Selection: When
jpd runis executed without arguments,jpddisplays an interactive list of available scripts frompackage.json(or tasks fromdeno.json) for you to choose from. -
Interactive Uninstall: Use
jpd uninstallwithout arguments or with the-iflag to interactively select and remove dependencies from your project. -
Automatic Package Manager Installation Prompt: If
jpddetects a lock file for a specific package manager (e.g.,yarn.lock) but that package manager is not installed on your system,jpdwill now interactively prompt you to provide a command to install it globally, ensuring you can quickly get started without manual setup. -
Flexible Agent Selection: Override automatic detection using the
--agent(-a) flag or theJPD_AGENTenvironment variable to explicitly specify your preferred package manager for a command or session. -
Change Directory Execution: Use the
--cwd(-C) flag to execute anyjpdcommand within a specified directory without changing your current shell’s working directory. This is particularly useful for running commands in sub-projects or remote locations without manually navigating. Note: paths provided to--cwdmust end with a trailing/(e.g.,/path/to/project/) unless the path is the root/. In CI builds that set the CI build flag via-ldflags, the trailing slash requirement is relaxed and bothpathandpath/are accepted. -
Comprehensive Shell Completion:
jpdprovides scripts to enable tab-completion for its commands and flags in popular shells, including Bash, Zsh, Fish, PowerShell, and Nushell. -
External Integrations: Generate Warp terminal workflows and Carapace completion specs with the
integratecommand. See Integrations section. -
Volta Integration: Automatically uses Volta to run Node.js package manager commands if Volta is detected on your system, ensuring the correct Node.js version (as defined by Volta) is used.
-
Debugging Capabilities: Enable a debug mode (
--debugor-d) to view verbose logging, aiding in troubleshooting and understanding command execution. -
Go-based Performance: Written in Go,
jpdis compiled into a single static binary, offering fast execution and easy distribution without runtime dependencies.
jpd is distributed as a single binary and can be installed via popular package managers or by downloading the binary directly.
# Via Homebrew (macOS/Linux)
brew install louiss0/tap/jpd
# Via Scoop (Windows)
scoop bucket add louiss0 https://github.com/louiss0/scoop-bucket.git
scoop install jpd
# Via Winget (Windows)
winget install jpd
# Via Chocolatey (Windows)
choco install jpd
# Via Nix (Linux/macOS)
nix profile install github:nix-community/nur#repos.the-code-fixer-23-nur.jpd
# Manual Installation (Cross-platform)
# Download the appropriate binary for your OS from the
# https://github.com/louiss0/javascript-package-delegator/releases[releases page]
# and place it in your system's PATH.|
Note
|
jpd create flags and flag passing:
Example (npm): jpd create vite@latest my-app -- --template react
# executes: npm exec create-vite@latest -- my-app --template react |
In Continuous Integration (CI) builds, you can toggle a build-time flag to relax the --cwd folder path trailing-slash validation. By default (local builds), --cwd values must end with / (except the root /). In CI mode, both path and path/ are accepted.
How to build in CI mode (relaxed --cwd):
# Tests
go test -ldflags "-X github.com/louiss0/javascript-package-delegator/build_info.rawCI=true" ./...
# Build
go build -ldflags "-X github.com/louiss0/javascript-package-delegator/build_info.rawCI=true" -o jpd ./...Notes:
- CI mode is controlled only via -ldflags (no environment detection).
- The relaxation applies only to the --cwd folder path flag; other validations are unchanged.
Once installed, you can use jpd in place of your usual package manager commands.
To see all available commands and global flags:
jpd --helpTo run a command:
jpd <command> [arguments...] [flags...]For command-specific help:
jpd <command> --helpA compact overview of jpd commands. For detailed usage, flags, and examples, see the complete command reference.
-
jpd install- Install dependencies -
jpd run dev- Run script/task
-
jpd exec create-react-app my-app- Execute packages -
jpd dlx create-react-app my-app- Execute packages with dedicated package runner
-
jpd create react-app my-app- Scaffold new projects with package names -
jpd -a deno create https://deno.land/x/fresh/init.ts my-app- Scaffold with deno URLs
-
jpd update- Update packages -
jpd uninstall lodash- Remove packages -
jpd clean-install- Clean install (CI/CD)
-
jpd agent- Show detected package manager
-
jpd integrate warp --output-dir ./workflows/- Generate Warp workflow files -
jpd integrate warp- Print workflows as multi-doc YAML -
jpd integrate carapace nushell --output ~/.config/nushell/completions/jpd.nu- Generate Nushell Carapace setup
Generate external tool integrations with the integrate command:
# Warp workflows
jpd integrate warp --output-dir ./workflows/
jpd integrate warp # print multi-doc YAML to stdout
# Carapace setup for Nushell users
jpd integrate carapace nushell --output ~/.config/nushell/completions/jpd.nuFor flags, precedence rules, and OS paths, see the Integrate command reference.
For developers maintaining shell setup docs: prefer jpd integrate carapace nushell for Nushell users, write the file to ~/.config/nushell/completions/, and tell users to source it from env.nu.
If a detected JavaScript package manager is not found a suitable installation command will be asked from you in an interative prompt. Once that happens the value will be stored in a file
NOTE:
.This project is developed using a Test-Driven Development (TDD) approach.
To run the test suite, use the ginkgo test runner:
ginkgo runTo watch files for changes and re-run tests automatically:
ginkgo watchTo validate behaviors related to --cwd path validation in CI mode, run tests with the CI build flag:
go test ./... -race -coverprofile=coverage.out -ldflags "-X github.com/louiss0/javascript-package-delegator/build_info.rawCI=true"The project follows a modular structure to ensure maintainability and testability:
├── cmd
│ ├── agent.go // 'agent' command logic
│ ├── clean-install.go// 'clean-install' command logic
│ ├── completion.go // 'completion' command logic, including all shell completions
│ ├── create.go // 'create' command logic (project scaffolding)
│ ├── dlx.go // 'dlx' command logic (dedicated package runner)
│ ├── exec.go // 'exec' command logic
│ ├── install.go // 'install' command logic
│ ├── integrate.go // 'integrate' command logic (warp)
│ ├── root.go // Main Cobra root command setup and persistent logic
│ ├── run.go // 'run' command logic
│ ├── uninstall.go // 'uninstall' command logic
│ └── update.go // 'update' command logic
├── cmd/assets // Contains embedded assets for commands (e.g., Nushell completion script)
│ └── jpd-extern.nu
├── custom_errors // Custom error definitions
│ └── root.go
├── custom_flags // Custom Cobra flags for common use cases, including path validation
│ └── root.go
├── detect // Package manager detection logic, including file system and path lookup abstractions for testability
│ └── root.go
├── env // Environment-related utilities (e.g., Go environment checks)
│ └── root.go
├── internal // Integration helpers and embedded completion assets
├── jpd-test // Test utilities and helpers
├── ni // (Potentially deprecated or internal alias related to `ni` inspiration)
├── scripts // Development and CI scripts for testing and cleanup
│ ├── check-coverage.sh // Coverage threshold checking with auto-cleanup
│ └── cleanup.sh // Clean up test artifacts and accidentally generated binaries
├── LICENSE
├── README.adoc // This documentation file
├── cmd_test.go // Tests for commands in `cmd` package
├── coverprofile.out // Go test coverage output
├── default.nix // Nix package configuration
├── detect_test.go // Tests for `detect` package
├── go.mod // Go module definition
├── go.sum // Go module checksums
├── goreleaser.yaml // GoReleaser configuration for releases
├── javascript-package-delegator_suite_test.go // Ginkgo test suite setup
└── main.go // Entry point of the application-
The
cmdpackage contains the implementation for alljpdcommands, organized into separate files for clarity. -
cmd/assetsis a new directory storing assets embedded directly with their Go code. -
custom_errorsis designed for creating named, reusable error types. -
custom_flagsprovides generic flag definitions for Cobra commands, now including robust path validation. -
The
detectpackage encapsulates the logic for identifying the JavaScript package manager in a project, now with improved testability via injected file system and path lookup interfaces. -
The
envpackage contains environment-related utilities, potentially including checks for production/development modes.
jpd is built using robust Go libraries and tools:
| Type | Name | Description |
|---|---|---|
CLI Framework |
|
A library for creating powerful modern CLI applications. |
Logging |
|
A structured, colorful logger for the terminal. |
Interactive UI |
|
A library for building interactive prompts and forms in the terminal. |
Utilities |
|
A Lodash-style Go library for collections and common helpers. |
Environment Loading |
|
Loads environment variables from |
Testing Framework |
|
A BDD-style testing framework for Go. |
Assertion Library |
|
A Go testing framework with useful assertions and mocks. |
Release Automation |
|
Automates the entire Go project release cycle. |
UI Styling |
|
Style definitions for nice terminal layouts. |
We welcome contributions to javascript-package-delegator! If you’re interested in contributing, please read our CONTRIBUTING.md (to be created) for guidelines on how to submit issues, features, and pull requests.
When creating a new command for jpd, please follow these steps:
-
Create a New File: In the
cmddirectory, create a new Go file named after your command (e.g.,mycommand.go). -
Define
New{CommandName}CmdFunction: Inside the new file, create a public functionNew{CommandName}Cmd()that returns a*cobra.Commandinstance. This function should contain the command’sUse,Short,Longdescriptions,Aliases(if any),Argsvalidation, and theRunEorPersistentPreRunElogic. -
Register Command in
root.go: In theinit()function ofjavascript-package-delegator/cmd/root.go, add your new command to therootCmdusingcmd.AddCommand(New{CommandName}Cmd()). -
Implement Flags and Arguments: Define any command-specific flags or arguments within your
New{CommandName}Cmdfunction. Ensure proper type and default value handling. -
Write Tests: Create corresponding tests for your new command in the
javascript-package-delegator_suite_test.gofile (or a dedicated test file if the command is complex), leveragingginkgoandtestify/assert.
|
Tip
|
Use cobra-cli add <command-name> as a starting point to generate the basic command structure.
|
|
Note
|
Remember to always add appropriate arguments and flags to your commands and handle them robustly. |
|
Caution
|
Ginkgo runs tests in parallel by default. Be mindful of shared state in tests. |
This project is licensed under the MIT License. See the LICENSE file for details.