Smart macOS Script Generator for MDM Automation
Shikomi is an intelligent script scaffolding tool that generates production-ready macOS management scripts with versioning, Git workflows, and best practices built-in. Named after the Japanese culinary term for preparation and mise en place - the foundation of great execution.
[*] Interactive Script Generation
- Guided wizard for parameter collection
- Support for MDM parameters ($4-$11 for Jamf Pro)
- NEW in v1.6.0: Multiple secret storage methods (1Password, file-based, or manual)
- Built-in secrets management with 1Password CLI integration
- Standard macOS variable library (serial number, logged in user, etc.)
[+] Production-Ready Output
- Semantic versioning (SemVer) built-in
- Automatic README and CHANGELOG generation
- Version bumping utility included
- Security checks via pre-commit hooks
[#] Security First
- Two-tier pre-commit hooks (basic: secrets only, enhanced: 9 checks)
- Gitleaks integration to prevent secret commits
- ShellCheck linting for script quality (enhanced mode)
- Smart secret detection and masking
- 1Password CLI integration support
- Configurable
.gitignorefor sensitive files
[~] Git Workflow Intelligence
- Monorepo and micro-repo modes
- Feature branch creation
- GitHub integration via
ghCLI - Optional GitHub Actions for CI/CD
# Clone the repository
git clone https://github.com/maparker/shikomi.git
cd shikomi
# Run the installer (installs to ~/.local/bin)
./install.sh
# Or for system-wide installation (requires sudo)
sudo ./install.sh --system
# Add ~/.local/bin to PATH if not already (for user installation)
echo 'export PATH="$PATH:$HOME/.local/bin"' >> ~/.zshrc
source ~/.zshrcAfter installation, you can run commands from anywhere:
shikomi my_awesome_script
bump-version my_script.sh patch "Fixed bug"Updating Shikomi:
cd /path/to/shikomi
./install.sh --updateThe update command will:
- Show current installed versions
- Pull latest changes from git (if available)
- Reinstall to the same location (user or system)
- Show new versions after update
Note: If you downloaded Shikomi as a ZIP file (instead of
git clone), the update command won't automatically fetch new code. To update:
- Download the latest ZIP from GitHub
- Extract and replace your existing files
- Run
./install.sh --updateto reinstallFor automatic updates, use
git cloneinstead of ZIP download.
# Clone the repository
git clone https://github.com/maparker/shikomi.git
cd shikomi
# Make scripts executable
chmod +x shikomi.sh bump-version.sh add_security_tools.sh
# Use with ./
./shikomi.sh my_awesome_script
./bump-version.sh my_script.sh patch "Fixed bug"# Create a new script
shikomi my_awesome_script
# Follow the interactive prompts:
# 1. Define MDM parameters ($4-$11)
# 2. Add static configuration variables
# 3. Select standard macOS variables
# 4. Choose pre-commit hook level (basic or enhanced)$ shikomi install_app
==============================================
macOS Script Generator (Monorepo Mode)
==============================================
--- Parameter 4 ---
Label (e.g. 'Target Dept'): App Name
Is this a secret? (y/n): n
Default Local Value: Slack
--- Parameter 5 ---
Label (e.g. 'Target Dept'): [Enter to skip]
--- Static Configuration Variables ---
Add static configuration variables? (y/n): y
Select from standard macOS variables:
1. SERIAL_NUMBER - Mac serial number
2. LOGGED_IN_USER - Currently logged in user
3. COMPUTER_NAME - Computer name
4. OS_VERSION - macOS version number
...
Selection: 1 2 4
Added: SERIAL_NUMBER
Added: LOGGED_IN_USER
Added: OS_VERSION
Pre-commit hooks protect against secrets and code quality issues.
Choose hook level - (b)asic [secrets only] or (e)nhanced [9 checks]? (b/e): e
Installing enhanced pre-commit hooks (9 checks)...
β Pre-commit hooks installed
[β] Script generated: install_app.sh (v1.0.0)Main script generator with intelligent wizards for:
- MDM parameter collection
- Static configuration variables
- Standard macOS variable selection
- Secrets management setup (1Password or file-based)
Version info:
shikomi --version # Show version
shikomi --help # Show usageSemantic version management utility:
# Initialize versioning for existing scripts
bump-version my_script.sh init "Initial versioned release"
# Bump version with change description
bump-version my_script.sh patch "Fixed bug in user detection"
bump-version my_script.sh minor "Added notification support"
bump-version my_script.sh major "Breaking: Changed API interface"munkipkg Integration:
bump-version automatically detects and updates munkipkg package versions:
- Searches for
build-info.jsonorbuild-info.plistin root,pkg/, andbuild/directories - Updates the version field to match your script version
- Supports both JSON and plist formats
- Keeps scripts and installer packages in perfect sync
# When you bump a script version, munkipkg build-info is updated automatically
bump-version my_script.sh minor "Added new feature"
# Output: Updating munkipkg version in: pkg/build-info.jsonSecurity tooling setup for repositories:
- Installs Gitleaks for secret scanning
- Configures pre-commit hooks
- Sets up GitHub Actions workflows
- Adds security-focused
.gitignorerules
Version info:
./add_security_tools.sh --version # Show version
./add_security_tools.sh --help # Show usageShikomi supports multiple script templates:
Full-featured automation scripts with:
- Jamf Pro parameters ($4-$11)
- Logging functions (log, log_warn, log_error, log_success)
- Secrets management (1Password or file-based)
- Static configuration variables
Use for: Installation, configuration management, user provisioning, automation workflows
Lightweight inventory reporting scripts with:
- Simple header with version tracking
- Static data collection variables
- Required
<result>VALUE</result>output format - No parameters, logging, or secrets management
- Optimized for fast execution
Use for: Jamf Pro inventory data collection, application version checking, compliance reporting
During script generation, you'll be prompted:
What type of script do you want to create?
1) Regular Script - Full-featured automation
2) Extension Attribute - Jamf inventory reporting
Selection (1/2) [1]:
$ shikomi crowdstrike_version
Selection: 2
Add '_ea' suffix? (y/n) [y]: y
# Generated: crowdstrike_version_ea.sh with <result> output formatShikomi includes 12 pre-configured macOS system variables:
| # | Variable | Description |
|---|---|---|
| 1 | SERIAL_NUMBER |
Mac serial number |
| 2 | LOGGED_IN_USER |
Currently logged in user |
| 3 | COMPUTER_NAME |
Computer name from System Preferences |
| 4 | OS_VERSION |
macOS version number |
| 5 | MODEL_IDENTIFIER |
Hardware model identifier |
| 6 | PRIMARY_IP |
Primary network IP address |
| 7 | HOSTNAME |
Network hostname |
| 8 | MAC_ADDRESS |
Primary MAC address |
| 9 | CURRENT_USER_HOME |
Home directory of logged in user |
| 10 | BOOT_VOLUME |
Name of boot volume |
| 11 | TOTAL_RAM_GB |
Total RAM in gigabytes |
| 12 | PROCESSOR_NAME |
CPU processor name |
Simply enter the numbers during script generation to include these variables.
Every generated script includes:
#!/bin/zsh
################################################################################
# SCRIPT: script_name.sh
# VERSION: 1.0.0
# AUTHOR: Your Name
# EMAIL: your.email@company.com
# DATE: 2025-12-07
# Description: Auto-generated description
################################################################################
# --- Script Metadata ---
readonly SCRIPT_VERSION="1.0.0"
readonly SCRIPT_NAME="script_name"
# --- Local Development Secrets ---
if [[ -f "$HOME/.jamf_secrets" ]]; then
source "$HOME/.jamf_secrets"
fi
# --- Static Configuration ---
SERIAL_NUMBER="$(system_profiler SPHardwareDataType | awk '/Serial/ {print $4}')"
# --- Configuration (MDM Parameters) ---
APP_NAME="${4:-"Slack"}"
# --- Logging Setup ---
LOG_FILE="/var/log/script_name.log"
function log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] INFO: $*"; }
function log_warn() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] WARN: $*" >&2; }
function log_error() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: $*" >&2; }
function log_success() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] SUCCESS: $*"; }
# --- Main Logic ---
log "Starting $SCRIPT_NAME v$SCRIPT_VERSION..."
log "Config: App Name [APP_NAME]: $APP_NAME"
log "System: Serial Number: $SERIAL_NUMBER"
# TODO: Add your logic here
log "$SCRIPT_NAME completed successfully"
exit 0Every generated script includes enhanced logging functions with severity levels:
| Function | Severity | Output | Use Case |
|---|---|---|---|
log() |
INFO | stdout | General information and progress updates |
log_warn() |
WARN | stderr | Non-critical warnings that don't stop execution |
log_error() |
ERROR | stderr | Critical errors requiring attention |
log_success() |
SUCCESS | stdout | Successful completion of operations |
# General information logging
log "Starting installation of Slack"
log "Downloading package from https://example.com/slack.dmg"
# Warning for non-critical issues
log_warn "User not logged in, using default settings"
log_warn "Optional dependency not found, skipping feature"
# Error logging (outputs to stderr)
log_error "Failed to download package from URL"
log_error "Insufficient disk space: ${AVAILABLE_SPACE}GB available"
# Success messages for completed operations
log_success "Application installed successfully"
log_success "Configuration file updated"All logs include timestamp and severity level:
[2026-01-18 14:30:15] INFO: Starting installation of Slack
[2026-01-18 14:30:16] WARN: User not logged in, using default settings
[2026-01-18 14:30:20] ERROR: Failed to download package from URL
[2026-01-18 14:30:25] SUCCESS: Application installed successfully
Use grep to filter by severity:
# Show only errors
grep "ERROR:" /var/log/my_script.log
# Show warnings and errors
grep -E "WARN:|ERROR:" /var/log/my_script.log
# Show only successful operations
grep "SUCCESS:" /var/log/my_script.log
# Count errors
grep -c "ERROR:" /var/log/my_script.logCapture errors and warnings separately:
# Run script and separate stdout/stderr
./my_script.sh > output.log 2> errors.log
# Or combine with timestamps
./my_script.sh 2>&1 | tee /var/log/my_script.logShikomi supports multiple secret storage methods, giving you flexibility based on your team's workflow.
When generating a script, Shikomi can integrate with 1Password CLI for secure, team-sharable secrets.
# Install 1Password CLI
brew install 1password-cli
# Authenticate (one-time setup)
op account addWhen you mark a parameter as a secret, you'll see:
Where should this secret be stored?
1) 1Password (recommended for team sharing)
2) ~/.jamf_secrets (traditional local file)
3) Skip (configure manually later)
Choose option 1 for 1Password integration. Shikomi will:
- Ask for vault name (default:
Private) - Ask for item name (default:
jamf-{script_name}) - Ask for field name (default: lowercase variable name)
- Optionally create/update the secret immediately
Scripts with 1Password secrets automatically fetch from 1Password at runtime:
# Fetch from 1Password with fallback to Jamf parameter
if command -v op &> /dev/null && op account list &> /dev/null 2>&1; then
API_KEY="$(op read 'op://Private/jamf-my_script/api_key' 2>/dev/null || echo "${4}")"
else
API_KEY="${4}" # Fallback to Jamf parameter
fi
# Logs show masked values
log "Config: API Key [API_KEY]: ******* (1Password)"- Team-sharable secrets across your organization
- No plaintext files to secure or accidentally commit
- Automatic fallback to Jamf parameters if 1Password unavailable
- Works seamlessly with existing 1Password workflows
- Optional immediate secret creation during script generation
# Test secret retrieval
op read "op://Private/jamf-my_script/api_key"
# Run script with 1Password integration
sudo ./my_script.shFor local development or simpler workflows, use traditional file-based secrets:
Create a secrets file for local testing:
# Create secrets file
cat > ~/.jamf_secrets << 'EOF'
# Local development secrets
LOCAL_API_KEY="your-test-api-key"
LOCAL_API_TOKEN="your-test-token"
EOF
# Secure the file
chmod 600 ~/.jamf_secretsShikomi automatically generates secret-aware code:
# In generated script (when you mark parameter as secret)
API_KEY="${LOCAL_API_KEY:-${4}}"
# Logs show masked values
log "Config: API Key [API_KEY]: ******* (Masked)"Choose option 3 during generation to configure secrets manually later. Shikomi will add TODO comments to guide you.
When run inside an existing Git repository:
- Creates scripts in current directory
- Offers feature branch creation
- Uses namespaced files (
script_name_README.md) - Preserves existing Git history
When run outside a Git repository:
- Creates new project directory
- Initializes fresh Git repo
- Optional GitHub repository creation
- Standalone project structure
Shikomi's bump-version utility seamlessly integrates with munkipkg for macOS package creation:
Automatic Version Synchronization:
When you bump your script version, bump-version automatically updates your munkipkg configuration:
- Detects
build-info.json(JSON format) orbuild-info.plist(Property List format) - Searches in multiple locations: root directory,
pkg/, andbuild/ - Updates the
versionfield to match your new script version - No manual editing of build-info files required
Example Workflow:
# Your project structure
my_installer/
βββ my_script.sh
βββ pkg/
β βββ build-info.json
β βββ payload/
βββ README.md
# Bump your script version
./bump-version.sh patch "Fixed installation bug"
# Output:
# Current version: 1.0.0
# New version: 1.0.1
# Updating munkipkg version in: pkg/build-info.json
# SUCCESS: Version bumped to 1.0.1
# Now build your package with munkipkg
munkipkg pkg/
# Package version automatically matches script version!This ensures your installer package versions always stay in sync with your script versions, eliminating version mismatch issues.
Optionally generate CI/CD workflows:
- Version validation (script vs README)
- ShellCheck linting
- Tag-based releases
# Auto-generated .github/workflows/validate-version.yml
name: Validate Version
on:
pull_request:
branches: [ main, master ]
push:
tags: [ 'v*' ]Shikomi offers two levels of pre-commit hooks during project creation:
Secret scanning only - lightweight protection:
# .pre-commit-config.yaml
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.18.0
hooks:
- id: gitleaksComprehensive security and quality suite with 9 checks:
repos:
# Secret scanning
- repo: https://github.com/gitleaks/gitleaks
rev: v8.18.0
hooks:
- id: gitleaks
# Shell script linting
- repo: https://github.com/shellcheck-py/shellcheck-py
rev: v0.9.0.6
hooks:
- id: shellcheck
args: [--severity=warning]
# General checks
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: trailing-whitespace # Remove trailing spaces
- id: end-of-file-fixer # Ensure newline at EOF
- id: check-yaml # Validate YAML syntax
- id: check-added-large-files # Block files > 1MB
- id: check-merge-conflict # Detect conflict markers
- id: detect-private-key # Find SSH/GPG keysDuring project creation, you'll be prompted to choose:
Choose hook level - (b)asic [secrets only] or (e)nhanced [9 checks]? (b/e):
For existing projects, use add_security_tools.sh to add enhanced hooks
- macOS (tested on macOS 10.15+)
- Bash/Zsh shell
- Git
- 1Password CLI (
op) - For 1Password secrets integration - GitHub CLI (
gh) - For GitHub repo creation - pre-commit - For security hooks
- Gitleaks - For secret scanning
Install optional tools:
brew install 1password-cli gh pre-commit gitleaks-
Generate Script
shikomi my_feature
-
Implement Logic Edit the generated script and add your implementation
-
Test Locally
sudo ./my_feature.sh
-
Bump Version
bump-version my_feature.sh patch "Implemented user validation" -
Commit & Push
git add . git commit -m "feat: add my_feature script" git push
- [β] DO: Store secrets in
~/.jamf_secretsor 1Password - [β] DO: Mark sensitive parameters as secrets
- [β] DO: Use pre-commit hooks
- DON'T: Hardcode credentials in scripts
- DON'T: Commit
.envor*_secretsfiles - DON'T: Skip secret detection warnings
- MDM-Agnostic Mode - Support for Intune, Kandji, Mosyle
- VS Code Extension - Native IDE integration
- Template Library - Pre-built script templates
- Script Testing Framework - Automated testing utilities
- Web UI - Browser-based script generator
Contributions welcome! Please:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Use Shikomi itself to generate your scripts
- Commit with conventional commits (
feat:,fix:,docs:) - Push and open a Pull Request
MIT License - See LICENSE for details
Shikomi (δ»θΎΌγΏ, shee-koh-mee) - A Japanese culinary term meaning "preparation" or "mise en place" - the meticulous prep work that chefs do before service begins. Like this tool, shikomi emphasizes proper preparation, organization, and building the foundation for flawless execution.
- Issues: GitHub Issues
- Discussions: GitHub Discussions
Made πͺ by macOS admins, for macOS admins