Skip to content

feat(catalog): add ble.sh (Bash Line Editor)#120

Merged
CybotTM merged 3 commits into
mainfrom
feat/add-blesh
Jul 22, 2026
Merged

feat(catalog): add ble.sh (Bash Line Editor)#120
CybotTM merged 3 commits into
mainfrom
feat/add-blesh

Conversation

@CybotTM

@CybotTM CybotTM commented Jul 22, 2026

Copy link
Copy Markdown
Member

Summary

Adds ble.sh (Bash Line Editor — syntax highlighting, autosuggestions, richer
completion UI for interactive Bash) to the catalog as a dedicated_script tool.

ble.sh is sourced into interactive Bash, not placed on PATH as a binary. It
installs to ~/.local/share/blesh/ble.sh via git clone --recursive +
make install PREFIX=~/.local, and is loaded through an idempotent managed
block in ~/.bashrc.

Changes

  • catalog/blesh.jsondedicated_script entry. version_command runs
    the sourced file (bash ~/.local/share/blesh/ble.sh --version).
  • scripts/install_blesh.shinstall / update / uninstall; ensures
    git/make/gawk; idempotent .bashrc block insert/remove that preserves
    surrounding content. Sourceable (main-guard) for testing.
  • tests/test_blesh.py — catalog structure + installer usage/idempotency
    (no network).
  • docs/superpowers/specs/… — design doc covering this PR and the follow-up
    bash-completion PR.

Verification (evidence, not assumption)

Installed ble.sh into a throwaway prefix to resolve the two design unknowns:

  • bash ~/.local/share/blesh/ble.sh --versionble.sh (Bash Line Editor), version 0.4.0-devel4+d69e4d5 (exit 0); extract_version_number(...)0.4.0.
  • collect_github('akinomyoga','ble.sh')('v0.4.0-devel3', '0.4.0') via the
    /releases/latest redirect (the nightly tag does not pollute it), so
    installed and upstream both normalize to 0.4.0 — no skip_upstream needed.

uv run python -m pytest → 717 passed, 1 skipped. Smoke + flake8 + pre-commit
hooks green.

Follow-up

Bash-completion installation framework ships in a separate PR (see the design doc).

https://claude.ai/code/session_01E3fMneH9KcaT7UYaHpfsHs

ble.sh is sourced into interactive Bash (not a PATH binary): installs to
~/.local/share/blesh/ble.sh via `git clone --recursive` + `make install`,
loaded through an idempotent managed block in ~/.bashrc.

- catalog/blesh.json: dedicated_script entry; version_command runs the sourced
  file (`bash ~/.local/share/blesh/ble.sh --version`), verified to extract
  0.4.0 and align with the github_repo upstream (no skip_upstream needed).
- scripts/install_blesh.sh: install/update/uninstall; deps (git/make/gawk);
  idempotent .bashrc block insert/remove that preserves surrounding content.
- tests/test_blesh.py: catalog structure + installer usage/idempotency (no net).
- docs/superpowers/specs: design doc for ble.sh + bash-completion (both PRs).

Claude-Session: https://claude.ai/code/session_01E3fMneH9KcaT7UYaHpfsHs
Signed-off-by: Sebastian Mendel <github@sebastianmendel.de>
Copilot AI review requested due to automatic review settings July 22, 2026 08:19
@gemini-code-assist

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@github-actions

Copy link
Copy Markdown
Contributor

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

CybotTM added 2 commits July 22, 2026 10:26
…markers

If the begin marker has no matching end marker (manual tampering or a write
interrupted mid-block), the previous awk set skip=1 and never cleared it,
deleting every line after the begin marker — including unrelated user content.
Buffer the region and, if no matching end marker is found by EOF, restore it
intact. Adds a regression test.

Found by adversarial review of #120.

Claude-Session: https://claude.ai/code/session_01E3fMneH9KcaT7UYaHpfsHs
Signed-off-by: Sebastian Mendel <github@sebastianmendel.de>
install_blesh.sh is POSIX shell; invoking it via `bash` fails on
windows-latest (CI on #120). Use the repo's existing skip_on_windows idiom for
the installer class; the catalog assertions stay platform-independent.

Claude-Session: https://claude.ai/code/session_01E3fMneH9KcaT7UYaHpfsHs
Signed-off-by: Sebastian Mendel <github@sebastianmendel.de>
@sonarqubecloud

Copy link
Copy Markdown

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@CybotTM
CybotTM merged commit ba360e0 into main Jul 22, 2026
24 of 25 checks passed
@CybotTM
CybotTM deleted the feat/add-blesh branch July 22, 2026 10:12
CybotTM added a commit that referenced this pull request Jul 22, 2026
## Summary

Adds **catalog-driven bash-completion installation**. A tool declares
how to get its
completion; the toolset installs it as part of the tool's normal
lifecycle and can
backfill everything already installed.

Independent of #120.

## Schema

A catalog entry may declare an optional `bash_completion` object with
exactly one of:

```jsonc
"bash_completion": { "command": "gh completion -s bash" }        // generate to stdout
"bash_completion": { "source_path": "completions/rbenv.bash" }   // copy, relative to clone_path
```

Files land in
`${XDG_DATA_HOME:-~/.local/share}/bash-completion/completions/`, named
after
**`binary_name`** so the framework lazy-loads them for that command.

## Changes

- `lib/completion.sh` — install/remove/post-install, framework
bootstrap, output validation
- `lib/bashrc.sh` — reusable idempotent managed-block insert/remove
- `install_tool.sh` — installs completion after a successful
install/update/reconcile,
removes on uninstall; best-effort, never fails the surrounding tool
operation
- `install_completion.sh` — CLI wrapper + `--all` backfill
- `make completions`, `make completion-<tool>`
- 40 catalog entries declare `bash_completion` (39 `command`, 1
`source_path`)
- `catalog/COVERAGE.md` records the full classification

## Verification

All 112 catalog entries were audited: each candidate generator was
**executed**, its output
validated, and checked to confirm it registers the entry's own
`binary_name`.
End-to-end: `install_completion.sh --all` installs **36** completions;
every file registers
its own command. `pytest` → 728 passed, 1 skipped.

### Findings that shaped the implementation

1. **Validation had to be strict.** A permissive check (any output
containing "complete")
accepted `bandit complete bash`, which actually *ran a security scan*.
The predicate now
   requires `complete -…` / `compgen ` / `COMPREPLY`.
2. **Six tools have a working generator that must not be used** — the
file is named after
`binary_name`, so a script registering a different command silently
shadows another tool:
`gh-aw` emits **gh's** completion, `rga` returns ripgrep's verbatim,
`compose` is
`binary_name: docker`, `fzf --bash` is shell integration (key bindings +
global
`complete -D`), `rustup` never registers `rustc`, `gcloud` has no
`clone_path`.
   A test enforces that no two declaring entries share a `binary_name`.

### Robustness fixes (post-review, each reproduced then verified)

- `_completion_catalog_file` returned 1 for an unknown tool, aborting
`set -e` callers before
their own no-op guard (`make completion-<typo>` failed with a bare
`Error 1`).
- `mkdir`/`mv` were unchecked and the trailing `echo` forced a 0 return
— an unwritable target
  reported "installed", wrote nothing, and leaked a temp file.
- The generator inherited stdin, so a generator that reads stdin would
hang the install
  forever. Now `</dev/null` (+ a timeout where the platform has one).
- The `~/.bashrc` block lacked an interactive guard; the distro
`bash_completion` has none of
its own and enables `extglob`/`progcomp` at top level, so a
non-interactive shell sourcing
  `~/.bashrc` silently got extended globbing.

`codex`, `pip`, `pipx` are not installed on the audit machine, so their
generators come from
official docs — runtime validation makes that safe (an invalid generator
writes nothing).

## Note on size

Exceeds the ~300 net-LOC guideline. The framework is small; the bulk is
40 mechanical
one-line catalog declarations plus the coverage table, done in one
sweep.
CybotTM added a commit that referenced this pull request Jul 22, 2026
…ts (#122)

CI runs the suite on `ubuntu-latest`, `macos-latest` **and
`windows-latest`**, while
everything under `scripts/` is POSIX Bash. Any test that invokes `bash`,
sources a
`scripts/lib/*.sh` helper, or executes an installer fails on the Windows
leg.

Thirteen test files already use the `skip_on_windows` marker, but the
convention was
undocumented — so it gets re-derived the hard way. It is invisible
locally: the suite
is green on Linux and only the Windows CI leg turns red (this happened
on #120 and
again on #121 during this work).

Documents the marker, and that it applies to the shell-invoking class
only — pure
Python assertions (catalog JSON structure, schema invariants) must keep
running on
every platform.

Docs only; no code or test changes.

Came from /retro: yes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants