关于 Jinni: Bring Your Project Into Context
Jinni 是一个将项目文件整理为 LLM 上下文的工具,提供 MCP 服务与命令行两种用法。每个文件内容前都带有路径标题,便于模型识别结构。
主要功能
- 01合并项目相关文件为统一视图
- 02每个文件前标注相对路径标题
- 03自动排除二进制文件
- 04支持 .gitignore 风格的过滤规则
- 05支持仅列出文件路径的模式
- 06支持多种文本编码识别
适用场景
- 01向 LLM 提供整个项目或指定模块的上下文
- 02在编码 Agent 中按需读取测试或某个目录
- 03将项目上下文复制到剪贴板后粘贴到聊天界面
MCP 相关
提供 read_context 与 usage 两个 MCP 工具,客户端可指定项目根目录、目标路径和过滤规则来读取上下文。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
Jinni:将项目纳入上下文
Jinni 是一款工具,可高效地向大模型提供项目上下文。它整合了相关项目文件的内容,克服了逐个读取文件的局限和低效问题。每个文件的内容前面都有一个简单的标题,标明其路径:
```path=src/app.py
print("hello")
这款工具秉持的理念是:大模型的上下文窗口足够大,模型也足够聪明,直接查看项目最能帮助模型应对你交给它的任何任务。
Jinni 提供一个用于与 AI 工具集成的 MCP(Model Context Protocol)服务,以及一个命令行工具(CLI),供用户手动使用。命令行工具会将项目上下文复制到剪贴板,方便你粘贴到所需位置。
这些工具对相关项目上下文的定义有明确取舍,以便在大多数使用场景下开箱即用,并自动排除:
* 二进制文件
* 点文件和隐藏目录
* 日志、构建目录、临时文件等常见命名模式
如有需要,可以通过 .contextfiles 对包含项和排除项进行细粒度自定义——其工作方式类似于 .gitignore,但用于定义包含项。系统也会自动遵循 .gitignore 文件,但 .contextfiles 中的规则优先级更高。
MCP 服务可以按需提供任意数量的项目内容。默认范围是整个项目,但模型也可以请求特定模块、匹配模式等内容。
MCP 快速入门
Cursor / Roo / Claude Desktop / 所选客户端的 MCP 服务配置文件:
{
"mcpServers": {
"jinni": {
"command": "uvx",
"args": ["jinni-server"]
}
}
}
为安全起见,如果担心大模型失控,可选将服务限制为只能读取指定目录树中的内容:在 args 列表中添加 "--root", "/absolute/path/"。
如果系统中尚未安装 uv,请安装:https://docs.astral.sh/uv/getting-started/installation/
重新加载 IDE 后,就可以让 Agent 读取上下文。
如果只想将范围限制在特定模块或路径,请直接提出要求,例如:“读取测试的上下文”。
Cursor 中的使用示例:
Cursor 用户须知
Cursor 可能会静默丢弃超过允许最大值的上下文。因此,如果项目较大,而 Agent 的表现像是工具调用从未发生过,请尝试减少导入的内容(“读取 xyz 的上下文”)。
组件
-
jinniMCP 服务:- 与 Cursor、Cline、Roo、Claude Desktop 等 MCP 客户端集成。
- 提供
read_context工具,返回指定项目目录中相关文件内容的拼接字符串。
-
jinniCLI:- 用于手动生成项目上下文转储的命令行工具。
- 可通过复制粘贴或文件输入的方式将上下文提供给大模型,也可以将输出传输到所需位置。
功能
- 高效收集上下文: 一次操作即可读取并拼接相关项目文件。
- 智能筛选(Gitignore 风格的包含规则):
- 使用基于
.gitignore语法的系统(pathspec库的gitwildmatch)。 - 自动从项目根目录向下加载
.gitignore文件。这些排除规则可由.contextfiles中的规则覆盖。 - 支持分层配置,可将
.contextfiles放置在项目目录中。系统会根据正在处理的文件或目录动态应用规则。 - 匹配行为: 模式会匹配相对于正在处理的目标目录的路径。输出路径仍相对于原始项目根目录。
- 规则根目录行为: 每个目标都有自己的规则根目录:
- 项目根目录(或 CWD)内的目标使用项目根目录/CWD 作为规则根目录
- 外部目标使用自身作为规则根目录,确保规则集独立完整
- 覆盖规则: 支持使用
--overrides(CLI)或rules(MCP)专门指定一组规则。启用覆盖规则后,内置默认规则和任何.contextfiles都会被忽略。覆盖规则的路径匹配仍相对于目标目录。 - 显式包含目标: 明确指定为目标的文件始终会被包含(跳过规则检查,但仍会进行二进制文件和大小检查)。
- 使用基于
- 可自定义配置(
.contextfiles/ 覆盖规则):- 使用应用于相对路径的
.gitignore风格模式,精确指定要包含或排除的文件/目录。 - 以
!开头的模式会反转匹配结果(作为排除模式)。(请参阅下文的配置部分。)
- 使用应用于相对路径的
- 处理大型上下文: 如果包含文件的总大小超过可配置的限制(默认值:100MB),则会以
DetailedContextSizeError中止。错误消息会列出对大小影响最大的 10 个文件,帮助你确定要排除的文件。有关如何管理上下文大小的指导,请参阅故障排除部分。 - 元数据标头: 输出会为每个包含的文件提供路径标头(例如 ````path=src/app.py
)。可通过list_only` 禁用此功能。 - 编码处理: 尝试使用多种常见文本编码(UTF-8、Latin-1 等)。
- 仅列出模式: 可选择只列出将被包含的文件的相对路径,而不输出文件内容。
用法
MCP 服务(read_context 工具)
- 设置: 配置 MCP 客户端(例如 Claude Desktop 的
claude_desktop_config.json),通过uvx运行jinni服务。 - 调用: 通过 MCP 客户端与大模型交互时,模型可以调用
read_context工具。project_root(字符串,必填): 项目根目录的绝对路径。规则发现和输出路径均相对于此根目录。targets(字符串 JSON 数组,必填): 指定要处理的project_root内文件和/或目录的必填列表。必须是由路径字符串组成的 JSON 数组(例如,["path/to/file1", "path/to/dir2"])。路径可以是绝对路径,也可以是相对于当前工作目录(CWD)的路径。所有目标路径必须解析到project_root内的位置。如果提供空列表[],则会处理整个project_root。rules(字符串 JSON 数组,必填): 内联过滤规则的必填列表(使用.gitignore风格语法,例如,["src/**/*.py", "!*.tmp"])。如果不需要特定规则,请提供空列表[](此时将使用内置默认规则)。如果列表非空,则仅使用这些规则,忽略内置默认规则和.contextfiles。list_only(布尔值,可选): 如果为 true,则仅返回相对文件路径列表,而不返回内容。size_limit_mb(整数,可选): 覆盖上下文大小限制(以 MB 为单位)。debug_explain(布尔值,可选): 启用服务端调试日志。exclusions(对象,可选): 排除配置,包含三个可选字段:global(字符串数组):全局排除关键词(例如,["tests", "deprecated"])scoped(对象):路径到关键词数组的映射,用于限定范围的排除(例如,{"src/legacy": ["old", "deprecated"]})patterns(字符串数组):要排除的文件模式(例如,["*.test.js", "*_old.*"])
- 输出: 工具会返回一个字符串,其中包含拼接后的内容(带标题)或文件列表。标题和列表中的路径均相对于所提供的
project_root。如果发生上下文大小错误,则会返回DetailedContextSizeError,其中包含最大文件的详细信息。
MCP 服务(usage 工具)
- 调用: 模型可以调用
usage工具(无需参数)。 - 输出: 以字符串形式返回
README.md文件的内容。
(详细的服务设置说明会因 MCP 客户端而异。通常,你需要配置客户端以执行 Jinni 服务。)
运行服务:
- 推荐方法: 使用
uvx直接运行服务入口点(要求jinni软件包已发布到 PyPI,或可由uvx找到):
MCP 客户端配置示例(例如,uvx jinni-server [OPTIONS]claude_desktop_config.json):{ "mcpServers": { "jinni": { "command": "uvx", "args": ["jinni-server"] } } }
如果担心大模型行为失控,可以将服务限制为只能在指定目录树中读取,以增强安全性:在 args 列表中添加 "--root", "/absolute/path/"。
有关具体的设置步骤,请参阅相应 MCP 客户端的文档。请确保已安装 uv。
命令行工具(jinni CLI)
jinni [OPTIONS] [<PATH...>]
<PATH...>(可选): 一个或多个要分析的项目目录或文件路径。如果未提供,默认为当前目录(.)。-r <DIR>/--root <DIR>(可选): 指定项目根目录。提供后,将从此处开始发现规则,输出路径也相对于此目录。未提供时,根目录将根据<PATH...>参数的共同祖先推断(如果只处理.,则使用当前工作目录)。--output <FILE>/-o <FILE>(可选): 将输出写入<FILE>,而不是打印到标准输出。--list-only/-l(可选): 仅列出将被纳入的文件的相对路径。--overrides <FILE>(可选): 将<FILE>中的规则作为高优先级规则添加,并与.contextfiles和.gitignore中的规则一起使用。--size-limit-mb <MB>/-s <MB>(可选): 覆盖上下文大小上限(单位:MB)。--debug-explain(可选): 将详细的纳入/排除原因打印到标准错误和jinni_debug.log。--root <DIR>/-r <DIR>(可选): 参见上文。--no-copy(可选): 打印到标准输出时,禁止自动将输出内容复制到系统剪贴板(默认会复制)。--not <keyword>(可选,可重复): 排除与关键词匹配的模块/目录(例如,--not tests --not vendor)。可多次使用。--not-in <path:keywords>(可选,可重复): 排除指定路径中的特定关键词(例如,--not-in src/legacy:old,deprecated)。可多次使用。--not-files <pattern>(可选,可重复): 排除与模式匹配的文件(例如,--not-files '*.test.js' --not-files '*_old.*')。可多次使用。--keep-only <modules>(可选): 仅保留指定的模块/目录,排除其他所有内容(以逗号分隔,例如,--keep-only src,lib,docs)。
排除示例
CLI 示例:
# Exclude all test directories
jinni --not tests
# Exclude multiple keywords
jinni --not tests --not vendor --not deprecated
# Exclude old code only in specific paths
jinni --not-in src/legacy:old,deprecated --not-in lib/v1:legacy
# Exclude specific file patterns
jinni --not-files "*.test.js" --not-files "*_old.*"
# Keep only src and docs, exclude everything else
jinni --keep-only src,docs
# Combine different exclusion types
jinni --not tests --not-in src/experimental:wip --not-files "*.bak"
注意: 排除命令(--not* 标志)会在现有 .gitignore 和 .contextfiles 规则的基础上进一步筛选原本将被纳入的内容。
MCP 示例:
{
"project_root": "/path/to/project",
"targets": [],
"rules": [],
"exclusions": {
"global": ["tests", "vendor"],
"scoped": {
"src/legacy": ["old", "deprecated"],
"lib/experimental": ["wip", "unstable"]
},
"patterns": ["*.test.js", "*_backup.*"]
}
}
安装
你可以使用 pip 或 uv 安装 Jinni:
使用 pip:
pip install jinni
使用 uv:
uv pip install jinni
这会使 jinni CLI 命令在你的环境中可用。如何根据安装方式启动 MCP 服务,请参阅上文的“运行服务”部分。
平台特定说明
Windows + WSL
Jinni v0.1.7+ 会自动转换 WSL 路径。
将以下任一值作为 project_root(CLI --root 或 MCP 参数):
/home/user/project
vscode-remote://wsl+Ubuntu-22.04/home/user/project
无需包装器、挂载或额外标志——Jinni 会在 Windows 上自动解析 UNC 路径(\\wsl$\...)。
UNC 路径格式: Jinni 始终使用 \\wsl$\<distro>\...,以最大程度兼容所有支持 WSL 的 Windows 版本。
发行版名称处理: 发行版名称中允许空格和大多数特殊字符。只有真正不合法的 UNC 字符会被替换为 _。
缓存: WSL 路径查询和转换会进行缓存,以提升性能。如果在 Jinni 运行期间安装 WSL,请重启 Jinni 以识别新的 wslpath。
选择退出: 设置环境变量 JINNI_NO_WSL_TRANSLATE=1 可禁用所有 WSL 路径转换逻辑。
只有 wsl+<distro> URI 和绝对 POSIX 路径(以 / 开头)会被转换;对于 SSH 或容器远程环境,请在该环境中运行 Jinni。
| 运行时操作系统 | 传入的值 | _translate_wsl_path() 的返回值 |
|---|---|---|
| Windows | vscode-remote://wsl%2BUbuntu/home/a/b | \\wsl$\\Ubuntu\home\a\b |
| Windows | /home/a/b | \\wsl$\\Ubuntu\home\a\b(通过 wslpath) |
| Linux/WSL | vscode-remote://wsl+Ubuntu/home/a/b | /home/a/b |
| Linux/WSL | /home/a/b | /home/a/b(保持不变) |
示例
-
将
my_project/的上下文转储到控制台:jinni ./my_project/ # 处理单个目录 jinni ./src ./docs/README.md # 处理多个目标 jinni # 处理当前目录(.) -
列出
my_project/中将被包含的文件,不包含文件内容:jinni -l ./my_project/ jinni --list-only ./src ./docs/README.md -
将
my_project/的上下文转储到名为context_dump.txt的文件:jinni -o context_dump.txt ./my_project/ -
使用
custom.rules中的覆盖规则,而不是.contextfiles:jinni --overrides custom.rules ./my_project/ -
显示调试信息:
jinni --debug-explain ./src -
转储上下文(默认会自动将输出复制到剪贴板):
jinni ./my_project/ -
转储上下文,但不复制到剪贴板:
jinni --no-copy ./my_project/
配置(.contextfiles 与覆盖规则)
Jinni 使用 .contextfiles(或覆盖规则文件)根据 .gitignore 风格的模式,确定要包含或排除的文件和目录。
- 核心原则: 遍历过程中动态应用规则,路径相对于正在处理的当前目标目录。
- 位置(
.contextfiles): 可将.contextfiles放在任意目录中。规则查找从规则根目录(内部目标为项目根目录,外部目标为目标本身)开始,向下延伸到正在处理的当前目录。 - 格式: UTF-8 编码的纯文本,每行一个模式。
- 语法: 使用标准的
.gitignore模式语法(具体为pathspec的gitwildmatch实现)。- 注释: 以
#开头的行会被忽略。 - 包含模式: 指定要包含的文件/目录(例如
src/**/*.py、*.md、/config.yaml)。 - 排除模式: 以
!开头的行表示应排除匹配的文件(否定该模式)。 - 锚定: 开头的
/会将模式锚定到包含该.contextfiles的目录。 - 目录匹配: 末尾的
/仅匹配目录。 - 通配符:
*、**、?的用法与.gitignore相同。
- 注释: 以
- 规则应用逻辑:
- 确定目标: Jinni 确定目标目录(显式指定的目录或项目根目录)。
- 检查覆盖规则: 如果提供了
--overrides(CLI)或rules(MCP),则仅使用这些规则。所有.contextfiles和内置默认规则都会被忽略。路径匹配相对于目标目录。 - 动态上下文规则(无覆盖规则时): 处理文件或子目录时:
- Jinni 会从规则根目录向下到当前项所在目录,查找所有
.gitignore和.contextfiles。 - 按以下顺序合并规则:内置默认规则、
.gitignore规则、.contextfiles规则(优先级最高)。 - 将合并后的规则编译为规范(
PathSpec)。 - 将当前文件/子目录的路径(相对于目标目录计算)与该规范进行匹配。
- Jinni 会从规则根目录向下到当前项所在目录,查找所有
- 匹配: 合并后的规则集中,最后一个匹配该项相对路径的模式决定其处理方式。
!会否定匹配。如果没有用户定义的模式匹配,则包含该项,除非它匹配内置默认排除规则(例如!.*)。 - 目标处理: 显式指定的目标文件会跳过规则检查。输出路径始终相对于原始的
project_root。
示例(.contextfiles)
示例 1:包含 Python 源文件和根目录配置文件
位于 my_project/.contextfiles:
# Include all Python files in the src directory and subdirectories
src/**/*.py
# Include the main config file at the root of the project
/config.json
# Include all markdown files anywhere
*.md
# Exclude any test data directories found anywhere
!**/test_data/
示例 2:在子目录中覆盖规则
位于 my_project/src/.contextfiles:
# In addition to rules inherited from parent .contextfiles...
# Include specific utility scripts in this directory
utils/*.sh
# Exclude a specific generated file within src, even if *.py is included elsewhere
!generated_parser.py
开发
-
设计详情: DESIGN.md
-
在本地运行服务: 开发期间(使用
uv pip install -e .或类似方式安装后),可直接运行服务模块:python -m jinni.server [OPTIONS]本地开发的 MCP 客户端配置示例:
{ "mcpServers": { "jinni": { // 根据需要调整 python 路径,或确保已激活正确的环境 "command": "python -m jinni.server" // 可选:限制服务仅读取指定目录树中的内容(出于安全考虑,建议这样做): // "command": "python -m jinni.server --root /absolute/path/to/repo" } } }
故障排除
上下文大小错误(DetailedContextSizeError)
如果遇到提示超出上下文大小限制的错误,Jinni 会列出它尝试纳入的 10 个最大文件,帮助你找出可能需要排除的文件。
解决方法:
- 检查最大文件: 查看错误消息中提供的列表。是否有不应纳入大模型上下文的大型文件(例如数据文件、日志、构建产物、媒体文件)?
- 配置排除项: 使用
.contextfiles或--overrides/rules选项排除不必要的文件或目录。- 示例(
.contextfiles): 要排除所有.log文件和某个大型数据目录:# Exclude all log files !*.log # Exclude a large data directory !large_data_files/ - 有关详细语法和用法,请参阅上文的配置部分。
- 示例(
- 提高限制(谨慎使用): 如果所有纳入的文件确实都不可或缺,可以使用
--size-limit-mb(CLI)或size_limit_mb(MCP)提高大小限制。请注意大模型上下文窗口的限制和处理成本。 - 使用
jinni usage/usage: 如果在排查问题时需要重新查看这些说明或配置详情,请使用jinni usage命令或usageMCP 工具。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。