Custom Shims
Beyond the basic shim creation functionality, Launchpad allows for advanced shim customization for more complex scenarios, performance optimization, and specialized workflows.
Understanding Shim Architecture
Launchpad shims are lightweight executable scripts that:
- Activate the appropriate environment
- Set necessary environment variables
- Execute the target binary with proper context
- Maintain isolation between different project environments
Manual Shim Creation
If you need more control over your shims than the standard launchpad shim
command provides, you can create them manually:
# Create a directory for your shims if it doesn't exist
mkdir -p ~/.local/bin
# Create a custom shim file
cat > ~/.local/bin/custom-node << EOF
#!/bin/sh
exec pkgx -q node@22.0.0 --max-old-space-size=4096 "\$@"
EOF
# Make it executable
chmod +x ~/.local/bin/custom-node
Shim Templates
Launchpad's shims generally follow this template:
#!/usr/bin/env -S pkgx -q [package]@[version]
For more complex requirements, you might want to use:
#!/bin/sh
# Custom environment settings
export NODE_OPTIONS="--max-old-space-size=8192"
export DEBUG=true
# Execute the actual command
exec pkgx -q [package]@[version] "$@"
Environment-Aware Shims
Create shims that integrate with Launchpad's environment system:
#!/bin/sh
# Custom Node.js shim with environment awareness
# Check if we're in a Launchpad environment
if [ -n "$LAUNCHPAD_ENV_HASH" ]; then
# Use environment-specific binary if available
ENV_NODE="$HOME/.local/share/launchpad/envs/$LAUNCHPAD_ENV_HASH/bin/node"
if [ -x "$ENV_NODE" ]; then
exec "$ENV_NODE" "$@"
fi
fi
# Fallback to global pkgx
exec pkgx -q node@22 "$@"
Package-specific Shims
Sometimes, you might want to create a shim for a specific command within a package:
#!/bin/sh
# Use TypeScript compiler from a specific version of TypeScript
exec pkgx -q typescript@5.0.0 tsc "$@"
Version Locking
Lock a shim to a specific package version:
#!/bin/sh
# Ensure we always use Node.js 22 for this shim
exec pkgx -q node@22 "$@"
Environment Variables
Add environment variables to a shim:
#!/bin/sh
# Set environment variables
export NODE_ENV=production
export DEBUG=false
# Execute the command
exec pkgx -q node "$@"
Performance-Optimized Shims
Create shims that directly reference installed binaries for better performance:
#!/bin/sh
# Direct execution shim (faster than pkgx resolution)
# Update path based on your actual installation
DIRECT_PATH="$HOME/.local/pkgs/nodejs.org/v22.0.0/bin/node"
if [ -x "$DIRECT_PATH" ]; then
exec "$DIRECT_PATH" "$@"
else
# Fallback to pkgx
exec pkgx -q node@22 "$@"
fi
Shell Message Integration
Create shims that provide feedback when used:
#!/bin/sh
# Shim with custom messaging
if [ "$LAUNCHPAD_SHOW_ENV_MESSAGES" = "true" ]; then
echo "🚀 Using custom Node.js shim" >&2
fi
exec pkgx -q node@22 "$@"
Compound Commands
Create shims that run multiple commands in sequence:
#!/bin/sh
# Run ESLint then Prettier
echo "🔍 Running ESLint..." >&2
pkgx -q eslint "$@" && {
echo "✨ Running Prettier..." >&2
pkgx -q prettier --write "$@"
}
Platform-specific Shims
Create shims that behave differently based on the platform:
#!/bin/sh
# Platform-specific behavior
case "$(uname)" in
Darwin)
# macOS-specific options
exec pkgx -q python@3.12 -m venv "$@"
;;
Linux)
# Linux-specific options
exec pkgx -q python@3.11 -m venv "$@"
;;
CYGWIN*|MINGW*|MSYS*)
# Windows-specific options
exec pkgx -q python@3.12 -m venv "$@"
;;
*)
# Default fallback
exec pkgx -q python@3.11 -m venv "$@"
;;
esac
Project-Aware Shims
Create shims that detect project context:
#!/bin/sh
# Project-aware Node.js shim
# Check for project-specific Node version
if [ -f package.json ]; then
# Extract Node version from engines field (requires jq)
if command -v jq >/dev/null 2>&1; then
NODE_VERSION=$(jq -r '.engines.node // empty' package.json 2>/dev/null)
if [ -n "$NODE_VERSION" ]; then
exec pkgx -q "node@$NODE_VERSION" "$@"
fi
fi
fi
# Check for .nvmrc
if [ -f .nvmrc ]; then
NODE_VERSION=$(cat .nvmrc)
exec pkgx -q "node@$NODE_VERSION" "$@"
fi
# Default to latest LTS
exec pkgx -q node@22 "$@"
Debugging Shims
Create a debug version of a shim:
#!/bin/sh
# Debug shim with detailed information
if [ "$LAUNCHPAD_DEBUG_SHIMS" = "true" ]; then
echo "🐛 Debug Info:" >&2
echo " Arguments: $*" >&2
echo " Working directory: $(pwd)" >&2
echo " PATH: $PATH" >&2
echo " Environment hash: $LAUNCHPAD_ENV_HASH" >&2
fi
# Run with verbose output if debugging
if [ "$LAUNCHPAD_DEBUG_SHIMS" = "true" ]; then
exec pkgx -v -q node "$@"
else
exec pkgx -q node "$@"
fi
Fallback Shims
Create shims with multiple fallback strategies:
#!/bin/sh
# Multi-fallback shim
# Try environment-specific binary first
if [ -n "$LAUNCHPAD_ENV_HASH" ]; then
ENV_BINARY="$HOME/.local/share/launchpad/envs/$LAUNCHPAD_ENV_HASH/bin/node"
if [ -x "$ENV_BINARY" ]; then
exec "$ENV_BINARY" "$@"
fi
fi
# Try system installation
for path in /usr/local/bin/node ~/.local/bin/node; do
if [ -x "$path" ]; then
exec "$path" "$@"
fi
done
# Try pkgx as last resort
if command -v pkgx >/dev/null 2>&1; then
exec pkgx -q node "$@"
fi
# Final fallback
echo "❌ Node.js not found. Install with: launchpad install node" >&2
exit 1
Managing Custom Shims
Organized Shim Directory
Keep track of custom shims by storing them in a Git repository:
# Create a repository for your custom shims
mkdir ~/my-shims
cd ~/my-shims
git init
# Create subdirectories for organization
mkdir -p {development,production,debug,platform-specific}
# Create your shims in appropriate directories
# development/node-dev
# production/node-prod
# debug/node-debug
# platform-specific/node-macos
# Add them to git
git add .
git commit -m "Add custom shims"
# Symlink them to your PATH
find ~/my-shims -type f -executable | while read shim; do
ln -sf "$shim" ~/.local/bin/
done
Shim Testing
Test your custom shims thoroughly:
# Test basic functionality
~/my-shims/development/node-dev --version
# Test with different arguments
~/my-shims/development/node-dev -e "console.log('test')"
# Test environment variable handling
LAUNCHPAD_DEBUG_SHIMS=true ~/my-shims/debug/node-debug --version
Shim Documentation
Document your custom shims:
# Create a README for your shims
cat > ~/my-shims/README.md << EOF
# Custom Launchpad Shims
## Development Shims
- \`node-dev\`: Node.js with development optimizations
- \`python-dev\`: Python with debugging enabled
## Production Shims
- \`node-prod\`: Node.js with production settings
- \`python-prod\`: Python with performance optimizations
## Debug Shims
- \`node-debug\`: Node.js with verbose debugging
- \`python-debug\`: Python with debug information
## Platform-Specific Shims
- \`node-macos\`: macOS-optimized Node.js
- \`python-linux\`: Linux-optimized Python
## Usage
Symlink desired shims to ~/.local/bin/ and ensure it's in your PATH.
EOF
Dynamic Shim Generation
Create a script to generate shims dynamically:
#!/bin/bash
# generate-shim.sh - Dynamic shim generator
PACKAGE="$1"
VERSION="$2"
TYPE="${3:-standard}"
OUTPUT_DIR="$HOME/.local/bin"
if [ -z "$PACKAGE" ] || [ -z "$VERSION" ]; then
echo "Usage: $0 <package> <version> [type]"
echo "Types: standard, debug, performance, environment-aware"
exit 1
fi
case "$TYPE" in
debug)
cat > "$OUTPUT_DIR/$PACKAGE" << EOF
#!/bin/sh
echo "🐛 Debugging $PACKAGE@$VERSION" >&2
exec pkgx -v -q $PACKAGE@$VERSION "\$@"
EOF
;;
performance)
cat > "$OUTPUT_DIR/$PACKAGE" << EOF
#!/bin/sh
# Performance-optimized shim
DIRECT_PATH="\$HOME/.local/pkgs/$PACKAGE/v$VERSION/bin/$PACKAGE"
if [ -x "\$DIRECT_PATH" ]; then
exec "\$DIRECT_PATH" "\$@"
else
exec pkgx -q $PACKAGE@$VERSION "\$@"
fi
EOF
;;
*)
cat > "$OUTPUT_DIR/$PACKAGE" << EOF
#!/bin/sh
exec pkgx -q $PACKAGE@$VERSION "\$@"
EOF
;;
esac
chmod +x "$OUTPUT_DIR/$PACKAGE"
echo "✅ Created $TYPE shim for $PACKAGE@$VERSION at $OUTPUT_DIR/$PACKAGE"
This approach allows you to version control your custom shims and easily deploy them to new machines or share them with team members.