结构化内容浏览工具

gopher-cli是一个多源结构化内容浏览工具,支持本地文件、RSS/Atom订阅、RDF知识图谱和Gopher服务器,提供CLI和TUI界面。

  • by penserai
  • Rust
  • 本地部署
  • 更新于
在 GitHub 查看 penserai/gopher-mcp

使用说明

gopher-cli

面向人类和代理的结构化内容发现。浏览本地文件, RSS/Atom提要、RDF知识图和Gopher服务器通过 单个CLI和TUI——不需要服务器。

       ┌───────┐     ┌───────┐     ┌────────┐     ┌───────┐
   ^   │ files │  ^  │ feeds │  ^  │ graphs │  ^  │  :70  │   ^
  /|\  └───┬───┘ /|\ └───┬───┘ /|\ └────┬───┘ /|\ └───┬───┘  /|\
  ~~~~~~~~~│~~~~~~~~~~~~~│~~~~~~~~~~~~~~│~~~~~~~~~~~~~~│~~~~~~~~~
  ░░░░░░░░░│░░░░░░░░░░░░░│░░░░░░░░░░░░░░│░░░░░░░░░░░░░░│░░░░░░░
  ░░░░┌────┘░░░░░░░┌─────┘░░░░░░░░┌─────┘░░░░░░░░┌─────┘░░░░░░░
  ░░░░│░░░░░░░░░░░░│░░░░░░░░░░░░░░│░░░░░░░░░░░░░░│░░░░░░░░░░░░░
  ░░░░└─────┐░░░░░░└──────┐░░░░░░░└──────┐░░░░░░░│░░░░░░░░░░░░░
  ░░░░░░░░░░└─────────────┴──────────────┴───────┘░░░░░░░░░░░░░
  ░░░░░░░░░░░░░░░░░░░░░░░░░│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  ░░░░░░░░░░░░░░░░░░░░░░░>(•.•)>░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  ░░░░░░░░░░░░░░░░░░░░░░░░░│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  ░░░░░░░░░░░░░░░░░┌───────┴───────┐░░░░░░░░░░░░░░░░░░░░░░░░░░░
  ░░░░░░░░░░░░░░░░░│  ◊  V A U L T │░░░░░░░░░░░░░░░░░░░░░░░░░░░
  ░░░░░░░░░░░░░░░░░│  publish  ↓↑  │░░░░░░░░░░░░░░░░░░░░░░░░░░░
  ░░░░░░░░░░░░░░░░░│  delete   ×   │░░░░░░░░░░░░░░░░░░░░░░░░░░░
  ░░░░░░░░░░░░░░░░░│  browse   ☰   │░░░░░░░░░░░░░░░░░░░░░░░░░░░
  ░░░░░░░░░░░░░░░░░│  fetch    ◆   │░░░░░░░░░░░░░░░░░░░░░░░░░░░
  ░░░░░░░░░░░░░░░░░│  search   ⌕   │░░░░░░░░░░░░░░░░░░░░░░░░░░░
  ░░░░░░░░░░░░░░░░░└───────────────┘░░░░░░░░░░░░░░░░░░░░░░░░░░░
  ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░

它的作用

使用以下命令将所有数据源投影到统一的菜单/文档层次结构中 Gopher内容模型。路径遵循以下格式 namespace/selector (例如。, local/welcome, feed.hackernews/, vault/notes/idea.md).

来源 示例 工作原理
文件系统 特工金库,杰基尔 _posts/,任何目录树 目录变成菜单,文本文件变成文档。可写命名空间支持发布/删除。
RSS/Atom 黑客新闻,博客提要 提要条目成为频道菜单下的文档
RDF/SPARQL 知识图、DBpedia、本地Turtle文件 类变成菜单,资源变成文档,SPARQL支持搜索
Gopher服务器 gopher.floodgap.com 透明TCP代理到实时Gopherspace

快速开始

# Build
cargo build -p gopher-cli --release

# Browse all namespaces
gopher-cli browse

# Browse a namespace
gopher-cli browse local/

# Read a document
gopher-cli fetch local/welcome

# Launch the interactive TUI
gopher-cli

安装

来源

git clone https://github.com/penserai/gopher-cli.git
cd gopher-cli
cargo install --path gopher-cli

交叉编译

make build              # Release build for host (darwin-arm64)
make build-darwin-arm64 # aarch64-apple-darwin
make build-darwin-x86   # x86_64-apple-darwin
make build-linux-arm64  # aarch64-unknown-linux-gnu (requires cross)
make build-linux-x86    # x86_64-unknown-linux-gnu (requires cross)
make build-all          # All architectures

达尔文目标使用本地 cargo build.Linux目标使用 cross (基于Docker)。二进制输出到 dist/.

命令行界面

CLI是人类和代理的主要界面。它嵌入了 全内容引擎——不需要服务器进程。

命令

gopher-cli browse [path]                  List items at a path
gopher-cli fetch <path>                   Retrieve document content
gopher-cli search <path> <query>          Search within a namespace
gopher-cli publish <path> [--content ..]  Write a document
gopher-cli delete <path>                  Delete a document
gopher-cli dump <source> <dest>           Bulk-copy between namespaces
gopher-cli [tui]                          Launch interactive browser

输出格式

当stdout被管道化时,输出自动为JSON(用于脚本和代理)。 在TTY上,输出是人性化的文本。随时强制JSON --json.

# Human — sees formatted text
gopher-cli browse local/
# [T] Welcome to gopher-cli                    local/welcome
#       -----------------------
# [+] Submenu Example                          local/sub

# Agent — stdout piped, gets JSON automatically
result=$(gopher-cli browse local/)
echo "$result"
# [{"type":"0","type_name":"TextFile","display":"Welcome to gopher-cli", ...}, ...]

浏览

列出路径中的项目。在没有路径的情况下,列出所有可用的命名空间。

gopher-cli browse                       # all namespaces
gopher-cli browse local/                # items in a namespace
gopher-cli browse local/sub             # subdirectory
gopher-cli browse gopher.floodgap.com/  # live Gopher server

获取

检索文档的文本内容。

gopher-cli fetch local/welcome
gopher-cli fetch feed.hackernews/entry/0
gopher-cli fetch gopher.floodgap.com/gopher/tech/
gopher-cli fetch feed.hackernews/entry/0 > article.txt  # save to file

搜索

在命名空间内搜索。按查询字符串过滤菜单项;适配器 使用本地搜索(RDF/SPARQL)使用自己的引擎。

gopher-cli search local/ "welcome"
gopher-cli search feed.hackernews/ "rust"
gopher-cli search gopherpedia.com/ "gopher protocol"

发布

编写或更新文档。从以下位置读取内容 --content 或stdin。仅 处理可写命名空间(例如。, vault).

# Inline content
gopher-cli publish vault/notes/idea.md --content "# My Idea
This could work."

# From stdin
echo "Quick note" | gopher-cli publish vault/scratch.md

# Pipe from another command
gopher-cli fetch feed.hackernews/entry/0 | gopher-cli publish vault/saved/hn-top.md

删除

从可写命名空间中删除文档或目录。

gopher-cli delete vault/notes/idea.md

转储

将文档从源递归复制到可写命名空间中。走 菜单最多 --max-depth 级别(默认值:3)。

gopher-cli dump feed.hackernews/ vault/mirrors/hn
gopher-cli dump rdf.demo/ vault/mirrors/rdf --max-depth 2
gopher-cli dump gopher.floodgap.com/gopher/tech vault/mirrors/floodgap-tech

全局选项

选项 环境变量 描述
--url <URL> GOPHER_CLI_URL 连接到远程服务器而不是嵌入式引擎
--no-seed 跳过将示例内容播种到 local 命名空间
--json 强制JSON输出(当stdout通过管道传输时自动启用)

连接优先级

CLI默认为嵌入式引擎。要连接到远程服务器,请执行以下操作:

  1. --url 标志(最高优先级)
  2. GOPHER_CLI_URL 环境变量
  3. url 领域 ~/.gopher-cli.toml
  4. 嵌入式引擎(默认设置——无需服务器)
# One-off remote command
gopher-cli --url http://localhost:8443 browse

# Set for the whole session
export GOPHER_CLI_URL=http://localhost:8443
gopher-cli browse

退出代码

代码 含义
0 成功
1 错误(stderr的详细信息,管道传输时为结构化JSON)

文本用户界面

交互式终端浏览器。未给出子命令时启动。

gopher-cli                  # start at root
gopher-cli tui               # explicit
gopher-cli tui local/        # start at a specific path

键绑定

关键 行动
j/k 或箭头 导航菜单
Enter 打开项目
b 或 Backspace 回去吧
Tab 切换窗格(菜单/内容)
Space 向下翻页(内容窗格)
PgUp/PgDn 滚动内容
/ 在当前命名空间内搜索
: GoTo弹出窗口(跳转到任何命名空间)
Tab (在GoTo中) 展开/折叠目录
Home 转到root
q 退出

代理使用

CLI的构建使AI代理可以使用Bash工具调用而不是MCP。 自动JSON输出、结构化错误、管道友好发布和可组合 命令意味着代理可以仅使用Bash工具与gopher-cli一起工作。

发现

# What namespaces are available?
gopher-cli browse

# What's in a namespace?
gopher-cli browse vault/

# Drill into a directory
gopher-cli browse vault/research/

阅读

# Get a document
gopher-cli fetch vault/research/topic.md

# Search then read the first result
gopher-cli search vault/ "machine learning"
gopher-cli fetch vault/research/ml-overview.md

写

# Save a note
gopher-cli publish vault/notes/idea.md --content "# Idea
Something interesting."

# Pipe content from another source
gopher-cli fetch feed.hackernews/entry/3 \
  | gopher-cli publish vault/saved/article.md

批量操作

# Copy all articles from a feed into the vault
gopher-cli dump feed.hackernews/ vault/mirrors/hn

# Verify what was copied
gopher-cli browse vault/mirrors/hn/

JSON输出引用

浏览/搜索 返回一个项目数组:

[
  {
    "type": "1",
    "type_name": "Menu",
    "display": "Submenu Example",
    "path": "local/sub",
    "mime": "application/x-gopher-menu"
  }
]

获取 返回路径和内容:

{ "path": "local/welcome", "content": "Document text here..." }

发布/删除 返回确认:

{ "ok": true, "path": "vault/notes/idea.md", "action": "published" }

转储 返回计数:

{ "ok": true, "source": "feed.hackernews/", "destination": "vault/mirrors/hn", "published": 15, "skipped": 2 }

错误 (在stderr上):

{ "error": "Fetch failed: Selector not found: /missing in local" }

物品类型

type type_name 含义
1 菜单 目录--传递到 browse
0 TextFile 文档--传递给 fetch
7 搜索 搜索端点--传递给 search
h Html Html文档--传递给 fetch
i 信息 仅显示文本(无路径)

配置

地点: ~/.gopher-cli.toml。由CLI命令和TUI使用。

# Remote mode — uncomment to connect to a running gopher-cli-server.
# url = "http://127.0.0.1:8443"

# Gopherspace sources (shown in the TUI GoTo popup)
sources = [
    "gopher.floodgap.com/",
    "gopher.quux.org/",
    "cosmic.voyage/",
]

# RSS / Atom feed
[[adapter]]
type = "rss"
namespace = "feed.hackernews"
url = "https://hnrss.org/frontpage"

# File system directory (writable = agent vault)
[[adapter]]
type = "fs"
namespace = "vault"
root = "/path/to/vault"
writable = true

# File system directory (read-only)
[[adapter]]
type = "fs"
namespace = "docs"
root = "/path/to/notes"
extensions = ["md", "txt"]

# RDF knowledge graph
[[adapter]]
type = "rdf"
namespace = "rdf.dbpedia"
sparql_endpoint = "https://dbpedia.org/sparql"
format = "turtle"

适配器类型

类型 必填字段 可选字段
rss namespace, url
fs namespace, root extensions (例如。, ["md", "txt"]), writable (bool)
rdf namespace source (文件或URL), format, sparql_endpoint

适配器在启动时将其内容同步到嵌入式引擎中。适配器 命名空间会自动添加到TUI GoTo弹出窗口中。

服务器

对于需要持久HTTP端点的用例(例如MCP集成 使用支持JSON-RPC的AI工具)。

# Generate dev certificates
./scripts/gen-certs.sh

# Run with mTLS
cargo run -p gopher-cli-server

# Run without TLS (development)
cargo run -p gopher-cli-server -- --no-tls

# Run with adapters
cargo run -p gopher-cli-server -- --no-tls --config examples/rss-demo.toml

将CLI指向服务器:

gopher-cli --url http://127.0.0.1:8443 browse local/

服务器公开了所有六个操作(浏览、获取、搜索、发布、, 删除、转储)作为MCP工具通过JSON-RPC在 /mcp,可选mTLS 用于相互认证。

建筑

带有三个板条箱的货物工作区:

板条箱 类型 描述
gopher-cli-core 库 内容路由器、本地存储、Gopher客户端、MCP处理程序、源适配器特性
gopher-cli 二进制 CLI+TUI。嵌入核心引擎。独立的单二进制文件。
gopher-cli-server 带mTLS的二进制 最大HTTP服务器。当您需要持久服务器进程时使用。
├── gopher-cli-core/           # library crate
│   └── src/
│       ├── lib.rs              # public re-exports
│       ├── router.rs           # content router (local store + Gopher proxy)
│       ├── store.rs            # in-memory content store (namespaces, menus, docs)
│       ├── gopher.rs           # Gopher client, ItemType, MenuItem
│       ├── mcp.rs              # MCP JSON-RPC handler and tool definitions
│       └── adapters/           # SourceAdapter trait + fs, rss, rdf adapters
├── gopher-cli/                # CLI + TUI binary
│   └── src/
│       ├── main.rs             # subcommands, embedded/remote startup
│       ├── cli.rs              # CLI command handlers, auto-JSON output
│       ├── client.rs           # ContentClient trait, McpClient, EmbeddedClient
│       ├── config.rs           # config file parsing, adapter creation
│       ├── app.rs              # TUI application state and logic
│       └── ui.rs               # ratatui rendering
└── gopher-cli-server/         # HTTP server binary
    └── src/
        ├── main.rs             # axum wiring, adapter sync, startup
        ├── config.rs           # server config parsing
        └── tls.rs              # mTLS certificate handling

内容模型

内容按以下方式组织 命名空间 包含 菜单 (目录) 和 文件 (文本文件),镜像Gopher协议的两个 基本内容类型。路由器解析 namespace/selector 路径 并查找本地内容或代理到真实的Gopher服务器 在港口70。

源适配器

适配器将外部数据投影到本地存储中:

#[async_trait]
pub trait SourceAdapter: Send + Sync {
    fn namespace(&self) -> &str;
    async fn sync(&self, store: &LocalStore) -> Result<(), AdapterError>;
    async fn search(&self, selector: &str, query: &str) -> Option<Vec<MenuItem>>;
}
适配器 投影
RSS/Atom 进料通道→ 根菜单,条目→ 文档、类别→ 子菜单
文件系统 目录→ 菜单、文本文件→ 文件, .gophermap → 自定义菜单
RDF/SPARQL 课程→ 子菜单、资源→ 文档,SPARQL端点→ 本地搜索

许可证

阿帕奇-2.0