{"id":50647275,"url":"https://github.com/adriancmiranda/glimpse.nvim","last_synced_at":"2026-06-09T08:01:12.032Z","repository":{"id":358418300,"uuid":"1241204048","full_name":"adriancmiranda/glimpse.nvim","owner":"adriancmiranda","description":"🖼️ Fast multi-format file previewer with inline Kitty graphics support, external pane previews, and integrations for file explorers and pickers.","archived":false,"fork":false,"pushed_at":"2026-06-07T20:39:11.000Z","size":267,"stargazers_count":3,"open_issues_count":4,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-07T21:23:09.713Z","etag":null,"topics":["image-preview","iterm2","kitty-graphics","kitty-graphics-protocol","lua","neo-tree","neovim","neovim-plugin","oil-nvim","sixel","wezterm"],"latest_commit_sha":null,"homepage":"","language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/adriancmiranda.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-17T04:47:58.000Z","updated_at":"2026-06-05T04:09:14.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/adriancmiranda/glimpse.nvim","commit_stats":null,"previous_names":["adriancmiranda/glimpse.nvim"],"tags_count":28,"template":false,"template_full_name":null,"purl":"pkg:github/adriancmiranda/glimpse.nvim","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adriancmiranda%2Fglimpse.nvim","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adriancmiranda%2Fglimpse.nvim/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adriancmiranda%2Fglimpse.nvim/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adriancmiranda%2Fglimpse.nvim/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/adriancmiranda","download_url":"https://codeload.github.com/adriancmiranda/glimpse.nvim/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adriancmiranda%2Fglimpse.nvim/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34096955,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-09T02:00:06.510Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["image-preview","iterm2","kitty-graphics","kitty-graphics-protocol","lua","neo-tree","neovim","neovim-plugin","oil-nvim","sixel","wezterm"],"created_at":"2026-06-07T14:00:19.036Z","updated_at":"2026-06-09T08:01:12.026Z","avatar_url":"https://github.com/adriancmiranda.png","language":"Lua","funding_links":[],"categories":["File Explorer"],"sub_categories":["Assembly"],"readme":"\u003c!-- markdownlint-disable MD013 MD034 MD060 MD025 --\u003e\n\n# glimpse.nvim\n\n\u003e Fast multi-format file previewer with inline Kitty graphics support,\n\u003e external pane previews, and integrations for file explorers and pickers.\n\n\u003chttps://github.com/user-attachments/assets/686e39aa-1fa9-4a79-8a07-70ce5d4062bb\u003e\n\n## Features\n\n- 🖼️ Inline rendering via **Kitty Graphics Protocol** (Kitty, Ghostty)\n- 🎬 **Video preview** via ffmpeg thumbnail extraction (cached)\n- 📦 **Archive preview** - list contents of zip/tar without extraction\n- 🗄️ **SQLite preview** - show tables and columns without modifying the database\n- 💾 **Binary preview** - detect binaries with `file` and show a short `xxd` hexdump\n- 🪟 External pane via **WezTerm CLI**, **kitten icat**, **iTerm imgcat**\n- 🎨 **Font rendering** via ImageMagick, with a textual fallback when rendering is unavailable\n- 🎨 **Sixel** fallback for terminals without Kitty Graphics support\n- 📂 **Oil.nvim** integration (`\u003cleader\u003ep` for preview, `;` to open)\n- 🔭 **Telescope** integration (scoped previews for images, videos, archives, SQLite, fonts, keys, certificates, and binaries)\n- 🌳 **Neo-tree** integration\n- 🔐 **Certificate preview** - show subject, issuer, validity, and\n  fingerprint for `.crt`/`.pem`\n- ⚡ Image conversion cache + background prefetch\n- 🔄 Auto re-render on window resize or tab switch\n- 📐 Contain resize (images always fully visible)\n\n## Requirements\n\n- Neovim \u003e= 0.10\n- [ImageMagick](https://imagemagick.org/) (`magick` CLI) - inline image conversion and font rendering\n- [ffmpeg](https://ffmpeg.org/) (optional) - video thumbnail extraction\n- [OpenSSL](https://www.openssl.org/) (`openssl` CLI) - certificate metadata extraction\n- [file](https://man7.org/linux/man-pages/man1/file.1.html) (`file` CLI) - binary type detection\n- [xxd](https://vimhelp.org/xxd.txt.html) (`xxd` CLI) - binary hexdump rendering\n- Terminal with support for at least one protocol:\n  - **Kitty Graphics** (recommended): Kitty, Ghostty\n  - **Terminal CLI**: WezTerm, iTerm2\n  - **Sixel**: xterm, foot, mlterm, contour\n\n\u003e [!NOTE]\n\u003e `magick` is required for inline image rendering and font rendering. Font preview still has a textual fallback if rendering is unavailable.\n\n### Feature Dependencies\n\n| Feature | Dependency | Required |\n|---|---|---|\n| Inline image preview | `magick` | Yes |\n| Font rendering | `magick` | Yes, with textual fallback if unavailable |\n| Video preview | `ffmpeg` | No |\n| Archive preview | `zipinfo`, `tar` | Yes when the archive type is used |\n| SQLite preview | `sqlite3` | Yes when the SQLite preview is used |\n| Certificate preview | `openssl` | Yes when the certificate preview is used |\n| Binary preview | `file`, `xxd` | Yes when the binary preview is used |\n| SSH/GPG key preview | `ssh-keygen`, `gpg` | Yes when the key preview is used |\n\n## Installing dependencies\n\n\u003e [!NOTE]\n\u003e Binary preview depends on `file` and `xxd`. They are usually available on Unix-like systems, but if your OS does not ship them by default, install them separately.\n\n### macOS (Homebrew)\n\n```bash\nbrew install imagemagick ffmpeg\n```\n\n### Linux (apt)\n\n```bash\nsudo apt install imagemagick ffmpeg\n```\n\n### Linux (pacman)\n\n```bash\nsudo pacman -S imagemagick ffmpeg\n```\n\n### Verify installation\n\n```bash\nmagick --version\nfile --version\nxxd -h\n```\n\n## Usage\n\n### Setup (lazy.nvim)\n\n```lua\n{\n  'adriancmiranda/glimpse.nvim',\n  ft = { 'oil', 'neo-tree' },\n  event = {\n    'BufReadPre *.png', 'BufReadPre *.jpg', 'BufReadPre *.jpeg',\n    'BufReadPre *.gif', 'BufReadPre *.bmp', 'BufReadPre *.webp',\n    'BufReadPre *.avif', 'BufReadPre *.svg', 'BufReadPre *.pdf',\n    'BufReadPre *.ttf', 'BufReadPre *.otf',\n    'BufReadPre *.crt', 'BufReadPre *.pem',\n    'BufReadPre *.zip', 'BufReadPre *.tar', 'BufReadPre *.tgz',\n    'BufReadPre *.jar', 'BufReadPre *.war', 'BufReadPre *.apk',\n    'BufReadPre *.db', 'BufReadPre *.sqlite', 'BufReadPre *.sqlite3',\n  },\n  opts = {\n    strategy = 'auto',        -- 'auto' | 'inline' | 'pane'\n    pane = {\n      position = 'right',     -- 'right' | 'bottom'\n      size = 40,              -- split/pane size percentage\n    },\n    inline = {\n      rerender_on_tab = true, -- re-render when switching back to image tab\n      close_with_q = true,    -- map key to close image buffer\n    },\n    keys = {\n      preview = '\u003cleader\u003ep',  -- preview image/video side by side (Oil)\n      open = ';',             -- open image (configurable: current tab or new tab) (Oil)\n      close = 'q',            -- close image buffer\n    },\n    debounce = {\n      prefetch = 200,         -- ms before pre-converting on cursor move\n      resize = 100,           -- ms before re-rendering on resize\n    },\n    cell_size = {\n      width = 20,             -- estimated pixels per terminal column\n      height = 40,            -- estimated pixels per terminal row\n    },\n    cache = {\n      dir = vim.fn.stdpath('cache') .. '/glimpse',\n      max_age_days = 7,      -- auto-remove cached files older than N days (0 to disable)\n    },\n    safety = {\n      max_file_size = 50 * 1024 * 1024, -- skip files larger than 50MB\n    },\n    loading = {\n      text = '  ⏳ Loading...',\n    },\n    image = {\n      formats = {            -- supported image extensions\n        '.png', '.jpg', '.jpeg', '.gif', '.bmp',\n        '.webp', '.avif', '.svg', '.pdf', '.pict',\n      },\n    },\n    video = {\n      formats = {            -- supported video extensions (requires ffmpeg)\n        '.mp4', '.mkv', '.avi', '.mov',\n        '.webm', '.flv', '.wmv', '.m4v',\n      },\n      open = nil,            -- command or function to open videos externally\n                              -- string: 'open' (macOS), 'xdg-open' (Linux)\n                              -- function: fun(filepath) for custom logic\n                              -- nil: opens as buffer in Neovim\n    },\n    archive = {\n      formats = {            -- supported archive extensions (preview only, no extraction)\n        '.zip', '.tar', '.tar.gz', '.tgz',\n        '.tar.bz2', '.tar.xz', '.txz',\n        '.jar', '.war', '.apk',\n      },\n    },\n    integrations = {\n      oil = {\n        enable = true,        -- keymaps in Oil\n        open = 'edit',        -- 'edit' | 'tabedit' | function(filepath)\n      },\n      neotree = {             -- Neo-tree integration\n        enable = false,       -- enable auto-preview in Neo-tree\n        auto_preview = true,  -- preview on cursor move (set false to disable)\n      },\n      telescope = {\n        enable = true,        -- enables image/video previews in :Telescope find_files\n      },\n    },\n  },\n}\n```\n\nBreaking change: the public config was reorganized into nested tables.\n\n### Keymaps (Oil.nvim)\n\n| Key | Action |\n|-----|--------|\n| `\u003cleader\u003ep` | Preview image/video side by side (reuses window) |\n| `;` | Open image (configurable: current tab or new tab) |\n| `q` | Close image buffer and residual empty window |\n\nWhen an image is opened, the current window follows that file's directory, so `Oil.nvim` opens in the same folder.\n\n### Keymaps (Neo-tree)\n\nEnable with `integrations = { neotree = { enable = true } }` in setup.\n\n| Key | Action |\n|-------|------|\n| `\u003cleader\u003ep` | Preview image/video side by side |\n| `;` | Open image inline or video with external player |\n\n### Telescope\n\nEnable with `integrations = { telescope = { enable = true } }` in setup. With lazy.nvim,\nglimpse applies its previewer when telescope.nvim loads. By default, only\n`:Telescope find_files` receives Glimpse previews.\n\n```lua\nrequire('glimpse').setup({\n  integrations = {\n    telescope = {\n      enable = true,\n    },\n  },\n})\n```\n\nTo choose the Telescope pickers that receive Glimpse previews:\n\n```lua\nrequire('glimpse').setup({\n  integrations = {\n    telescope = {\n      enable = true,\n      pickers = { 'find_files', 'git_files' },\n    },\n  },\n})\n```\n\nTo disable specific preview kinds inside Telescope while keeping the integration\nenabled:\n\n```lua\nrequire('glimpse').setup({\n  integrations = {\n    telescope = {\n      enable = true,\n      pickers = { 'find_files', 'git_files' },\n      image = true,\n      video = true,\n      archive = true,\n      sqlite = false,\n      font = false,\n      cert = true,\n      key = true,\n      binary = false,\n    },\n  },\n})\n```\n\nIf you prefer configuring Telescope manually, use the exported previewer:\n\n```lua\nrequire('telescope').setup({\n  pickers = {\n    find_files = {\n      previewer = require('glimpse.integrations.telescope').previewer(),\n    },\n  },\n})\n```\n\n- **Images** are rendered inline via Kitty Graphics Protocol with a 100ms debounce\n- **Videos** extract a thumbnail via ffmpeg before rendering\n- **Archives, SQLite databases, fonts, keys, certificates, and binaries** use the matching Glimpse previewer inside the Telescope preview pane\n- **Other files** fall back to Telescope's default previewer\n\nSwitching between files is fast after thumbnails and conversions are cached.\n\n### API\n\n```lua\nlocal img = require('glimpse')\n\nimg.can_preview(filepath)    -- check whether Glimpse knows how to preview it\nimg.get_preview_kind(filepath) -- return the preview kind that would be used\nimg.show(filepath)           -- show image or video thumbnail\nimg.preview(filepath)        -- show reusing existing window\nimg.close()                  -- close active preview\nimg.is_image(filepath)       -- check if supported image\nimg.is_video(filepath)       -- check if supported video\nimg.is_archive(filepath)     -- check if supported archive\nimg.is_sqlite(filepath)      -- check if supported SQLite database\nimg.is_previewable(filepath) -- check if supported previewable file\nimg.is_cert(filepath)        -- check if supported certificate\nimg.is_font(filepath)        -- check if supported font\nimg.is_key(filepath)         -- check if supported GPG/SSH key\nimg.get_terminal()           -- return detected terminal\nimg.supports_inline()        -- check whether inline rendering is supported\nimg.in_tmux()                -- check whether Neovim runs inside tmux\n```\n\n## Security \u0026 Privacy\n\nglimpse.nvim runs **only local commands** on files you explicitly select.\nIt never makes network requests or sends data externally.\n\n\u003e [!IMPORTANT]\n\u003e The plugin only uses local tools on files you explicitly select. When a tool is missing, the affected previewer fails safely instead of breaking the rest of the plugin.\n\n### File validation\n\n- **Symlinks** are rejected (prevents reading unintended targets)\n- **Large files** above `safety.max_file_size` are skipped (default: 50MB)\n- **SVG files** are processed with restricted XML parsing (no entity expansion, no external resources)\n- **Archive preview** never extracts files, only reads metadata\n- **Shell commands** use list arguments (no shell interpolation)\n\n### External tools used\n\n| Tool | Purpose | When |\n|------|---------|------|\n| magick (ImageMagick) | Image resize/conversion | Image preview |\n| ffmpeg | Video thumbnail extraction | Video preview |\n| openssl | X.509 certificate metadata extraction | Certificate preview |\n| zipinfo | Archive listing (read-only) | Archive preview |\n| tar | Archive listing (read-only) | tar/tgz preview |\n| sqlite3 | Schema listing (read-only) | SQLite preview |\n\nNo files are extracted, modified, or uploaded. All processing is local and read-only.\n\n\u003c!-- markdownlint-disable MD033 --\u003e\n\u003cdetails\u003e\n\u003csummary\u003eOptional: ImageMagick resource policy\u003c/summary\u003e\n\nOptional extra protection: place this in `~/.config/ImageMagick/policy.xml`.\n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\u003c!DOCTYPE policymap [\n  \u003c!ELEMENT policymap (policy)*\u003e\n  \u003c!ATTLIST policymap xmlns CDATA #FIXED \"\"\u003e\n  \u003c!ELEMENT policy EMPTY\u003e\n  \u003c!ATTLIST policy xmlns CDATA #FIXED \"\"\u003e\n  \u003c!ATTLIST policy domain NMTOKEN #REQUIRED\u003e\n  \u003c!ATTLIST policy name NMTOKEN #IMPLIED\u003e\n  \u003c!ATTLIST policy pattern CDATA #IMPLIED\u003e\n  \u003c!ATTLIST policy rights NMTOKEN #IMPLIED\u003e\n  \u003c!ATTLIST policy stealth NMTOKEN #IMPLIED\u003e\n  \u003c!ATTLIST policy value CDATA #IMPLIED\u003e\n]\u003e\n\u003cpolicymap\u003e\n  \u003cpolicy domain=\"resource\" name=\"memory\" value=\"256MiB\"/\u003e\n  \u003cpolicy domain=\"resource\" name=\"map\" value=\"512MiB\"/\u003e\n  \u003cpolicy domain=\"resource\" name=\"disk\" value=\"1GiB\"/\u003e\n  \u003cpolicy domain=\"resource\" name=\"time\" value=\"30\"/\u003e\n  \u003cpolicy domain=\"resource\" name=\"thread\" value=\"2\"/\u003e\n  \u003cpolicy domain=\"resource\" name=\"list-length\" value=\"64\"/\u003e\n  \u003c!--\n  \"area\" is an extra safety limit and may block very large images.\n  If Glimpse starts rejecting legitimate previews, remove or\n  increase it.\n  --\u003e\n  \u003cpolicy domain=\"resource\" name=\"area\" value=\"100MP\"/\u003e\n\u003c/policymap\u003e\n```\n\n\u003c/details\u003e\n\u003c!-- markdownlint-enable MD033 --\u003e\n\n## Supported terminals\n\n| Terminal | Strategy | Method |\n|----------|----------|--------|\n| Kitty | inline | Kitty Graphics + unicode placeholders |\n| Ghostty | inline | Kitty Graphics + unicode placeholders |\n| WezTerm | pane | `wezterm cli split-pane` + `wezterm imgcat` |\n| iTerm2 | pane | `imgcat` |\n| xterm/foot/mlterm | pane (sixel) | `magick ... sixel:-` via tmux |\n\n### WezTerm + tmux\n\n`wezterm cli` needs access to the WezTerm GUI socket. Inside tmux, the\n`WEZTERM_UNIX_SOCKET` variable can become stale if WezTerm restarts.\n\nAdd to `tmux.conf`:\n\n```bash\nset -ga update-environment WEZTERM_UNIX_SOCKET\n```\n\nIf preview stops working, update manually:\n\n```bash\n# Find the active socket\nls ~/.local/share/wezterm/gui-sock-*\n\n# Export the correct one\ntmux set-environment WEZTERM_UNIX_SOCKET ~/.local/share/wezterm/gui-sock-\u003cPID\u003e\n```\n\n## Supported formats\n\n**Images:** PNG, JPG, JPEG, GIF, BMP, WebP, AVIF, SVG, PDF, PICT\n\n**Certificates:** CRT, PEM (X.509 certificates)\n\n**Videos:** MP4, MKV, AVI, MOV, WebM, FLV, WMV, M4V (requires ffmpeg)\n\n## Architecture\n\n```bash\nlua/\n├── glimpse/\n│   ├── init.lua              -- Public API: setup(), show(), preview(), close(), helpers\n│   ├── detect.lua            -- Terminal detection via tmux client_termname\n│   ├── kitty.lua             -- Kitty Graphics Protocol (transmit, delete, prefetch)\n│   ├── renderer.lua          -- Placement management and extmarks\n│   ├── sixel.lua             -- Sixel protocol (fallback)\n│   ├── thumbnail.lua         -- Video thumbnail extraction (ffmpeg, async)\n│   ├── magickwand.lua        -- FFI bindings for libMagickWand\n│   ├── util.lua              -- Image, video and certificate format detection\n│   ├── archive.lua           -- Archive listing and suspicious path detection\n│   ├── font.lua              -- Font metadata extraction and rendering\n│   ├── sqlite.lua            -- SQLite schema preview\n│   ├── safety.lua            -- File validation and safety checks\n│   ├── previewer/\n│   │   ├── archive.lua       -- Archive previewer\n│   │   ├── cert.lua          -- X.509 certificate previewer\n│   │   ├── binary.lua        -- Binary previewer (file + hexdump)\n│   │   ├── font.lua          -- Font previewer\n│   │   ├── image.lua         -- Inline image previewer\n│   │   ├── key.lua           -- GPG/SSH key previewer\n│   │   └── sqlite.lua        -- SQLite previewer\n│   ├── strategy/\n│   │   ├── inline.lua        -- Inline rendering + autocmds\n│   │   └── pane.lua          -- External pane rendering (WezTerm, iTerm2)\n│   └── integrations/\n│       ├── oil.lua           -- Oil.nvim integration\n│       ├── neotree.lua       -- Neo-tree integration (auto-preview)\n│       └── telescope.lua     -- Telescope integration (scoped picker preview)\n```\n\n## Credits\n\n- [snacks.nvim](https://github.com/folke/snacks.nvim) - inspiration for the rendering protocol\n- [Yazi](https://github.com/sxyazi/yazi) - inspiration for performance optimizations\n- [Reddit post](https://www.reddit.com/r/neovim/comments/1e1txpz/) - original WezTerm preview concept\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadriancmiranda%2Fglimpse.nvim","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fadriancmiranda%2Fglimpse.nvim","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadriancmiranda%2Fglimpse.nvim/lists"}