workon
v3.8.0
Published
Work on something great!
Maintainers
Readme
workon
Work on something great! 🚀
A productivity CLI tool that helps developers quickly switch between projects with automatic environment setup. No more manually navigating to project directories, opening IDEs, or remembering project-specific commands.
Features
✨ Smart Project Switching - Switch between projects in your current shell (no nested processes!)
🔧 IDE Integration - Automatically open projects in VS Code, IntelliJ IDEA, or Atom
🌐 Web Integration - Launch project websites and documentation
🌳 Git Branch Support - Different configurations for different branches
🌲 Git Worktrees - Create, open, and manage git worktrees with tmux integration
📁 Auto Directory Change - Seamlessly cd into project directories
⚡ Interactive Setup - Guided project configuration
🔄 Backward Compatible - Legacy nested shell mode still available
Requirements
- Node.js >= 20
Installation
Option 1: Global Installation (Recommended)
# Install globally
npm install -g workon
# Set up shell integration (one time setup)
echo 'eval "$(workon --init)"' >> ~/.zshrc # for zsh
echo 'eval "$(workon --init)"' >> ~/.bashrc # for bash
# Reload your shell
source ~/.zshrc # or ~/.bashrcOption 2: Using npx (No Global Install)
# Set up shell integration
echo 'eval "$(npx workon --init)"' >> ~/.zshrc # for zsh
echo 'eval "$(npx workon --init)"' >> ~/.bashrc # for bash
# Reload your shell
source ~/.zshrc # or ~/.bashrcVerify Installation
workon --helpQuick Start
Add your first project:
cd ~/code/myproject workon add . # Register current directory as a projectOr use interactive mode:
workon # Start interactive setup wizardSwitch to a project:
workon myproject # Automatically cd + open IDEList available projects:
workon config list
Project Configuration
Projects are configured with:
- Path: Where your project lives
- IDE: Which editor to open (
code,idea,atom) - Events: What happens when switching to the project
cwd: Change directory to project pathide: Open project in configured IDEweb: Open project homepage/docsclaude: Launch Claude Code (with optional tmux split)npm: Run npm scripts (with optional tmux pane)docker: Start Docker containers
Interactive Project Setup
Run workon to start the interactive setup wizard:
$ workon
8 v1.0.0-alpha.1
Yb db dP .d8b. 8d8b 8.dP .d8b. 8d8b.
YbdPYbdP 8' .8 8P 88b 8' .8 8P Y8
YP YP `Y8P' 8 8 Yb `Y8P' 8 8
? What do you want to do?
❯ Start a new project
Open an existing project
Manage projects
ExitManual Configuration
# Set base directory for all projects
workon config set project_defaults.base ~/code
# Add a project
workon config set projects.myapp.path myapp
workon config set projects.myapp.ide code
workon config set projects.myapp.events.cwd true
workon config set projects.myapp.events.ide trueUsage Examples
Adding Projects
# Add current directory as a project
cd ~/code/myproject
workon add .
# Add with a custom name
workon add . --name my-awesome-project
# Add with specific IDE
workon add . --ide idea
# Add a project from any path
workon add ~/code/another-projectBasic Project Switching
# Switch to project (changes directory + opens IDE)
workon myproject
# Shell mode - outputs commands instead of executing
workon myproject --shell
# Output: cd "/path/to/myproject"
# code "/path/to/myproject" &Colon Syntax (Run Specific Events)
Use the colon syntax to run only specific events for a project:
# Run only the cwd event (just change directory)
workon myproject:cwd
# Run multiple specific events
workon myproject:cwd,ide
# Show available events for a project
workon myproject:helpBranch-Specific Configuration
# Configure different settings for a git branch
workon myproject#feature-branchGit Worktrees
Manage git worktrees with full tmux integration. There are two commands:
workon worktrees- Manage worktrees (run from the main repository)workon worktree- Operate on the current worktree you're inside
Managing Worktrees (from main repo)
cd ~/code/myproject
# Show interactive worktree menu
workon worktrees
# List worktrees
workon worktrees list
# Create a new worktree
workon worktrees add feature-branch
# Open workon session in a worktree (creates tmux session)
workon worktrees open feature-branch
# Remove a worktree
workon worktrees remove feature-branch
# Merge worktree branch and remove
workon worktrees merge feature-branch
# Create branch from detached HEAD (for PR workflow)
workon worktrees branch my-worktree new-branch-name --pushOperating on Current Worktree (from inside a worktree)
When you're inside a worktree, use workon worktree (singular):
cd ~/code/myproject/.worktrees/feature-branch
# Show status of current worktree
workon worktree
workon worktree status
# Merge this worktree's branch into main/master
workon worktree merge
# Recycle worktree for the next task (ff to latest main)
workon worktree recycle
# Remove this worktree (shows instructions to exit first)
workon worktree removeIf you run workon worktrees from inside a worktree, you'll get a helpful error directing you to use workon worktree instead.
Notes
- If you run worktree commands from an unregistered git repository, workon will prompt you to register it first
- Worktrees created by workon are stored in
.worktrees/inside the project - External worktrees (created elsewhere) show as "(external)" in the list
Post-Setup Hook
Create .workon/worktree-setup.sh in your project to run commands after creating a worktree:
#!/bin/bash
# Install dependencies
[ -f "package.json" ] && npm install
# Copy environment file
[ -f "$PROJECT_PATH/.env" ] && cp "$PROJECT_PATH/.env" .envEnvironment variables available:
WORKTREE_PATH- Absolute path to the new worktreePROJECT_PATH- Absolute path to the main project
Legacy Mode (Nested Shells)
# Use the old behavior if needed (spawns new shell)
workon myproject --no-shell # (this is the default)Configuration Management
# List all configuration
workon config list
# Set a value
workon config set key value
# Remove a value
workon config unset keyShell Integration Details
The modern shell integration works by:
- Setup:
workon --initoutputs a shell function - Usage: When you run
workon myproject, the function:- Calls
workon myproject --shellto get commands - Uses
evalto execute them in your current shell
- Calls
- Result: No nested shells, seamless directory changes
Manual Shell Integration
If you prefer not to modify your shell config:
# Get commands and execute manually
eval "$(workon myproject --shell)"
# Or see what commands would run
workon myproject --shellFor AI Agents
All worktree commands support a -y, --yes flag that skips interactive prompts, making them safe to call from AI agents, scripts, and CI pipelines.
Non-Interactive Worktree Lifecycle
# Create a worktree (auto-defaults base branch to current)
workon worktrees add feat-x -b main -y
# Create and immediately open a session
workon worktrees add feat-x -b main -y -o
# Open an existing worktree session
workon worktrees open feat-x -y
# Create a branch from a worktree and push it
workon worktrees branch feat-x my-branch -y -p
# Merge, remove worktree, and delete the branch
workon worktrees merge feat-x -i main -y --delete-branch
# Force-remove a worktree with uncommitted changes
workon worktrees remove feat-x -y -fColon Syntax with Worktrees
Run specific events in a worktree using the extended colon syntax:
# project:events:worktree-name
workon myproject:cwd:feat-x # cd into worktree
workon myproject:claude:feat-x # open Claude in worktree
workon myproject:cwd,claude:feat-x # specific events in worktree
workon myproject::feat-x # all events in worktreeNon-Interactive Flags Reference
worktrees(plural) = manage worktrees from the main repo.worktree(singular) = operate on the worktree you're currently inside.
workon worktrees (from main repo)
| Command | Flag | Effect when set |
|---------|------|-----------------|
| worktrees add | -y, --yes | Skips registration prompt, auto-defaults base branch, skips "open session?" prompt |
| worktrees add | -b, --base <branch> | Sets base branch (avoids branch selection prompt) |
| worktrees add | -o, --open | Opens session after creation (avoids prompt) |
| worktrees add | --no-hook | Skips post-setup hook |
| worktrees open | -y, --yes | Skips registration prompt |
| worktrees branch | -y, --yes | Skips "push to origin?" prompt (use -p to push) |
| worktrees branch | -p, --push | Pushes branch (avoids prompt) |
| worktrees remove | -y, --yes | Skips confirmation prompt |
| worktrees remove | -f, --force | Force-removes with uncommitted changes |
| worktrees remove | --no-hook | Skips pre-teardown hook |
| worktrees merge | -y, --yes | Skips all prompts, auto-selects target branch (main/master/develop/dev) |
| worktrees merge | -i, --into <branch> | Sets target branch explicitly |
| worktrees merge | -s, --squash | Uses squash merge (default: regular merge) |
| worktrees merge | -k, --keep | Keeps worktree after merge |
| worktrees merge | --delete-branch | Deletes merged branch (avoids prompt) |
workon worktree (from inside a worktree)
| Command | Flag | Effect when set |
|---------|------|-----------------|
| worktree merge | -y, --yes | Skips all prompts, auto-selects target branch (main/master/develop/dev) |
| worktree merge | -i, --into <branch> | Sets target branch explicitly |
| worktree merge | -s, --squash | Uses squash merge (default: regular merge) |
| worktree merge | --delete-branch | Deletes merged branch (avoids prompt) |
| worktree recycle | [branch] | Remote branch to fast-forward to (auto-detects main/master/develop/dev) |
| worktree recycle | -y, --yes | Skips confirmation prompt |
| worktree remove | -y, --yes | Skips confirmation prompt |
| worktree remove | -f, --force | Force-removes with uncommitted changes |
Commands That Are Already Non-Interactive
These commands produce output only and never prompt:
workon worktrees list/workon worktrees list -aworkon worktree/workon worktree status
Example: Automating a Feature Branch Workflow
This is a typical developer workflow that can be fully automated by an AI agent using the non-interactive flags. Here's the manual version compared to the automated version:
Manual workflow (interactive):
# 1. cd into the project
workon my-project:cwd
# 2. Create a worktree (prompts for base branch, open session, etc.)
workon worktrees add my-feature
# 3. Do your work...
# 4. Push, create a PR, get it reviewed and merged
# 5a. Tear down the worktree
workon worktrees remove my-feature
# 5b. Or recycle for the next task (ff to latest main, keep worktree)
workon worktree recycleAutomated workflow (non-interactive, agent-friendly):
# 1. cd into the project
workon my-project:cwd
# 2. Create a worktree and open a session — no prompts
workon worktrees add my-feature -b main -y -o
# 3. Agent does the work in the worktree...
# (or use colon syntax to target it directly)
# workon my-project:claude:my-feature
# 4. Push, create a PR, get it reviewed and merged
workon worktrees branch my-feature pr-branch -y -p
# ... PR merged via gh/API ...
# 5a. Tear down: remove worktree and delete the branch
workon worktrees remove my-feature -y
# 5b. Or recycle: ff to latest main and reuse for the next task
workon worktree recycle -yThe key difference is that every step in the automated version completes without waiting for user input, making it safe to chain together in scripts or have an AI agent drive the entire flow.
Advanced Usage
Environment Detection
workon automatically detects when you're in a configured project directory and shows relevant options.
Shell Completion
Set up tab completion:
workon --completionDebug Mode
Troubleshoot with debug output:
workon myproject --debugConfiguration Storage
Configuration is stored using the conf package in your system's config directory:
- macOS:
~/Library/Preferences/workon/ - Linux:
~/.config/workon/ - Windows:
%APPDATA%/workon/
Migration from Legacy Mode
If you've been using the nested shell mode, the new shell integration provides the same functionality without the shell nesting issues. Both modes continue to work:
- Legacy:
workon myproject(spawns new shell) - Modern:
workon myproject(with shell integration setup)
Contributing
# Install dependencies
pnpm install
# Development
pnpm run dev # Run with tsx
pnpm run build # Build with tsup
pnpm run lint # Lint
pnpm run type-check # Type check
pnpm run test # Run testsReleases are automated via release-please.
License
MIT © Israel Roldan
