How Mole's Shell Scripts Are Structured: A Layered Architecture Guide
Mole's shell scripts follow a convention-over-configuration architecture organized into nine distinct layers, from user-facing binaries in bin/ to core utilities in lib/core/ and specialized management modules in lib/manage/.
Mole is an open-source macOS optimization tool maintained by tw93 that is built almost entirely from Bash scripts. Understanding how Mole's shell scripts are structured reveals a modular, maintainable architecture that separates entry points, core libraries, and UI components into a clear directory hierarchy designed for easy navigation and testing.
The Nine-Layer Directory Architecture
Mole organizes its shell scripts into a logical hierarchy where each directory serves a specific architectural purpose. This separation ensures that low-level utilities never depend on high-level business logic.
Entry Points (bin/)
The bin/ directory contains user-facing commands that are executed directly from the terminal. Each script corresponds to a high-level action such as installation, uninstallation, or system optimization.
Representative files include bin/installer.sh for the main installation flow, bin/uninstall.sh for removal operations, and bin/optimize.sh for running maintenance tasks.
Convenience Helpers (scripts/)
The scripts/ directory houses small wrappers used by CI pipelines or developers for tasks like testing or environment setup. These are not intended for end-users but support development workflows.
Key files include scripts/test.sh for running the test suite and scripts/setup-quick-launchers.sh for configuring development shortcuts.
Core Library (lib/core/)
The lib/core/ directory contains low-level utilities that the rest of the codebase depends on. These scripts provide foundational functionality including logging, argument parsing, timeout handling, privilege escalation, and file operations.
Essential files include lib/core/log.sh for unified logging functions, lib/core/commands.sh for command execution wrappers, lib/core/file_ops.sh for safe file manipulation, and lib/core/base.sh which serves as the main entry point for sourcing other core modules.
UI Components (lib/ui/)
The lib/ui/ directory contains small interactive helpers that render menus or selectors in the terminal. These components are deliberately decoupled from core logic so they can be swapped or modified without affecting business rules.
Notable files include lib/ui/menu_simple.sh for basic selection menus, lib/ui/menu_paginated.sh for handling long lists, and lib/ui/app_selector.sh for interactive application selection.
Management Functions (lib/manage/)
The lib/manage/ directory implements higher-level actions like updating, purging paths, whitelisting, or fixing system state. These scripts orchestrate core utilities and UI helpers to complete complex workflows.
Key files include lib/manage/update.sh for self-update logic, lib/manage/purge_paths.sh for removing specific paths, and lib/manage/autofix.sh for automated system repairs.
Cleaning Utilities (lib/clean/)
The lib/clean/ directory contains dedicated scripts for removing caches, brew data, Maven artifacts, and other temporary files. These keep the system tidy after installations or repairs.
Representative files include lib/clean/caches.sh for general cache removal, lib/clean/brew.sh for Homebrew cleanup, and lib/clean/maven.sh for Maven artifact purging.
Health-Check and Diagnostics (lib/check/)
The lib/check/ directory gathers system health information used by the mole check command. These scripts generate JSON reports and overall status summaries.
Key files include lib/check/health_json.sh for generating JSON health reports and lib/check/all.sh for comprehensive system diagnostics.
Uninstall Helpers (lib/uninstall/)
The lib/uninstall/ directory contains logic for clean removal of components installed by Mole, ensuring services are stopped and caches are cleared.
Essential files include lib/uninstall/brew.sh for removing Homebrew dependencies and lib/uninstall/batch.sh for batch uninstallation operations.
Testing Suite (tests/)
The tests/ directory contains standalone test scripts that validate diagnostics, uninstall flow, and other behaviors without requiring the full toolchain.
A representative file is tests/test_diagnostic_reports_standalone.sh, which tests health report generation in isolation.
How the Layers Interact
Mole's shell script architecture follows a strict dependency flow that prevents circular references and maintains clear separation of concerns.
When a user executes a command, the interaction flow follows these steps:
-
User runs a binary script in
bin/(e.g.,./bin/installer.sh). -
The binary script sources core utilities (
lib/core/*.sh) for logging, argument parsing, and permission handling. -
For any interactive prompt, it calls UI helpers (
lib/ui/*.sh) to render menus. -
Business-logic actions (install, update, purge) are delegated to management scripts in
lib/manage/. -
Those management scripts may invoke cleaning or check modules to ensure a consistent system state.
-
When the user asks to uninstall, the binary script routes the request to
lib/uninstall/*which safely removes files, services, and caches.
This modular hierarchy keeps each script focused on a single responsibility, simplifies testing, and makes the overall codebase easy to navigate.
Code Examples
Running Top-Level Commands
The bin/ directory contains executable entry points that users invoke directly:
# Install Mole (high-level entry point)
./bin/installer.sh
# Check system health
./bin/check.sh
# Optimize system (runs cleanup & maintenance tasks)
./bin/optimize.sh
Each of these scripts begins with a standard header that sources the core library:
#!/usr/bin/env bash
# shellcheck source=../lib/core/base.sh
source "$(dirname "$0")/../lib/core/base.sh"
Management Scripts Calling Core Utilities
The following excerpt from lib/manage/update.sh demonstrates how higher-level scripts leverage core utilities:
#!/usr/bin/env bash
source "$(dirname "$0")/../core/log.sh"
source "$(dirname "$0")/../core/file_ops.sh"
log_info "Starting Mole update..."
if ! file_exists "/usr/local/bin/mole"; then
log_error "Mole is not installed."
exit 1
fi
# Pull latest version from GitHub
git -C "/usr/local/Cellar/mole" pull origin main
log_success "Mole updated successfully."
The script uses log_* functions from lib/core/log.sh and file_exists from lib/core/file_ops.sh, demonstrating cross-layer reuse.
Interactive UI Components
The lib/ui/menu_simple.sh script provides reusable interactive elements:
# Inside lib/ui/menu_simple.sh
menu_simple() {
local options=("$@")
PS3="Select an option: "
select opt in "${options[@]}" "Cancel"; do
case "$REPLY" in
[0-9]*) echo "$opt"; return;;
*) echo "Invalid choice.";;
esac
done
}
A management script can invoke it like:
choice=$(menu_simple "Clean caches" "Update Mole" "Quit")
case "$choice" in
"Clean caches") lib/clean/caches.sh ;;
"Update Mole") lib/manage/update.sh ;;
"Quit") exit 0 ;;
esac
Key Files
| File | Role | Location |
|---|---|---|
bin/installer.sh |
Main installer entry point | bin/installer.sh |
bin/uninstall.sh |
Uninstall entry point | bin/uninstall.sh |
bin/optimize.sh |
Runs cleaning + maintenance | bin/optimize.sh |
lib/core/base.sh |
Sets up environment, loads other core modules | lib/core/base.sh |
lib/core/log.sh |
Unified logging (info, warn, error) | lib/core/log.sh |
lib/ui/menu_simple.sh |
Simple interactive menu implementation | lib/ui/menu_simple.sh |
lib/manage/update.sh |
Handles Mole self-updates | lib/manage/update.sh |
lib/clean/caches.sh |
Clears various application caches | lib/clean/caches.sh |
lib/check/health_json.sh |
Generates JSON health report | lib/check/health_json.sh |
tests/test_diagnostic_reports_standalone.sh |
Example test for health-report generation | tests/test_diagnostic_reports_standalone.sh |
Summary
- Mole's shell scripts are organized into a nine-layer hierarchy that separates entry points, core libraries, UI components, and domain-specific logic.
- The core library (
lib/core/) provides foundational utilities like logging and file operations that all higher layers depend on. - Management scripts (
lib/manage/) orchestrate complex workflows by combining core utilities with UI helpers (lib/ui/) for interactive prompts. - All executable entry points in
bin/follow a standard pattern of sourcinglib/core/base.shto initialize the environment. - The modular structure enables standalone testing via the
tests/directory and ensures that utility functions remain decoupled from business logic.
Frequently Asked Questions
What is the purpose of the lib/core/ directory in Mole?
The lib/core/ directory contains the foundational utilities that the rest of Mole's shell scripts depend on. It includes log.sh for unified logging functions, file_ops.sh for safe file manipulation, commands.sh for command execution wrappers, and base.sh which serves as the main initialization module that other scripts source to set up their environment.
How do Mole's shell scripts handle user interaction?
User interaction is handled through dedicated UI components located in lib/ui/. These scripts, such as menu_simple.sh and app_selector.sh, provide reusable functions for rendering interactive menus and selectors in the terminal. Management scripts in lib/manage/ call these UI helpers when they need to prompt users for choices, keeping the presentation logic decoupled from business logic.
Can I run individual Mole components without the full installation?
Yes, individual components can be executed independently. The bin/ directory contains standalone entry points like bin/optimize.sh and bin/check.sh that can be run directly. Additionally, the tests/ directory includes standalone test scripts such as tests/test_diagnostic_reports_standalone.sh that validate specific functionality without requiring the full Mole toolchain to be installed.
Where are Mole's test scripts located?
Mole's test scripts are located in the tests/ directory at the repository root. This directory contains standalone validation scripts that test specific behaviors such as diagnostic report generation. For example, tests/test_diagnostic_reports_standalone.sh validates the health-check functionality without needing the full application context, demonstrating the modular testability of Mole's shell script architecture.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →