Skip to content
budhashPublic

About

Lightning-fast bash script generator

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

zap-sh

zap-sh logo
Lightning-fast bash script generator

Version npm CI License: MIT Bash 3.2+ Language Issues

A bash script template generator for creating maintainable shell scripts.

Try it in your browser: budhash.com/zap-sh The wizard generates scripts in the browser, entirely client-side. It uses the same generator as the CLI (see JavaScript generator), whose output matches zap-sh init byte-for-byte.

Status: Stable (v1.1.0). Also available as a JavaScript package (@budhash/zap-sh) and a browser wizard.

Table of Contents

Overview

What is zap-sh?

zap-sh generates bash scripts from templates, similar to how cookiecutter works for other languages. Instead of starting from scratch or copying boilerplate, you get a structured script with proper error handling, logging, and cross-platform utilities.

The key idea: Your code lives in a protected section (##( app) while the framework can be updated independently. This means you can improve your scripts' infrastructure without touching your business logic.

Key Features

  • Self-contained scripts with no runtime dependencies
  • Interactive CLI setup wizard for new projects
  • Built-in license templates (MIT, Apache, GPL)
  • Your code stays safe during framework updates
  • Cross-platform support (Bash 3.2+ for macOS compatibility)
  • Piped execution support with configurable restrictions
  • Automatic updates from GitHub
  • JavaScript generator + browser wizard with byte-for-byte parity (@budhash/zap-sh)

Quick Start

# Install zap-sh (Homebrew)
brew install budhash/tools/zap-sh
# ...or download the script directly:
# curl -Lo ~/.local/bin/zap-sh https://raw.githubusercontent.com/budhash/zap-sh/main/zap-sh && chmod +x ~/.local/bin/zap-sh

# Create your first script (templates auto-download on first use)
zap-sh init -w

# Or quick generation
zap-sh init my-script --author="Your Name" --email="you@example.com" --license="mit"

# Start coding in the ##( app section
./my-script.sh --help

One-Line Script Generation

You can also generate scripts directly using piped execution:

# Interactive wizard
curl -sL https://raw.githubusercontent.com/budhash/zap-sh/main/zap-sh | bash -s -- init -w

# Basic script
curl -sL https://raw.githubusercontent.com/budhash/zap-sh/main/zap-sh | bash -s -- init my-tool

# Enhanced script with options
curl -sL https://raw.githubusercontent.com/budhash/zap-sh/main/zap-sh | \
  bash -s -- init api-client -t enhanced --author="Jane Doe" --license=mit

Installation

# Homebrew (recommended)
brew install budhash/tools/zap-sh
# or: brew tap budhash/tools && brew install zap-sh

# User installation
curl -Lo ~/.local/bin/zap-sh https://raw.githubusercontent.com/budhash/zap-sh/main/zap-sh
chmod +x ~/.local/bin/zap-sh

# System-wide installation
sudo curl -Lo /usr/local/bin/zap-sh https://raw.githubusercontent.com/budhash/zap-sh/main/zap-sh
sudo chmod +x /usr/local/bin/zap-sh

# Verify installation
zap-sh -v
zap-sh -h

How It Works

Templates

Basic Template - Essential utilities for simple scripts (~170 lines)

Enhanced Template - Rich utilities for complex tools (~600 lines)

  • All basic features plus 40+ utility functions
  • JSON processing, HTTP helpers
  • Advanced argument parsing
  • Array and string operations
  • View enhanced.sh template →

Template Structure

Generated scripts follow a section-based organization:

#!/usr/bin/env bash
##( header          # Script metadata, license, description
##( configuration   # Bash safety settings (set -eEuo pipefail)
##( metadata        # Internal script variables and constants
##( globals         # Colors, error codes, global constants
##( helpers         # Utility functions (u.* namespace)
##( app             # YOUR CODE GOES HERE - preserved during updates
  ##[ config        # Your configuration and constants
  ##[ functions     # Your business logic functions
    _main()         # Your main entry point
##) app
##( core            # Framework bootstrap and initialization

Section Markers

The section system enables safe updates:

  • ##( section / ##) section - Major sections
  • ##[ subsection / ##] subsection - Subsections within major sections
  • Your code goes in the ##( app section and is preserved during updates
  • Framework code in other sections gets updated automatically

The Protected App Section

When you generate a script, your business logic goes in the ##( app section:

##( app
# YOUR CODE GOES HERE - this section is never touched by updates

_main() {
  # Your application logic
  u.info "Hello from my app!"
}
##) app

Everything else (error handling, utilities, configuration) can be updated to newer versions while your code stays untouched.

Usage

Command Overview

zap-sh init <project>        # Generate new script from template
zap-sh init -w               # Interactive guided setup (recommended)
zap-sh update -f <script>    # Update framework sections (preserves your code)
zap-sh snip -f <script>      # Extract sections for reuse
zap-sh upgrade               # Update zap-sh binary and templates
zap-sh upgrade --templates-only  # Update only templates (useful in piped mode)

Script Generation (init)

Generate new bash scripts from templates with customizable metadata.

Interactive Wizard (Recommended)

# Guided setup with prompts for all options
zap-sh init -w

# Example wizard flow:
# >> Template (basic / enhanced [basic]): enhanced
# >> Project name: api-client
# >> Output file (api-client.sh): tools/api-client.sh
# >> Author (anonymous): Jane Doe
# >> Email (optional): jane@company.com
# >> Brief description (Generated by zap-sh): API client for external services
# >> Long description (...): Comprehensive API client with retry logic and authentication
# >> License (mit / apache / gpl [mit]): apache

Command Line Generation

# Minimal script (uses defaults)
zap-sh init my-tool

# With custom output path
zap-sh init backup-tool -o scripts/backup.sh

# Complete metadata
zap-sh init api-client \
  -o tools/api.sh \
  --author="John Smith" \
  --email="john@company.com" \
  --license="apache"

Template Selection

# Use basic template (default - minimal, fast)
zap-sh init simple-tool -t basic

# Use enhanced template (comprehensive utilities)
zap-sh init complex-tool -t enhanced -o bin/tool.sh

# With license selection
zap-sh init production-tool \
  -t enhanced \
  --author="DevOps Team" \
  --license="mit"

Advanced Options

# Custom version and details
zap-sh init deploy-script \
  --author="SRE Team" \
  --version="3.1.0" \
  --detail="Deployment automation script" \
  --description="Handles blue-green deployments with rollback support"

# Custom template directory
ZAP_HOME=/path/to/templates zap-sh init custom-tool

Script Updates (update)

Update framework sections of existing scripts while preserving your app code. The header and app sections remain untouched, while all other sections (configuration, metadata, globals, helpers, core) get updated to the latest template.

Basic Updates

# Update script sections (preserves ##( app section)
zap-sh update -f my-script.sh

# Force specific template
zap-sh update -f my-script.sh -t basic

# Update with template detection
zap-sh update -f auto-detect.sh  # Detects original template

Update Examples

# Update an old script to latest framework
zap-sh update -f legacy-tool.sh

# Update but force different template (with warning)
zap-sh update -f basic-script.sh -t enhanced

# Skip confirmation prompts
zap-sh update -f my-script.sh -y

Note: Updates preserve your code in the ##( app section and script metadata in the ##( header section while refreshing all framework sections with the latest template improvements.

Section Extraction (snip)

Templates are organized into logical sections, with the expectation that your business logic lives in the ##( app section. The main purpose of snip is to extract the app section from a script for reuse or analysis.

Basic Extraction

# Extract app section to console (most common use)
zap-sh snip -f my-script.sh

# Extract specific section
zap-sh snip -f my-script.sh -s helpers

# Extract to file
zap-sh snip -f my-script.sh -s app -o reusable-logic.sh

Advanced Extraction

# Extract different sections
zap-sh snip -f my-script.sh -s header -o script-header.txt
zap-sh snip -f my-script.sh -s globals -o script-globals.txt

Self-Updating (upgrade)

Keep zap-sh and templates current with the latest version.

# Check for updates and upgrade
zap-sh upgrade

# Force upgrade regardless of version
zap-sh upgrade --force

# Debug output
DEBUG=true zap-sh upgrade

JavaScript generator

zap-sh init also has a JavaScript implementation, @budhash/zap-sh, that produces the same script as the bash tool. It runs the browser wizard and works in Node or the browser.

npm install @budhash/zap-sh
import { generate } from '@budhash/zap-sh';

const { filename, content } = generate({
  template: 'enhanced',            // 'basic' | 'enhanced'
  project: 'my-tool',              // becomes {{app}}
  license: 'mit',                  // 'mit' | 'apache' | 'gpl' (optional)
  variables: { author: 'Jane Doe', email: 'jane@example.com', version: '1.2.0' },
});
// content === what `zap-sh init my-tool -t enhanced --license=mit ...` writes

CommonJS (require) and TypeScript declarations are included. Scope is generation only (the init path); update, snip, and upgrade remain bash-only. See the package README for the full API.

Parity

The bash tool defines the output. Two things keep the JS implementation in sync:

  • SPEC.md — a versioned contract for what zap-sh init emits (sections, variable order, substitution rules, licenses, determinism).
  • test/conformance/ — shared fixtures plus golden files generated by the real zap-sh init. A bash runner and the JS runner both check every fixture in CI, so bash and JS output must match byte-for-byte.

Development

Template Storage

Templates are stored in:

  1. ZAP_HOME (if set)
  2. ~/.config/zap-sh/ (default)

Structure:

~/.config/zap-sh/
├── templates/
│   ├── basic.sh           # Minimal template
│   ├── enhanced.sh        # Full-featured template
│   └── licenses/          # License templates
│       ├── MIT.txt
│       ├── Apache.txt
│       └── GPL.txt

Remote Configuration

# Use different repository
ZAP_REMOTE=https://raw.githubusercontent.com/your-org/zap-templates/main zap-sh upgrade

# Custom template directory
ZAP_HOME=/path/to/templates zap-sh init project

Local Template Development

# Enable development mode (uses local templates/ directory)
ZAP_DEV=true zap-sh init test-project

# Directory structure for development
zap-sh/
├── zap-sh              # Binary
├── templates/
│   ├── basic.sh
│   ├── enhanced.sh
│   └── licenses/
│       ├── MIT.txt
│       └── Apache.txt

Repository Structure

zap-sh/
├── zap-sh                 # Main binary (self-contained generator)
├── templates/
│   ├── basic.sh           # Minimal template
│   ├── enhanced.sh        # Full-featured template
│   └── licenses/          # License templates (MIT, Apache, GPL)
├── packages/generator/    # @budhash/zap-sh (JavaScript generator)
├── docs/                  # Browser wizard (GitHub Pages)
├── test/
│   ├── test-*.sh          # Test suites
│   ├── conformance/       # Shared bash/JS parity fixtures + golden files
│   └── .common/           # Test framework
├── SPEC.md                # Generation contract (bash/JS parity)
├── version.txt            # Current version for updates
├── manifest.txt           # File manifest for downloads
├── .github/
│   ├── workflows/         # CI and release automation
│   └── scripts/           # Release automation scripts
├── Makefile               # Development automation
└── README.md

Release Process

Creating a new release:

# 1. Prepare release (runs CI + updates version files)
make bump-version VERSION=1.0.0

# 2. Review and commit changes
git diff                    # Review what changed
git add zap-sh version.txt
git commit -m "Bump version to 1.0.0"

# 3. Tag and push (triggers automatic release)
git tag v1.0.0
git push origin main v1.0.0

What happens automatically (on a v* tag):

  • GitHub Actions runs full CI validation (Ubuntu + macOS)
  • Release archive (zap-sh-<version>.zip) is created from manifest.txt
  • GitHub Release is published with the changelog from README
  • @budhash/zap-sh is published to npm via OIDC trusted publishing (with provenance, no long-lived token) when the tag matches the package version

Development commands:

make ci                     # Run full CI pipeline locally
make bump-version VERSION=1.0.0  # Update version files
make create-archive VERSION=1.0.0  # Test release creation
make version                # Show all component versions

Testing

# Test basic functionality
zap-sh init test-basic -t basic
./test-basic.sh --help

# Test enhanced template
zap-sh init test-enhanced -t enhanced
./test-enhanced.sh --version

# Test wizard mode
zap-sh init -w

# Test development mode
ZAP_DEV=true zap-sh init dev-test

Requirements

  • bash 3.2+ (macOS default) / 4+ (Linux)
  • curl (for template downloads and updates)
  • Standard Unix tools: sed, grep, find

Environment Variables

ZAP_DEV=true           # Enable development mode (use local templates)
ZAP_HOME=/path         # Custom template directory location  
ZAP_REMOTE=https://... # Custom remote repository for templates
DEBUG=true             # Enable debug logging

Script Configuration

Generated scripts have several configuration options in the ##[ config section:

Piped Execution Support

Scripts can be executed via pipe (e.g., curl ... | bash), which is useful for installation scripts. This behavior is controlled by the __ALLOW_PIPED variable:

##[ config
readonly __NAME=my-script
readonly __OS=(mac linux)
readonly __APP_DEPS=(curl jq)
readonly __ALLOW_PIPED=true  # Set to false to disable piped execution
##] config

When __ALLOW_PIPED=false, the script will:

  • Exit with error code 8 (_E_PIPE) when piped
  • Display error: "script is disabled in piped mode"
  • Work normally when executed directly

This is useful for scripts that:

  • Need to read from stdin
  • Require file system access relative to the script location
  • Have security concerns about piped execution

Other Configuration Options

  • __NAME: Script name used in logs and messages
  • __OS: Array of supported operating systems
  • __APP_DEPS: Array of required external commands
  • __ARG_AUTO: (enhanced template only) Enable automatic argument parsing

Automatic Argument Parsing (Enhanced Template)

The enhanced template includes sophisticated argument parsing controlled by __ARG_AUTO:

##[ config
readonly __ARG_AUTO=true     # Enable automatic argument parsing
# format: "short_spec|variable_name|long_name|description"
readonly __APP_OPTS=(
  "n:|_name|name|Your name for personalized greeting"
  "c:|_count|count|Number of greetings (default: 1)"
  "l|_loud|loud|Use uppercase output"
)
##] config

When __ARG_AUTO=true:

  • Arguments are automatically parsed based on __APP_OPTS definitions
  • Variables are set according to the specifications (e.g., _name, _count, _loud)
  • Positional arguments are collected in __ARG_FNL array
  • Help text is auto-generated from option descriptions

Option format: "short_spec|variable_name|long_name|description"

  • short_spec: Single letter option (add : for options requiring values)
  • variable_name: Variable to store the value
  • long_name: Long option name (for documentation)
  • description: Help text for the option

Workflow Examples

Typical Development Workflow

# 1. Generate script with wizard
zap-sh init -w
# Choose template, set project name, output path, author, license

# 2. Develop your logic in ##( app section
vim scripts/deploy.sh

# 3. Update framework when needed (preserves your ##( app code)
zap-sh update -f scripts/deploy.sh

# 4. Extract reusable components
zap-sh snip -f scripts/deploy.sh -s app -o shared/deploy-logic.sh

Command Line Workflow

# Quick generation with specific options
zap-sh init deploy-tool -t enhanced -o scripts/deploy.sh \
  --author="DevOps Team" --license="apache"

# Your business logic goes here
# Edit the ##( app section in scripts/deploy.sh

# Keep framework updated
zap-sh update -f scripts/deploy.sh

FAQ

Q: How is this different from other script generators?
A: zap-sh focuses on updateable templates with section-based organization. Your code stays protected in the ##( app section while framework sections can be updated independently.

Q: Can I modify the generated script?
A: Yes! It's your script. Keep custom code in the ##( app section to preserve it during updates.

Q: What's the difference between basic and enhanced templates?
A: Basic (~170 lines) provides essential utilities for simple scripts. Enhanced (~600 lines) includes 40+ utility functions for complex tools, JSON processing, and HTTP utilities.

Q: Is bash 3.2 supported?
A: Yes! Bash 3.2 is supported. This ensures scripts work on macOS (which ships with bash 3.2) without requiring users to upgrade bash.

Q: How do updates work?
A: zap-sh upgrade downloads the latest binary and templates. zap-sh update -f script.sh updates framework sections while preserving your app code.

Q: Can I use my own templates?
A: Not yet.

Q: What happens if GitHub is down?
A: zap-sh uses cached templates from ~/.config/zap-sh/. First download requires internet, subsequent use is offline-capable.

Support

  • Issues: GitHub Issues
  • Documentation: This README and built-in help (zap-sh --help)

License

MIT License. See LICENSE file for details.

Generated scripts inherit their license from the template used (configurable via --license option or wizard).

Changelog

v1.1.3

  • Accept --help and --version as aliases for -h/-v (bash tool only; the @budhash/zap-sh npm package is unchanged and stays at 1.1.2).

v1.1.2

  • Homebrew tap support: brew install budhash/tools/zap-sh. Each v* tag now generates Formula/zap-sh.rb and pushes it to budhash/homebrew-tools (non-fatal; the GitHub release and npm publish are unaffected if the tap push fails).

v1.1.1

  • @budhash/zap-sh now has zero dependencies — the build dropped esbuild for a pure-Node bundler. No runtime or generated-output change.

v1.1.0

JavaScript generator + wizard

  • @budhash/zap-sh — a JavaScript port of zap-sh init, published to npm, that produces the same scripts byte-for-byte (Node and browser).
  • A live browser wizard built on it.
  • Parity is enforced in CI by a shared SPEC.md + test/conformance/ fixtures and a differential test that diffs the live bash tool against the JS generator.

Fixes

  • Variable substitution no longer hangs on a value that contains its own placeholder (single pass).
  • Reject a newline inside a variable value (bash and JS agree).
  • Enhanced template: fix the _app_cleanup typo that made scripts exit 127, and only write <app>.log when file-logging is enabled.
  • snip -s validates the section name before using it in grep/sed.
  • All remote downloads require HTTPS.
  • Re-enabled and repaired the Bash 3.2 compatibility test suite.

v1.0.0 - Initial Release

Features

  • Script generation with zap-sh init command
  • Interactive wizard mode with zap-sh init -w
  • Framework updates with zap-sh update (preserves user code)
  • Section extraction with zap-sh snip
  • Self-updating with zap-sh upgrade
  • Built-in license support (MIT, Apache, GPL)
  • Zero-friction setup with automatic template downloads on first use
  • Piped execution support for one-line installations
  • --templates-only flag for upgrade command
  • Production-ready defaults (development mode off)

Templates

  • Basic Template: Essential utilities for simple scripts (~170 lines)
  • Enhanced Template: Comprehensive utilities with 40+ functions (~600 lines)

Compatibility

  • No runtime dependencies for generated scripts

About

Lightning-fast bash script generator

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages