Skip to content

Commit 06884ba

Browse files
committed
latest updates
1 parent c6ab4ee commit 06884ba

8 files changed

Lines changed: 174 additions & 44 deletions

File tree

AGENTS.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Repository Guidelines
2+
3+
## Project Structure & Module Organization
4+
This repo is a collection of shell-focused utilities and dotfiles.
5+
6+
- `scripts/`: standalone utility scripts (bash/sh). Example: `scripts/cloudflare-ddns.sh`.
7+
- `dotfiles/`: shell, editor, and tool configs intended to be symlinked into `$HOME`.
8+
- `config/`: supplemental config files (e.g., `config/inputrc`, `config/eslintrc.json`).
9+
- `systemd/`: unit/timer files (e.g., `systemd/cloudflare-ddns.service`).
10+
- `install.sh`: installer that symlinks dotfiles/config into the target prefix.
11+
12+
## Build, Test, and Development Commands
13+
- `./install.sh`: install dotfiles/config into `$HOME` (or `INSTALL_PREFIX`).
14+
- `./install.sh -u`: uninstall and restore backups.
15+
- `npm install`: install optional CLI dependencies used by some scripts.
16+
- `./scripts/lint.sh`: run `shellcheck` across repository shell scripts.
17+
18+
## Coding Style & Naming Conventions
19+
- Shell scripts use bash (`#!/bin/bash`), with `set -e` where appropriate.
20+
- Indentation is 4 spaces in scripts; keep consistent with surrounding files.
21+
- File naming favors lowercase with hyphens, e.g., `cloudflare-ddns.sh`.
22+
- Run `shellcheck` (via `./scripts/lint.sh`) before submitting changes.
23+
24+
## Testing Guidelines
25+
- Primary check is `shellcheck`. There is no separate unit test framework.
26+
- If you add new scripts, ensure they are picked up by `./scripts/lint.sh`.
27+
- Prefer small, focused scripts and add usage examples in comments if helpful.
28+
29+
## Commit & Pull Request Guidelines
30+
- Commit messages are short, imperative, and lowercase (e.g., “fix ssh-agent issue”).
31+
- PRs should include a concise summary, the affected paths, and any setup steps.
32+
- If changes affect installation behavior, note new env vars or flags.
33+
- For config or credential-related changes, include safety notes (permissions, paths).
34+
35+
## Security & Configuration Tips
36+
- Cloudflare integration expects `~/.config/cloudflare/credentials` with `600` perms.
37+
- Avoid committing secrets; prefer environment variables and local config files.

IMPROVEMENTS.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Improvement Plan
2+
3+
## 1) Make Lint Actionable
4+
Goal: Turn `./scripts/lint.sh` into a reliable quality gate.
5+
- Audit current `shellcheck` findings and categorize as fixable vs. intentional.
6+
- Fix high-signal warnings (quoting, redirections, `cd` safety, missing shell directive).
7+
- For intentional patterns, add `# shellcheck disable=SCxxxx` with brief justification.
8+
- Decide whether to lint `dotfiles/sh_config.d` as `bash` or `zsh` and pass `-s` to shellcheck.
9+
- Update `scripts/lint.sh` to reflect the chosen scope and add `--severity` if needed.
10+
11+
## 2) Add Compatibility Notes
12+
Goal: Clarify OS/tooling assumptions to reduce breakage.
13+
- Document supported OS targets (macOS, Linux) and known differences (GNU/BSD utils).
14+
- Note required tools (e.g., `shellcheck`, `git`, `systemd` for `systemd/` usage).
15+
- Add bash version expectations if any scripts rely on `bash` 4+ behavior.
16+
17+
## 3) Minimal Test/Verification Strategy
18+
Goal: Provide low-effort checks for critical scripts.
19+
- Add a "Smoke Tests" section to `README.md` with sample commands.
20+
- Add dry-run flags or safe read-only modes for critical scripts when feasible.
21+
- Identify 2–3 critical scripts (e.g., `install.sh`, `cloudflare-ddns.sh`) and define expected outputs.
22+
23+
## 4) Standardize Shell Directives
24+
Goal: Remove ambiguity about which shell each file targets.
25+
- Add shebangs or shellcheck directives to `dotfiles/sh_config.d/*.sh`.
26+
- Ensure `bash`-specific features aren’t used in `sh`-intended files.
27+
- Align file names or headers to indicate `bash` vs `zsh` intent.
28+
29+
## 5) Document Installer Behavior
30+
Goal: Make install/uninstall operations safe and predictable.
31+
- Describe symlink behavior, backup naming, and restore behavior.
32+
- Clarify `INSTALL_PREFIX`, `DOTFILES_ROOT`, `CONFIG_ROOT` precedence.
33+
- Provide a short "Rollback" note if installation is interrupted.
34+
35+
## 6) Script Index
36+
Goal: Improve discoverability.
37+
- Add `scripts/README.md` listing script names, purposes, and example usage.
38+
- Keep each entry to 1–2 lines with a minimal example.
39+
40+
## 7) Consistent Error Handling
41+
Goal: Reduce runtime surprises in scripts.
42+
- Adopt `set -euo pipefail` where safe; document exceptions.
43+
- Replace unsafe `cd` with `cd ... || exit` or `return`.
44+
- Quote variable expansions and use `printf` safely.
45+
46+
## 8) Centralize Security Notes
47+
Goal: Prevent accidental exposure of secrets.
48+
- Add a "Security & Credentials" section in `README.md`.
49+
- Note permission requirements (e.g., `chmod 600` on credentials).
50+
- Add `.gitignore` entries for known local secret files if needed.
51+
52+
## 9) Add CI for Linting
53+
Goal: Prevent regressions without manual checks.
54+
- Add a GitHub Actions workflow that runs `./scripts/lint.sh`.
55+
- Optionally add a quick `bash -n` syntax check for all scripts.
56+
- Keep CI lightweight; no external deps beyond `shellcheck`.
57+
58+
## 10) Commit/PR Checklist
59+
Goal: Encourage consistent contributions.
60+
- Add a short checklist to `README.md` or `AGENTS.md`:
61+
- Run `./scripts/lint.sh`
62+
- Verify install/uninstall
63+
- Add/update usage notes for new scripts
64+
- Mention any OS-specific constraints
65+
66+
## Suggested Order of Execution
67+
1. Make lint actionable (unblocks other work).
68+
2. Standardize shell directives.
69+
3. Fix error handling/quoting issues.
70+
4. Add compatibility notes and installer documentation.
71+
5. Add script index.
72+
6. Add security notes.
73+
7. Add CI workflow.
74+
8. Add commit/PR checklist.

install.sh

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ log_verbose() {
101101
backup_file() {
102102
local file="$1"
103103
if [ -e "$file" ] && [ ! -L "$file" ]; then
104-
local backup="${file}.backup.$(date +%Y%m%d_%H%M%S)"
104+
local backup
105+
backup="${file}.backup.$(date +%Y%m%d_%H%M%S)"
105106
log_verbose "Creating backup: $file -> $backup"
106107
cp -r "$file" "$backup"
107108
echo " backed up to: $backup"
@@ -111,7 +112,13 @@ backup_file() {
111112
# Function to restore latest backup
112113
restore_backup() {
113114
local file="$1"
114-
local latest_backup=$(ls -t "${file}.backup."* 2>/dev/null | head -n1)
115+
local latest_backup=""
116+
local backup
117+
for backup in "${file}.backup."*; do
118+
if [ -e "$backup" ]; then
119+
latest_backup="$backup"
120+
fi
121+
done
115122
if [ -n "$latest_backup" ]; then
116123
log_verbose "Restoring backup: $latest_backup -> $file"
117124
rm -rf "$file"
@@ -137,7 +144,8 @@ create_symlink() {
137144
local target_name="$3"
138145

139146
if [ -L "$target" ]; then
140-
local current_target=$(readlink "$target")
147+
local current_target
148+
current_target=$(readlink "$target")
141149
if [ "$current_target" = "$source" ]; then
142150
log_verbose "Symlink already correct: $target -> $source"
143151
echo " already linked correctly"
@@ -172,7 +180,7 @@ init_submodules() {
172180
if [ "$VERBOSE" = true ]; then
173181
git submodule update --init --recursive "$submodule_path"
174182
else
175-
git submodule update --init --recursive "$submodule_path" 2>&1 > /dev/null
183+
git submodule update --init --recursive "$submodule_path" > /dev/null 2>&1
176184
fi
177185
return 0
178186
else
@@ -350,7 +358,7 @@ if [ ! -d "$ZSH" ]; then
350358
-c fsck.zeroPaddedFilemode=ignore \
351359
-c fetch.fsck.zeroPaddedFilemode=ignore \
352360
-c receive.fsck.zeroPaddedFilemode=ignore \
353-
--depth=1 https://github.com/ohmyzsh/ohmyzsh.git "$ZSH" 2>&1 > /dev/null
361+
--depth=1 https://github.com/ohmyzsh/ohmyzsh.git "$ZSH" > /dev/null 2>&1
354362
fi
355363
echo " Done"
356364
else
@@ -369,9 +377,9 @@ if [ ! -d "$ZSH_CUSTOM/themes/powerlevel10k" ]; then
369377
if [ -d "$ZSH" ] && confirm "Install Powerlevel10k theme?"; then
370378
log_verbose "Cloning Powerlevel10k theme to $ZSH_CUSTOM/themes/powerlevel10k"
371379
if [ "$VERBOSE" = true ]; then
372-
git clone --depth=1 https://github.com/romkatv/powerlevel10k.git $ZSH_CUSTOM/themes/powerlevel10k
380+
git clone --depth=1 https://github.com/romkatv/powerlevel10k.git "$ZSH_CUSTOM"/themes/powerlevel10k
373381
else
374-
git clone --depth=1 https://github.com/romkatv/powerlevel10k.git $ZSH_CUSTOM/themes/powerlevel10k 2>&1 > /dev/null
382+
git clone --depth=1 https://github.com/romkatv/powerlevel10k.git "$ZSH_CUSTOM"/themes/powerlevel10k > /dev/null 2>&1
375383
fi
376384
echo " Done"
377385
else

scripts/cloudflare-ddns.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ log() {
2929
local level="$1"
3030
shift
3131
local message="$*"
32-
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
32+
local timestamp
33+
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
3334
echo "[${timestamp}] [${level}] ${message}" | tee -a "${LOG_FILE}"
3435
}
3536

scripts/install-cloudflare-ddns.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ EOF
164164
echo " Zone: ${zone}"
165165
echo " Records:"
166166
for record in "${records[@]}"; do
167-
IFS=':' read -r id name proxy <<< "${record}"
167+
IFS=':' read -r _ name proxy <<< "${record}"
168168
echo " - ${name} (proxy: ${proxy})"
169169
done
170170
}

scripts/lint.sh

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,12 @@ echo
2727

2828
# Track errors
2929
ERRORS=0
30+
SHELLCHECK_STRICT_FLAGS=(-s bash)
31+
SHELLCHECK_RELAXED_FLAGS=(-s bash -S error)
3032

3133
# Check install.sh
3234
echo -e "${YELLOW}Checking install.sh...${NC}"
33-
if shellcheck install.sh; then
35+
if shellcheck "${SHELLCHECK_STRICT_FLAGS[@]}" install.sh; then
3436
echo -e "${GREEN}✓ install.sh passed${NC}"
3537
else
3638
echo -e "${RED}✗ install.sh failed${NC}"
@@ -42,7 +44,7 @@ echo
4244
echo -e "${YELLOW}Checking dotfiles/sh_config.d/*.sh...${NC}"
4345
for file in dotfiles/sh_config.d/*.sh; do
4446
if [[ -f "$file" ]]; then
45-
if shellcheck "$file"; then
47+
if shellcheck "${SHELLCHECK_RELAXED_FLAGS[@]}" "$file"; then
4648
echo -e "${GREEN}$file passed${NC}"
4749
else
4850
echo -e "${RED}$file failed${NC}"
@@ -56,7 +58,7 @@ echo
5658
echo -e "${YELLOW}Checking dotfiles/sh_functions.d/*.bash...${NC}"
5759
for file in dotfiles/sh_functions.d/*.bash; do
5860
if [[ -f "$file" ]]; then
59-
if shellcheck "$file"; then
61+
if shellcheck "${SHELLCHECK_RELAXED_FLAGS[@]}" "$file"; then
6062
echo -e "${GREEN}$file passed${NC}"
6163
else
6264
echo -e "${RED}$file failed${NC}"
@@ -70,7 +72,7 @@ echo
7072
echo -e "${YELLOW}Checking scripts/*.sh...${NC}"
7173
for file in scripts/*.sh scripts/*.bash; do
7274
if [[ -f "$file" ]]; then
73-
if shellcheck "$file"; then
75+
if shellcheck "${SHELLCHECK_STRICT_FLAGS[@]}" "$file"; then
7476
echo -e "${GREEN}$file passed${NC}"
7577
else
7678
echo -e "${RED}$file failed${NC}"

scripts/lspd.bash

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,19 @@
33
DIR="."
44
if [ -d "$1" ]; then
55
# echo "valid dir"
6-
DIR=$1
6+
DIR="$1"
77
fi
88

99

1010
MODULE_DEPS=$(
11-
find $DIR -name '*.pm' -exec grep '^use ' {} \;| \
11+
find "$DIR" -name '*.pm' -exec grep '^use ' {} \; | \
1212
awk '{ if ($2 == "base") print $3; else if ($2 != "strict;") print $2 }'| \
1313
sed "s/[';]//g" | \
1414
sort | uniq
1515
);
1616

1717
TEST_DEPS=$(
18-
find $DIR -name '*.t' -exec grep '^use ' {} \;| \
18+
find "$DIR" -name '*.t' -exec grep '^use ' {} \; | \
1919
awk '{ if ($2 == "base") print $3; else if ($2 != "strict;") print $2 }'| \
2020
sed "s/[';]//g" | \
2121
sort | uniq

scripts/spotify-cache-stats.sh

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,44 @@
11
#!/bin/bash
22

3-
CACHEDIR=/var/lib/squeezeboxserver/cache/spotifycache/Storage
3+
CACHEDIR="/var/lib/squeezeboxserver/cache/spotifycache/Storage"
44

5-
cd $CACHEDIR
5+
cd "$CACHEDIR" || exit 1
66

7-
clear;
8-
while true; do
9-
tput eo
10-
tput cup 0 0
11-
echo "Cache Size: $(du -sh .)"
12-
echo "Directory Count: $(ls -1 | grep -v index.dat | wc -l) "
13-
tput el
14-
echo ""
7+
clear
8+
while true; do
9+
tput eo
10+
tput cup 0 0
11+
echo "Cache Size: $(du -sh .)"
12+
dir_count=$(find . -maxdepth 1 -mindepth 1 ! -name 'index.dat' | wc -l)
13+
echo "Directory Count: ${dir_count}"
14+
tput el
15+
echo ""
1516

16-
OPENFILES=$(sudo lsof +D $CACHEDIR | grep 'file$' | cut -d'/' -f8-)
17-
for FILE in $OPENFILES; do
18-
SIZE=$(stat -c %s $CACHEDIR/$FILE)
19-
CTIME=$(stat -c %x $CACHEDIR/$FILE)
20-
printf "File: %s %9s, Time: $CTIME\n" $FILE $SIZE
21-
done
22-
tput el
23-
echo ""
24-
for DIR in $(ls -1tr | grep -v index.dat | tail -n 10); do
25-
printf "%2s: %s, " $DIR $(du -sh $DIR | cut -f1)
26-
done
17+
OPENFILES=$(sudo lsof +D "$CACHEDIR" 2>/dev/null | grep 'file$' | cut -d'/' -f8-)
18+
for FILE in $OPENFILES; do
19+
SIZE=$(stat -c %s "$CACHEDIR/$FILE")
20+
CTIME=$(stat -c %x "$CACHEDIR/$FILE")
21+
printf "File: %s %9s, Time: %s\n" "$FILE" "$SIZE" "$CTIME"
22+
done
23+
tput el
24+
echo ""
2725

28-
echo "";
26+
mapfile -t recent_entries < <(
27+
find . -maxdepth 1 -mindepth 1 ! -name 'index.dat' -printf '%T@ %P\n' \
28+
| sort -n \
29+
| tail -n 10 \
30+
| awk '{print $2}'
31+
)
32+
for DIR in "${recent_entries[@]}"; do
33+
printf "%2s: %s, " "$DIR" "$(du -sh "$DIR" | cut -f1)"
34+
done
2935

30-
tput el
31-
for I in {1..5}; do
32-
sleep 1;
33-
echo -n ".";
34-
done
35-
tput el1
36+
echo ""
37+
38+
tput el
39+
for _ in {1..5}; do
40+
sleep 1
41+
echo -n "."
42+
done
43+
tput el1
3644
done

0 commit comments

Comments
 (0)