Common Workflows¶
This guide shows you how to use bunenv in real-world scenarios. Each workflow is task-oriented and ready to copy-paste into your projects.
Development Workflows¶
Local Development with Version Control¶
The standard workflow for a project with bunenv:
# Initial setup
cd my-project
bunenv .venv --bun=1.3.3
echo ".venv/" >> .gitignore # Don't commit the environment
echo "1.3.3" > .bun-version # Do commit the version
# Daily workflow
source .venv/bin/activate
bun install
bun run dev
# When done
deactivate_bun
Key Points:
Put the version in
.bun-versionfor teammatesAdd
.venv/to.gitignoreTeammates run
bunenv .venvand it reads the version automatically
Multiple Projects with Different Versions¶
Keep separate projects isolated:
# Legacy project
cd ~/projects/legacy-app
bunenv .venv --bun=1.0.0
source .venv/bin/activate
(legacy-app) $ bun --version # 1.0.0
# Deactivate
deactivate_bun
# Modern project
cd ~/projects/new-app
bunenv .venv --bun=latest
source .venv/bin/activate
(new-app) $ bun --version # 1.3.3
# Work continues without conflicts!
Testing Against Multiple Bun Versions¶
Test your library against different Bun releases:
# Test matrix
for version in 1.0.0 1.1.0 1.2.0 1.3.0; do
echo "Testing with Bun $version"
bunenv "test-env-$version" --bun="$version"
source "test-env-$version/bin/activate"
bun install
bun test
deactivate_bun
done
# Cleanup
rm -rf test-env-*
CI/CD Integration¶
GitHub Actions¶
Basic workflow for GitHub Actions:
# .github/workflows/test.yml
name: Test
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install bunenv
run: pip install bunenv
- name: Setup Bun environment
run: |
bunenv .venv --bun=1.3.3
source .venv/bin/activate
echo "$PWD/.venv/bin" >> $GITHUB_PATH
- name: Install dependencies
run: bun install
- name: Run tests
run: bun test
Matrix Testing Across Bun Versions¶
Test against multiple Bun versions:
# .github/workflows/test-matrix.yml
name: Test Matrix
on: [push, pull_request]
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
bun-version: ['1.0.0', '1.1.0', '1.2.0', 'latest']
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install bunenv
run: pip install bunenv
- name: Setup Bun
run: bunenv .venv --bun=${{ matrix.bun-version }}
- name: Activate Bun (Unix)
if: runner.os != 'Windows'
run: |
source .venv/bin/activate
echo "$PWD/.venv/bin" >> $GITHUB_PATH
- name: Activate Bun (Windows)
if: runner.os == 'Windows'
run: |
.venv\Scripts\activate.bat
echo "$PWD\.venv\Scripts" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
- name: Run tests
run: bun test
GitLab CI¶
# .gitlab-ci.yml
image: python:3.11
stages:
- test
test:
stage: test
before_script:
- pip install bunenv
- bunenv .venv --bun=1.3.3
- source .venv/bin/activate
script:
- bun install
- bun test
Travis CI¶
# .travis.yml
language: python
python:
- "3.11"
before_install:
- pip install bunenv
- bunenv .venv --bun=1.3.3
- source .venv/bin/activate
install:
- bun install
script:
- bun test
CircleCI¶
# .circleci/config.yml
version: 2.1
jobs:
test:
docker:
- image: cimg/python:3.11
steps:
- checkout
- run:
name: Install bunenv
command: pip install bunenv
- run:
name: Setup Bun
command: |
bunenv .venv --bun=1.3.3
source .venv/bin/activate
echo 'export PATH=$PWD/.venv/bin:$PATH' >> $BASH_ENV
- run:
name: Install dependencies
command: bun install
- run:
name: Run tests
command: bun test
workflows:
version: 2
test:
jobs:
- test
Python Integration¶
Bun Inside Python Virtualenv¶
Use Bun and Python together in one environment:
# Create Python virtualenv
python -m venv .venv
source .venv/bin/activate
# Install bunenv in the virtualenv
pip install bunenv
# Install Bun into the same virtualenv
bunenv --python-virtualenv --bun=latest
# Now you have both!
(venv) $ python --version # Python 3.11.x
(venv) $ bun --version # 1.3.3
# Deactivate deactivates both
(venv) $ deactivate_bun
(venv) $ deactivate
Polyglot Project: Python Backend + Bun Frontend¶
Typical full-stack setup:
my-app/
├── backend/ # Python code
│ └── requirements.txt
├── frontend/ # Bun/TypeScript code
│ ├── package.json
│ └── src/
├── .python-version # Python version
└── .bun-version # Bun version
Setup script:
#!/bin/bash
# setup.sh
# Backend setup
cd backend
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
# Frontend setup (install bunenv in Python venv)
pip install bunenv
cd ../frontend
bunenv --python-virtualenv --bun=$(cat ../.bun-version)
bun install
echo "Setup complete! Both Python and Bun are ready."
Using pyproject.toml for Configuration¶
If your Python project uses pyproject.toml, you can configure bunenv there:
# pyproject.toml
[tool.bunenv]
bun = "1.3.3"
variant = ""
github_token = "" # Or use environment variable
Then run:
bunenv --python-virtualenv --config-file=pyproject.toml
Package Management¶
Requirements File¶
Install packages from a requirements file:
# bun-requirements.txt
express
typescript
@types/node
zod
drizzle-orm
Install during environment creation:
bunenv .venv --bun=latest --requirements=bun-requirements.txt
Or install later:
source .venv/bin/activate
while read pkg; do
[[ "$pkg" =~ ^#.*$ ]] && continue # Skip comments
bun add "$pkg"
done < bun-requirements.txt
Global vs Local Packages¶
bunenv environments are isolated, so “global” means “global to this environment”:
source .venv/bin/activate
# Install globally in this environment
(venv) $ bun add --global typescript
# It's available as a command
(venv) $ tsc --version
# But only in this environment!
(venv) $ deactivate_bun
$ tsc --version # Error: command not found
Lock Files and Reproducibility¶
Commit bun.lockb for reproducible installs:
# First developer
bunenv .venv --bun=1.3.3
source .venv/bin/activate
bun install
git add bun.lockb .bun-version
git commit -m "Lock dependencies"
# Second developer
git pull
bunenv .venv # Reads .bun-version automatically
source .venv/bin/activate
bun install # Uses bun.lockb for exact versions
Platform-Specific Workflows¶
macOS (Apple Silicon)¶
bunenv automatically detects and uses aarch64 binaries:
# On M1/M2/M3 Mac
bunenv .venv --bun=latest
# Verify it's ARM
source .venv/bin/activate
(venv) $ file .venv/bin/bun
# Output: Mach-O 64-bit executable arm64
For Rosetta compatibility (x64):
# Force x64 binary (runs under Rosetta)
arch -x86_64 bunenv .venv --bun=latest
Alpine Linux / musl¶
bunenv auto-detects musl and downloads the correct variant:
# On Alpine Linux
bunenv .venv --bun=latest
# Automatically downloads bun-linux-x64-musl
# Verify
source .venv/bin/activate
(venv) $ ldd .venv/bin/bun
# Shows musl, not glibc
Windows with WSL¶
WSL users should use Linux commands:
# Inside WSL
bunenv .venv --bun=latest
source .venv/bin/activate # Linux activation
# NOT Windows activation
Avoid GitHub API Rate Limits¶
GitHub limits unauthenticated API requests to 60/hour. For CI or heavy use:
# Create token at https://github.com/settings/tokens
# No scopes needed for public repos
# One-time use
bunenv .venv --bun=latest --github-token=ghp_your_token
# Persistent config
echo "github_token = ghp_your_token" >> ~/.bunenvrc
bunenv .venv --bun=latest # Uses token automatically
# CI environment variable
export GITHUB_TOKEN=ghp_your_token
bunenv .venv --bun=latest --github-token=$GITHUB_TOKEN
Migration Scenarios¶
From System Bun to bunenv¶
# Check current version
bun --version # 1.2.0
# Create environment with same version
bunenv .venv --bun=1.2.0
source .venv/bin/activate
# Move global packages (if any)
# Note: Bun doesn't have traditional global packages like npm
# Update your workflow
# Old: bun install
# New: source .venv/bin/activate && bun install
From nodeenv to bunenv¶
If you’re migrating from Node.js/nodeenv:
# Old Node.js project
nodeenv .nodeenv --node=18.0.0
source .nodeenv/bin/activate
npm install
# New Bun project
bunenv .venv --bun=latest
source .venv/bin/activate
bun install # Reads package.json from npm
# Bun is compatible with npm packages!
From Docker Bun to bunenv¶
Replace Docker for local development:
# Old: Docker-based development
docker run -v $(pwd):/app oven/bun bun install
# New: Local isolated environment
bunenv .venv --bun=1.3.3
source .venv/bin/activate
bun install
# Still use Docker for production!
Monorepo Workflows¶
Multiple Services, Different Bun Versions¶
my-monorepo/
├── services/
│ ├── api/ # Bun 1.3.0
│ │ ├── .venv/
│ │ └── .bun-version
│ ├── worker/ # Bun 1.2.0
│ │ ├── .venv/
│ │ └── .bun-version
│ └── frontend/ # Bun latest
│ ├── .venv/
│ └── .bun-version
└── setup.sh
Setup script:
#!/bin/bash
# setup.sh
for service in services/*; do
echo "Setting up $service..."
cd "$service"
bunenv .venv --bun=$(cat .bun-version)
source .venv/bin/activate
bun install
deactivate_bun
cd ../..
done
Automation Scripts¶
Auto-Activate on Directory Change¶
Add to your .bashrc or .zshrc:
# Auto-activate bunenv when .venv/ exists
bunenv_auto_activate() {
if [[ -f ".venv/bin/activate" ]] && [[ "$VIRTUAL_ENV" != "$PWD/.venv" ]]; then
source .venv/bin/activate
fi
}
# Hook into directory change
cd() {
builtin cd "$@"
bunenv_auto_activate
}
Project Initialization Script¶
#!/bin/bash
# init-bun-project.sh
set -e
PROJECT_NAME=${1:-my-project}
BUN_VERSION=${2:-latest}
echo "Creating Bun project: $PROJECT_NAME"
# Create directory
mkdir -p "$PROJECT_NAME"
cd "$PROJECT_NAME"
# Create bunenv
bunenv .venv --bun="$BUN_VERSION"
source .venv/bin/activate
# Initialize Bun project
bun init -y
# Setup git
git init
echo ".venv/" >> .gitignore
echo "node_modules/" >> .gitignore
echo "$BUN_VERSION" > .bun-version
echo "Project ready! Run: cd $PROJECT_NAME && source .venv/bin/activate"
Cleanup Script¶
Remove unused environments:
#!/bin/bash
# cleanup-bunenvs.sh
find ~ -type d -name ".venv" -path "*/bin/bun" | while read env; do
echo "Found: $env"
read -p "Delete? [y/N] " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
rm -rf "$(dirname "$env")"
echo "Deleted!"
fi
done
Best Practices Summary¶
DO:
✓ Use .bun-version for version pinning
✓ Add .venv/ to .gitignore
✓ Commit bun.lockb for reproducibility
✓ Use GitHub tokens for CI to avoid rate limits
✓ Create separate environments per project
DON’T:
✗ Commit the .venv/ directory
✗ Use sudo with bunenv
✗ Mix system Bun with environment Bun
✗ Forget to activate before installing packages
✗ Share environments between projects
Next Steps¶
These workflows should cover most use cases. For more advanced topics:
Advanced Topics - Custom variants, mirrors, edge cases
Configuration Guide - Deep dive into config files and options
Troubleshooting - When things don’t work as expected
Got a workflow we missed? Open an issue and we’ll add it!