pickhardt/betty
Friendly English-like interface for your command line. Don't remember a command? Ask Betty.
Stale and unlicensed — last commit 5y ago
worst of 4 axesno license — legally unclear; last commit was 5y ago
no license — can't legally use code; last commit was 5y ago
Documented and popular — useful reference codebase to read through.
no license — can't legally use code; last commit was 5y ago
- ✓19 active contributors
- ✓Distributed ownership (top contributor 25% of recent commits)
- ✓CI configured
Show 3 more →Show less
- ✓Tests present
- ⚠Stale — last commit 5y ago
- ⚠No license — legally unclear to depend on
What would change the summary?
- →Use as dependency Concerns → Mixed if: publish a permissive license (MIT, Apache-2.0, etc.)
- →Fork & modify Concerns → Mixed if: add a LICENSE file
- →Deploy as-is Concerns → Mixed if: add a LICENSE file
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 "Great to learn from" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/pickhardt/betty)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/pickhardt/betty on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: pickhardt/betty
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/pickhardt/betty 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
AVOID — Stale and unlicensed — last commit 5y ago
- 19 active contributors
- Distributed ownership (top contributor 25% of recent commits)
- CI configured
- Tests present
- ⚠ Stale — last commit 5y ago
- ⚠ No license — legally unclear to depend on
<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 pickhardt/betty
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/pickhardt/betty.
What it runs against: a local clone of pickhardt/betty — 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 pickhardt/betty | Confirms the artifact applies here, not a fork |
| 2 | Default branch master exists | Catches branch renames |
| 3 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 4 | Last commit ≤ 1811 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of pickhardt/betty. If you don't
# have one yet, run these first:
#
# git clone https://github.com/pickhardt/betty.git
# cd betty
#
# 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 pickhardt/betty and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "pickhardt/betty(\\.git)?\\b" \\
&& ok "origin remote is pickhardt/betty" \\
|| miss "origin remote is not pickhardt/betty (artifact may be from a fork)"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "main.rb" \\
&& ok "main.rb" \\
|| miss "missing critical file: main.rb"
test -f "lib/commands.rb" \\
&& ok "lib/commands.rb" \\
|| miss "missing critical file: lib/commands.rb"
test -f "lib/template.rb" \\
&& ok "lib/template.rb" \\
|| miss "missing critical file: lib/template.rb"
test -f "lib/config.rb" \\
&& ok "lib/config.rb" \\
|| miss "missing critical file: lib/config.rb"
test -f "install.rb" \\
&& ok "install.rb" \\
|| miss "missing critical file: install.rb"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 1811 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~1781d)"
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/pickhardt/betty"
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
Betty is a Ruby-based command-line interface that translates natural English phrases into shell commands, eliminating the need to memorize obscure CLI syntax. Users can ask questions like 'betty how many words are in this directory' and Betty parses the intent, identifies matching commands from lib/*.rb modules (calc, files, git, process, etc.), and executes them, optionally showing multiple matches for user selection. Monolithic structure: main.rb is the entry point that orchestrates command parsing; lib/ contains ~25 modular handlers (lib/commands.rb routes input, lib/calc.rb handles math, lib/git.rb wraps git operations, lib/files.rb handles file operations, etc.). spec/ and test/spec/ contain RSpec tests. install.rb provides shell integration via bash alias.
👥Who it's for
DevOps engineers, sysadmins, and developers who work heavily in the terminal but struggle to recall specific command syntax; they want to ask questions in plain English rather than memorize commands or leave the shell to search online.
🌱Maturity & risk
Experimental/unmaintained. The project is fully functional (v0.1.8) with CI via CircleCI, a test suite in spec/ and test/, and modular command handlers, but the maintainer explicitly stated they no longer actively develop it and are seeking new maintainers. Last activity appears dormant based on the note in README.
Single-maintainer risk is acute—the original author is no longer maintaining the project and actively seeking handoff. The test suite is incomplete (spec files exist for calc, files, fun, git, os, rock_paper_scissors, shutdown, and user, but many lib/ modules like spotify.rb, itunes.rb, cmus.rb lack tests). No dependency lockfile details visible, and the Ruby ecosystem has evolved significantly since v0.1.8.
Active areas of work
No active development. The project is in maintenance mode with no visible PRs or recent commits. The ROADMAP.md and NOTICE.md files suggest the maintainer is open to community contributions but not driving new features.
🚀Get running
git clone https://github.com/pickhardt/betty && cd betty && ruby install.rb (automatic) or manually add alias betty='~/path/to/betty/main.rb' to ~/.bashrc. No Gemfile-based installation; dependencies are minimal and built-in.
Daily commands:
Direct invocation: betty <english-query>. Examples: betty whats my username, betty how many words are in this directory, betty uncompress something.tar.gz. No server or background service; runs as a subprocess calling system commands.
🗺️Map of the codebase
main.rb— Entry point that orchestrates the entire Betty command-line interface; all user interactions flow through this filelib/commands.rb— Core command routing and parsing logic that maps English-like input to actual shell commandslib/template.rb— Template system that provides the abstraction layer for translating user queries into executable commandslib/config.rb— Configuration management that handles user preferences and settings across all modulesinstall.rb— Installation script that sets up Betty and integrates it with the user's shell environmentautocomplete.rb— Bash autocomplete integration that enables intelligent command suggestions in the shellspec/spec_helper.rb— Test configuration and shared test utilities that all specs depend on for execution
🧩Components & responsibilities
- main.rb (Ruby, Shell) — Accepts command-line arguments, orchestrates the command processing pipeline, and outputs results to stdout
- Failure mode: If entry point fails, Betty is unusable; all user input is lost
- lib/commands.rb (Ruby regex, module require/load) — Routes parsed English queries to appropriate domain modules and coordinates command assembly
- Failure mode: If routing fails, queries cannot be dispatched; users see 'command not recognized' even for supported queries
- lib/template.rb (Ruby string interpolation) — Provides abstraction for building shell commands from template patterns with variable substitution
- Failure mode: If template generation fails, commands are malformed or incomplete; execution produces errors
- Domain Modules (lib/files.rb, lib/git.rb, etc.) (Ruby, Unix shell commands) — Implement English-to-shell mappings for specific domains (files, version control, system, etc.)
- Failure mode: If a module fails, that domain's commands become unavailable; other domains unaffected
- lib/config.rb (Ruby file I/O, YAML or similar (inferred)) — Manages user preferences and configuration state across all modules
- Failure mode: If config fails to load, defaults are used; customizations are lost or overridden
🔀Data flow
User (shell prompt)→main.rb— User types 'betty <query>' and shell executes main.rb with ARGV containing the querymain.rb→lib/commands.rb— Entry point parses ARGV and calls command router to identify the appropriate handlerlib/commands.rb→Domain Modules (lib/*.rb)— Router dispatches to relevant module (files, git, os, etc.) based on query keywordsDomain Modules→lib/template.rb— Modules use template engine to construct shell command strings from patternslib/template.rb→main.rb— Template engine returns fully formed shell command string back to entry pointmain.rb→Shell (backtick execution— undefined
🛠️How to make changes
Add a New Command Module
- Create a new module file in lib/ (e.g., lib/newfeature.rb) following the template structure (
lib/template.rb) - Implement command methods that return command strings or execution logic (
lib/template.rb) - Register the new module in lib/commands.rb to integrate it into the command routing system (
lib/commands.rb) - Add test cases in spec/ following the existing test patterns (e.g., spec/newfeature_spec.rb) (
spec/spec_helper.rb)
Add a New English Query Pattern
- Identify which module handles the domain (e.g., lib/files.rb for file operations) (
lib/commands.rb) - Add a pattern-matching case or method in the relevant module to recognize the English phrase (
lib/files.rb) - Map the matched phrase to a shell command template using lib/template.rb conventions (
lib/template.rb) - Write a test in the corresponding spec file to verify the phrase parses correctly (
spec/files_spec.rb)
Extend Configuration Options
- Add new configuration keys and default values in lib/config.rb (
lib/config.rb) - Update the configuration loading logic to persist user settings (
lib/config.rb) - Reference the new config values in modules that need them (e.g., lib/commands.rb) (
lib/commands.rb)
🔧Why these technologies
- Ruby — Interpreted language ideal for rapid CLI prototyping and natural language pattern matching with regex
- Shell integration (Bash aliases) — Provides seamless integration with existing shell workflows and enables Betty to execute arbitrary commands
- RSpec — Ruby's standard testing framework for validating command parsing and translation accuracy
- Modular architecture (lib/*.rb) — Allows independent domain-specific implementations without core dependencies, enabling easy extensibility
⚖️Trade-offs already made
-
Pattern-based English matching instead of NLP/ML
- Why: Simpler implementation, no external dependencies, predictable behavior for deterministic command translation
- Consequence: Less flexible with phrasing variations; developers must maintain regex/pattern mappings for each supported phrase
-
Shell command string generation instead of direct API calls
- Why: Platform agnostic and leverages existing Unix tools and their power
- Consequence: Requires shell execution overhead; limited to what shell commands can express; security requires careful input sanitization
-
Monolithic main.rb instead of microservices
- Why: Keeps Betty lightweight and fast with minimal dependencies for a CLI tool
- Consequence: Scaling to many commands requires careful organization; single point of failure for the entire tool
🚫Non-goals (don't propose these)
- Does not provide authentication or security-aware command execution
- Does not handle interactive shell sessions or persistent state management
- Does not support Windows natively (Unix/Linux/macOS focused)
- Does not perform predictive analytics or machine learning on command patterns
- Does not maintain a centralized command database; all logic is embedded in source modules
🪤Traps & gotchas
- The project assumes a Unix-like shell (bash/zsh); Windows compatibility is not mentioned or tested. 2. install.rb modifies ~/.bashrc directly; concurrent installations or multiple users may conflict. 3. Some lib/*.rb modules (spotify.rb, itunes.rb, cmus.rb) wrap external tools that must be installed separately and may not exist on all systems—commands silently fail if dependencies aren't present. 4. The phrase-to-command matching logic in lib/commands.rb is regex-based and brittle; natural language variations not explicitly registered will not match.
🏗️Architecture
💡Concepts to learn
- Natural Language Command Parsing — Understanding Betty's core function requires grasping how lib/commands.rb uses regex patterns and intent matching to convert user phrases like 'how many words in this folder' into structured command handlers.
- Shell Integration via Alias — Betty achieves transparency by registering as a bash alias (install.rb → ~/.bashrc), making it callable without path prefixes; understanding this pattern is essential for modifying Betty's startup behavior.
- Subprocess Command Execution — Betty wraps system commands (git, find, du, etc.) by shelling out; understanding how lib/*.rb modules use backticks or system() calls and capture output is critical for adding new handlers.
- REPL-style User Selection UI — When multiple commands match user input, Betty prompts for selection with numbered options; this interactive model is core to the UX and visible in main.rb.
- Handler Module Pattern — Each lib/*.rb file is a self-contained handler module; understanding this pattern (each exports a method that returns matches + shell commands) is essential for extending Betty with new features.
- Configuration Persistence via Files — lib/config.rb stores user preferences (e.g., voice on/off) between invocations; understanding how Betty reads/writes config files ensures new features integrate cleanly with existing state management.
- Regex-based Intent Recognition — lib/commands.rb uses regex patterns to match user phrases (e.g., /how many .* in/) to specific handlers; understanding regex limitations here explains why Betty's language understanding is brittle.
🔗Related repos
thefuck/thefuck— Similar goal (user-friendly CLI interaction), but thefuck corrects mistyped commands; Betty translates natural language to new commandsnicolargo/glances— System monitoring CLI with natural language intent—represents the ecosystem of user-facing CLI tools that abstract command syntaxtldr-pages/tldr— Companion tool: tldr provides simplified man page summaries; Betty users often consult tldr when unsure of command syntax before asking Bettychubin/cheat.sh— Overlapping use case: quick command lookup without leaving the shell; users might choose between Betty (generative parsing) and cheat.sh (curated snippets)
🪄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 suite for lib/commands.rb
lib/commands.rb is a critical core module that likely orchestrates command parsing and routing, but there is no corresponding spec/commands_spec.rb file. This is a major gap given that other modules (calc, files, fun, git, os, user, etc.) have test coverage. Adding tests here would improve reliability and prevent regressions in the core command translation logic.
- [ ] Create spec/commands_spec.rb following the pattern used in spec/calc_spec.rb and spec/git_spec.rb
- [ ] Write tests for command parsing logic, including edge cases and natural language variations
- [ ] Test command routing to appropriate lib modules
- [ ] Run full test suite with
raketo ensure no regressions - [ ] Aim for >80% code coverage of lib/commands.rb
Add unit tests for lib/internet.rb and lib/translate.rb modules
Several lib modules lack corresponding test files (internet.rb, translate.rb, desktop.rb, permissions.rb, process.rb, etc.). internet.rb and translate.rb are user-facing features that make external API calls and are error-prone. Adding tests would catch breaking changes and improve maintainability for a project seeking new maintainers.
- [ ] Create spec/internet_spec.rb with mocked HTTP responses for URL/connectivity commands
- [ ] Create spec/translate_spec.rb with tests for language detection and translation outputs
- [ ] Use existing spec patterns from spec/spec_helper.rb for test setup
- [ ] Test both happy paths and failure scenarios (network errors, API unavailability)
- [ ] Run tests locally and verify they integrate with CircleCI (see circle.yml)
Consolidate duplicate test structure: move test/spec/count_spec.rb to spec/count_spec.rb
The test suite is fragmented with spec/ and test/spec/ directories. The count_spec.rb exists only in test/spec/ but not in spec/, while all other tests are in spec/. This inconsistency makes test discovery unclear and suggests incomplete test migration. Consolidating this would improve maintainability and ensure consistent test execution in CI/CD.
- [ ] Copy test/spec/count_spec.rb to spec/count_spec.rb with any necessary path adjustments
- [ ] Verify spec/count_spec.rb runs correctly with
rake specor test runner - [ ] Remove test/spec/count_spec.rb and test/spec/ directory if no other files exist there
- [ ] Update Rakefile if needed to ensure all specs in spec/ are discovered
- [ ] Confirm CircleCI build passes with consolidated test structure
🌿Good first issues
- Add missing test coverage: lib/spotify.rb, lib/itunes.rb, lib/cmus.rb, lib/translate.rb, and lib/map.rb have no corresponding spec files. Start by writing spec/spotify_spec.rb with basic tests for command generation.
- Improve error handling in lib/files.rb and lib/find.rb: currently they assume commands succeed; add try-catch patterns and user-friendly error messages when file operations fail (e.g., permission denied, file not found).
- Extend phrase matching in lib/commands.rb to support more natural language variations (e.g., 'show my username' → whoami, 'who am i' → whoami, 'display username'); document the pattern in README.md with examples.
⭐Top contributors
Click to expand
Top contributors
- @pickhardt — 25 commits
- [@Samuel Tarling](https://github.com/Samuel Tarling) — 14 commits
- @brysgo — 14 commits
- @joanjoc — 8 commits
- @fuzzygroup — 6 commits
📝Recent commits
Click to expand
Recent commits
f95c4e3— Merge pull request #190 from jonmarkprice/master (Joshua Horwitz)462be29— Merge pull request #195 from Chipcius/fixing_zip_behaviour (Joshua Horwitz)b674de8— Merge pull request #188 from pickhardt/dev (Joshua Horwitz)0a7e017— Merge pull request #193 from escallic/patch-1 (Joshua Horwitz)9f91988— Removed extra space that got added by accident (Chipcius)32a6f48— Fixed compress and uncompress to work better with bzip2 and zip files (Chipcius)5bd0ed4— calculate n choose k (Jordan)dc457f5— Make directory to copy files from be relative to install.rb rather than the working directory. (Jonathan Price)792246a— Removed non-functioning "go home" command. (Jonathan Price)5722907— Merge pull request #176 from fuzzygroup/master (pickhardt)
🔒Security observations
The Betty codebase presents significant security concerns primarily around command injection risks from shell execution, outdated/unmaintained dependencies, and insufficient input validation. The application's core functionality of translating user input into system commands creates inherent risks if not properly secured. The lack of active maintenance increases vulnerability exposure. Critical improvements needed include implementing parameterized command execution, comprehensive input validation, updating dependencies, and adding security-focused
- High · Command Injection Risk in Shell Command Execution —
lib/*.rb files (especially lib/commands.rb, lib/files.rb, lib/process.rb, lib/git.rb). The codebase appears to be a command-line interface that translates English phrases into shell commands. Multiple library files (lib/git.rb, lib/files.rb, lib/process.rb, lib/shutdown.rb, lib/find.rb, etc.) likely execute system commands. Without visible input sanitization patterns, there is a significant risk of command injection if user input is not properly escaped before being passed to system execution functions. Fix: Use parameterized command execution instead of string interpolation. In Ruby, usesystem()with array arguments orOpen3module with properly separated command and arguments. Never use backticks or %x{} with unsanitized user input. Implement strict input validation and whitelisting for command parameters. - High · Outdated Dependencies —
Gemfile, Gemfile.lock. The Gemfile and Gemfile.lock are present but content was not provided. Given that this project is stated as unmaintained (README indicates the maintainer lacks time for active maintenance), there is a high risk that Ruby gem dependencies have known vulnerabilities and have not been updated. Fix: Runbundle auditto identify vulnerable gems. Update all dependencies to the latest secure versions. Consider establishing a maintenance plan or finding new maintainers. Implement automated dependency scanning in CI/CD pipeline. - Medium · No Visible Input Validation Framework —
lib/commands.rb, main.rb. The file structure shows no evidence of input validation, sanitization, or schema validation libraries. Given the nature of the application (translating user input to commands), lack of structured input validation is concerning. Fix: Implement comprehensive input validation using a library likedry-validationor similar. Define strict schemas for all user inputs. Validate input type, length, format, and content before processing. - Medium · Potential API/Service Integration Vulnerabilities —
lib/internet.rb, lib/spotify.rb, lib/itunes.rb, lib/map.rb, lib/translate.rb, lib/config.rb. Multiple library files reference external services (lib/internet.rb, lib/spotify.rb, lib/itunes.rb, lib/map.rb, lib/translate.rb). Without visible authentication credential management, there may be hardcoded API keys or insecure credential storage. Fix: Use environment variables or secure credential management tools (e.g.,dotenvgem with .env.example documentation) for API keys. Never commit credentials to version control. Implement.gitignorerules for sensitive files. Use encrypted credential storage for production. - Medium · Insufficient Error Handling and Information Disclosure —
lib/*.rb files (especially lib/process.rb, lib/files.rb, lib/os.rb). Without visible error handling patterns across multiple command execution modules, errors may expose sensitive system information, file paths, or stack traces to users. Fix: Implement comprehensive error handling that catches exceptions and returns user-friendly error messages without exposing system details. Log detailed errors securely server-side only. - Low · No Visible Security Testing —
spec/. The spec/ directory shows test coverage for various modules, but no security-focused tests (e.g., injection attack tests, malicious input handling) are apparent. Fix: Add security-focused test cases including command injection attempts, path traversal attacks, and malicious input patterns. Use fuzzing for edge cases. - Low · No Visible Rate Limiting or DoS Protection —
lib/internet.rb, lib/spotify.rb, lib/map.rb, lib/translate.rb. As a CLI tool that may interact with external services, there's no visible protection against abuse or rate limiting for API calls. Fix: Implement rate limiting and request throttling for external API calls. Add caching to reduce redundant requests.
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.