project-switch
-
v0.10 - Inline math calculator
Added an inline math calculator to the
listcommand. Typing=followed by a math expression (like=5+3*2) evaluates it live in the autocomplete suggestions usingmeval. Integer results display without decimal places, and invalid expressions show an error inline. It’s a small quality-of-life feature that saves opening a separate calculator.Also fixed a CRLF line ending issue that was breaking the Docker build on Linux, added a
.gitattributesto enforce LF endings, and deduplicated shortcuts that appeared multiple times from overlapping scan directories. -
v0.9 - Cross-platform hotkey and macOS support
Made the hotkey listener cross-platform — it now works on both macOS and Windows. On macOS, it uses Core Graphics event taps to listen for the ALT+SPACE combination and launches
project-switch listin a new Terminal window. The platform-specific code is cleanly separated intoplatform/macos.rsandplatform/windows.rsmodules behind conditional compilation.Added macOS
.appbundle scanning to the shortcuts feature. It scans/Applicationsand~/Applicationsfor.appbundles and surfaces them alongside Windows.lnkshortcuts in the autocomplete, usingopen -ato launch them.Fixed the hotkey to fire only on key press (not release), cleaned up the Docker build pipeline by removing bash as a dependency, and added cargo registry volume caching for the lint container.
-
v0.8.1 - Cross-compilation fixes and config auto-create
Fixed the Docker cross-compilation pipeline to work on ARM hosts (like Apple Silicon Macs). The Dockerfile now uses conditional platform targeting so it can build Windows and Linux x86_64 binaries regardless of the host architecture. Added a
build.shscript for non-Windows environments that skips the lint Docker image.Also added auto-creation of the config file — if
~/.project-switch.ymldoesn’t exist when the program starts, it creates one with sensible defaults instead of erroring. Added cargo registry caching in the Docker build to speed up repeated builds. -
v0.8 - File path autocomplete and fixes
Added file path autocomplete to the
listcommand. When you start typing a Windows path (drive letter likeC:\or a UNC path), the autocomplete switches to browsing the filesystem instead of matching commands. It auto-expands when there’s a single directory match and displays directories and files with distinct styling. This makesproject-switchusable as a quick file/folder opener too.Fixed multi-word shortcut selection — shortcuts with spaces in their names weren’t being matched properly in the autocomplete. Also added a fallback so the
listcommand works even without a current project set, showing only global commands and shortcuts.On the hotkey side, added logic to kill any prior
project-switch-hotkey.exeinstances on startup so you don’t end up with duplicate listeners, and the hotkey now creates a default config file if one doesn’t exist. -
v0.7 - Config includes, system tray, and shortcut indexing
Packed day with three big features landing.
First, added config file includes. The main
~/.project-switch.ymlcan now specify anincludepath pointing to another YAML file, and the two get merged at load time. Project-specific commands overlay base commands by key, and projects merge by name. This lets me keep a shared config in a git repo and machine-specific overrides locally.Building on that, the hotkey listener now auto-syncs the included config’s git repo in the background — it does a
git pullon startup and periodically, then stages, commits, and pushes any local changes. All git operations run withCREATE_NO_WINDOWso nothing flashes on screen.Second, migrated the hotkey listener from a plain console app to a proper Windows system tray application using
tray-iconandmuda. It shows a notification area icon with a right-click “Exit” menu, and runs with#![windows_subsystem = "windows"]so there’s no console window. Generated a simple icon using a Python script with Pillow.Third, added Windows shortcut (
.lnk) indexing. Thelistcommand now scans configured shortcut directories and surfaces.lnkfiles alongside regular commands in the autocomplete. This means Start Menu shortcuts and other Windows shortcuts are searchable from the same prompt.Also added
cargo fmt,clippy, andcargo auditas verification checks, committedCargo.lockfor reproducible builds, and wired the build script to restart the hotkey listener after a successful build. -
v0.6 - ALT+SPACE hotkey listener
Built a companion binary,
project-switch-hotkey, that runs in the background on Windows and listens for a global ALT+SPACE hotkey. When triggered, it kills any runningproject-switch.exeinstances and launchesproject-switch listin a new Windows Terminal tab. The idea is to make project switching feel as instant as an app launcher — press the hotkey from anywhere and you’re immediately in the selection prompt.The hotkey registration uses the Windows
RegisterHotKeyAPI withMOD_ALT | MOD_NOREPEAT, and the message loop polls withPeekMessageWon a 50ms sleep. It handles graceful shutdown viactrlcand wraps the launched command incmd /c ... & exit /b 0so the terminal tab closes cleanly even whentaskkillforce-kills a prior instance.It’s a standalone crate under
hotkey/(not a workspace member) and gets cross-compiled through the existing Docker pipeline alongside the main binary. -
v0.5 - Direct URL opening support
Added the ability to type a URL directly into the
listprompt or pass one toopen, without needing it to be a configured command. If the input doesn’t match any command key but looks like a URL (starts withhttp,www., or matches adomain.tldpattern), it gets opened in the project’s configured browser. Bare domains likeexample.comautomatically get anhttps://prefix.Also deprecated the
opencommand in favour oflist— it’s now hidden from help output. Theopencommand still works but includes the same URL fallback behaviour for backwards compatibility. -
v0.4.1 - Autocomplete fixes and YAML preservation
Fixed a couple of annoying issues with the
listcommand’s autocomplete. Selecting a suggestion was inserting the full formatted string including ANSI colour codes and the URL arrow, so I added an ANSI stripping function and taught the completion handler to extract just the command key from highlighted suggestions. Also fixed input parsing to handle cases where the formatted suggestion text leaked into the user’s input.The other fix was around YAML field ordering. Previously, saving the config would re-serialise the entire struct which shuffled fields into alphabetical order — not great when you’ve carefully organised your config file. Now the config manager preserves the raw YAML on load and only patches the changed fields (
currentProject,projects) back into it on save, keeping everything else untouched.Added
skip_serializing_ifannotations across the config structs soNonefields andfalsedefaults don’t clutter the output. -
v0.4 - Command args, global commands, and browser profiles
Big batch of enhancements to
project-switchtoday. Added support for command arguments — you can now type extra text after a command key and it gets appended to the URL (with optional URL encoding via aurl_encodeconfig flag). This is great for search URLs where you want to pass a query string directly from the prompt.Introduced global commands in the config file. These are available across all projects and show up alongside project-specific commands in the
listview, with project commands taking priority over globals when there’s a key collision.Browser profiles are now supported too. The browser string in the config can include arguments like
firefox -P work, and the launcher correctly parses and passes those through on Windows, macOS, and Linux.Also reworked the
listcommand to useinquire’s autocomplete instead of a select menu, so you can type to filter commands and append arguments inline. Commands that aren’t URLs are now treated as terminal commands and spawned directly in the shell. -
v0.3 - List command and build script
Added a
listsubcommand that shows an interactive menu of all openable items from the current project. It displays each command’s key alongside a truncated URL, and opens the selected item in the configured browser. This makes it much quicker to jump to project resources compared to remembering exact command keys foropen.Extracted browser-opening logic into a shared
utils::browsermodule since bothopenandlistneed it. Also fixed the browser launch on Windows — switched fromcmd /C startto PowerShell’sStart-Process, which handles URLs with special characters more reliably.Created a
build.ps1script that stops any runningproject-switch.exeprocesses, cleans thebin/folder, and runs the Docker cross-compilation build. Cleaned updocker-compose.ymlto remove unused profiles and volumes. -
v0.2 - Rewriting project-switch in Rust
Rewrote
project-switchentirely from TypeScript to Rust. The Node.js version had noticeable startup latency (~100-200ms) which felt sluggish for something that should be instant. The Rust version starts in under 5ms.Ported all four subcommands (
switch,add,current,open) to Rust usingclapfor argument parsing,serde_yamlfor config file handling, andinquirefor interactive prompts. The config format stays the same —~/.project-switch.ymlwith projects, commands, and browser overrides — so it’s a drop-in replacement.Set up a Docker-based cross-compilation pipeline that builds both Windows and Linux binaries from a single
docker-compose up buildcommand, usinggcc-mingw-w64for the Windows target. -
v0.1 - Project switch genesis
Started
project-switchtoday — a CLI tool for quickly switching between project directories. I’ve been wanting a way to jump between repos without hunting through nested folders, and this scratches that itch.Built it as a TypeScript project with three subcommands:
switchfor fuzzy-matching a project name and changing to its directory,addfor registering new projects interactively, andopenfor launching a project directly in VS Code. Configuration lives in a YAML file at~/.project-switch.ymlwhere each project has a name, path, and optional tags.The
switchcommand presents an interactive list usingenquirerwhen there are multiple matches, and jumps straight there on an exact match. Theaddcommand walks through prompts for name, path, and tags, with the path defaulting to the current directory. Spent a bit of time fixing a path resolution bug for the config file location.