显示 HN:在 Emacs 中浏览 GitHub 仓库,无需克隆。
Show HN: Browse GitHub repos in Emacs without cloning

原始链接: https://github.com/agzam/remoto.el

## Remoto.el:在Emacs中直接浏览GitHub仓库 Remoto.el 允许你在Emacs中*无需*克隆即可浏览任何GitHub仓库。它通过注册一个虚拟文件系统来实现,将标准的Emacs文件操作(如`find-file`和`dired`)转换为通过`gh` CLI调用GitHub API。 这对于快速查看代码、README文件或项目结构,而无需下载整个仓库的开销非常理想。它是只读的,利用GitHub的API进行身份验证并透明地处理私有仓库。 主要功能包括:缓存的目录树以实现快速浏览、按需获取文件内容,以及在`dired`和`find-file`中自动检测GitHub URL。该包尚未发布到MELPA,但可通过Straight获取。 Remoto.el 避免使用TRAMP,因为它过于复杂且不适合无状态REST API,而是选择通过Emacs的`file-name-handler-alist`进行更高效、更直接的集成。目前仅限于GitHub,但计划未来支持其他代码托管平台。

一个新Emacs包允许用户在Emacs的Dired模式中直接浏览GitHub仓库,*无需*克隆。该包在Hacker News上分享,允许用户在文件查找命令()中输入GitHub URL并浏览仓库的文件。 讨论集中在包是否*需要*使用GitHub API。虽然有人建议使用HTTP或SSH等替代方案,但开发者解释说,API对于访问私有仓库、列出子目录(原始GitHub URL不支持)、分支列表和仓库搜索等功能是必要的。 使用Git自身的协议进行浏览会更加复杂,基本上需要重新实现Git的部分功能。目前的基于API的方法更有效地一次性浏览整个树形结构。还提供了一个指向r/emacs相关讨论的链接。
相关文章

原文

El Remoto logo

https://github.com/agzam/remoto.el/actions/workflows/run-tests.yml/badge.svg

El Remoto - browse any GitHub repository in Emacs without cloning it.

./test/demo.gif

remoto.el registers a virtual filesystem via file-name-handler-alist that translates standard Emacs file operations into GitHub API calls via the gh CLI. The result: find-file, dired, tab-completion, dired-subtree - all standard Emacs file tooling works against a remote GitHub repo. Read-only.

Sometimes you just want to look at code. Check a function signature, read a README, browse a project structure. Cloning a repo for that is overkill - it takes disk space, creates another directory to manage, and breaks your flow.

For now it works only with GitHub repos. Future plans include support for other forges - GitLab, Codeberg, etc.

You need to load the package so it can register its file handler and advice.

(use-package remoto
  :straight (:host github :repo "agzam/remoto.el")
  :demand t)

The package is not on MELPA yet. Maybe upvote the submission PR, who knows, perhaps it gets accepted faster.

The main entry point. Accepts any GitHub URL format:

M-x remoto-browse RET https://github.com/torvalds/linux RET
M-x remoto-browse RET [email protected]:torvalds/linux.git RET
M-x remoto-browse RET torvalds/linux RET

GitHub URLs are detected automatically in dired and find-file:

C-x d /github.com/torvalds/linux RET
C-x C-f https://github.com/torvalds/linux/blob/master/README RET

The virtual filesystem uses paths of the form:

/github:OWNER/REPO@REF:/PATH

REF is optional - omitting it uses the repo’s default branch.

CommandDescription
remoto-browsePrompt for a repo, open dired at root
remoto-refreshClear tree cache for current repo, re-fetch
remoto-copy-github-urlCopy github.com URL for current file/line to kill ring
  1. On first access to any file in a repo, the full directory tree is fetched via the Git Trees API (one HTTP call).
  2. Directory listings, file-exists-p, completions - all served from the cached tree in memory.
  3. File contents are fetched on demand when you actually open a file.
  4. Content is cached by SHA, so re-opening the same file is instant.
  5. Authentication, SSO, private repos - all handled transparently by gh.

Why this isn’t a TRAMP backend?

  • TRAMP fundamentally is a shell-over-transport abstraction. Every TRAMP backend assumes a remote shell on the other end, remoto.el has no remote shell.
  • TRAMP’s backend API is large. You’d need to implement or stub dozens of operations, many of which assume concepts that don’t map to a REST API (process execution, file ownership, symlink resolution, timestamps).
  • TRAMP’s connection management (open/close/reuse) is built around persistent sessions. The GitHub API is stateless HTTP - there’s no connection to manage.
  • TRAMP’s caching layer is path-based and per-connection. remoto’s tree cache (one API call fetches the entire repo tree, then everything is served from memory) is a fundamentally different - and much more efficient - model for a read-only tree-structured API.
  • file-name-handler-alist IS the same mechanism TRAMP uses. Registering there directly gives you the same integration (dired, find-file, completions) without the framework overhead.

For a read-only tree browser backed by a REST API, a direct file-name-handler is the simpler, more natural fit

Why not just use plain HTTP?

Git’s own protocols let you talk to a remote repo without cloning it, so why not use that, right?

  • Tree listing. There’s no raw HTTP URL that gives you a directory listing. raw.githubblabla.com can’t do directory indexes. You’d have to shell out to `git ls-tree … etc.` over the ssh, which means essentially implementing a partial git client.
  • Branch listing and repo search - no git protocol equivalent for those - need the API
  • Current approach fetches the entire tree in one API call. Doing the same over git pack protocol means negotiating a fetch, receiving packfile data and parsing it. Much heavier, much more code.

We can only imagine a world where git’s transport layer gives you a browsable filesystem interface. It doesn’t - git’s protocols are optimized for syncing object graphs, not random-access file browsing.

  • Read-only. No commits, no pushes, no file modifications.
  • No git operations (log, blame, diff).
  • Timestamps in dired are synthetic (the tree API has no timestamps).
  • Very large repos (100k+ files) use slower per-directory fetching.
  • Rate limit: 5,000 requests/hour (normal browsing stays well within this).
联系我们 contact @ memedata.com