Skip to content

amittamari/hop

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

167 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐Ÿ‡ hop

Fast full-text search and resume for coding-agent sessions (Claude Code, Codex, and Cursor).

hop aggregates your past Claude Code, Codex, and Cursor sessions into a single full-text index, allowing you to jump straight back into any of them. Type a few words you remember, pick the result, hit Enter, and you are immediately resumed in the original agent and the original working directory.

hop demo: search, preview, and resume coding-agent sessions


โœจ Features

  • ๐Ÿ”Ž Full-text search across every session โ€” A Tantivy index over your entire Claude Code, Codex, and Cursor history. Fuzzy and exact matching across full conversation transcripts, not just titles.
  • ๐Ÿค– Multi-agent, one index โ€” Claude Code, Codex, and Cursor sessions live side by side, normalized into a single searchable view.
  • โšก Instant resume โ€” Pick a session and hop restores the terminal, chdirs to the original working directory, and exec-replaces itself with the right agent CLI. No copy-pasting paths.
  • ๐Ÿงฎ Rich, responsive results grid โ€” Agent, repo, branch, title, message count, PR status, and time โ€” with columns that gracefully drop on narrow terminals.
  • ๐Ÿงน Clean transcript previews โ€” On-demand previews strip tool calls, command tags, and system noise, with syntax-highlighted code and highlighted query matches.
  • ๐Ÿท๏ธ Powerful query keywords โ€” Filter by agent:, dir:, repo:, and relative/duration date: expressions inline with free-text search.
  • ๐Ÿ”— GitHub PR awareness โ€” Associated PRs are resolved in the background via the gh CLI and cached on disk.
  • ๐Ÿš€ Background streaming index โ€” Existing data renders instantly on launch; new sessions sync in the background without blocking the UI.

๐Ÿš€ Quick Start

Installation

Homebrew (macOS & Linux):

brew install amittamari/tap/hop

From source:

cargo install --locked --path .

Dependencies

hop works standalone for searching and previewing sessions. Additional tools unlock more features:

Dependency Purpose Notes
git Resolve repo names and branches at index time Effectively always present on developer machines
gh PR column and Ctrl+O open-in-browser Without it, the PR column stays empty โ€” everything else works fine
claude Resume Claude Code sessions Only needed if you use Claude Code
codex Resume Codex sessions Only needed if you use Codex
cursor-agent Resume Cursor sessions Only needed if you use Cursor

Usage Examples

hop                      # Open the TUI, auto-scoped to the current repo (if any)
hop "auth refresh"       # Pre-filled query, still scoped to the current repo
hop --all                # Search across all repos (disable auto-scoping)
hop -a claude -d api     # Filter by agent and directory on launch
hop -r hop               # Filter to one repo across all its worktrees
hop --rebuild            # Wipe and rebuild the search index
hop hooks install --all  # Install metadata hooks for detected agents
hop hooks status         # Show metadata-hook installation status
hop hooks uninstall      # Remove installed hop metadata hooks

Metadata hooks capture the final working directory and Git state at session start and stop, writing them to sidecar files that hop merges in at index time. How each agent's hooks are installed varies:

Agent Events Install mechanism
Claude Code SessionStart + SessionEnd Local plugin (hop-session-metadata@hop-local) registered via claude plugin, kept out of your ~/.claude/settings.json
Codex SessionStart + Stop Local plugin (hop-session-metadata@hop-local) registered via codex plugin
Cursor stop only Merged into ~/.cursor/hooks.json (best-effort; Cursor provides no session id or cwd to the hook)

hop hooks uninstall removes exactly what was installed โ€” the plugins and their marketplace registrations for Claude/Codex, and hop's entries from Cursor's hooks.json.


๐Ÿค– Supported Agents

hop indexes Claude Code, Codex, and Cursor sessions side by side. What hop can show depends on what each agent records on disk, so coverage varies by column:

Capability Claude Code Codex Cursor
Full-text search & clean preview โœ… โœ… โœ…
Resume in the original directory โœ… โœ… โœ…
Yolo / skip-permissions resume โœ… โœ… โœ…
Session title โœ… โœ… โœ…
Working directory + dir: filter โœ… โœ… โœ… โ€ 
Repo column + repo: filter โœ… โœ… โœ…
Branch column โœ… โœ… โœ… โ€ก
PR column โœ… โœ… โœ… โ€ก

โ€  Cursor doesn't store the working directory in its transcript; hop recovers it from the session's worker.log, so it's unavailable when that log is missing. โ€ก Cursor records no branch of its own. hop derives it โ€” and, in turn, the PR โ€” from the working directory's Git state at index time, so it's available only while that directory still exists on disk and reflects its current checkout (unless metadata hooks captured the branch at session time).

Repo is resolved from the git remote (git remote get-url origin) once per directory at index time, so it's identical across every worktree of a repo. Branch comes straight from agent metadata where the agent records it (Claude's gitBranch, Codex's git.branch). Cursor records none, so hop fills it from live Git at index time when the working directory still exists โ€” or captures it exactly when metadata hooks are installed. Installing metadata hooks (see hop hooks install) also captures worktree paths and the session's Git state at start and stop for every agent.

Not yet supported

The following providers aren't wired up yet โ€” contributions are welcome. Each provider is added through a session adapter, so it's mostly a matter of mapping its on-disk session format to hop's core types.

  • Gemini CLI
  • Aider
  • opencode

โŒจ๏ธ Keyboard Shortcuts

The query is always live โ€” just start typing to filter. Navigation lives on the arrows and secondary actions on Ctrl chords, so no key ever does double duty (there is no vim-style normal/insert mode โ€” see the note below). The Ctrl chords below are rebindable via [keybindings] in config.toml (see Configuration).

Key Action
Typing Filters search results
โ†‘ / โ†“ Move selection up / down
PgUp / PgDn Page viewport up / down
Tab / Shift+Tab Simple mode: move focus between the query and the Scope / Sort toolbar. Raw mode: autocomplete keywords (e.g., agent:cl โ†’ agent:claude)
โ† / โ†’ Adjust the focused toolbar control, or move the query cursor when the query is focused
Home / End Jump the query cursor
Enter Resume selected session (prompts for yolo when supported)
Ctrl + R Toggle simple โ‡„ raw search (see Search Modes)
Ctrl + O Open the selected session's PR in the browser (when one is resolved)
Ctrl + P Toggle the preview pane
Ctrl + U / D Scroll preview pane up / down by viewport
Ctrl + N / B Go to next / previous preview match
Ctrl + โ† / โ†’ Resize the preview pane
? Show help menu
Esc Clear the query, or quit when it's already empty
Ctrl + C Quit

No modal (vim) keymode. Because the query field is always live, hop stays modeless โ€” bare j/k type into the query rather than navigating, matching how fuzzy-finder pickers like fzf, atuin, and Codex's /resume behave. Reach for raw search mode (below) when you want the full query language, not a key mode.


๐Ÿงญ Search Modes

hop starts in simple mode: type plain text to fuzzy-match, and use the guided toolbar under the query for the common filters โ€” no query syntax to learn.

Control Values Effect
Scope This repo ยท All Limit to the current repo (when launched inside one) or search everywhere
Sort Relevance ยท Recent ยท Oldest Order by blended relevance+recency, newest-first, or oldest-first

Tab / Shift+Tab move focus to a control; โ† / โ†’ change its value. Press Ctrl + R to switch to raw mode, where the query line accepts the full query syntax directly and the toolbar is hidden. Set the startup default with search_mode = "simple" or "raw" in config.toml; typing DSL or passing --agent/--dir on the command line starts in raw mode automatically.


๐Ÿ” Query Syntax

These keywords power raw mode (Ctrl + R); most everyday filtering is covered by the simple-mode toolbar above. Keywords can be mixed with regular free-text search, and still work if typed in simple mode.

Example Filter Type Description
auth refresh Free-text Matches terms (fuzzy + exact) across full conversation history
agent:claude,codex Include Agent Restrict results to specific agents
-agent:codex or agent:claude,!codex Exclude Agent Exclude specific agents from results
dir:api / -dir:vendor Directory Substring include or exclude on directory paths
repo:hop / -repo:vendor Repository Substring include or exclude on the git remote URL โ€” matches every worktree of a repo
date:today / date:yesterday Relative Date Local calendar-day filters
date:week / date:month Date Windows Broad recency windows
date:<2d / date:>1w Duration Matches within (<) or older than (>) durations (h/d/w)

Auto-scope: When launched from inside a git repo, hop prepends a repo:owner/name filter for you so you see that repo's sessions first. Pass --all to search every repo, or just edit/delete the repo: token in the query bar to broaden mid-session. Supplying your own -r/repo: filter (or running outside a git repo) disables auto-scoping.


๐Ÿ“Š Interface & Columns

Each row in the TUI is organized into a dynamic, aligned grid:

$$\text{AGENT} \quad\cdot\quad \text{REPO} \quad\cdot\quad \text{BRANCH} \quad\cdot\quad \text{TITLE} \quad\cdot\quad \text{MSGS} \quad\cdot\quad \text{PR} \quad\cdot\quad \text{TIME}$$

  • Branch & Repo: The Repo column shows the repository name parsed from the git remote URL, resolved once per directory at index time (git remote get-url origin) โ€” so worktrees of the same repo collapse to one consistent name instead of showing distinct folder names. Sessions outside a git repo fall back to the directory's basename. The Branch column comes from agent metadata where recorded; full paths are shown in the preview header, and the Branch column distinguishes worktrees at a glance. Per-agent coverage is summarized in the Supported Agents table above.
  • Titles: Uses the recorded AI title/summary if available, otherwise falls back to the first user prompt. Titles are whitespace-normalized.
  • PR Column: Resolved asynchronously in the background using the gh CLI and cached on disk. Shows โŸณ while loading, and โ€” if no PR is associated.
  • Responsive Layout: Narrow terminals automatically drop columns based on priority:

$$\text{PR} \rightarrow \text{MSGS} \rightarrow \text{TIME} \rightarrow \text{BRANCH} \rightarrow \text{REPO}$$

Leftover width is dynamically allocated to the conversation Title.


๐Ÿง  How It Works

  • Streaming Index: The index is stored in your platform's cache directory (e.g., ~/.cache/hop/). On launch, existing data renders instantly. New sessions sync seamlessly in the background without blocking the UI.
  • Instant Resume: When you select a session, hop restores the terminal state, changes the directory (chdir), and exec-replaces the process directly with the respective agent CLI.
  • Clean Previews: The preview pane re-parses selected sessions on demand. It strips out internal noise (tool calls, <command-*> tags, system reminders) and displays a clean transcript with syntax-highlighted code and highlighted query matches.

โš™๏ธ Configuration

An optional configuration file can be created in your platform's config directory (e.g., ~/.config/hop/config.toml).

# Startup search mode: "simple" (guided toolbar, the default) or "raw" (query DSL).
search_mode = "simple"

[preview]
visible = true
width_pct = 50
metadata_header = true

[columns]
disabled = []   # e.g., ["pr"] to disable background GitHub PR resolution
order = []      # e.g., ["agent", "title", "time"]. Unspecified columns follow naturally.

[keybindings]
# Rebind any Ctrl-chord action. Values must include `ctrl` (the chord-only
# invariant keeps chords from colliding with query editing). Unset commands keep
# their default. Invalid values, unknown command names, and conflicts are logged
# to stderr at launch and fall back to the default rather than failing.
toggle_preview        = "ctrl+p"   # default
scroll_preview_up     = "ctrl+u"
scroll_preview_down   = "ctrl+d"
jump_match_prev       = "ctrl+b"
jump_match_next       = "ctrl+n"
resize_preview_smaller = "ctrl+left"
resize_preview_larger  = "ctrl+right"
open_pr                = "ctrl+o"
toggle_search_mode     = "ctrl+r"
quit                  = "ctrl+c"

Binding values accept letters (ctrl+t), digits, and named keys (ctrl+left, ctrl+right, ctrl+up, ctrl+down, ctrl+home, ctrl+end, ctrl+pageup, ctrl+pagedown, ctrl+space). Ctrl + C always quits regardless of the quit binding, as an emergency exit. The help overlay (?) reflects your active bindings.

โš™๏ธ Note: The theme table is accepted for forward-compatibility but is currently reserved and not applied. Preview width and visibility choices persist automatically across restarts.


๐Ÿ“„ Documentation Index

For deeper technical context, explore the following documentation files:

  • AGENTS.md โ€” Overview of contributor and agent context.
  • docs/PROJECT.md โ€” Core project goals and scope.
  • docs/ARCHITECTURE.md โ€” System design and internals.
  • docs/specs/, docs/reviews/, docs/plans/ โ€” Dated specifications, review artifacts, and execution roadmaps.

๐Ÿ™ Credits

Inspired by angristan/fast-resume, which also served as a reference for the Claude Code and Codex session adapters.

About

Fast full-text search and resume for coding-agent sessions

Topics

Resources

License

Stars

5 stars

Watchers

0 watching

Forks

Contributors

Languages