From dace45998606d14e8e43b71b7472e76c0f1a7949 Mon Sep 17 00:00:00 2001 From: Jay Bendon Date: Tue, 17 Feb 2026 12:48:53 -0800 Subject: [PATCH 01/15] fix install bugs --- install.sh | 14 ++++++-------- shlibs/lsp-deps.sh | 2 +- zsh/env.zsh | 4 ++-- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/install.sh b/install.sh index f018784..ce608cc 100755 --- a/install.sh +++ b/install.sh @@ -16,7 +16,7 @@ libncurses5-dev libssl-dev build-essential htop libffi-dev libffi7 xz-utils" # DEB_BACKPORTS_DEPS="" # DEB_BACKPORTS_REPO="" # DEB_TESTING_DEPS="" -OSX_DEPS="ctags wget tmux zsh vim git gh readline xz htop" +OSX_DEPS="ctags wget tmux zsh vim git gh readline xz htop grep" GO_VERSION=1.18.4 PY3_VERSION=3.13.7 RUBY_VERSION=3.1.2 # update in nvim/lua/options.lua @@ -153,7 +153,7 @@ install_ast_grep() { cargo install ast-grep } -iinstall_uv() { +install_uv() { cargo install --git https://github.com/astral-sh/uv uv } @@ -194,7 +194,7 @@ install_neovim() { install_zsh() { # install oh-my-zsh if ! grep -q /opt/homebrew/bin/zsh /etc/shells; then - echo "/opt/homebrew/bin/zsh" >>/etc/shells + echo "/opt/homebrew/bin/zsh" | sudo tee -a /etc/shells > /dev/null fi chsh -s /opt/homebrew/bin/zsh $USER @@ -217,8 +217,8 @@ install_deps() { else brew update fi - brew install "${OSX_DEPS}" - brew upgrade "${OSX_DEPS}" + brew install ${OSX_DEPS} + brew upgrade ${OSX_DEPS} elif [[ "${OS}" == "linux" ]]; then if [ "${ID}" == "ubuntu" ] || [ "${ID}" == "debian" ] || [ "${ID}" == "raspbian" ] || [ "${ID}" == "armbian" ]; then for PKG in ${DEB_DEPS}; do @@ -284,11 +284,9 @@ install_configs() { } install() { + install_deps install_configs - install_fonts - - install_deps } purge_dotfiles() { diff --git a/shlibs/lsp-deps.sh b/shlibs/lsp-deps.sh index d5d17f9..4bc6a49 100755 --- a/shlibs/lsp-deps.sh +++ b/shlibs/lsp-deps.sh @@ -68,7 +68,7 @@ jdtls_bazel() { curl -L -o "$(pwd)/${fname}.zip" "${url}" || TRACE "failed to download jdtls bazel plugins" unzip ${fname}.zip mkdir -p "${install_dir}" - cp "$(pwd)/${fname}/plugins/*.jar" "${install_dir}/" + cp "$(pwd)/plugins/*.jar" "${install_dir}/" rmtmp } diff --git a/zsh/env.zsh b/zsh/env.zsh index 34f42c4..a39f48d 100644 --- a/zsh/env.zsh +++ b/zsh/env.zsh @@ -11,14 +11,14 @@ check_if_dir_exists() { check_add_langenv() { local envbin=${HOME}/.$1/bin if [ ! -e ${envbin} ];then - return false + return 1 fi if ! command -v $1 >/dev/null; then export PATH="${envbin}:${PATH}" fi - return true + return 0 } check_shims() { From fcd8e4ac0de2c168c46a338f57bdaef7b229a73d Mon Sep 17 00:00:00 2001 From: Jay Bendon Date: Tue, 24 Feb 2026 13:56:50 -0800 Subject: [PATCH 02/15] update dotfiles configuration and add GEMINI.md - add GEMINI.md project overview - update gemini settings structure - add syncmain git alias and work gitconfig include - optimize zsh env init by replacing check_shims with function checks - add byte conversion functions (tokb, etc.) and rmkhkey to zsh - add new zsh plugins (gh, pyenv, nodenv, asdf, poetry) - update .gitignore and install script --- .gitignore | 2 ++ GEMINI.md | 54 ++++++++++++++++++++++++++++++++++++++++ gemini/settings.json | 59 ++++++++++++++++++++++++++++++++++++++++++-- gitconfig | 5 ++++ install.sh | 2 +- zsh/env.zsh | 10 ++++---- zsh/functions.zsh | 20 +++++++++++++++ zshrc | 5 ++++ 8 files changed, 149 insertions(+), 8 deletions(-) create mode 100644 GEMINI.md diff --git a/.gitignore b/.gitignore index 6a40d02..011e8ef 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ nvim/snapshot nvim/plugin nvim/nvim +gemini/history +gemini/tmp diff --git a/GEMINI.md b/GEMINI.md new file mode 100644 index 0000000..1faed1a --- /dev/null +++ b/GEMINI.md @@ -0,0 +1,54 @@ +# Dotfiles Project Overview + +This repository contains personal configuration files (dotfiles) for various tools, including Zsh, Neovim, Tmux, Git, and more. It is designed to be portable across macOS (Darwin) and Linux (Debian-based distributions). + +## Core Technologies +- **Shell:** Zsh with [Oh My Zsh](https://ohmyz.sh/), [ys theme](https://github.com/ohmyzsh/ohmyzsh/wiki/Themes#ys), and several plugins (`gh`, `git`, `vi-mode`, `pyenv`, `nodenv`, `asdf`, `poetry`). +- **Editor:** Neovim configured using [LazyVim](https://www.lazyvim.org/) and [lazy.nvim](https://github.com/folke/lazy.nvim). +- **Terminal Multiplexer:** Tmux with platform-specific configurations (`tmux/Darwin.conf` and `tmux/Linux.conf`). +- **Tool Managers:** Supports `pyenv`, `nodenv`, `rbenv`, `goenv`, `tfenv`, and `rustup`. +- **Package Managers:** Homebrew (macOS) and `apt` (Linux). + +## Directory Structure +- `bin/`: Custom scripts and binaries. +- `nvim/`: Neovim configuration (`init.lua`, `lua/config/`, `lua/plugins/`). +- `shlibs/`: Shell libraries for installation, logging, and environment detection. +- `tmux/`: Tmux configurations, including OS-specific overrides. +- `zsh/`: Zsh environment, aliases, functions, and SSH agent setup. +- `install.sh`: The main installation script for dependencies and configuration linking. + +## Building and Running + +### Installation +The primary entry point for setting up the environment is `install.sh`. + +```bash +# General installation (deps + config) +./install.sh install + +# Only install configurations (symlinking) +./install.sh config + +# Fast installation (skips some prompts) +./install.sh fast-install + +# Install only Neovim and its dependencies +./install.sh install-neovim +``` + +The `install.sh` script performs the following actions: +1. Installs system-level dependencies via Homebrew or `apt`. +2. Sets up tool version managers (`pyenv`, `nodenv`, etc.). +3. Installs Rust, Neovim, and various CLI tools (`ripgrep`, `fd`, `gh`). +4. Symlinks configuration files from the repository to the home directory (e.g., `~/.zshrc`, `~/.tmux.conf`, `~/.config/nvim`). + +### Maintenance +- **Purge configurations:** `./install.sh purge` removes the symlinks created by the installer. +- **Update Neovim:** The installer includes a `compile_neovim` function for Linux environments to build from source. + +## Development Conventions + +- **Shell Scripting:** Shared logic is modularized in `shlibs/`. Use `shlibs/logging.sh` for output and `shlibs/os.sh` for platform detection. +- **Neovim Configuration:** Follows the `LazyVim` structure. Custom plugins should be added to `nvim/lua/plugins/`, and core configurations to `nvim/lua/config/`. +- **Environment Variables:** Managed in `zsh/env.zsh`. Paths and tool initializations should be added there to ensure they are available in the shell. +- **Aliases:** Custom aliases are located in `zsh/aliases.zsh`. diff --git a/gemini/settings.json b/gemini/settings.json index 14a3cff..9377dbc 100644 --- a/gemini/settings.json +++ b/gemini/settings.json @@ -1,6 +1,9 @@ { - "selectedAuthType": "oauth-personal", - "preferredEditor": "neovim", + "security": { + "auth": { + "selectedType": "oauth-personal" + } + }, "checkpointing": { "enabled": true }, @@ -32,5 +35,57 @@ "CONTEXT7_API_KEY": "${CONTEXT7_API_KEY}" } } + }, + "context": { + "fileName": [ + "AGENTS.md", + "CONTEXT.md", + "GEMINI.md", + "CLAUDE.md", + ".claude/CLAUDE.md" + ] + }, + "tools": { + "allowed": [ + "run_shell_command(git status)", + "run_shell_command(git diff)", + "run_shell_command(git log)", + "run_shell_command(diff)", + "run_shell_command(find)", + "run_shell_command(pwd)", + "run_shell_command(grep)", + "run_shell_command(cat)", + "run_shell_command(poetry run flake8)", + "run_shell_command(poetry run pyright)", + "run_shell_command(cd)", + "list_directory", + "read_file" + ], + "exclude": [ + "run_shell_command(git commit)", + "run_shell_command(git push)" + ], + "core": [ + "list_directory", + "read_file", + "grep_search", + "glob", + "replace", + "write_file", + "web_fetch", + "run_shell_command", + "save_memory", + "google_web_search", + "ask_user", + "codebase_investigator", + "cli_help", + "activate_skill" + ] + }, + "general": { + "preferredEditor": "neovim" + }, + "experimental": { + "plan": true } } diff --git a/gitconfig b/gitconfig index 1c0fceb..99317c5 100644 --- a/gitconfig +++ b/gitconfig @@ -19,3 +19,8 @@ [credential "https://gist.github.com"] helper = helper = !/opt/homebrew/bin/gh auth git-credential + +[includeIf "gitdir:~/repos/work/"] + path = ~/.gitconfig-work +[alias] + syncmain = "!f() { CURRENT_BRANCH=$(git symbolic-ref --short HEAD); git checkout main && git pull origin main && git checkout $CURRENT_BRANCH && git rebase origin/main && git push origin $CURRENT_BRANCH --force-with-lease; }; f" diff --git a/install.sh b/install.sh index ce608cc..c81eb42 100755 --- a/install.sh +++ b/install.sh @@ -10,7 +10,7 @@ git rev-parse --abbrev-ref --symbolic-full-name '@{u}' || { exit 1 } -DOT_FILES=$(git ls-tree '@{u}' | awk '{print $4}' | grep -Ev '(/|LICENSE|README|install.sh|shlibs|test.sh|.gitignore|.gitmodules|bashrc|^vim|vimrc|screenrc|gemini)') +DOT_FILES=$(git ls-tree '@{u}' | awk '{print $4}' | grep -Ev '(/|LICENSE|README|install.sh|shlibs|test.sh|.gitignore|.gitmodules|bashrc|^vim|vimrc|screenrc)') DEB_DEPS="zip unzip curl exuberant-ctags wget tmux zsh zsh-common vim git xclip zlib1g zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev \ libncurses5-dev libssl-dev build-essential htop libffi-dev libffi7 xz-utils" # DEB_BACKPORTS_DEPS="" diff --git a/zsh/env.zsh b/zsh/env.zsh index a39f48d..1208e11 100644 --- a/zsh/env.zsh +++ b/zsh/env.zsh @@ -66,23 +66,23 @@ fi # golang if check_add_langenv goenv; then - check_shims goenv || eval "$(goenv init -)" + (( $+functions[goenv] )) || eval "$(goenv init -)" fi # ruby / rbenv if check_add_langenv rbenv; then - check_shims rbenv || eval "$(rbenv init -)" + (( $+functions[rbenv] )) || eval "$(rbenv init -)" fi # python / pyenv / pyenv-virtualenv if check_add_langenv pyenv; then - check_shims pyenv || eval "$(pyenv init -)" - check_shims "pyenv/plugins/pyenv-virtualenv" || eval "$(pyenv virtualenv-init -)" + (( $+functions[pyenv] )) || eval "$(pyenv init -)" + (( $+functions[_pyenv_virtualenv_hook] )) || eval "$(pyenv virtualenv-init -)" fi # node / nodenv if check_add_langenv nodenv; then - check_shims nodenv || eval "$(nodenv init -)" + (( $+functions[nodenv] )) || eval "$(nodenv init -)" fi # terraform / tfenv diff --git a/zsh/functions.zsh b/zsh/functions.zsh index c2073c0..78a682d 100644 --- a/zsh/functions.zsh +++ b/zsh/functions.zsh @@ -34,3 +34,23 @@ tmuxsession () { tmux attach -t ${name} fi } + +tokb() { + jq -n "$1 / 1024" +} + +tomb() { + jq -n "$(tokb $1) / 1024" +} + +togb() { + jq -n "$(tomb $1) / 1024" +} + +totb() { + jq -n "$(togb $1) / 1024" +} + +rmkhkey() { + sed -i '' "${1}d" ~/.ssh/known_hosts +} diff --git a/zshrc b/zshrc index f34a437..8a1c719 100644 --- a/zshrc +++ b/zshrc @@ -72,8 +72,13 @@ ZSH_CUSTOM=${HOME}/.zsh # Example format: plugins=(rails git textmate ruby lighthouse) # Add wisely, as too many plugins slow down shell startup. plugins=( + gh git vi-mode + pyenv + nodenv + asdf + poetry ) source $ZSH/oh-my-zsh.sh From d09d64ef71c7d8514f7b9bbdc19d37c4d4294c05 Mon Sep 17 00:00:00 2001 From: Jay Bendon Date: Tue, 24 Feb 2026 14:00:58 -0800 Subject: [PATCH 03/15] fix zsh syntax errors in env.zsh for bash compatibility --- zsh/env.zsh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/zsh/env.zsh b/zsh/env.zsh index 1208e11..aadf229 100644 --- a/zsh/env.zsh +++ b/zsh/env.zsh @@ -66,23 +66,23 @@ fi # golang if check_add_langenv goenv; then - (( $+functions[goenv] )) || eval "$(goenv init -)" + typeset -f goenv >/dev/null || eval "$(goenv init -)" fi # ruby / rbenv if check_add_langenv rbenv; then - (( $+functions[rbenv] )) || eval "$(rbenv init -)" + typeset -f rbenv >/dev/null || eval "$(rbenv init -)" fi # python / pyenv / pyenv-virtualenv if check_add_langenv pyenv; then - (( $+functions[pyenv] )) || eval "$(pyenv init -)" - (( $+functions[_pyenv_virtualenv_hook] )) || eval "$(pyenv virtualenv-init -)" + typeset -f pyenv >/dev/null || eval "$(pyenv init -)" + typeset -f _pyenv_virtualenv_hook >/dev/null || eval "$(pyenv virtualenv-init -)" fi # node / nodenv if check_add_langenv nodenv; then - (( $+functions[nodenv] )) || eval "$(nodenv init -)" + typeset -f nodenv >/dev/null || eval "$(nodenv init -)" fi # terraform / tfenv From 60bd493ae66293d0c27b64fd9e1f2cda1e74e198 Mon Sep 17 00:00:00 2001 From: Jay Bendon Date: Tue, 24 Feb 2026 14:03:11 -0800 Subject: [PATCH 04/15] ignore untracked gemini and nvim files --- .gitignore | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.gitignore b/.gitignore index 011e8ef..9e67ebd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,13 @@ nvim/snapshot nvim/plugin nvim/nvim +nvim/lazy-lock.json + gemini/history gemini/tmp +gemini/google_accounts.json +gemini/installation_id +gemini/oauth_creds.json +gemini/projects.json +gemini/state.json +gemini/trustedFolders.json From 2e029a6d6d61ee83155078dea2099beb8a3b5f39 Mon Sep 17 00:00:00 2001 From: Jay Bendon Date: Fri, 6 Mar 2026 17:56:38 -0800 Subject: [PATCH 05/15] gemini policies --- gemini/policies/tools.toml | 143 +++++++++++++++++++++++++++++++++++++ gemini/settings.json | 31 +++----- install.sh | 8 +-- 3 files changed, 157 insertions(+), 25 deletions(-) create mode 100644 gemini/policies/tools.toml diff --git a/gemini/policies/tools.toml b/gemini/policies/tools.toml new file mode 100644 index 0000000..ff22f4f --- /dev/null +++ b/gemini/policies/tools.toml @@ -0,0 +1,143 @@ +# Project-level tool permissions migrated from tools.allowed and tools.exclude +# Generated to comply with Gemini CLI 1.0 Policy Engine migration. + +# Allowed shell commands (No-prompt) +[[rule]] +toolName = "run_shell_command" +commandPrefix = "git status" +decision = "allow" +priority = 100 + +[[rule]] +toolName = "run_shell_command" +commandPrefix = "git diff" +decision = "allow" +priority = 100 + +[[rule]] +toolName = "run_shell_command" +commandPrefix = "git log" +decision = "allow" +priority = 100 + +[[rule]] +toolName = "run_shell_command" +commandPrefix = "git grep" +decision = "allow" +priority = 100 + +[[rule]] +toolName = "run_shell_command" +commandPrefix = "git branch --show-current" +decision = "allow" +priority = 100 + +[[rule]] +toolName = "run_shell_command" +commandPrefix = "gh pr status" +decision = "allow" +priority = 100 + +[[rule]] +toolName = "run_shell_command" +commandPrefix = "gh show" +decision = "allow" +priority = 100 + +[[rule]] +toolName = "run_shell_command" +commandPrefix = "gh pr checks" +decision = "allow" +priority = 100 + +[[rule]] +toolName = "run_shell_command" +commandPrefix = "gh pr view" +decision = "allow" +priority = 100 + +[[rule]] +toolName = "run_shell_command" +commandPrefix = "gh run view" +decision = "allow" +priority = 100 + +[[rule]] +toolName = "run_shell_command" +commandPrefix = "diff" +decision = "allow" +priority = 100 + +[[rule]] +toolName = "run_shell_command" +commandPrefix = "find" +decision = "allow" +priority = 100 + +[[rule]] +toolName = "run_shell_command" +commandPrefix = "pwd" +decision = "allow" +priority = 100 + +[[rule]] +toolName = "run_shell_command" +commandPrefix = "grep" +decision = "allow" +priority = 100 + +[[rule]] +toolName = "run_shell_command" +commandPrefix = "cat" +decision = "allow" +priority = 100 + +[[rule]] +toolName = "run_shell_command" +commandPrefix = "ls" +decision = "allow" +priority = 100 + +[[rule]] +toolName = "run_shell_command" +commandPrefix = "poetry run flake8" +decision = "allow" +priority = 100 + +[[rule]] +toolName = "run_shell_command" +commandPrefix = "poetry run pyright" +decision = "allow" +priority = 100 + +[[rule]] +toolName = "run_shell_command" +commandPrefix = "cd" +decision = "allow" +priority = 100 + +# Other allowed tools +[[rule]] +toolName = "list_directory" +decision = "allow" +priority = 100 + +[[rule]] +toolName = "read_file" +decision = "allow" +priority = 100 + +# Explicitly denied shell commands +[[rule]] +toolName = "run_shell_command" +commandPrefix = "git commit" +decision = "deny" +priority = 100 +deny_message = "Git commit is restricted by project policy. Please use git commands directly if needed." + +[[rule]] +toolName = "run_shell_command" +commandPrefix = "git push" +decision = "deny" +priority = 100 +deny_message = "Git push is restricted by project policy. Please use git commands directly if needed." diff --git a/gemini/settings.json b/gemini/settings.json index 9377dbc..38ad101 100644 --- a/gemini/settings.json +++ b/gemini/settings.json @@ -1,4 +1,7 @@ { + "policyPaths": [ + "./gemini/policies" + ], "security": { "auth": { "selectedType": "oauth-personal" @@ -46,25 +49,6 @@ ] }, "tools": { - "allowed": [ - "run_shell_command(git status)", - "run_shell_command(git diff)", - "run_shell_command(git log)", - "run_shell_command(diff)", - "run_shell_command(find)", - "run_shell_command(pwd)", - "run_shell_command(grep)", - "run_shell_command(cat)", - "run_shell_command(poetry run flake8)", - "run_shell_command(poetry run pyright)", - "run_shell_command(cd)", - "list_directory", - "read_file" - ], - "exclude": [ - "run_shell_command(git commit)", - "run_shell_command(git push)" - ], "core": [ "list_directory", "read_file", @@ -83,9 +67,14 @@ ] }, "general": { - "preferredEditor": "neovim" + "preferredEditor": "neovim", + "sessionRetention": { + "enabled": true, + "maxAge": "30d", + "warningAcknowledged": true + } }, "experimental": { "plan": true } -} +} \ No newline at end of file diff --git a/install.sh b/install.sh index c81eb42..3407d43 100755 --- a/install.sh +++ b/install.sh @@ -16,7 +16,7 @@ libncurses5-dev libssl-dev build-essential htop libffi-dev libffi7 xz-utils" # DEB_BACKPORTS_DEPS="" # DEB_BACKPORTS_REPO="" # DEB_TESTING_DEPS="" -OSX_DEPS="ctags wget tmux zsh vim git gh readline xz htop grep" +OSX_DEPS="ctags wget tmux zsh vim git gh readline xz htop grep fzf colima docker yq jq libpq pre-commit direnv" GO_VERSION=1.18.4 PY3_VERSION=3.13.7 RUBY_VERSION=3.1.2 # update in nvim/lua/options.lua @@ -179,10 +179,10 @@ install_neovim() { install_uv if [[ "${OS}" == "darwin" ]]; then - if which nvim >/dev/null; then + if which -a nvim | grep -v aliased >/dev/null; then brew upgrade neovim else - brew install neovim + brew install neovim --HEAD fi else if [ "$(nvim -v | head -n 1)" != "NVIM ${NEOVIM_VERSION}" ]; then @@ -194,7 +194,7 @@ install_neovim() { install_zsh() { # install oh-my-zsh if ! grep -q /opt/homebrew/bin/zsh /etc/shells; then - echo "/opt/homebrew/bin/zsh" | sudo tee -a /etc/shells > /dev/null + echo "/opt/homebrew/bin/zsh" | sudo tee -a /etc/shells >/dev/null fi chsh -s /opt/homebrew/bin/zsh $USER From 9c07eda4dceec4b61bf7e2ade917b373dfe08d1a Mon Sep 17 00:00:00 2001 From: Jay Bendon Date: Fri, 6 Mar 2026 18:58:03 -0800 Subject: [PATCH 06/15] add address-pr-feedback skill and update gemini policies --- gemini/policies/tools.toml | 26 ++++++++++ gemini/skills/address-pr-feedback/SKILL.md | 55 ++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 gemini/skills/address-pr-feedback/SKILL.md diff --git a/gemini/policies/tools.toml b/gemini/policies/tools.toml index ff22f4f..62faf25 100644 --- a/gemini/policies/tools.toml +++ b/gemini/policies/tools.toml @@ -32,6 +32,12 @@ commandPrefix = "git branch --show-current" decision = "allow" priority = 100 +[[rule]] +toolName = "run_shell_command" +commandPrefix = "git remote -v" +decision = "allow" +priority = 100 + [[rule]] toolName = "run_shell_command" commandPrefix = "gh pr status" @@ -127,6 +133,26 @@ toolName = "read_file" decision = "allow" priority = 100 +# Explicitly allowed git commands for specific repositories +# Uses argsPattern to match both the command and the dir_path (keys are sorted alphabetically) +[[rule]] +toolName = "run_shell_command" +argsPattern = '"command":"git add.*"dir_path":"/Users/jaybendon/repos/jaybocc2/.*"' +decision = "allow" +priority = 120 + +[[rule]] +toolName = "run_shell_command" +argsPattern = '"command":"git commit.*"dir_path":"/Users/jaybendon/repos/jaybocc2/.*"' +decision = "allow" +priority = 120 + +[[rule]] +toolName = "run_shell_command" +argsPattern = '"command":"git push.*"dir_path":"/Users/jaybendon/repos/jaybocc2/.*"' +decision = "ask_user" +priority = 120 + # Explicitly denied shell commands [[rule]] toolName = "run_shell_command" diff --git a/gemini/skills/address-pr-feedback/SKILL.md b/gemini/skills/address-pr-feedback/SKILL.md new file mode 100644 index 0000000..516ea0d --- /dev/null +++ b/gemini/skills/address-pr-feedback/SKILL.md @@ -0,0 +1,55 @@ +--- +name: address-pr-comments +description: Address review comments on a GitHub pull request. Use when the user asks to "address PR comments", "respond to review feedback", "handle reviewer comments", or "resolve review threads". +disable-model-invocation: true +--- + +# Address PR Review Comments + +## Context + +- Current branch: !`git branch --show-current` +- get pull request review with git mcp: `pull_request_read` + +## Your task + +Work through every unresolved review thread on this PR systematically. For each thread: + +### Step 1 — Understand the comment +Read the comment carefully. Identify: +- What file and line it refers to +- What the reviewer is asking for (change, question, clarification, nitpick) +- Whether a code change is actually required + +### Step 2 — Make changes if needed +If a code change is warranted: +- Read the relevant file(s) first +- Make the change using Edit (or Write for new files) +- Do NOT commit yet — collect all changes first + +If no change is needed (e.g. the reviewer asked a question, or you disagree), prepare a clear explanation. + +### Step 3 — Commit each change separately +After addressing a comment that requires code changes, create a single follow-up commit. Write a short message that summarizes what was changed (e.g. `"fix: use const for immutable bindings per review"`) rather than a generic message: + +Skip this step if no code changes were made. +Provide a commit message and wait until prompted to continue if not allowed to commit. + +### Step 4 — Reply to each comment +use github mcp + +Good reply patterns: +- For changes made: "Done — ." +- For questions answered: "< direct answer to question >." +- For declined suggestions: "I kept the existing approach because ." + +### Step 5 — Resolve each thread +Resolve every thread if satisfactory +use git mcp + +## Notes + +- Work through all unresolved threads before committing — batch the code changes into one commit +- If the PR has no open review threads, report that there is nothing to address +- Always reply before resolving so the reviewer sees the response +- Keep replies concise and direct From 050d3a9502e1418a8ace9980993f921cb598868e Mon Sep 17 00:00:00 2001 From: Jay Bendon Date: Fri, 6 Mar 2026 20:02:52 -0800 Subject: [PATCH 07/15] more tweaks --- gemini/policies/tools.toml | 19 ++++++------------- gemini/skills/address-pr-feedback/SKILL.md | 7 +++++-- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/gemini/policies/tools.toml b/gemini/policies/tools.toml index 62faf25..0470500 100644 --- a/gemini/policies/tools.toml +++ b/gemini/policies/tools.toml @@ -137,30 +137,23 @@ priority = 100 # Uses argsPattern to match both the command and the dir_path (keys are sorted alphabetically) [[rule]] toolName = "run_shell_command" -argsPattern = '"command":"git add.*"dir_path":"/Users/jaybendon/repos/jaybocc2/.*"' +argsPattern = '"command":"git (add|commit|push|pull|fetch|rebase|reset|stash|status|diff|log|grep).*""dir_path":"/.*/repos/jaybocc2/.*"' decision = "allow" priority = 120 [[rule]] toolName = "run_shell_command" -argsPattern = '"command":"git commit.*"dir_path":"/Users/jaybendon/repos/jaybocc2/.*"' -decision = "allow" -priority = 120 - -[[rule]] -toolName = "run_shell_command" -argsPattern = '"command":"git push.*"dir_path":"/Users/jaybendon/repos/jaybocc2/.*"' +commandPrefix = "git commit" decision = "ask_user" -priority = 120 +priority = 100 -# Explicitly denied shell commands [[rule]] toolName = "run_shell_command" -commandPrefix = "git commit" -decision = "deny" +commandPrefix = "git add" +decision = "ask_user" priority = 100 -deny_message = "Git commit is restricted by project policy. Please use git commands directly if needed." +# Explicitly denied shell commands [[rule]] toolName = "run_shell_command" commandPrefix = "git push" diff --git a/gemini/skills/address-pr-feedback/SKILL.md b/gemini/skills/address-pr-feedback/SKILL.md index 516ea0d..aaca05e 100644 --- a/gemini/skills/address-pr-feedback/SKILL.md +++ b/gemini/skills/address-pr-feedback/SKILL.md @@ -44,9 +44,12 @@ Good reply patterns: - For declined suggestions: "I kept the existing approach because ." ### Step 5 — Resolve each thread -Resolve every thread if satisfactory -use git mcp +Resolve every thread/comment if satisfactory +use git mcp / gh cli and GraphQL id field: +``` +gh api graphql -f query='mutation { resolveReviewThread(input: {threadId: ""}) { thread { id isResolved } } }' +``` ## Notes - Work through all unresolved threads before committing — batch the code changes into one commit From 4f6916227c80c6cfef8d8d6ed1fb825c2f9bb8ea Mon Sep 17 00:00:00 2001 From: Jay Bendon Date: Thu, 19 Mar 2026 12:50:44 -0700 Subject: [PATCH 08/15] gemini: update config and skills; nvim: remove copilot --- gemini/GEMINI.md | 15 +++++++++++++++ gemini/policies/tools.toml | 5 +++++ gemini/settings.json | 11 ++++++++++- gemini/skills/address-pr-feedback/SKILL.md | 7 +++++-- nvim/lazyvim.json | 2 -- 5 files changed, 35 insertions(+), 5 deletions(-) create mode 100644 gemini/GEMINI.md diff --git a/gemini/GEMINI.md b/gemini/GEMINI.md new file mode 100644 index 0000000..f489d30 --- /dev/null +++ b/gemini/GEMINI.md @@ -0,0 +1,15 @@ + +# Use Tools available +use mcp_context7_query-docs to query for api documentation +use mcp_github for relevant github tasks +use mcp_astgrep for abstract syntax tree dumps and efficient structured code search + +# Making changes +- break down commits by units of work +- commits should be broken down into logical parts +- do not group unrelated changes into a single commit +- do not comment code. +- code should be self documenting. +- use clear naming, descriptive variables. +- code should prioritize readability +- code should be concise, but not obfuscated. diff --git a/gemini/policies/tools.toml b/gemini/policies/tools.toml index 0470500..6b6f77f 100644 --- a/gemini/policies/tools.toml +++ b/gemini/policies/tools.toml @@ -123,6 +123,11 @@ decision = "allow" priority = 100 # Other allowed tools +[[rule]] +toolName = "find_code" +decision = "allow" +priority = 100 + [[rule]] toolName = "list_directory" decision = "allow" diff --git a/gemini/settings.json b/gemini/settings.json index 38ad101..50ab305 100644 --- a/gemini/settings.json +++ b/gemini/settings.json @@ -26,13 +26,15 @@ ] }, "github": { + "description": "Connect AI assistants to GitHub - manage repos, issues, PRs, and workflows through natural language.", "httpUrl": "https://api.githubcopilot.com/mcp/", "headers": { - "Authorization": "${GITHUB_PAT}" + "Authorization": "Bearer ${GITHUB_PAT}" }, "timeout": 5000 }, "context7": { + "description": "Up-to-date code docs for any prompt", "httpUrl": "https://mcp.context7.com/mcp", "headers": { "CONTEXT7_API_KEY": "${CONTEXT7_API_KEY}" @@ -76,5 +78,12 @@ }, "experimental": { "plan": true + }, + "vimMode": true, + "fileFiltering": { + "respectGitIgnore": true + }, + "model": { + "name": "auto-gemini-3" } } \ No newline at end of file diff --git a/gemini/skills/address-pr-feedback/SKILL.md b/gemini/skills/address-pr-feedback/SKILL.md index aaca05e..59e1005 100644 --- a/gemini/skills/address-pr-feedback/SKILL.md +++ b/gemini/skills/address-pr-feedback/SKILL.md @@ -33,7 +33,7 @@ If no change is needed (e.g. the reviewer asked a question, or you disagree), pr After addressing a comment that requires code changes, create a single follow-up commit. Write a short message that summarizes what was changed (e.g. `"fix: use const for immutable bindings per review"`) rather than a generic message: Skip this step if no code changes were made. -Provide a commit message and wait until prompted to continue if not allowed to commit. +Provide a commit message and wait until prompted to continue if not allowed by policy to commit. ### Step 4 — Reply to each comment use github mcp @@ -42,6 +42,7 @@ Good reply patterns: - For changes made: "Done — ." - For questions answered: "< direct answer to question >." - For declined suggestions: "I kept the existing approach because ." +- For issues already resolved in code: "I fixed this in " ### Step 5 — Resolve each thread Resolve every thread/comment if satisfactory @@ -52,7 +53,9 @@ gh api graphql -f query='mutation { resolveReviewThread(input: {threadId: " Date: Tue, 24 Mar 2026 23:37:13 -0700 Subject: [PATCH 09/15] fix: add missing comma in gemini policy argsPattern --- gemini/policies/tools.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gemini/policies/tools.toml b/gemini/policies/tools.toml index 6b6f77f..ddf8e47 100644 --- a/gemini/policies/tools.toml +++ b/gemini/policies/tools.toml @@ -142,7 +142,7 @@ priority = 100 # Uses argsPattern to match both the command and the dir_path (keys are sorted alphabetically) [[rule]] toolName = "run_shell_command" -argsPattern = '"command":"git (add|commit|push|pull|fetch|rebase|reset|stash|status|diff|log|grep).*""dir_path":"/.*/repos/jaybocc2/.*"' +argsPattern = '"command":"git (add|commit|push|pull|fetch|rebase|reset|stash|status|diff|log|grep).*","dir_path":"/.*/repos/jaybocc2/.*"' decision = "allow" priority = 120 From e684770f79880a9acd47b519b1b4bf221c0ddde6 Mon Sep 17 00:00:00 2001 From: Jay Bendon Date: Tue, 24 Mar 2026 23:37:45 -0700 Subject: [PATCH 10/15] fix: optimize byte conversion and fix sed portability in zsh/functions.zsh --- zsh/functions.zsh | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/zsh/functions.zsh b/zsh/functions.zsh index 78a682d..353e564 100644 --- a/zsh/functions.zsh +++ b/zsh/functions.zsh @@ -40,17 +40,21 @@ tokb() { } tomb() { - jq -n "$(tokb $1) / 1024" + jq -n "$1 / (1024 * 1024)" } togb() { - jq -n "$(tomb $1) / 1024" + jq -n "$1 / (1024 * 1024 * 1024)" } totb() { - jq -n "$(togb $1) / 1024" + jq -n "$1 / (1024 * 1024 * 1024 * 1024)" } rmkhkey() { - sed -i '' "${1}d" ~/.ssh/known_hosts + if [[ "$(uname)" == "Darwin" ]]; then + sed -i '' "${1}d" ~/.ssh/known_hosts + else + sed -i "${1}d" ~/.ssh/known_hosts + fi } From a40c90d1c8bab3124da318b1424d8fbbaecb1ec4 Mon Sep 17 00:00:00 2001 From: Jay Bendon Date: Tue, 24 Mar 2026 23:53:15 -0700 Subject: [PATCH 11/15] . --- install.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/install.sh b/install.sh index 3407d43..9335ef6 100755 --- a/install.sh +++ b/install.sh @@ -182,6 +182,7 @@ install_neovim() { if which -a nvim | grep -v aliased >/dev/null; then brew upgrade neovim else + # install development version to support plugins brew install neovim --HEAD fi else From 9dae3d8abee03a6b7d1c9b73a03ecc41c4819c29 Mon Sep 17 00:00:00 2001 From: Jay Bendon Date: Wed, 25 Mar 2026 00:04:24 -0700 Subject: [PATCH 12/15] perf: use native zsh arithmetic for byte unit conversions --- zsh/functions.zsh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/zsh/functions.zsh b/zsh/functions.zsh index 353e564..57afcc9 100644 --- a/zsh/functions.zsh +++ b/zsh/functions.zsh @@ -36,19 +36,19 @@ tmuxsession () { } tokb() { - jq -n "$1 / 1024" + echo $(( $1.0 / 1024 )) } tomb() { - jq -n "$1 / (1024 * 1024)" + echo $(( $1.0 / (1024 * 1024) )) } togb() { - jq -n "$1 / (1024 * 1024 * 1024)" + echo $(( $1.0 / (1024 * 1024 * 1024) )) } totb() { - jq -n "$1 / (1024 * 1024 * 1024 * 1024)" + echo $(( $1.0 / (1024 * 1024 * 1024 * 1024) )) } rmkhkey() { From f6d38a85cfd3e08308d832d795bf92cb3abbfb75 Mon Sep 17 00:00:00 2001 From: Jay Bendon Date: Wed, 25 Mar 2026 00:04:24 -0700 Subject: [PATCH 13/15] fix: add guard to syncmain alias to prevent running on main --- gitconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gitconfig b/gitconfig index 99317c5..52485da 100644 --- a/gitconfig +++ b/gitconfig @@ -23,4 +23,4 @@ [includeIf "gitdir:~/repos/work/"] path = ~/.gitconfig-work [alias] - syncmain = "!f() { CURRENT_BRANCH=$(git symbolic-ref --short HEAD); git checkout main && git pull origin main && git checkout $CURRENT_BRANCH && git rebase origin/main && git push origin $CURRENT_BRANCH --force-with-lease; }; f" + syncmain = "!f() { CURRENT_BRANCH=$(git symbolic-ref --short HEAD); if [ \"$CURRENT_BRANCH\" = main ]; then echo 'Error: cannot run syncmain on main branch.' >&2; exit 1; fi; git checkout main && git pull origin main && git checkout \"$CURRENT_BRANCH\" && git rebase origin/main && git push origin \"$CURRENT_BRANCH\" --force-with-lease; }; f" From bdff168cccab7059fa86461597c5eff3047f8cb9 Mon Sep 17 00:00:00 2001 From: Jay Bendon Date: Wed, 25 Mar 2026 00:04:24 -0700 Subject: [PATCH 14/15] fix: improve jdtls_bazel jar copy robustness --- shlibs/lsp-deps.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/shlibs/lsp-deps.sh b/shlibs/lsp-deps.sh index 4bc6a49..79f512e 100755 --- a/shlibs/lsp-deps.sh +++ b/shlibs/lsp-deps.sh @@ -68,7 +68,11 @@ jdtls_bazel() { curl -L -o "$(pwd)/${fname}.zip" "${url}" || TRACE "failed to download jdtls bazel plugins" unzip ${fname}.zip mkdir -p "${install_dir}" - cp "$(pwd)/plugins/*.jar" "${install_dir}/" + if [ -d "plugins" ]; then + cp plugins/*.jar "${install_dir}/" + else + cp "${fname}/plugins/*.jar" "${install_dir}/" + fi rmtmp } From 9c9a103d2ac0c1c52ce873b2141cbb7578467e75 Mon Sep 17 00:00:00 2001 From: Jay Bendon Date: Wed, 25 Mar 2026 10:46:24 -0700 Subject: [PATCH 15/15] ignore worktrees --- gitignore_global | 1 + 1 file changed, 1 insertion(+) diff --git a/gitignore_global b/gitignore_global index d57981a..c3062ca 100644 --- a/gitignore_global +++ b/gitignore_global @@ -24,3 +24,4 @@ # misc # ######## *.sw? +.worktrees/