Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 4 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
name: Formatting checks

on: [push]
on:
push:
pull_request:

env:
TERM: xterm
Expand All @@ -10,7 +12,7 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v4
with:
fetch-depth: 1

Expand Down
2 changes: 0 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ vim/log
vim/plugged
.netrwhist
.idea
offlineimap/Account*
offlineimap/Repository*
docker
__pycache__
.DS_Store
Expand Down
27 changes: 17 additions & 10 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,21 +1,28 @@
YAML_FILES := $(shell git ls-files '*.yml' '*.yaml' | while IFS= read -r file; do [ -f "$$file" ] && printf "%s " "$$file"; done)
MARKDOWN_FILES := $(shell git ls-files '*.md' | while IFS= read -r file; do [ -f "$$file" ] && printf "%s " "$$file"; done)
PYTHON_FILES := $(shell git ls-files '*.py' | while IFS= read -r file; do [ -f "$$file" ] && printf "%s " "$$file"; done)
LUA_FILES := $(shell git ls-files '*.lua' | while IFS= read -r file; do [ -f "$$file" ] && printf "%s " "$$file"; done)

.PHONY: all apply fmt fmt_check nvim-health nvim-check

all: fmt apply nvim-check

apply:
uv run ansible-playbook -i ~/.dotfiles/ansible/inventory.ini ~/.dotfiles/ansible/dotfiles.yml

fmt:
npx --loglevel error --yes prettier --write **/*.yml
uvx --with mdformat-gfm --with mdformat-frontmatter mdformat --wrap 80 --number **/*.md
uvx ruff format --line-length=100 **/*.py
uvx ruff check --fix --line-length=100 **/*.py
npx --loglevel error --yes @johnnymorganz/stylua-bin -- **/*.lua
@if [ -n "$(YAML_FILES)" ]; then npx --loglevel error --yes prettier --write $(YAML_FILES); fi
@if [ -n "$(MARKDOWN_FILES)" ]; then uvx --with mdformat-gfm --with mdformat-frontmatter mdformat --wrap 80 --number $(MARKDOWN_FILES); fi
@if [ -n "$(PYTHON_FILES)" ]; then uvx ruff format --line-length=100 $(PYTHON_FILES); fi
@if [ -n "$(PYTHON_FILES)" ]; then uvx ruff check --fix --line-length=100 $(PYTHON_FILES); fi
@if [ -n "$(LUA_FILES)" ]; then npx --loglevel error --yes @johnnymorganz/stylua-bin -- $(LUA_FILES); fi

fmt_check:
npx --loglevel error --yes prettier --check **/*.yml
uvx --with mdformat-gfm --with mdformat-frontmatter mdformat --check --wrap 80 --number **/*.md
uvx ruff format --check --line-length=100 **/*.py
uvx ruff check --line-length=100 **/*.py
npx --loglevel error --yes @johnnymorganz/stylua-bin --check -- **/*.lua
@if [ -n "$(YAML_FILES)" ]; then npx --loglevel error --yes prettier --check $(YAML_FILES); fi
@if [ -n "$(MARKDOWN_FILES)" ]; then uvx --with mdformat-gfm --with mdformat-frontmatter mdformat --check --wrap 80 --number $(MARKDOWN_FILES); fi
@if [ -n "$(PYTHON_FILES)" ]; then uvx ruff format --check --line-length=100 $(PYTHON_FILES); fi
@if [ -n "$(PYTHON_FILES)" ]; then uvx ruff check --line-length=100 $(PYTHON_FILES); fi
@if [ -n "$(LUA_FILES)" ]; then npx --loglevel error --yes @johnnymorganz/stylua-bin --check -- $(LUA_FILES); fi

nvim-health:
nvim --headless "+checkhealth" +qa
Expand Down
35 changes: 14 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,36 @@

My personal dotfiles for macOS, managed with Ansible.

## Ansible
## Quick start

```bash
# Clone the repository
git clone https://github.com/michaelbarton/dotfiles.git ~/.dotfiles

# Apply configuration with Ansible
cd ~/.dotfiles
./ansible/apply_ansible
make apply
```

### Fish Shell
## Run specific Ansible tags

```bash
curl -sL https://git.io/fisher | source && fisher install jorgebucaran/fisher
fish -c "fisher update"
uv run ansible-playbook -i ~/.dotfiles/ansible/inventory.ini ~/.dotfiles/ansible/dotfiles.yml --tags "hooks,setup"
```

### Email Setup

1. Create maildb directory:
## Maintenance

```bash
mkdir -p ~/.maildb/michaelbarton
```

2. Set up Gmail password in keychain:

```bash
security add-generic-password -a acct.gmail -s acct.gmail -w
```
```bash
make fmt_check
make nvim-check
```

3. Set up automated email sync:
### Fish Shell

```bash
launchctl load -w ~/Library/LaunchAgents/uk.me.michaelbarton.offlineimap.plist
```
```bash
curl -sL https://git.io/fisher | source && fisher install jorgebucaran/fisher
fish -c "fisher update"
```

## Customization

Expand Down
8 changes: 0 additions & 8 deletions Rprofile

This file was deleted.

6 changes: 4 additions & 2 deletions ansible/dotfiles.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
# - Configuring OS-specific launch agents
# - Linking dotfiles to their proper locations
#
# To run only specific tags: ./apply_ansible [tag1,tag2]
# Available tags: links, python, agents
# To run only specific tags:
# uv run ansible-playbook -i ~/.dotfiles/ansible/inventory.ini ~/.dotfiles/ansible/dotfiles.yml --tags "hooks,setup"
# Common tags: links, nvim, tmux, skills, hooks, setup, agents, paperless, paperless-backup

- name: Playbook to manage dotfiles
hosts: localhost
Expand All @@ -32,6 +33,7 @@
- { path: "{{ config_dir }}/atuin" }
- { path: "{{ config_dir }}/lazygit" }
- { path: "{{ config_dir }}/ripgrep" }
- { path: "{{ config_dir }}/uv" }
- { path: "{{ ansible_user_dir }}/cache" }
- { path: "{{ ansible_user_dir }}/.bin" }
- { path: "{{ ansible_user_dir }}/.hammerspoon" }
Expand Down
4 changes: 4 additions & 0 deletions ansible/tasks/link_files.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
- { src: "atuin/config.toml", dest: ".config/atuin/config.toml" }
- { src: "lazygit/config.yml", dest: ".config/lazygit/config.yml" }
- { src: "starship/starship.toml", dest: ".config/starship.toml" }
- { src: "uv/uv.toml", dest: ".config/uv/uv.toml" }

# Scripts for working with data
- { src: "parquet/csv_to_parquet.py", dest: ".bin/csv_to_parquet" }
Expand All @@ -32,6 +33,9 @@
# Misc. scripts and config
- { src: "zettel/today.sh", dest: ".bin/today" }
- { src: "git/gitconfig", dest: ".gitconfig" }
- { src: "gitignore", dest: ".gitignore" }
- { src: "duckdb/duckdbrc", dest: ".duckdbrc" }
- { src: "visidata/visidatarc", dest: ".visidatarc" }
- { src: "markdown/md2docx.sh", dest: ".bin/md2docx" }
- {
src: "poetry/update_poetry_dependencies.py",
Expand Down
1 change: 0 additions & 1 deletion ansible/tasks/paperless_backup.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
cmd: launchctl load "{{ ansible_user_dir }}/Library/LaunchAgents/uk.me.michaelbarton.paperless-backup.plist"
args:
creates: "{{ ansible_user_dir }}/Library/LaunchAgents/uk.me.michaelbarton.paperless-backup.plist"

# One-time manual setup required (run these once before first backup):
#
# security add-generic-password -a $USER -s paperless-backup-b2-id -w '<keyID>'
Expand Down
20 changes: 13 additions & 7 deletions bash/bashrc
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#!/bin/bash

set -o nounset
if [ -n "${BASH_VERSION:-}" ]; then
set -o nounset
fi

###################################################################
#
Expand Down Expand Up @@ -57,21 +59,25 @@ alias grep='grep --color=auto'
PYTHON_BIN=${HOME}/.venv/bin
USER_BIN=${HOME}/.bin
LOCAL_BIN=${HOME}/.local/bin
DOTFILES_BIN=${HOME}/.dotfiles/bin
HOMEBREW_BIN=/opt/homebrew/bin
NPM_BIN=${HOME}/.npm-global/bin

export PATH=${NPM_BIN}:${HOMEBREW_BIN}:${DOTFILES_BIN}:${USER_BIN}:${LOCAL_BIN}:${PATH}
export PATH=${NPM_BIN}:${HOMEBREW_BIN}:${USER_BIN}:${LOCAL_BIN}:${PATH}

###################################################################
#
# Misc. environment variables
#
###################################################################

# fzf should use ripgrep for search
export FZF_DEFAULT_COMMAND='rg --files'
export FZF_DEFAULT_OPTS='-m --height 50% --border'
# fzf and ripgrep search defaults
if command -v fd >/dev/null 2>&1; then
export FZF_DEFAULT_COMMAND='fd --type f --hidden --follow --exclude .git'
else
export FZF_DEFAULT_COMMAND='rg --files --hidden --glob "!.git"'
fi
export FZF_DEFAULT_OPTS='--height 50% --border'
export RIPGREP_CONFIG_PATH="$HOME/.config/ripgrep/rc"

export MANWIDTH=80
export EDITOR=nvim
Expand Down Expand Up @@ -107,7 +113,7 @@ export LANG='en_GB.UTF-8'
#
###################################################################

if [ -n "$BASH_VERSION" ]; then
if [ -n "${BASH_VERSION:-}" ]; then
# Shell history improvements
export HISTSIZE=50000
export HISTFILESIZE=100000
Expand Down
29 changes: 20 additions & 9 deletions claude/hooks/plan-review.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,32 @@ if [ ! -f "$planning_rule" ]; then
exit 1
fi

# Strip the YAML frontmatter (between the first two `---` lines).
rule_body=$(awk 'BEGIN{f=0} /^---$/{f++; next} f>=2{print}' "$planning_rule")
# The gate list is the single source of truth: it lives in the rule as a
# `<!-- gates ... -->` comment (invisible in Cursor's rendered view) and is
# extracted here rather than duplicated, so the two can never drift.
gates=$(awk '/^<!-- gates$/{f=1; next} /^-->$/{f=0} f' "$planning_rule")
if [ -z "$gates" ]; then
echo "plan-review hook: no gate manifest (<!-- gates ... -->) in $planning_rule" >&2
exit 1
fi

# Strip the YAML frontmatter (between the first two `---` lines) and the gate
# manifest comment, leaving the human-readable rule to inject verbatim.
rule_body=$(awk '
BEGIN{f=0}
/^---$/{f++; next}
f<2{next}
/^<!-- gates$/{s=1; next}
/^-->$/{if(s){s=0; next}}
!s{print}
' "$planning_rule")

prompt=$(
cat <<PROMPT
You just edited a plan document. Before any implementation, audit it
against the planning rule in <planning_rule> below. The gates are:

1. Success & exit criteria
2. Invariants
3. What is the grain of the data
4. Failure modes (including the one-line premortem)
5. Assumptions & unknowns
6. Minimal viable change
7. Visualization confirmation (only when the plan involves figures)
$gates

A gate passes ONLY if you can quote the plan line(s) that satisfy it.
Paraphrases, "implied somewhere," or "this is obvious" do NOT count.
Expand Down
2 changes: 2 additions & 0 deletions claude/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
],
"defaultMode": "auto"
},
"model": "sonnet",
"hooks": {
"PostToolUse": [
{
Expand Down Expand Up @@ -47,6 +48,7 @@
}
]
},
"effortLevel": "high",
"tui": "fullscreen",
"theme": "auto",
"skipAutoPermissionPrompt": true
Expand Down
2 changes: 1 addition & 1 deletion cursor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ ln -sf ~/.dotfiles/cursor/rules ~/.cursor/rules
Or run Ansible with the `hooks` or `setup` tag:

```bash
./apply_ansible hooks
uv run ansible-playbook -i ~/.dotfiles/ansible/inventory.ini ~/.dotfiles/ansible/dotfiles.yml --tags hooks
```

### Cursor: enable third-party hooks
Expand Down
Loading
Loading