Micromanage
A Micro-services Helpers Framework | Easily manage multiple repositories and projects
- Microservices
- Bash
- Developer Tools
- Git
Beamery Micromanage - A Micro-services Helpers Framework
Status: This code lived in a former employer's GitHub organization and is no longer public; both the original repo and its install scripts 404 today. This page is kept as a retrospective on the design, which I still think holds up for anyone building shell tooling over many repos.
At we followed a , which has real advantages: easier scaling, independently deployable services, no long-term commitment to a single technology stack. It also has a very mundane cost that architecture diagrams never show. We had over 50 git repositories, and developing a feature very often touched several of them at once. Changing branches, syncing remotes, and keeping every checkout in order meant endlessly flipping between terminal tabs.
Micromanage was a set of shell helper functions (bash >= 4.0 and zsh >= 5.0) that automated operations across all the repos in a directory: one command, executed in every folder that qualified. It shipped as a plugin for both the and plugin frameworks, with a manual fallback of sourcing a single entry script from your .bash_profile or .bashrc.
What it did
The helpers covered the daily rituals of multi-repo work:
- audit_git_branches: List all the branches of a git repository sorted by creation date
- check_node_package_usage: Check where a certain npm package is used across all the repos
- clean_git_branches / clean_git_local_branches / clean_git_remote_branches: Prune branches merged into master, locally and on remotes
- clean_git_stash: Clean stashed commits
- clean_npm_modules / generate_npm_report / link_node_modules: Audit, clean, and link node modules across every repo
- list_git_active_branch: List the current branch in each repo
- switch_git_branch / switch_git_branch_and_update: Switch every repo to a branch, optionally pulling the latest from the remote
- track_all_remote_git_branches / update_git_branch: Track untracked remote branches and update from origin
Git functions defaulted to origin and master but accepted overrides positionally:
Autocompletion worked in both shells: hitting tab after beamery listed the available plugins, and beamery help PLUGIN_NAME (or a --help flag on any call) printed the plugin's docs.
The architecture: execute as the single primitive
The part of this project I'm still fond of is how little machinery it needed. Every helper reduced to the same prerequisite: run this function in every folder, but only where it makes sense. That lived in one dispatcher function, execute, which took the command to run plus flags describing what kind of folder qualified:
- -s: only execute in the current folder
- -g: only in git folders, verified by the existence of a valid
.gitdirectory - -n: only in node folders, verified by the existence of a
package.json - -h: include hidden folders, which are skipped by default
- -p: suppress the per-folder debug line
Because every plugin went through execute, the folder-type flags were automatically supported by every helper. beamery clean_npm_modules -s ran the cleanup only in the current folder, with no per-plugin code to make that work.
Plugins as files, help from comments
New commands were added by dropping a file into the plugins/ folder. The conventions were deliberately minimal:
- The plugin filename is the command name
- Each plugin sources the shared
pluginsInterface.shto get access toexecute - Help docs are extracted directly from the comments at the top of the plugin file, with the first comment line being the plugin name; writing documentation and registering the command were the same act
- Plugins that needed special behavior for the
-sflag implemented it themselves
The installed layout, in the manual setup, was just:
- .beamery
- beamery.sh
- plugins
- pluginsInterface.sh
Since the whole thing sat as a git repo hooked into bash-it or oh-my-zsh, updating it was beamery update or a git pull in the installation folder.
What I'd keep
A single dispatch primitive, plugins as flat files, and help text extracted from comments meant the tool grew organically: anyone on the team could add a helper in five minutes without touching the core. If I were rebuilding it today, the shape would be the same.