Skip to content

Commit d8a9bb1

Browse files
1shoopermanclaude
andauthored
feat: add convert-video, shared bootstrap, common lib, fix sast brew bug (#10)
* feat: add convert-video, shared bootstrap, common lib, fix sast brew bug - Add bin/_bootstrap: single location for symlink-crawl and CLI_TOOL_ROOT export - All bin scripts source _bootstrap instead of inlining the while loop - Extract gecho/show_progress/color vars into lib/common.sh - Add bin/convert-video and lib/ffmpegcmds.sh for H.264/AAC MP4 conversion - Fix sast defaulting PLUGINS_DIR to script install path (broke brew installs) - Add tests for _bootstrap and common.sh; fix test_gitcmds and test_sast for new structure - Update README structure section and add convert-video docs Closes #9 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: pass all args to convert_vid so --silent works Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 1efbbe9 commit d8a9bb1

14 files changed

Lines changed: 178 additions & 51 deletions

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,6 @@ build/
3131
!.env.example
3232

3333

34-
change-summary.md
34+
change-summary.md
35+
wiki/**
36+
!.gitkeep

README.md

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# cli-tools
22

3-
Personal shell utilities for git branch hygiene, GPG cache warming, and Claude plugin static analysis.
3+
Personal shell utilities for git branch hygiene, GPG cache warming, video conversion, and Claude plugin static analysis.
44

55
## Installation
66

@@ -52,9 +52,17 @@ Warms the GPG agent cache by performing a throwaway clearsign. Useful to pre-unl
5252
cache-gpg
5353
```
5454

55-
### `sast`
55+
### `convert-video [file]`
5656

57-
Static analysis for Claude plugin markdown files. Scans `plugins/` for risky `allowed-tools` declarations in YAML frontmatter.
57+
Converts a video file to H.264/AAC MP4 using ffmpeg. Output is written alongside the input with a `.mp4` extension. Requires `ffmpeg`.
58+
59+
```sh
60+
convert-video input.mov
61+
```
62+
63+
### `sast [plugins-dir]`
64+
65+
Static analysis for Claude plugin markdown files. Scans `plugins/` (default: `./plugins`) for risky `allowed-tools` declarations in YAML frontmatter.
5866

5967
| Severity | Check |
6068
|----------|-------|
@@ -63,7 +71,8 @@ Static analysis for Claude plugin markdown files. Scans `plugins/` for risky `al
6371
| WARN | Bare `WebFetch` — any domain fetchable |
6472

6573
```sh
66-
sast
74+
sast # scans ./plugins
75+
sast /path/to/plugins # scans a specific directory
6776
```
6877

6978
Exits non-zero if any ERROR findings are found.
@@ -72,12 +81,16 @@ Exits non-zero if any ERROR findings are found.
7281

7382
```
7483
bin/
75-
cache-gpg # warms GPG agent cache
76-
gitprune # wrapper for gitprune()
77-
gitrefresh # wrapper for gitrefresh()
78-
sast # static analysis for claude plugin frontmatter
84+
_bootstrap # resolves CLI_TOOL_ROOT; sourced by all bin scripts
85+
cache-gpg # warms GPG agent cache
86+
convert-video # wrapper for convert_vid()
87+
gitprune # wrapper for gitprune()
88+
gitrefresh # wrapper for gitrefresh()
89+
sast # static analysis for claude plugin frontmatter
7990
lib/
80-
gitcmds.sh # shared function definitions
91+
common.sh # shared color vars, gecho, show_progress
92+
ffmpegcmds.sh # convert_vid() implementation
93+
gitcmds.sh # gitprune() and gitrefresh() implementations
8194
```
8295

8396
## License

bin/_bootstrap

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/usr/bin/env bash
2+
_src="${BASH_SOURCE[0]}"
3+
while [ -L "$_src" ]; do
4+
_dir="$(cd -P "$(dirname "$_src")" && pwd)"
5+
_src="$(readlink "$_src")"
6+
[[ "$_src" != /* ]] && _src="$_dir/$_src"
7+
done
8+
CLI_TOOL_ROOT="$(cd -P "$(dirname "$_src")/.." && pwd)"
9+
export CLI_TOOL_ROOT
10+
unset _src _dir

bin/convert-video

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#!/bin/bash
2+
# shellcheck source=bin/_bootstrap
3+
source "${BASH_SOURCE[0]%/*}/_bootstrap"
4+
# shellcheck source=lib/ffmpegcmds.sh
5+
source "$CLI_TOOL_ROOT/lib/ffmpegcmds.sh"
6+
7+
convert_vid "$@"

bin/gitprune

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
#!/bin/bash
2+
# shellcheck source=bin/_bootstrap
3+
source "${BASH_SOURCE[0]%/*}/_bootstrap"
24
# shellcheck source=lib/gitcmds.sh
3-
_src="${BASH_SOURCE[0]}"
4-
while [ -L "$_src" ]; do
5-
_dir="$(cd -P "$(dirname "$_src")" && pwd)"
6-
_src="$(readlink "$_src")"
7-
[[ "$_src" != /* ]] && _src="$_dir/$_src"
8-
done
9-
source "$(cd -P "$(dirname "$_src")" && pwd)/../lib/gitcmds.sh"
5+
source "$CLI_TOOL_ROOT/lib/gitcmds.sh"
106

117
gitprune "$1"

bin/gitrefresh

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
#!/bin/bash
2+
# shellcheck source=bin/_bootstrap
3+
source "${BASH_SOURCE[0]%/*}/_bootstrap"
24
# shellcheck source=lib/gitcmds.sh
3-
_src="${BASH_SOURCE[0]}"
4-
while [ -L "$_src" ]; do
5-
_dir="$(cd -P "$(dirname "$_src")" && pwd)"
6-
_src="$(readlink "$_src")"
7-
[[ "$_src" != /* ]] && _src="$_dir/$_src"
8-
done
9-
source "$(cd -P "$(dirname "$_src")" && pwd)/../lib/gitcmds.sh"
5+
source "$CLI_TOOL_ROOT/lib/gitcmds.sh"
106

117
gitrefresh "$1"

bin/sast

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
#!/bin/bash
22
set -euo pipefail
33

4-
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
5-
PLUGINS_DIR="${1:-$REPO_ROOT/plugins}"
4+
# shellcheck source=bin/_bootstrap
5+
source "${BASH_SOURCE[0]%/*}/_bootstrap"
6+
7+
PLUGINS_DIR="${1:-$(pwd)/plugins}"
68

79
FINDINGS=0
810
EXIT_CODE=0
@@ -22,7 +24,7 @@ while IFS= read -r file; do
2224
tools_line=$(awk '/^---/{f=!f; next} f && /^allowed-tools:/' "$file" | head -1)
2325
[[ -z "$tools_line" ]] && continue
2426

25-
rel="${file#"$REPO_ROOT"/}"
27+
rel="${file#"$(pwd)"/}"
2628

2729
# Bare Bash (no constraint) — allows any shell command
2830
if echo "$tools_line" | grep -qE '\bBash\b[^(]|Bash\s*\]|Bash\s*,'; then

lib/common.sh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/usr/bin/env bash
2+
GREEN='\033[32m'
3+
GREY='\033[2m'
4+
RESET='\033[0m'
5+
6+
gecho() { printf "${GREEN}%s${RESET}\n" "$*"; }
7+
8+
show_progress() {
9+
while IFS= read -r line; do
10+
printf "\r${GREY}%-120s${RESET}" "${line:0:120}"
11+
done
12+
printf "\r%-120s\r" ""
13+
}

lib/ffmpegcmds.sh

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
convert_vid() {
2+
local silent=0
3+
local input=""
4+
5+
for arg in "$@"; do
6+
if [[ "$arg" == "--silent" ]]; then
7+
silent=1
8+
else
9+
input="$arg"
10+
break
11+
fi
12+
done
13+
14+
if ! command -v ffmpeg &>/dev/null; then
15+
echo "convert_vid: ffmpeg is not installed. Please install ffmpeg to use this function." >&2
16+
return 1
17+
fi
18+
19+
if [[ -z "$input" ]]; then
20+
echo "convert_vid: usage: convert_vid [--silent] <input-file>" >&2
21+
return 1
22+
fi
23+
24+
if [[ ! -f "$input" ]]; then
25+
echo "convert_vid: input file not found: $input" >&2
26+
return 1
27+
fi
28+
29+
local output="${input%.*}.mp4"
30+
31+
if [[ $silent -eq 1 ]]; then
32+
ffmpeg -i "$input" -vcodec libx264 -crf 23 -preset medium -acodec aac -b:a 128k "$output" &>/dev/null
33+
else
34+
ffmpeg -i "$input" -vcodec libx264 -crf 23 -preset medium -acodec aac -b:a 128k "$output"
35+
fi
36+
}

lib/gitcmds.sh

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,6 @@
11
#!/usr/bin/env bash
2-
3-
GREEN='\033[32m'
4-
GREY='\033[2m'
5-
RESET='\033[0m'
6-
7-
gecho() { printf "${GREEN}%s${RESET}\n" "$*"; }
8-
9-
show_progress() {
10-
while IFS= read -r line; do
11-
printf "\r${GREY}%-120s${RESET}" "${line:0:120}"
12-
done
13-
printf "\r%-120s\r" ""
14-
}
2+
# shellcheck source=lib/common.sh
3+
source "$CLI_TOOL_ROOT/lib/common.sh"
154

165
gitprune() {
176
gecho "Pruning local git branches"

0 commit comments

Comments
 (0)