Skip to content

About

A Neovim bridge for staging Sidekick-style editor context in Herdr-native agent panes.

Resources

Contributing

Stars

5 stars

Watchers

0 watching

Forks

Repository files navigation

herdr-agent-bridge.nvim

A small Neovim bridge for keeping your editor context close to an agent running in a native Herdr pane.

The plugin owns neither the agent terminal UI nor the agent conversation. Neovim produces context, Herdr owns the pane and agent lifecycle, and the agent keeps its normal terminal interface.

Relationship to Sidekick

This project is inspired by and builds on the workflow and context model pioneered by folke/sidekick.nvim. In particular, it adopts Sidekick's context-template vocabulary, prompt-oriented UX, and {this} / {position} / {selection} semantics.

  • When Sidekick is installed, the bridge builds directly on its public sidekick.cli.render and sidekick.cli.prompt APIs. Sidekick remains the source of truth for prompts, custom context variables, diagnostics, quickfix entries, and Tree-sitter text objects.
  • Without Sidekick, the built-in provider offers an independent, dependency-free compatibility implementation of the core context workflow.
  • Sidekick's terminal and multiplexer layer is not embedded here. Herdr owns pane and agent lifecycle, while this project supplies the adapter and safety boundary between Neovim context and Herdr transport.

Sidekick is licensed under the Apache License 2.0. This project is independently distributed under MIT and does not bundle Sidekick source code.

Important

This project is an early preview. It is tested with Herdr 0.8.2 and Codex CLI on macOS. Linux is covered by unit tests; Windows integration has not been verified yet.

Features

  • Starts, reveals, or focuses one agent in the current Herdr tab.
  • Toggles between Agent View and Code View without stopping the agent or rebuilding its pane.
  • Creates a right-hand agent pane at 30% width by default.
  • Sends the current file, cursor/range, or visual selection without nesting tmux inside Herdr.
  • Focuses an agent instead of typing when the latest Herdr discovery response reports it as blocked.
  • Treats Herdr's startup agent_not_ready response as a recoverable interactive state.
  • Resolves the live pane, tab, and workspace before each action, so moving a pane does not leave discovery on stale launch-time context.
  • Works without Sidekick through a built-in Neovim context provider.
  • Optionally reuses Sidekick's context renderer and prompt library.

Requirements

  • Neovim 0.10 or newer.
  • Herdr 0.8.2 or newer. The bridge relies on 0.8.2's calling-pane resolution for pane current --current and uses native pane layout and zoom commands for Code View.
  • An agent executable supported by Herdr, such as codex, installed and authenticated normally.
  • Neovim must run inside a Herdr pane so HERDR_ENV and HERDR_PANE_ID are available. The live tab and workspace are resolved from that caller pane for every action; inherited workspace and tab variables are launch-time information only.

The optional Sidekick provider follows Sidekick's own requirements, currently Neovim 0.11.2 or newer.

Installation

With lazy.nvim:

{
  "WorksOnMyVM/herdr-agent-bridge.nvim",
  main = "herdr_agent",
  lazy = false,
  opts = {
    context = { provider = "auto" },
    pane = { size = 0.30 },
    keymaps = {
      toggle = "<leader>aa",
      -- open = "<leader>ao", -- optional: always reveal and focus the agent
      send_this = "<leader>at",
      send_file = "<leader>af",
      send_selection = "<leader>av",
      prompt = "<leader>ap",
    },
  },
}

For local development, replace the repository string with:

{
  dir = "/path/to/herdr-agent-bridge",
  main = "herdr_agent",
  lazy = false,
  opts = { --[[ same options ]] },
}

No keymaps are installed unless explicitly configured.

keymaps.toggle is recommended for <leader>aa. keymaps.open remains available when you always want to reveal and focus the agent.

Recommended workflow

Mapping Context Result
<leader>aa — Create/focus an agent if needed; otherwise toggle Agent View / Code View
<leader>at {this} Cursor/range reference in a file; this plus selection in a non-file buffer
<leader>af {file} Current file reference, such as @lua/example.lua
<leader>av {selection} Dedented visual selection
<leader>ap Prompt library Select a rendered prompt and stage it in the agent input

Code View uses Herdr's tab-local pane zoom: only Neovim is shown. All sibling panes in that tab are temporarily hidden, but their processes and the underlying split layout remain intact. Each toggle reads the live Herdr layout instead of caching a hidden-state flag. Returning to Agent View restores the layout and focuses the selected agent.

open() and :HerdrAgentOpen remain deterministic: they always reveal and focus the current tab's agent. After a context action, text is pasted into the agent input, the layout is revealed, and the agent pane is focused. It is deliberately not submitted automatically, so you can inspect or extend it before pressing Enter.

Agent reuse is scoped to the caller's Herdr tab. If another tab in the same workspace already has a Codex pane, using the bridge from the current tab creates or focuses a separate pane here instead of switching tabs. View-changing actions run in invocation order, so rapid shortcut presses cannot race each other or create duplicate agent panes.

Context providers

context.provider accepts "auto", "builtin", "sidekick", or a custom provider table.

Built-in

The built-in provider has no plugin dependency and supports:

  • {file}, {position}, {line}, {this}, {selection}
  • {buffers}, {diagnostics}, {diagnostics_all}, {quickfix}
  • configurable prompt templates rendered through vim.ui.select

Sidekick

When folke/sidekick.nvim is installed, "auto" uses its public sidekick.cli.render and sidekick.cli.prompt interfaces. This preserves Sidekick prompts, custom context variables, diagnostics, quickfix entries, and Tree-sitter text objects while Herdr remains the transport.

The adapter contains a tested compatibility shim for Sidekick's first lazy load. All Sidekick-specific knowledge is isolated in lua/herdr_agent/context/sidekick.lua.

The built-in provider intentionally follows Sidekick's {this} behavior: it resolves to a cursor or visual-range reference in a real file, and to this plus {selection} in a non-file buffer. Use {selection} / <leader>av when the selected source text itself must be sent from a file.

Custom

require("herdr_agent").setup({
  context = {
    provider = {
      render = function(template)
        return template == "{file}" and "@custom-context.lua" or nil
      end,
      select_prompt = function(callback)
        callback("Review @custom-context.lua")
      end,
    },
  },
})

Commands

  • :HerdrAgentToggle — switch between Agent View and Code View, creating an agent when needed.
  • :HerdrAgentOpen — always reveal and focus the current tab's agent.
  • :HerdrAgentSendThis — stage the current file range or non-file selection.
  • :HerdrAgentSendFile — stage the current file reference.
  • :HerdrAgentSendSelection — stage the active visual selection.
  • :HerdrAgentPrompt — select and stage a rendered prompt.
  • :checkhealth herdr_agent — check Herdr and context-provider availability.

Lua API

require("herdr_agent") exposes setup, toggle, open, send_this, send_file, send_selection, prompt, and context_provider. toggle is the user-facing view switch; open always reveals and focuses the agent. The last function returns the active provider name ("builtin", "sidekick", or a custom provider's name) and is useful for diagnostics.

Configuration

require("herdr_agent").setup({
  executable = nil, -- HERDR_BIN_PATH, then "herdr"
  agent = {
    kind = "codex",
    -- globally unique string matching [a-z][a-z0-9_-]{0,31},
    -- function(workspace_id, tab_id),
    -- or a globally unique name generated from the current tab ID
    name = nil,
  },
  pane = {
    direction = "right",
    size = 0.30, -- share assigned to the new agent pane
  },
  context = {
    provider = "auto",
    sidekick = { plugin = "sidekick.nvim" },
  },
  prompts = {
    -- merged with the built-in prompt library
  },
  keymaps = {
    toggle = false,
    open = false,
    send_this = false,
    send_file = false,
    send_selection = false,
    prompt = false,
  },
  max_context_bytes = 64 * 1024,
})

Herdr agent names are globally unique across all live agents. The default name is derived from the current tab ID. If you override agent.name and use several tabs or workspaces at once, prefer a function(workspace_id, tab_id) that derives a distinct valid name. Existing one-argument functions still run because workspace_id remains the first argument, but Herdr will reject a second live agent if that function returns the same name for multiple tabs.

If an automatically named agent pane is moved to another tab, the bridge adds a short numeric suffix when rebuilding the original tab's agent. Explicit string or function names are never changed automatically.

Safety boundaries

  • The plugin does not accept Codex directory trust, approvals, or interactive questions for you.
  • An agent reported as blocked by the latest discovery snapshot is focused instead of sent staged context.
  • Existing Herdr agents and panes are reused only within the current tab; the plugin does not migrate tmux sessions.
  • View-changing actions are serialized, and multi-agent selections are revalidated against the live tab before focus or terminal input.
  • Code View changes presentation only: sibling panes are temporarily hidden by Herdr zoom, while their processes and split layout remain intact.
  • Context is limited to 64 KiB by default.
  • Context containing terminal control bytes is rejected before raw pane transport.
  • The project does not inspect nested tmux sessions.

Staging is intentionally implemented with Herdr's raw pane surface because agent prompt submits immediately, while this plugin leaves the text editable in the agent input. State can change after discovery, so this check is a safety guard rather than an atomic approval boundary; Herdr and the agent remain responsible for interactive approvals.

Development

make test
stylua --check lua plugin tests

Tests use only Neovim's headless Lua runner; no Lua test framework is required.

The module boundaries and transport safety decisions are documented in docs/architecture.md.

Non-affiliation

This is an independent community project. It is not affiliated with or endorsed by Herdr, Sidekick, or OpenAI.

Acknowledgements

Special thanks to Folke Lemaitre and the Sidekick contributors. Sidekick established the Neovim context and prompt workflow that this bridge adapts to a Herdr-native agent pane.

License

MIT

About

A Neovim bridge for staging Sidekick-style editor context in Herdr-native agent panes.

Resources

Contributing

Stars

5 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages