An open API service indexing awesome lists of open source software.

https://github.com/stefanbartl/reposcope.nvim

๐Ÿ“ก A powerful Telescope extension for discovering and previewing code repositories directly within Neovim. Search GitHub repositories by keyword or topic and preview their README.md content in a floating window โ€” right from your editor. Future support planned for GitLab, Codeberg, and other platforms.
https://github.com/stefanbartl/reposcope.nvim

developer-tools fuzzy-search github github-api lua markdown-clone neovim neovim-plugin neovim-ui nvim readme-preview repositories repository-search seatch

Last synced: about 3 hours ago
JSON representation

๐Ÿ“ก A powerful Telescope extension for discovering and previewing code repositories directly within Neovim. Search GitHub repositories by keyword or topic and preview their README.md content in a floating window โ€” right from your editor. Future support planned for GitLab, Codeberg, and other platforms.

Awesome Lists containing this project

README

          

# reposcope.nvim
![version](https://img.shields.io/badge/version-0.1-blue.svg)
![State](https://img.shields.io/badge/status-beta-orange.svg)
![Lazy.nvim compatible](https://img.shields.io/badge/lazy.nvim-supported-success)
![Neovim](https://img.shields.io/badge/Neovim-0.9+-success.svg)
![Lua](https://img.shields.io/badge/language-Lua-yellow.svg)

> ๐Ÿ”ง Beta stage โ€“ under active development. Changes possible.

```
_ __ ___ _ __ ___ ___ ___ ___ _ __ ___
| '__| / _ \| '_ \ / _ \ / __| / __| / _ \ | '_ \ / _ \
| | | __/| |_) || (_) |\__ \| (__ | (_) || |_) || __/
|_| \___|| .__/ \___/ |___/ \___| \___/ | .__/ \___|
| | | |
|_| |_|
```

Search, preview and clone GitHub repositories โ€“ directly from inside Neovim.
Modular, minimal, Telescope-inspired interface.

---

- [Features](#features)
- [Features Demo](#features-demo)
- [Roadmap](#roadmap)
- [Installation](#installation)
- [With Lazy.nvim](#with-lazynvim)
- [With packer.nvim](#with-packernvim)
- [Configuration](#configuration)
- [Available Options](#available-options)
- [Usage](#usage)
- [UI Keymaps](#ui-keymaps)
- [Available Commands](#available-commands)
- [:ReposcopePromptReload](#reposcopepromptreload-)
- [:ReposcopeFilterRepos](#reposcopefilterrepos-text)
- [:ReposcopeFilterPrompt](#reposcopefilterprompt)
- [Authentication](#authentication)
- [Architecture Overview](#architecture-overview)
- [Development & Debugging](#development-debugging)
- [License](#license)
- [Contribution](#contribution)

---

## Features

- ๐Ÿ” Dynamic GitHub repository search by topic, owner, language, etc.
- ๐Ÿ“„ Live preview of `README.md` with inline Markdown rendering
- ๐Ÿง  Persistent README caching (RAM + file system)
- ๐Ÿ”ง Clone support: `git`, `gh`, `wget`, `curl`
- ๐Ÿ” Debounced README fetches to avoid redundant API calls
- ๐Ÿ“ฆ Clean, fully modular architecture (UI, state, providers, controllers)
- ๐Ÿงช Strongly annotated with EmmyLua for LuaLS support
- ๐Ÿ“Š Built-in request metrics and logging (optional toggle)
- ๐Ÿ“‘ README viewer (``) or README editor buffer (``)
- โŒจ๏ธ Keymaps for navigation, cloning, and UI control
- ๐Ÿ“ Customizable prompt fields (e.g. `prefix`, `keywords`, `owner`, ...)

---

## Features Demo:

https://github.com/user-attachments/assets/85dece1d-d755-4de9-9cd1-84a751901fc2

---

## Roadmap

- [x] GitHub repository search (field-based)
- [x] GitHub README rendering (raw + API fallback)
- [x] Clone repo with tool of choice (`git`, `gh`, `curl`, `wget`)
- [x] File-based README cache
- [x] Full UI (list, prompt, preview, background) in dynamic layout
- [x] Metrics, logging, and developer diagnostics
- [x] Viewer/editor for README content
- [x] Help docs via `:h reposcope`
- [ ] GitLab + Codeberg provider support
- [ ] Persistent session save/restore

---

## Installation

### With [Lazy.nvim](https://github.com/folke/lazy.nvim)

```lua
{
"StefanBartl/reposcope.nvim",
name = "reposcope",
event = ""VeryLazy,
dependencies = {
"nvim-lua/plenary.nvim",
"nvim-telescope/telescope.nvim",
},
config = function()
require("reposcope.init").setup({})
end,
}
```

### With [packer.nvim](https://github.com/wbthomason/packer.nvim)

```lua
use {
"StefanBartl/reposcope.nvim",
name = "reposcope",
event = ""VeryLazy,
requires = {
"nvim-lua/plenary.nvim",
"nvim-telescope/telescope.nvim",
},
config = function()
require("reposcope.init").setup({})
end,
}
```

---

## Configuration

`reposcope.nvim` is fully configurable. You can start with the defaults:

```lua
require("reposcope").setup({})
```

Or define a custom setup with fine-grained control:

```lua
require("reposcope").setup({
prompt_fields = {
"prefix", "owner", "keywords", "language", "topic", "stars"
}, -- Prompt fields shown to the user
provider = "github", -- Which backend to use: "github" (default), "gitlab" (planned)
request_tool = "curl", -- Tool for API requests: "gh", "curl", "wget"
layout = "default", -- Currently only "default" supported
github_token = os.getenv("GITHUB_TOKEN"), -- If higher API Limits neeeded set the token here. If that doesn't works: [Authentication](#authentication)
keymaps = {
open = "rs", -- Mapping to open the UI
close = "rc", -- Mapping to close the UI
},
clone = {
std_dir = "~/projects", -- Default directory to clone into
type = "git", -- Clone method: "git", "gh", "wget", "curl"
},
metrics = true, -- Enables request timing and logging (for debugging)
})
```

---

### Available Options

| Option | Type | Description |
| --------------- | ---------- | ------------------------------------------------------------------ |
| `prompt_fields` | `string[]` | Controls which input fields appear in the prompt UI |
| `provider` | `string` | Active backend (currently only `"github"` supported) |
| `request_tool` | `string` | CLI tool to fetch data: `"gh"`, `"curl"`, `"wget"` |
| `layout` | `string` | UI layout style (currently only `"default"`) |
| `keymaps.open` | `string` | Keymap to open Reposcope UI |
| `keymaps.close` | `string` | Keymap to close the UI cleanly |
| `clone.std_dir` | `string` | Base path for repository cloning |
| `clone.type` | `string` | Tool used to perform clone: `"git"`, `"gh"`, `"wget"`, or `"curl"` |
| `metrics` | `boolean` | Enable internal request logging and performance tracking |

> โ„น๏ธ You can dynamically reload prompt fields with `:ReposcopePromptReload prefix topic`.

---

## Usage

Launch Reposcope UI:

```vim
:ReposcopeStart
```

Or map it in your Neovim config:

```lua
vim.keymap.set("n", "rs", function()
vim.cmd("ReposcopeStart")
end, { desc = "Open Reposcope" })
```

### UI Keymaps

| Key | Mode | Action |
| ------------- | ---- | ------------------------------------- |
| `` | any | Close Reposcope UI |
| `/` | n/i | Navigate repository list |
| `` | n/i | View README in floating window |
| `` | n/i | Open README in editable hidden buffer |
| `` | n/i | Clone selected repository |
| `` | i | Cycle to next prompt field |
| `` | i | Cycle to previous prompt field |

---

### Available Commands

**UI Lifecycle & Prompt Configuration**

| Command | Description |
| ---------------------------- | ------------------------------------------------------------------- |
| `:ReposcopeStart` | Opens the Reposcope UI |
| `:ReposcopeClose` | Closes all Reposcope windows and buffers |
| `:ReposcopePromptReload ...` | Dynamically sets new prompt fields (e.g. `prefix`, `keywords`, ...) |

**Repository List: Sorting & Filtering**

| Command | Description |
| ------------------------------ | ---------------------------------------------------------------------- |
| `:ReposcopeSortPrompt` | Opens an interactive selection menu to choose a sort mode |
| `:ReposcopeFilterRepos {text}` | Filters the currently shown repositories by case-insensitive substring |
| `:ReposcopeFilterPrompt` | Opens a floating prompt window to input a filter string interactively |
| `:ReposcopeFilterClear` | Clears any active filter and restores the full list of repositories |

**Debugging, Stats & Metrics**

| Command | Description |
| -------------------------- | ------------------------------------------------------------------------ |
| `:ReposcopeToggleDev` | Toggles developer mode (enables debug logging, internal info, etc.) |
| `:ReposcopePrintDev` | Prints whether developer mode is currently active |
| `:ReposcopeSkippedReadmes` | Shows number of skipped README fetches (debounced during fast scrolling) |
| `:ReposcopeStats` | Displays collected request stats and metrics |

---

#### `:ReposcopePromptReload ...`

This user command updates the active prompt fields dynamically. It closes and reopens the Reposcope UI to apply the new configuration โ€” the specified fields will then appear in the prompt layout.

> ๐Ÿง  Prompt fields must be chosen from: `prefix`, `keywords`, `owner`, `language`, `topic`, `stars`.
> If no fields are given, it defaults to: `keywords`, `owner`, `language`.

Example:

```vim
:ReposcopePromptReload keywords topic "prompt without prefix: ๏€‚
:ReposcopePromptReload prefix topic stars "prompt with prefix, topice and stars field
:ReposcopePromptReload "resets to default
```

---

#### `:ReposcopeFilterRepos {text}`

Filters the current list of repositories using a case-insensitive substring
match.
The input is matched against the format: `owner/name: description`.

> If called without arguments, it resets the list to the original API result.

Examples:

```vim
:ReposcopeFilterRepos typescript bun "matches any repository with strings
:ReposcopeFilterRepos openai "filter by organization or description
:ReposcopeFilterRepos "clears filter and restores all results
```

---

#### `:ReposcopeFilterPrompt`

Opens a small floating input field where you can type a filter query.
The behavior is identical to `:ReposcopeFilterRepos`, but interactively.

Examples:

```vim
:ReposcopeFilterPrompt "opens floating input to enter 'react', 'api', etc.
```

> Press `` to confirm and filter; leave input empty to cancel.

---

## Authentication

`reposcope.nvim` works out of the box โ€” **no authentication is required** for basic usage.

However, if you want to use the `gh` CLI as your request backend, you **must** set a valid `GITHUB_TOKEN` manually:

```sh
export GITHUB_TOKEN=ghp_your_token_here
```

โš ๏ธ **Important:** Logged-in `gh` sessions (via `gh auth login`) are **not** accessible to child processes started via `uv.spawn()` inside Neovim. Without an explicit `GITHUB_TOKEN`, `gh`-based requests will silently fail.

As an alternative, you can use `curl` or `wget` without authentication โ€” but youโ€™ll have lower API rate limits.

---

### Recommended: Set it explicitly in `setup({ ... })`

In some systems or plugin managers, Neovim **does not inherit** environment variables defined in `.zshenv`, `.profile`, or GUI launch contexts.

To avoid issues, we recommend passing the token directly during setup:

```lua
require("reposcope").setup({
github_token = os.getenv("GITHUB_TOKEN") or "gh__example_token", -- Explicitly forward the env variable
...
})
```

This ensures the token is correctly passed to internal request handlers, regardless of how Neovim was started.

If you do not set a token, `curl` or `wget` will still work โ€” but you may hit GitHub's anonymous rate limits.

---

## Architecture Overview

```
reposcope/
โ”‚
โ”œโ”€โ”€ init.lua โ†’ Setup and UI lifecycle
โ”œโ”€โ”€ config.lua โ†’ User options and dynamic resolution
โ”œโ”€โ”€ ui/ โ†’ Modular UI: prompt, list, preview, background
โ”œโ”€โ”€ providers/ โ†’ GitHub (others coming soon)
โ”œโ”€โ”€ cache/ โ†’ In-memory and file-based caching
โ”œโ”€โ”€ controllers/ โ†’ Unified dispatch: readme, repositories, clone
โ”œโ”€โ”€ state/ โ†’ Buffers, windows, user input state
โ”œโ”€โ”€ network/ โ†’ HTTP clients and request tools (curl, gh, ...)
โ”œโ”€โ”€ utils/ โ†’ Debug, protection, encoding, os-tools
```

---

## Development & Debugging

* Use `:ReposcopePromptReload prefix topic` to dynamically reload prompt fields
* Use `require("reposcope.utils.debug").notify(...)` for developer output
* Toggle metrics in config: `metrics = true`
* Debug file paths and logs are stored in:
* `~/.local/share/nvim/reposcope/data/readme/`
* `~/.local/share/nvim/reposcope/logs/request_log.json`

---

## License

[MIT-License](./LICENSE)

---

## Contribution

Issues, suggestions and pull requests are welcome!
Clone, symlink into your Neovim config, and hack away.

```
git clone https://github.com/StefanBartl/reposcope.nvim ~/.config/nvim/reposcope.nvim
```

---