Skip to content

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:

bash
# 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:

sh
#!/usr/bin/env -S pkgx -q [package]@[version]

For more complex requirements, you might want to use:

sh
#!/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:

bash
#!/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:

bash
#!/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:

bash
#!/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:

bash
#!/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:

bash
#!/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:

bash
#!/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:

bash
#!/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:

bash
#!/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:

bash
#!/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:

bash
#!/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:

bash
#!/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:

bash
# 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:

bash
# 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:

bash
# 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:

bash
#!/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.

Released under the MIT License.