Skip to content

Repository files navigation

herdr-context

Project context, docked next to your terminal.
A Herdr plugin that puts your files and LLM conversation history in a narrow pane beside the active terminal or coding agent.

About · Highlights · Install · Sidebar summary · Controls · Configuration

Latest release CI License Requires Herdr 0.8.0 or newer Linux and macOS

Note

herdr-context is an independent plugin built entirely on Herdr's public plugin surface, and is discoverable through the community marketplace. External history discovery covers exactly the provider versions listed below; anything else degrades gracefully instead of closing the dock.

About

herdr-context docks two views to the right of your work: a Files browser with Git/Jujutsu status markers, and a History browser for LLM conversations tied to the current project. Both render in one Ratatui process, and the project context is captured from the originating terminal before the dock ever takes focus.

┌────────────────┬──────────────────────────────────┬────────────────────────┐
│ Native sidebar │ Terminal / agent                 │ herdr-context          │
│ Herdr          │                                  │ Project / view icons   │
└────────────────┴──────────────────────────────────┴────────────────────────┘

The dock is a narrow Herdr pane rather than an extension of the native sidebar. That keeps the plugin on Herdr's public plugin surface, compatible with upstream Herdr, and independently installable. As an opt-in extra, the plugin can also publish a compact VCS summary into the native sidebar's existing Spaces rows — see Sidebar summary.

Docks survive Herdr server restarts: toggling a dock records where it was open, and after herdr server stop and a fresh start a startup hook re-opens those docks — without stealing focus and at their saved width. Herdr restores the old dock slot as a plain shell; the startup hook closes that shell once the dock is ready, provided another terminal remains in the tab. Opt out with [dock] restore_on_startup = false in the plugin config (herdr plugin config-dir herdr-context).

The goal is simple: know where the project stands — files, changes, conversations — without leaving the tab.

Highlights

  • Two views, one process — switch between Files and History without restarting the dock; selection, scroll position, and collapsed groups survive tab switches.
  • Compact dock — a shared bold uppercase project title above padded, icon-only view buttons, a two-column tree indent and one state chevron per row; the full-width neutral selection band keeps icon and status colors.
  • VCS-aware tree — status markers use green, yellow or red; directories inherit the strongest status of their descendants, and deleted files remain visible even though they left disk.
  • Modified-files list — every changed path in one flat list beneath the tree, with green +N / red -N workspace diff totals on the divider.
  • History across tools — Claude Code, Codex CLI, Pi, OMP, and OpenCode sessions associated with the project, merged with live Herdr sessions.
  • Resume in one keystroke — Enter on a session opens it in a new focused tab of the current workspace.
  • File references — Enter on a file row inserts its project-relative @path into the originating pane and hands focus back to it.
  • Path filter — / searches project-relative paths across collapsed directories through a bounded background index.
  • Responsive by construction — disk reads, Git/Jujutsu commands, and transcript parsing never block the rendering thread.
  • Read-only and local — the plugin never modifies project files or VCS history, sends nothing over the network, and caches metadata only.

Files

  • browse the directory the dock was opened from;
  • expand and collapse directories with keyboard or mouse;
  • show the lexical opening directory's basename as a shared bold uppercase title above both views, rather than substituting the repository root;
  • honor .gitignore and configurable hidden-file visibility;
  • search paths across collapsed directories; the field appears only while editing or a filter is active, opened by the loupe or configured shortcut. The index follows the same visibility and ignore rules as the tree;
  • support Git and Jujutsu (jj) workspaces behind one normalized status model — added, modified, deleted, renamed, copied, untracked, conflicted;
  • split into a top tree and a bottom flat list of every file carrying a status, separated by a rule showing +N / -N tracked line totals (file count when the diff is unavailable); the rule lights up while the flat pane holds focus, and the flat pane hides while the path filter is active;
  • keep file names neutral, preserve typed file icons and their configured colors, and place VCS markers at the right edge. Deterministic truecolor status colors prevent terminal palette remapping from turning red green;
  • show the focused Tree or Changes selection's relative path and metadata in a compact footer, followed by configured shortcuts when they fit;
  • never intentionally modify project files or VCS history.

Jujutsu status requires jj 0.37 or newer and is integration-tested against jj 0.44.0. The default Fresh mode snapshots only when Files activates or you press r — it never polls in the background. The opt-in Passive mode adds --ignore-working-copy and always marks the shown status as potentially stale. The plugin never issues commit, bookmark, or rewrite commands.

History

  • list conversations associated with the current project or worktree;
  • prefer histories stored inside the project, then discover external stores elsewhere on the filesystem through canonical project metadata;
  • merge filesystem history with live Herdr sessions as enrichment, never as the sole source;
  • group providers alphabetically with most-recent sessions first; collapsing a provider group loads and exposes no transcript content;
  • show one compact title row per session, with a short UTC date at the right when space permits; only the selected session's tool, state, resume capability, update time and provenance appear in the two-line footer. Selecting a provider instead shows its group details;
  • isolate failures per source, so one unreadable store cannot hide the others.
Source Kind
Claude Code 2.1.232 external store
Codex CLI 0.147.0 external store
Pi 0.84.1 external store
OMP 17.3.2 external store
OpenCode 1.18.18 external store
Project-local records .herdr/conversations/, .jsonl, .json
Live Herdr sessions runtime enrichment

Project-local records are read shallowly — direct children of .herdr/conversations/ plus two fixed filenames, never a recursive scan. Each record needs session_id, the canonical project-root cwd, an RFC 3339 timestamp, a role, and a string message. Message bodies are validated and never returned to the UI or diagnostics.

External stores are only hints until verified: encoded directory layouts and filenames count for nothing unless native session IDs, timestamps, and canonical cwd evidence agree. Live sessions match by tool plus native ID, then transcript path plus fingerprint, then verified path identity — titles, timestamps, and prefixes are never identities. Unmatched live rows appear transiently and survive until the filesystem transcript appears; Herdr failures are warnings while filesystem history stays visible.

Discovery runs in bounded recent-first pages on the low-priority worker. Large JSONL sessions advance through complete-record cursors instead of being loaded whole, and sessions disappear only after a refresh proves they were deleted or replaced. Incomplete inventories keep prior metadata, and source-scoped warnings stay visible beside healthy adapters.

Install

From GitHub

herdr plugin install Anthodev/herdr-context

Herdr clones the repository, runs the manifest build (cargo build --release --locked), stores a managed checkout, and registers the plugin. This path needs git and a Rust toolchain (the crate pins 1.97.1). There is no separate update command in plugin v1 — reinstall to refresh.

Requirements

  • Herdr 0.8.0 or newer and a POSIX shell.
  • git plus a Rust toolchain (the crate pins 1.97.1) for the source install; the build runs cargo build --release --locked on your machine.
  • Git is optional at runtime; Jujutsu status needs jj 0.37 or newer, and missing VCS tools degrade the affected status view without closing the dock.

Upgrade and uninstall

There is no separate update command in plugin v1 — run herdr plugin install Anthodev/herdr-context again to refresh the managed checkout, and herdr plugin uninstall herdr-context to remove it. Reinstall and uninstall preserve Herdr-managed config, state, and conversation histories.

Sidebar summary

Optional, off by default, and verified against Herdr 0.9.3. When enabled, a small background publisher reports each Space's VCS state to the token $herdr_context_vcs, which you place yourself in the native sidebar's existing Spaces rows — the plugin never rewrites your layout:

[ui.sidebar.spaces]
rows = [
  ["state_icon", "workspace"],
  ["branch"],
  ["$herdr_context_vcs"],
]
[sidebar]
enabled = false    # startup hook creates the publisher only when true
interval_ms = 5000 # 1000..300000; independent of the dock's VCS cadences

[sidebar.roots."<absolute session socket>"]
"<workspace_id>" = "/absolute/path/to/project"

Get the socket from the socket: line of herdr status server and the Space IDs from herdr workspace list, passing the same --session to both if you run a named session. Roots resolve in order: an explicit mapping for that socket and workspace ID, then Herdr's native WorkspaceInfo.worktree.checkout_path, then worktree list — which uses the unique worktrees[] entry whose open_workspace_id matches the Space, or source.source_checkout_path only when source.source_workspace_id matches that same Space; a foreign source association yields no root, and a malformed or ambiguous association is a protocol error. Absent mappings use these native paths normally; a nonexistent or invalid explicit mapping value is an error that never falls back to another project, another checkout, or an active pane's cwd, and no repo_root or pane cwd inference exists. A Jujutsu workspace that is not colocated has no native checkout root and needs an explicit mapping. Without a resolvable root or a selected VCS, the token is absent.

Token values, refreshed by real collection only. The value is the same added/deleted line diffstat as the dock's modified-files list totals — Git counts tracked staged + unstaged changes against HEAD (untracked files are not included), and Jujutsu diffs @ against its parent the same way Files does:

State Value
Working-copy status is dirty +123/-45
Working-copy status is clean No changes
Collection or root/protocol error vcs error
No project or VCS available token cleared

Clean versus dirty is decided from status, not from the line counts, so a working copy with only renames, binary changes, or untracked files (Git) can report +0/-0 rather than No changes. The backend, its mode, and changed-file counts are not shown — the token value itself is the whole summary (dirty values are prefixed with the Nerd Font Git logo `` U+E702, which requires a Nerd Font terminal; the Jujutsu passive mode still applies under the hood: it can hold `No changes` until the next working-copy snapshot).

Each value carries a TTL of 3 × interval_ms + 7000 ms (22000 by default); an expired value disappears from the sidebar. Collections run with all docks closed, and the summary follows its Space's own project root — switching to a tab in another project does not change it. The [vcs] backend and jujutsu_mode settings are shared with the dock; only the cadence differs.

To activate on an already-running server (the startup hook fires on Herdr start only):

herdr plugin action invoke herdr-context.sidebar-start

Honest limits: a single owner per session holds a canonical lock keyed on the socket, and a detected socket replacement or generation change makes the old writer exit without touching the successor's data — but the underlying stat + CLI probe is not atomic with the CLI's connect, so a replacement between the two is still possible; values are temporary and TTL-bounded, so the sidebar cannot show stale data for long. Disabling the config or the plugin stops scheduling and clears the token within a bounded cleanup budget; otherwise TTL expiry covers it. A crashed worker is not supervised or restarted automatically — run the sidebar-start action again to recover. Herdr's own version handoff behavior is not exercised by this plugin's verification.

Controls

Input Action
Tab / Shift+Tab, 1 / 2 Switch views without restarting the dock
Arrows or h j k l Navigate the focused pane (tree, modified-files list, or conversation rows)
Home / End Select the first or last visible row
Enter / Space Expand or collapse directories and provider groups; insert @path from a file row; resume a resumable session in a new focused tab
w Move focus between the Files tree and its modified-files list; activating a missing file reports in the notice line instead of inserting a reference
/ or Files loupe Open the path filter — Enter keeps a nonempty filter, Ctrl+U clears the query while editing, Esc clears it and restores Tree/Changes
Mouse Click anywhere in a view or search button, including its padding, or select and focus a list row; right-click toggles and wheel scrolls inside lists. Titles, gaps, notices and footers are not list targets
q, Esc with no filter, Ctrl+C Close the dock and restore the terminal

The table shows default keys. Custom bindings also update the footer hints; only complete hints that fit after the selection details are shown. History shows the two view-switch hints, while Files can also show search and focus.

View and search controls occupy one row, with two cells of horizontal padding on each side when space permits. Only the active view has a neutral background; inactive views and the search control stay background-free. One blank, noninteractive row separates the controls from the lists; short docks omit it. The active view and an open or active search filter use bold accent icons.

Configuration

The plugin reads config.toml from HERDR_PLUGIN_CONFIG_DIR on a worker, after the first frame. An absent file silently uses safe defaults; malformed files and invalid fields fall back field-by-field and produce a sanitized warning in the dock.

[dock]
initial_width = 40       # 24..60
restore_on_startup = true   # re-open docks after a Herdr server restart

[ui]
display_mode = "ascii" # ascii, unicode, or nerd
colored_icons = true   # nerd mode only: type-colored file icons

[files]
show_hidden = false
show_ignored = false          # `i` toggles ignored files in-session
search_ignored = false        # search ignored paths without showing them normally
exclusions = ["target", "generated/cache"] # project-relative paths

[conversations]
enabled_sources = [
  "claude-code",
  "codex-cli",
  "omp",
  "opencode",
  "pi",
  "project-local-generic-jsonl",
]
project_roots = [".agents/history"] # additional shallow project-local roots
page_size = 128                     # 1..512 records per source and pass
cache_entries = 4096                # 16..4096 metadata rows

[conversations.external_roots]
claude-code = ["/home/me/.claude/projects"]
pi = ["/home/me/.pi/agent/sessions"]

[vcs]
backend = "auto"            # auto, git, or jj
jujutsu_mode = "fresh"      # fresh or passive
git_cadence = "manual"      # manual or adaptive
git_min_interval_ms = 2000  # adaptive only; 250..300000
git_max_interval_ms = 30000
passive_jujutsu_interval_ms = 0 # 0 disables; otherwise 1000..300000

[sidebar]
enabled = false              # opt-in VCS summary for the native sidebar
interval_ms = 5000           # 1000..300000

[sidebar.roots."/path/to/session/socket"]
"<workspace_id>" = "/absolute/project/root" # explicit roots (JJ-only Spaces)

[keybindings]
refresh = ["r"]
search = ["/"]
toggle_files_focus = ["w"]
toggle_ignored_files = ["i"]
quit = ["q", "esc", "ctrl+c"]

Extra project roots are project-relative; extra external roots are absolute. Every configured root remains subject to its adapter's version, layout, and metadata bounds, and unreadable roots are isolated so healthy sources stay visible.

Rows share one anatomy in every mode — status marker, two-column indent, state glyph, optional icon, name — with no tree guide connectors:

Mode Look Requires
ascii + / - directories, f / l files; * / - / ? History states Nothing — the compact default
unicode ▸ / ▾ chevrons, Unicode file and session bullets A Unicode-capable terminal
nerd Chevrons plus Nerd Font folder and typed-file icons, colored by type (colored_icons = false for monochrome) A Nerd Font

Selection is a full-width neutral band in both views; markers and names keep their colors on top of it.

Changing modes reuses cached state — no additional filesystem reads or traversal.

Files and VCS refresh immediately when Files activates or refresh fires. Adaptive Git polling starts at the minimum interval, doubles while status is unchanged up to the maximum, resets on change, and suspends outside the Files view. Fresh Jujutsu never polls; passive Jujutsu polls only when its interval is non-zero and always renders status as potentially stale.

Privacy

  • Config: herdr plugin config-dir herdr-context, normally below ${XDG_CONFIG_HOME:-$HOME/.config}/herdr/plugins/config/herdr-context/.
  • State and metadata-only conversation cache: normally below ${XDG_STATE_HOME:-$HOME/.local/state}/herdr/plugins/herdr-context/.
  • Managed source checkout: shown by herdr plugin list for the herdr-context entry.

Nothing is packaged or shipped: the install path is a source checkout built on your machine. Conversation content never leaves the machine; the disposable cache stores display, provenance, resume, and watermark metadata only, with private permissions and atomic generation replacement. Platforms that cannot enforce owner-only cache permissions fail closed instead of persisting external metadata.

Limitations

  • The manifest declares Linux and macOS only; Windows is unsupported, and the source build targets whatever the pinned Rust toolchain builds.
  • External history discovery is restricted to the fixture-validated provider versions above; undocumented, encrypted, or remote-only histories need a dedicated adapter and cannot be inferred safely.
  • History can resume sessions but never edits, deletes, summarizes, or uploads them.

Design principles

  • Public Herdr integration — manifest, injected context, CLI, and socket API only.
  • One Rust/Ratatui binary — no cross-pane IPC for the core experience.
  • Filesystem-first history — project-local and external conversations are indexed independently of Herdr's session lifecycle.
  • Responsive by construction — nothing slow ever runs on the rendering thread.
  • Bounded work — lazy expansion, coalesced jobs, limited caches, incremental indexing, suspended refreshes for inactive views.
  • VCS-neutral core — Git and Jujutsu feed one normalized model without leaking backend specifics into the UI.
  • Read-only and resilient — a missing VCS, malformed transcript, or absent tool must never close the dock.
  • Local privacy — conversation content stays off the network; caches hold only what discovery and display require.

Build from source

Requirements: Rust 1.97.1 (pinned in Cargo.toml) and a POSIX shell; git and jj 0.37+ are optional at runtime.

git clone https://github.com/Anthodev/herdr-context.git
cd herdr-context
cargo build --release --locked
herdr plugin link "$PWD"

CI gates every change on rustfmt, Clippy with warnings denied, and the full test suite.

Release status

Version 0.20.0 is the current release line. Tag v0.20.0, Cargo metadata, both manifests, and the minimum Herdr version are validated together; pushing a v* tag runs formatting, Clippy, the full test suite, and the contract checks, then publishes curated release notes taken from the versioned CHANGELOG.md section. There are no packaged assets to install.

Every performance budget has a retained independent review in release/performance-review.toml; a failed budget blocks a tagged release unless its record names the accepting authority, rationale, scope, and follow-up issue. Ratatui measurements exclude terminal-driver and multiplexer transport latency — see docs/performance.md for budgets, baselines, and residual risks.

Acknowledgements

Contributing

Issues and pull requests are welcome. Bug reports should include the Herdr version, OS, terminal, and VCS backend, with steps to reproduce — and no conversation content or other personal data.

License

MIT.

About

Project context dock for herdr — file tree with git status and LLM conversation history, always at your agent's side

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Contributors

Languages