Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 2 additions & 0 deletions claude/.claude/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ Assume these are installed on my machine. **Use them first** when proposing or r

**Indexed / fast repo search:** Where the environment exposes **fff** (e.g. MCP server, editor integration, or project tooling), prefer **fff** for search and file discovery over long chains of generic grep/find when it reduces noise and round-trips.

**Neovim context (`nvim-ctx`):** When Greg mentions code he's looking at in nvim, references his neovim screen, or asks about something open in his editor — run `nvim-ctx` proactively before responding. Don't ask him to paste; fetch it yourself. It outputs JSON with `file`, `start_line`, `end_line`, and `text` (selection if active, whole buffer otherwise). Takes an optional session name: `nvim-ctx [session]`. If it fails, say so briefly and ask Greg to paste instead.

If something is missing in a given environment, fall back to standard tools and note it briefly.

**Scope:** These preferences target everyday repo work (search, navigation, diffs). One-off diagnostics (**`dex dir`**, **`ls`** on a known path, **`head`**/**`cat`** on a single file) do not need to be forced through **`fd`**/**`rg`**/**`eza`** when that only adds friction.
Expand Down
27 changes: 27 additions & 0 deletions nvim/.config/nvim/lua/greg/ctx.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
local M = {}

---@return string JSON with file, start_line, end_line, text
function M.json()
local sl = vim.fn.line("'<")
local el = vim.fn.line("'>")
local file = vim.fn.expand("%:p")
local text

if sl == 0 then
sl = 1
el = vim.fn.line("$")
text = table.concat(vim.api.nvim_buf_get_lines(0, 0, -1, false), "\n")
else
text = table.concat(vim.fn.getline(sl, el) --[[@as string[] ]], "\n")
end
Comment on lines +5 to +16

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Use active mode detection instead of stale visual marks.

Line 10 currently treats any existing '< mark as an active selection. That can return a previous selection during normal-mode remote calls, violating the “selection if active, otherwise full buffer” contract.

Proposed fix
 function M.json()
-  local sl = vim.fn.line("'<")
-  local el = vim.fn.line("'>")
+  local sl = vim.fn.line("'<")
+  local el = vim.fn.line("'>")
   local file = vim.fn.expand("%:p")
   local text
 
-  if sl == 0 then
+  local mode = vim.api.nvim_get_mode().mode
+  local has_active_visual = (mode == "v" or mode == "V" or mode == "\22")
+
+  if not has_active_visual then
     sl = 1
     el = vim.fn.line("$")
     text = table.concat(vim.api.nvim_buf_get_lines(0, 0, -1, false), "\n")
   else
     text = table.concat(vim.fn.getline(sl, el) --[[`@as` string[] ]], "\n")
   end
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@nvim/.config/nvim/lua/greg/ctx.lua` around lines 5 - 16, The code uses stale
visual marks (line("'<") and line("'>")) to detect if a selection is active, but
these marks persist from previous selections even when no selection is currently
active. Instead of relying on mark existence, use Vim's active mode detection to
determine if a visual selection is currently active. Check the current mode
using Vim's mode detection function to distinguish between an active visual
selection and a previous selection that no longer exists, then conditionally
fetch either the selected lines or the entire buffer accordingly.


return vim.json.encode({ file = file, start_line = sl, end_line = el, text = text })
end

_G.NvimCtxJSON = M.json

vim.api.nvim_create_user_command("NvimCtx", function()
print(M.json())
end, {})

return M
1 change: 1 addition & 0 deletions nvim/.config/nvim/lua/greg/init.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require("greg.remap")
require("greg.ctx")

if vim.g.vscode then
return
Expand Down
39 changes: 39 additions & 0 deletions zsh/.local/bin/nvim-ctx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/bin/sh

session=$1

if [ -n "$session" ]; then
pane_id=$(tmux list-panes -t "$session" -F '#{pane_id} #{pane_current_command}' 2>/dev/null | awk '/nvim/{print $1; exit}')
else
pane_id=$(tmux list-panes -s -F '#{pane_id} #{pane_current_command}' 2>/dev/null | awk '/nvim/{print $1; exit}')
fi

if [ -z "$pane_id" ]; then
printf 'nvim-ctx: no nvim pane found\n' >&2
exit 1
fi

pane_pid=$(tmux display-message -t "$pane_id" -p '#{pane_pid}')
nvim_pid=$(pgrep -P "$pane_pid" 2>/dev/null | head -1)
[ -z "$nvim_pid" ] && nvim_pid=$pane_pid

# Verify the found process is actually nvim (pane_current_command can lag after exit)
cmd=$(ps -o comm= -p "$nvim_pid" 2>/dev/null)
if [ "$cmd" != "nvim" ]; then
printf 'nvim-ctx: nvim is not running\n' >&2
exit 1
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
fi

# nvim forks a server child — search direct child and its children for the socket
socket=
for pid in "$nvim_pid" $(pgrep -P "$nvim_pid" 2>/dev/null); do
socket=$(find /var/folders -path "*/T/nvim.$(id -un)/*" -name "nvim.${pid}.*" 2>/dev/null | head -1)
[ -n "$socket" ] && break
done

if [ -z "$socket" ]; then
printf 'nvim-ctx: no socket found for nvim pid %s\n' "$nvim_pid" >&2
exit 1
fi

nvim --server "$socket" --remote-expr 'v:lua.NvimCtxJSON()'