Skip to content

Latest commit

 

History

27 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

paj.nvim

Neovim client for the Paj Unix-socket bridge. It discovers live Pi sessions for the current project, sends editor context without terminal scraping, and streams responses into a scratch buffer.

Requirements

  • Neovim 0.10 or newer
  • A current paj CLI on PATH
  • A live Pi session with the current Paj extension enabled

The CLI, extension, and plugin must be updated together; older Paj versions do not provide the native structured actions this plugin expects.

Installation

With lazy.nvim:

{
  "jlodenius/paj.nvim",
  config = true,
}

With vim.pack:

vim.pack.add({ "https://github.com/jlodenius/paj.nvim" })
require("paj").setup()

Or add the repository to runtimepath and call require("paj").setup().

Usage

Start Pi in the same project as Neovim, then query or review editor source:

:%PajQuery
:'<,'>PajReview

Paj automatically targets bridged sessions with the primary role. When exactly one primary is available, it is selected even if subagents are also running; when multiple primaries are available, Paj opens vim.ui.select for those primary sessions and remembers the choice per project while it remains a candidate. If the topology changes to a sole primary, that session is selected instead. If no primary is available, Paj falls back to all bridged sessions for compatibility. Picker entries show each session's name, role, branch, and task.

Use :PajSessions to explicitly choose any bridged session, including a subagent. That override is remembered per project while Neovim is running; if the selected session disappears, normal primary selection resumes.

Commands

Command Description
:PajSessions Select the target Pi session for the current project
:PajAttach Alias for :PajSessions
:[range]PajQuery Open an editable floating query for the selected lines or entire buffer; write it to send
:[range]PajExplain [focus] Explain the selected lines, or the entire buffer without a range
:[range]PajReview [focus] Review the selected lines, or the entire buffer without a range

Examples:

:'<,'>PajQuery
:'<,'>PajExplain focus on ownership
:%PajReview focus on error handling
:PajReview focus on concurrency

PajQuery opens a centered multiline floating buffer with a :w=submit q=cancel footer. Enter a question and use :write to send it, or press q in normal mode to cancel.

PajQuery, PajExplain, and PajReview send the source path, line range, and buffer content as a structured editor request. With no range they use the entire current buffer. The Pi extension retains that structure and exposes the source to the agent as untrusted data through the read-only paj_editor_context tool. Query, explanation, review, and follow-up turns cannot use mutation-capable tools. Responses stream into a temporary Markdown scratch buffer.

While a request is running, use buffer-local :PajCancel or press q to cancel it. Press q again to close the output, or use buffer-local :PajClose to cancel and close immediately.

Every completed response shows a sticky action footer pinned to the bottom of its output window and supports a follow-up with f or buffer-local :PajFollowUp. This opens the same multiline editor and sends the question to the same Pi session. Paj supplies proposed changes as native structured actions alongside ordinary Markdown response text; the plugin does not parse hidden Markdown metadata. When a response includes one or more proposals, the footer shows an accept action. Press a or run buffer-local :PajAccept; when there are multiple proposals, select one with vim.ui.select. Follow-up questions, accepted changes, and subsequent agent responses are appended to the existing output buffer as a conversation. Closing a response without accepting simply leaves its proposals unimplemented.

Configuration

require("paj").setup({
  command = "paj",
  timeout = 300,
  output_size = 30,
  output_position = "bottom",
  max_request_bytes = 200 * 1024,
})
Option Description
command Paj executable name or path
timeout Bridge request timeout in seconds
output_size Response split size as a percentage from 1 to 100
output_position Response split position: "top", "bottom", "left", or "right"
max_request_bytes Maximum encoded editor request size accepted by the plugin

For top and bottom splits, output_size is a percentage of the editor height. For left and right splits, it is a percentage of the editor width.

Requests are encoded as JSON and piped directly to paj bridge request --request-stdin; they are not stored in temporary files.

Troubleshooting

No live sessions

Check that Pi is running with the Paj extension in the same Git repository:

paj --json session list

Session discovery is project-scoped. Neovim uses the current buffer's Git root, falling back to its working directory outside a Git repository.

Session has no bridge

Inspect the selected session:

paj bridge status <session>

If it is unavailable, confirm that the Pi session loaded the Paj extension and that its registration is healthy.

Session is busy

A Pi session handles one bridge request at a time. Wait for its current turn to finish, cancel the request from its output buffer, or select another session with :PajSessions.

Cancel a request

In the request's output buffer, run :PajCancel or press q. Cancellation stops the Paj bridge client and asks the connected Pi session to abort that bridge request. Closing or wiping a running output buffer also cancels it.

Request times out

Increase timeout in setup() for requests that need longer to complete. The value is forwarded to paj bridge request --timeout.

Development

stylua --check lua plugin tests
nvim --headless -u NONE -l tests/headless.lua

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages