bashly-framework/bashly
Bash command line framework and CLI generator
Healthy across all four use cases
Permissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 7w ago
- ✓2 active contributors
- ✓MIT licensed
Show 4 more →Show less
- ✓CI configured
- ✓Tests present
- ⚠Small team — 2 contributors active in recent commits
- ⚠Single-maintainer risk — top contributor 99% of recent commits
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/bashly-framework/bashly)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/bashly-framework/bashly on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: bashly-framework/bashly
Generated by RepoPilot · 2026-05-10 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/bashly-framework/bashly shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across all four use cases
- Last commit 7w ago
- 2 active contributors
- MIT licensed
- CI configured
- Tests present
- ⚠ Small team — 2 contributors active in recent commits
- ⚠ Single-maintainer risk — top contributor 99% of recent commits
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live bashly-framework/bashly
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/bashly-framework/bashly.
What it runs against: a local clone of bashly-framework/bashly — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in bashly-framework/bashly | Confirms the artifact applies here, not a fork |
| 2 | License is still MIT | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | Last commit ≤ 77 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of bashly-framework/bashly. If you don't
# have one yet, run these first:
#
# git clone https://github.com/bashly-framework/bashly.git
# cd bashly
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of bashly-framework/bashly and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "bashly-framework/bashly(\\.git)?\\b" \\
&& ok "origin remote is bashly-framework/bashly" \\
|| miss "origin remote is not bashly-framework/bashly (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
&& ok "license is MIT" \\
|| miss "license drift — was MIT at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 77 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~47d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/bashly-framework/bashly"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
Bashly is a Ruby-based CLI generator that transforms YAML configuration files into standalone, production-ready bash scripts with automatic argument parsing, validation, help text generation, and modular command handling. It eliminates boilerplate bash scaffolding by letting developers define commands, subcommands, flags, and arguments declaratively, then generates shellcheck-compliant output with optional standard library utilities (colors, config parsing, YAML handling, completions). Single-repo structure: bin/bashly is the CLI entrypoint (Ruby executable), src/ likely contains the generator logic (YAML parser → bash template renderer), examples/ contains 15+ runnable project templates (argfile, catch-all-advanced, catch-all-stdin, minimal, etc.), each with its own bashly.yml → src/ commands → test.sh validation cycle. The Dockerfile and docker-compose.yml enable containerized execution without local Ruby.
👥Who it's for
Bash script developers and DevOps engineers who need to build feature-rich CLI tools quickly without manually writing argument parsing, validation, and help systems. Users range from individual contributors building personal utilities to teams generating corporate CLI frameworks from a single source-of-truth YAML definition.
🌱Maturity & risk
Actively developed and production-ready. The project has comprehensive GitHub Actions CI (test.yml, static-analysis.yml, docker builds), a Changelog tracking updates, RSpec test suite (.rspec config present), RuboCop linting setup, and multiple versioned examples demonstrating stability. Docker images are published to hub.docker.com/r/dannyben/bashly in both 'latest' and 'edge' channels, indicating regular releases.
Low to moderate risk. The primary risk is single-maintainer dependency (authored by 'dannyben' across the codebase), though the generated bash output is standalone and doesn't require runtime dependencies. The Ruby codebase (260KB) is substantial, but the Gemfile and dependencies are not shown, so dependency quality is unknown. No obvious breaking changes are visible, and the stable YAML-input/bash-output contract reduces coupling.
Active areas of work
Active maintenance visible in CHANGELOG.md updates and multiple GitHub Actions workflows. Edge Docker builds suggest ongoing development (edge/Dockerfile exists separately from stable path). The project has issue templates (bug_report.yml, feature_request.yml, documentation_issue.yml) and a CONTRIBUTING.md guide, indicating organized contribution processes. No specific recent commits are shown, but the infrastructure suggests regular releases.
🚀Get running
git clone https://github.com/bashly-framework/bashly.git
cd bashly
gem install bundler
bundle install
bundle exec bin/bashly init --help
Or use Docker: docker run -it -v $PWD:/app dannyben/bashly init. The .envrc.example suggests direnv support for development.
Daily commands:
Development: bundle exec bin/bashly init to scaffold a new project, then bundle exec bin/bashly generate to build the CLI. Testing: bundle exec rspec (inferred from .rspec file). Examples: cd examples/minimal && bash test.sh to validate a generated example. Docker: docker-compose up (docker-compose.yml present but content not shown).
🗺️Map of the codebase
- bin/bashly: The CLI entrypoint; running this is how users interact with the framework and generate their bash CLIs
- bashly.gemspec: Defines the gem metadata, dependencies, and version; required for publishing to rubygems.org
- examples/minimal/src/bashly.yml: The canonical example YAML schema showing commands, flags, and arguments; the primary documentation by example
- .github/workflows/test.yml: CI pipeline definition that tests the generator against real bash outputs; indicates what passes validation
- CONTRIBUTING.md: Governance and contribution guidelines; required reading before opening PRs
- Dockerfile: Containerized distribution method; many users run Bashly via
docker runrather than local gem install
🛠️How to make changes
Contributers should start in these areas: (1) Generator logic in lib/ (inferred) for core parsing/output changes, (2) Templates in lib/templates/ for bash output format, (3) Examples in examples/*/src/bashly.yml to add feature demonstrations, (4) Tests in spec/ for regression safety. The examples are excellent starting points to understand the YAML→bash workflow. Modify .rubocop.yml and run linting before commit.
🪤Traps & gotchas
The generated bash scripts depend on exact bash version features (arrays, process substitution); users must test output on their target shell (bash 4.x vs 5.x differences). The src/ directory structure within example projects mirrors the generated CLI structure, which can be confusing—changes to src/bashly.yml require re-running bashly generate to update the CLI. The framework generates a single merged bash file; splitting it again requires manual editing or re-architecting. Shellcheck compliance is generated but users must still pass their command implementations through shellcheck themselves.
💡Concepts to learn
- YAML-to-Code Generation (Domain-Specific Language compilation) — Bashly's core value is converting declarative YAML into executable bash; understanding this pattern is essential to extending the generator or understanding why certain YAML structures map to specific bash idioms
- Template-based code generation (ERB or Liquid templates) — Bashly likely uses Ruby templating to render bash output; contributors must understand how variables in templates map to YAML schema fields to add new features
- Bash argument parsing (getopts vs. manual getopt vs. shift-based) — The generator must produce bash argument parsing logic that handles flags, options, and positional arguments—a non-trivial problem that the generated code solves; reading the output teaches this pattern
- Bash subshell and command composition — Bashly-generated scripts use subshells and function composition to handle nested commands; understanding variable scoping and exit codes in bash is critical when debugging generated output
- Vendoring / stdlib bundling — Bashly includes optional bash libraries (colors, config parsing) inline in the generated script; this 'vendoring' pattern eliminates runtime dependencies and is why the output is truly standalone
- Bash completion specification (bash_completion, compgen) — Bashly generates bash completion scripts; understanding compgen and completion word lists is necessary to use or extend the completions feature
- Defensive bash scripting (set -euo pipefail, error handling) — Generated scripts must be production-safe and shellcheck-compliant; the generator enforces strict bash modes and error propagation patterns that users must understand when writing command implementations
🔗Related repos
click/click— Python equivalent providing declarative CLI argument parsing and help generation; shows the same architectural pattern applied to a different language ecosystemurfave/cli— Go CLI framework with similar YAML/struct-based command definitions and auto-generated help; competing approach in a compiled languagecasey/just— Modern bash task runner with declarative syntax; overlaps in the 'simplify bash scripting' problem space but focuses on task definition rather than distributed CLIsbats-core/bats-core— Bash testing framework; many Bashly users will want to test their generated scripts, and Bashly examples use manual test.sh files instead of Batskoalaman/shellcheck— Static analyzer for bash; Bashly explicitly generates shellcheck-compliant output, and the output is validated against this tool's rules
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive test coverage for bashly.yml parsing and validation
The repo contains many examples with bashly.yml files (argfile, catch-all, colors-usage, etc.) but there's no dedicated test suite visible for YAML schema validation. New contributors could add RSpec tests to validate bashly.yml parsing, error messages, and edge cases. This would prevent regressions as the YAML schema evolves and improve the developer experience when users provide invalid configurations.
- [ ] Create spec/lib/bashly_yml_validator_spec.rb with tests for valid/invalid bashly.yml files
- [ ] Test edge cases: missing required fields, invalid command names, circular dependencies in subcommands
- [ ] Add fixtures in spec/fixtures/ using existing examples from examples/ directory
- [ ] Reference examples/argfile/src/bashly.yml, examples/catch-all/src/bashly.yml for test data
- [ ] Run
bundle exec rspecand ensure tests integrate with existing .rspec config
Create a GitHub Actions workflow to validate all example projects
The examples/ directory contains 20+ example projects (argfile, catch-all-advanced, colors-usage, etc.), each with their own test.sh scripts, but there's no CI workflow testing them. A new workflow would automatically run all examples' test.sh scripts on every PR, catching breakage early. This is similar to the existing test.yml workflow structure.
- [ ] Create .github/workflows/validate-examples.yml based on the pattern in .github/workflows/test.yml
- [ ] Add a job that loops through examples/*/test.sh and executes each one
- [ ] Ensure the workflow runs on pull_request events and reports results
- [ ] Test locally by running: for dir in examples/*/; do bash "$dir/test.sh"; done
- [ ] Document the new workflow in CONTRIBUTING.md
Add static type checking and documentation for the bashly.yml configuration schema
The project has .rubocop.yml and .rubycritic.yml for code quality, but no schema documentation for the bashly.yml format itself. Contributors could create a JSON Schema or OpenAPI-style specification of the bashly.yml format, then use it for IDE autocomplete, validation, and documentation. This would significantly improve the developer experience and reduce support requests.
- [ ] Create schema/bashly.schema.json defining the complete bashly.yml structure (commands, arguments, flags, subcommands, etc.)
- [ ] Reference existing YAML examples to identify all supported fields: examples/argfile/src/bashly.yml, examples/colors-usage/src/bashly.yml
- [ ] Document in docs/ or README.md how to use the schema with VS Code (add to .vscode/settings.json)
- [ ] Add validation logic to bin/bashly to report clear errors when YAML doesn't match the schema
- [ ] Test against all examples in examples/ directory to ensure schema is complete
🌿Good first issues
- Add test coverage for the edge case of deeply nested subcommand hierarchies (3+ levels); examples/ shows max 2 levels currently, and the generator may have untested code paths for commands..commands..commands structures.
- Document the exact bash version requirements in README.md and in generated script headers; the codebase targets POSIX + bash 4+ features but this isn't stated explicitly for contributors to validate against.
- Create an example in examples/ showing integration with external config file management (e.g., parsing a .myapprc file); the Config file management feature is mentioned in README but no examples demonstrate it end-to-end.
📝Recent commits
Click to expand
Recent commits
3db2bed— fix example readme (DannyBen)f1e0951— changelog (DannyBen)0537009— version 1.3.8 (DannyBen)9b8c1f3— Merge pull request #705 from bashly-framework/add/argfile-env-var (DannyBen)e985b90— fix shfmt (DannyBen)ad82d59— - Allow disabling and overriding argfile with env var (DannyBen)3363442— Merge pull request #704 from bashly-framework/fix/argfile (DannyBen)47aa242— fix shellcheck (DannyBen)a412ba3— test argfile with unique repeatable flags (DannyBen)d4f42c5— update argfile example (DannyBen)
🔒Security observations
The bashly framework codebase demonstrates generally good security practices with no critical vulnerabilities detected. The main concerns are related to Docker image configuration and dependency management: unspecified base image digests, hardcoded versions without auto-update mechanisms, and missing security hardening options. The project appears to be a legitimate open-source framework with proper documentation and CI/CD workflows. Recommend implementing container image digest pinning, version management automation, and security context hardening in Docker configurations.
- Medium · Hardcoded Version in Dockerfile —
Dockerfile (line: ENV BASHLY_VERSION=1.3.8). The Dockerfile contains a hardcoded BASHLY_VERSION (1.3.8) which may become outdated and could contain known vulnerabilities. This version is fixed and won't receive security updates automatically. Fix: Use a build argument with a default value instead, or implement a version pinning strategy with regular updates. Consider using 'latest' only in development environments. - Medium · Unspecified Alpine Ruby Base Image —
Dockerfile (FROM dannyben/alpine-ruby:4.0). The base image 'dannyben/alpine-ruby:4.0' is a third-party image without explicit digest pinning. This could lead to using different versions across builds and introduces supply chain risk. Fix: Pin the image to a specific digest (e.g., 'dannyben/alpine-ruby:4.0@sha256:...'). Additionally, verify the maintainers and security practices of third-party images. - Low · Missing Security Headers in Docker Configuration —
docker-compose.yml and Dockerfile. The Docker configuration does not specify security options such as read-only filesystem, dropped capabilities, or resource limits, which could increase the attack surface. Fix: Add security context with: security_opt, cap_drop, read_only: true (where applicable), and resource limits (memory, cpus). - Low · Pandoc Installation Without Version Pinning —
Dockerfile (RUN apk add --no-cache pandoc-cli). The Dockerfile installs 'pandoc-cli' without specifying a version, which could result in different versions being installed depending on when the image is built. Fix: Pin to a specific version: 'apk add --no-cache pandoc-cli=<version>'. Use 'apk update && apk add' pattern for consistency. - Low · Missing HEALTHCHECK in Docker Configuration —
Dockerfile. The Dockerfile and docker-compose.yml lack a HEALTHCHECK instruction, making it difficult to detect if the container is in a broken state. Fix: Add a HEALTHCHECK instruction to verify the container is functional and responsive.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.