Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
8009041
Add CI pipeline with shellcheck linting
claude Jan 25, 2026
51f0c82
Fix shellcheck errors and add suppressions
claude Jan 25, 2026
655e6f7
Add shellcheck directives to zsh/*.sh and exclude local-only file
claude Jan 25, 2026
b8c12dc
Suppress SC1091 for missing sourced files in CI
claude Jan 25, 2026
8e2b7f5
Add Python linting (ruff, mypy), YAML validation, and fix install script
claude Jan 25, 2026
8103889
Add more CI checks: trailing whitespace, typos, shebangs, large files
claude Jan 25, 2026
035e59c
Rename underware files back (project name, not typo) and lint aider c…
claude Jan 26, 2026
69d019b
Capitalize shellcheck suppression comments
claude Jan 26, 2026
302a203
Simplify install script sudo handling
claude Jan 26, 2026
8850720
Use inline SC1091 suppressions instead of global flag
claude Jan 26, 2026
d8ebbed
Revert underware references and restore commented sudo block
claude Jan 26, 2026
00ac4dd
Add vint for Vimscript linting and fix typos false positives
claude Jan 26, 2026
8b1accf
Include vimrc in vint linting
claude Jan 26, 2026
ffa232c
Fix all vint issues in vimrc
claude Jan 26, 2026
01684a0
Use inline vint disables instead of global config
claude Jan 26, 2026
b0be0ac
WIP add task dev command
bobwhitelock Jan 26, 2026
1a4c689
Add zsh syntax and load checking to CI
claude Jan 26, 2026
6dbfa25
Replace separate checks with single integration test
claude Jan 26, 2026
b522d46
Fix CI integration test directory structure
claude Jan 26, 2026
49124cf
Simplify CI integration test to focus on zsh loading
claude Jan 26, 2026
946cae1
Make install script CI-compatible
claude Jan 26, 2026
2fef22b
Fix CI directory paths for dotbot
claude Jan 26, 2026
4dbbb19
Make install script check for actual requirements
claude Jan 26, 2026
6b4abdc
Fix env.sh: move ZSH_DIR after DOTFILES is set
claude Jan 26, 2026
4e24764
Fix: source env.sh without pipeline to preserve exports
claude Jan 26, 2026
8840e40
Add debug output for install script failure
claude Jan 26, 2026
416d196
Debug: run install steps manually in CI
claude Jan 26, 2026
70f73de
CI: Skip dotbot, just test zsh loading
claude Jan 26, 2026
d96bfdb
Debug: verbose zsh test output
claude Jan 26, 2026
ca15330
Restore install script and strict zsh test
claude Jan 26, 2026
a6959bf
Debug: identify which lib file produces output
claude Jan 26, 2026
59efd59
Fix kubernetes.sh to check for kubectl before running
claude Jan 26, 2026
a329ee0
Add debug output to install script
claude Jan 26, 2026
0ab11ad
Simplify install script for debugging
claude Jan 26, 2026
10a306e
Skip dotbot for debugging
claude Jan 26, 2026
ee58641
Debug: test each lib file individually
claude Jan 26, 2026
91c49bf
Debug: don't fail on output to see what's detected
claude Jan 26, 2026
67db9d5
Add zsh output to step summary for debugging
claude Jan 26, 2026
f2687ff
Fix git.sh: only call compdef if available
claude Jan 26, 2026
5e34754
Restore full install script functionality
claude Jan 26, 2026
1ab2e1f
Debug: check DOTFILES and dotbot path
claude Jan 26, 2026
c563264
Skip dotbot if not found (submodules may not be populated)
claude Jan 26, 2026
56eb69b
Debug: minimal install script
claude Jan 26, 2026
58cf0ee
Debug: add back link_files and install_dependencies
claude Jan 26, 2026
fbaa50e
Add back dotbot, tmux, and tweak_system_files
claude Jan 26, 2026
5ac801a
Make dotbot failure non-fatal
claude Jan 26, 2026
9d64c93
Clean up install script
claude Jan 26, 2026
3cafc4e
Expect submodules to be initialized, fail if not
claude Jan 27, 2026
ac176e1
Skip tmux plugin install if tmux not installed
claude Jan 27, 2026
f76fd39
Install vim and tmux in CI for thorough testing
claude Jan 27, 2026
c677b5e
Add debug output to install script step
claude Jan 27, 2026
403acac
Add explicit error messages for dotbot and tpm failures
claude Jan 27, 2026
93d1966
Comment out optional yarn packages install
claude Jan 27, 2026
3fba419
Debug: break install into separate steps in CI
claude Jan 27, 2026
869bb8a
Debug: track which install steps fail in CI
claude Jan 27, 2026
d4cae05
Simplify CI to run full install script
claude Jan 27, 2026
7e4cc0a
Add debug output to CI
claude Jan 27, 2026
de8518b
Add per-file zsh lib debugging to CI
claude Jan 27, 2026
c2009e8
Add ignore-missing to dotfiles-private links
claude Jan 27, 2026
bfd8409
Fix dotfiles-private placeholder path for CI
claude Jan 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
name: CI

on:
pull_request:

jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- uses: pre-commit/action@v3.0.1

integration:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Install dependencies
run: sudo apt-get update && sudo apt-get install -y zsh vim tmux
- name: Setup environment
run: |
mkdir -p ~/src/bobwhitelock
ln -s ${{ github.workspace }} ~/src/bobwhitelock/dotfiles
- name: Run install script
run: |
set -x
cd ~/src/bobwhitelock/dotfiles
./install
echo "Install script completed successfully"
- name: Verify zsh loads without errors
run: |
set -x
echo "=== Testing zsh lib files individually ==="
export DOTFILES="$HOME/src/bobwhitelock/dotfiles"
export ZSH_DIR="$DOTFILES/zsh"
export ZSH_LIB="$ZSH_DIR/lib"

# First test env.sh alone
echo "Testing env.sh..."
output=$(zsh -c "source '$ZSH_DIR/env.sh'" 2>&1) || true
if [ -n "$output" ]; then
echo "env.sh produced output: $output"
fi

# Test each lib file
for f in "$ZSH_LIB"/*; do
fname=$(basename "$f")
output=$(zsh -c "
source '$ZSH_DIR/env.sh'
source '$f'
" 2>&1) || true
if [ -n "$output" ]; then
echo "ERROR: $fname produced output:"
echo "$output"
else
echo "OK: $fname"
fi
done

echo "=== Full zsh load test ==="
output=$(zsh -c '
export DOTFILES="$HOME/src/bobwhitelock/dotfiles"
export ZSH_DIR="$DOTFILES/zsh"
export ZSH_LIB="$ZSH_DIR/lib"
source "$ZSH_DIR/env.sh"
for f in "$ZSH_LIB"/*; do
source "$f"
done
' 2>&1) || true

if [ -n "$output" ]; then
echo "ERROR: zsh produced unexpected output:"
echo "$output"
exit 1
fi
echo "zsh loaded successfully with no output"
50 changes: 50 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-merge-conflict
- id: check-added-large-files
- id: check-executables-have-shebangs

- repo: https://github.com/crate-ci/typos
rev: v1.28.4
hooks:
- id: typos

- repo: https://github.com/koalaman/shellcheck-precommit
rev: v0.10.0
hooks:
- id: shellcheck
args: ["-x"] # follow source statements
files: \.(sh|bash)$|^bin/|^libexec/
exclude: \.(py|pl)$|colours-to-rgb|extract_urls|git-ls-revisions|stripcolours|todoist-to-markdown|env\.private\.example\.sh

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.6
hooks:
- id: ruff
args: [--fix]
- id: ruff-format

- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.14.1
hooks:
- id: mypy
additional_dependencies: []

- repo: https://github.com/adrienverge/yamllint
rev: v1.35.1
hooks:
- id: yamllint
args: [-c, .yamllint.yml]

- repo: local
hooks:
- id: vint
name: vint
entry: vint
language: python
additional_dependencies: [vim-vint]
files: \.vim$|vimrc$|gvimrc$
7 changes: 7 additions & 0 deletions .typos.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[default.extend-words]
# Vim mapping <leader>ue for UltiSnipsEdit
ue = "ue"
# Project name, not underwear
underware = "underware"
# Alias for git rebase --abort
grea = "grea"
20 changes: 20 additions & 0 deletions .yamllint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
extends: default

# tmuxinator files use ERB templating which makes them invalid YAML
ignore:
- tmuxinator/

rules:
line-length:
max: 150
truthy:
check-keys: false
document-start: disable
comments:
min-spaces-from-content: 1
empty-lines:
max-start: 1
indentation:
indent-sequences: whatever
comments-indentation: disable
key-duplicates: disable
42 changes: 42 additions & 0 deletions Taskfile.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
version: '3'

tasks:
dev:
desc: Install development dependencies
cmds:
- pipx install pre-commit vint

# TODO BW 2026-01-26: Add install and other scripts in here instead? Though
# then need `task` installed first.

lint:
desc: Run all linters
cmds:
- pre-commit run --all-files

integration:
desc: Run install script and verify zsh loads cleanly
cmds:
- ./install
- |
output=$(zsh -c '
export DOTFILES="$HOME/src/bobwhitelock/dotfiles"
export ZSH_DIR="$DOTFILES/zsh"
export ZSH_LIB="$ZSH_DIR/lib"
source "$ZSH_DIR/env.sh"
for f in "$ZSH_LIB"/*; do
source "$f"
done
' 2>&1) || true
if [ -n "$output" ]; then
echo "ERROR: zsh produced unexpected output:"
echo "$output"
exit 1
fi
echo "zsh loaded successfully with no output"

ci:
desc: Full CI pipeline
cmds:
- task: lint
- task: integration
4 changes: 3 additions & 1 deletion aider.conf.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
#
# Can also run
# ```
# yaml_to_json /home/bob/src/Aider-AI/aider/aider/website/_data/polyglot_leaderboard.yml | jq '[.[] | select(.seconds_per_case < 30 and (.command | contains("openrouter") | not))] | sort_by(.pass_rate_2)'
# yaml_to_json .../polyglot_leaderboard.yml | \
# jq '[.[] | select(.seconds_per_case < 30 and
# (.command | contains("openrouter") | not))] | sort_by(.pass_rate_2)'
# ```
# to see models I might be able to use, that are not too slow, by speed at
# Aider benchmark (but also take with a pinch of salt - a lot of people think
Expand Down
2 changes: 1 addition & 1 deletion bin/add_window
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ IFS=$'\n\t'
main() {
local tmux_command

# shellcheck disable=SC1090
# shellcheck disable=SC1090,SC1091
source "$ZSH_LIB/tmux.sh"

if [ -n "$TMUX" ]; then
Expand Down
2 changes: 1 addition & 1 deletion bin/clone
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ main() {
gh repo clone "$repo"
fi

# shellcheck disable=SC1090
# shellcheck disable=SC1090,SC1091
source "$ZSH_LIB/tmux.sh"
add_window --vim-pane "$name"
}
Expand Down
2 changes: 2 additions & 0 deletions bin/colours-to-rgb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/env python3

import sys

import webcolors

# Convert hex or named CSS3 colours on stdin to rgb values on stdout.
Expand All @@ -15,5 +16,6 @@ def main():

print(colour, *rgb)


if __name__ == "__main__":
main()
4 changes: 2 additions & 2 deletions bin/extract_urls
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python3

import sys
import re
import sys

# Extract URLs from a file given as the first argument, or stdin, and output
# one URL per line.
Expand All @@ -11,7 +11,7 @@ URL_PATTERN = r'https?://[^\s<>"{}|\\^`\[\]()]+'

def main():
if len(sys.argv) > 1:
with open(sys.argv[1], "r") as f:
with open(sys.argv[1]) as f:
extract_urls_from_lines(f)
else:
extract_urls_from_lines(sys.stdin)
Expand Down
1 change: 1 addition & 0 deletions bin/git-about
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ IFS=$'\n\t'


main() {
# shellcheck disable=SC2198 # Auto-suppressed when enabling Shellcheck.
if [ ! -e "$@" ]; then
echo "Error: Path does not exist: $*"
exit 1
Expand Down
21 changes: 6 additions & 15 deletions bin/git-ls-revisions
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import operator
import subprocess


# Lists all tracked files in repo along with the number of commits which have
# changed them, in order from most to least.

Expand All @@ -13,34 +12,26 @@ import subprocess


def main():
tracked_files = output_lines(
['git', 'ls-tree', '--full-tree', '--name-only', '-r', 'HEAD']
)
tracked_files = output_lines(["git", "ls-tree", "--full-tree", "--name-only", "-r", "HEAD"])

file_to_revisions = {}
for file in tracked_files:
try:
revisions = output_lines(
['git', 'log', '--oneline', '--follow', file]
)
revisions = output_lines(["git", "log", "--oneline", "--follow", file])
file_to_revisions[file] = len(revisions)
except subprocess.CalledProcessError as ex:
print(ex)

sorted_files = sorted(
file_to_revisions.items(),
key=operator.itemgetter(1),
reverse=True
)
sorted_files = sorted(file_to_revisions.items(), key=operator.itemgetter(1), reverse=True)

for file, revision_count in sorted_files:
print('{} - {}'.format(file, revision_count))
print(f"{file} - {revision_count}")


def output_lines(command):
output = subprocess.check_output(command, universal_newlines=True)
return [line for line in output.split('\n') if len(line) > 0]
return [line for line in output.split("\n") if len(line) > 0]


if __name__ == '__main__':
if __name__ == "__main__":
main()
1 change: 0 additions & 1 deletion bin/git-sync-branches
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,3 @@ _sync_branch() {


main "$@"

1 change: 1 addition & 0 deletions bin/git-wip
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ IFS=$'\n\t'

main() {
local message
# shellcheck disable=SC2124 # Auto-suppressed when enabling Shellcheck.
message="WIP $@"
git commit --no-verify -m "$message"
}
Expand Down
3 changes: 2 additions & 1 deletion bin/mv_notes
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ update_wikilinks() {
fi

# Create a temporary file for the updates
local temp_file=$(mktemp)
local temp_file
temp_file=$(mktemp)

# Update wikilinks that reference the old path
# This handles cases like:
Expand Down
2 changes: 1 addition & 1 deletion bin/replace_window
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ IFS=$'\n\t'
main() {
local current_window new_window

# shellcheck disable=SC1090
# shellcheck disable=SC1090,SC1091
source "$ZSH_LIB/tmux.sh"

# shellcheck disable=SC2063
Expand Down
4 changes: 2 additions & 2 deletions bin/rofr.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ usage()

-b,--browser Browser search by keyword (requires surfraw)

-q,--qalculate Persistant calculator dialog (requires libqalculate)
-q,--qalculate Persistent calculator dialog (requires libqalculate)

-c,--clipboard Select previous clipboard entries (requires greenclip)

Expand Down Expand Up @@ -79,7 +79,7 @@ for arg in "$@"; do
-padding 50 -line-padding 4)"
;;
-l|--logout)
if grep -q 'exec startx' $HOME/.*profile; then
if grep -q 'exec startx' "$HOME"/.*profile; then
ANS="$(rofi -sep "|" -dmenu -i -p 'System' -width 20 \
-hide-scrollbar -line-padding 4 -padding 20 \
-lines 3 <<< " Lock| Reboot| Shutdown")"
Expand Down
Loading
Loading