pm cd command to actually change your shell’s working directory, rather than just printing a path.
Quick Setup
Add this line to your shell configuration file:What Gets Activated
Thepm activate command outputs two things:
- Shell wrapper function - Intercepts
pm cdto enable directory navigation - Enhanced completions - Adds package name completions for
pm cd
The Shell Wrapper
Here’s what the wrapper function does (fromsrc/commands/activate.ts):
Shell wrapper (simplified)
Intercepts pm cd
When you run
pm cd @myapp/web, the shell function catches it before the actual CLI runs.Executes the CLI command
Calls
command pm cd @myapp/web to get the package directory path from the Better PM CLI.Changes directory
If the CLI succeeds and returns a valid directory, uses
builtin cd to navigate there.Enhanced Completions
The activation also sets up intelligent completions that list your workspace packages when you type:Zsh Integration
For zsh, the activation adds custom completion logic:Zsh completions
- First loads the base completions generated by Better PM’s CLI framework
- Wraps the completion function to add custom behavior for
pm cd - When completing the first argument after
pm cd, callspm cd --completionsto get package names - For all other commands, delegates to the base completion function
The
--completions flag is handled by src/commands/cd.ts and outputs one package name per line.Bash Integration
Bash uses a similar but slightly different approach:Bash completions
- Uses
COMP_WORDSarray instead of zsh’s$words - Uses
compgenfor completion generation - Registers with the
completebuiltin instead of zsh’s completion system
Using pm cd
Once shell integration is active, you can navigate your workspace:Without Shell Integration
If you haven’t activated shell integration,pm cd still works but only prints the path:
-p / --path flag explicitly:
Troubleshooting
pm cd doesn't change directory
pm cd doesn't change directory
Symptoms: Running
pm cd @myapp/web prints the path but doesn’t navigate.Diagnosis:-
Check if the shell wrapper is loaded:
Should show:
pm is a shell function(notpm is /path/to/pm) -
Verify activation line is in your shell config:
- Add
eval "$(pm activate zsh)"to your~/.zshrc(or bash equivalent) - Reload:
source ~/.zshrc
Completions don't show package names
Completions don't show package names
Symptoms: Typing
pm cd <TAB> doesn’t show your workspace packages.Diagnosis:-
Test completions directly:
Should list all workspace package names.
-
Check if you’re in a monorepo:
Should list your packages. If not, you may not be in a workspace.
- Ensure you have workspace configuration (see Monorepo Setup)
- Reload shell after adding activation line
- For zsh, ensure
compinitruns after the activation line
Conflicts with other pm tools
Conflicts with other pm tools
Symptoms: The shell wrapper interferes with other tools named Or rename the Better PM binary during installation if conflicts are severe.
pm.Solution:
You can selectively disable the wrapper for specific commands:Slow completions in large monorepos
Slow completions in large monorepos
Symptoms: Tab completion for
pm cd takes several seconds.Cause: The CLI is being invoked synchronously to generate completions.Mitigation:- Install via Homebrew (recommended): Uses native binary, completions resolve in ~60ms
- If using npm install: Completions invoke Node.js which is slower
- Large monorepos (100+ packages) may still see slight delays
Advanced Usage
Multiple Shells
If you use both zsh and bash, add activation to both config files:~/.zshrc
~/.bashrc
pm activate command outputs shell-specific code, so each shell gets the correct syntax.
Custom Prompts
The shell wrapper doesn’t interfere with prompt customization. You can still use tools like:- Starship
- Oh My Zsh themes
- Powerline
- Custom PS1/PROMPT variables
Integration with Directory Jumpers
Better PM works alongside tools like:z/zoxide- Frecency-based jumpingautojump- Smart directory navigationj- Jump to recent directories
Scripting with pm cd
In scripts, use the--path flag to avoid shell wrapper complications:
Script example
Performance Considerations
The shell wrapper adds minimal overhead:- Function check: ~0.1ms (checks if command is
cd) - CLI invocation: 60ms (Homebrew) or 200-500ms (npm install)
- Directory change: <1ms
Source Code Reference
The shell integration is implemented in/src/commands/activate.ts (lines 6-66):
shellWrapper(lines 6-22): The bash/zsh function that interceptspm cdzshCompletions(lines 24-34): Zsh-specific completion enhancementbashCompletions(lines 36-44): Bash-specific completion enhancementactivateCmd(lines 57-66): Command that outputs the combined activation code
pm cd --completions flag is handled in /src/commands/cd.ts (lines 31-36).