# 命令行工具

在 Windows、macOS 或 Linux 上安装 `oleafly` 命令，从终端或 CI 构建和检查项目，与在线 LaTeX 服务同步，并通过它的 MCP 服务器和技能连接编程代理。

Oleafly 自带 `oleafly`，一个与应用处理同样项目的命令行工具。你可以在终端、脚本或 CI 中构建或检查论文，给编程代理一条可靠的途径进入你的项目，与在线 LaTeX 服务或 Oleafly 服务器同步，或者不打开应用就运行 Oleafly 代理。

它在每个平台上都随应用一起提供。本页介绍 Oleafly 0.4.8 及更高版本中的命令。更早的版本命令较少，所以依赖它的脚本请固定你的 Oleafly 版本。

## 安装

| 系统 | 应用把它放在哪里 | 把 `oleafly` 放到你的 PATH 中 |
|---|---|---|
| Windows | `oleafly-cli.exe` 位于应用旁边：安装程序版在 `%LOCALAPPDATA%\Oleafly`，MSI 包在 `C:\Program Files\Oleafly` | 在**设置 → 通用**的**终端命令**一行选择**安装**，会把它复制到 `%LOCALAPPDATA%\Oleafly\bin\oleafly.exe`，并把该文件夹添加到你的 PATH |
| macOS | `Oleafly.app/Contents/MacOS/oleafly-cli` | 在**终端命令**一行选择**安装**，会在你有写入权限时把 `oleafly` 链接到 `/usr/local/bin`，否则链接到 `~/.local/bin` |
| Linux 软件包（.deb、.rpm） | `/usr/bin/oleafly-cli` | 无需操作：软件包会安装 `/usr/bin/oleafly` |
| Linux AppImage | AppImage 内部 | **安装**会把它复制到 `~/.local/bin/oleafly` |

由 Oleafly 启动的程序，例如它自己的终端和 CLI 代理，即使你还没有安装，也总能在 PATH 中找到 `oleafly`。`OLEAFLY_CLI` 变量保存着它的完整路径。

### Windows

1. 打开**设置 → 通用**，在**终端命令**一行选择**安装**。
2. 打开新的 PowerShell 或命令提示符窗口。已经打开的窗口仍使用旧的 PATH。
3. 检查它是否可用：

```powershell
Get-Command oleafly
oleafly version
```

同一行的**移除**会删除这份副本，并把该文件夹从你的 PATH 中去掉。Oleafly 更新后，会在下次启动时刷新这份副本。

### macOS

请先把 Oleafly 移到“应用程序”文件夹。从磁盘映像中运行的副本，会显示“请先将 Oleafly 移到‘应用程序’文件夹”，而不是**安装**。

该命令是指向应用的链接，所以更新 Oleafly 也会更新这个命令。如果该文件夹不在你的 PATH 中，这一行会显示要添加到 shell 配置文件里的那一行。用 `command -v oleafly` 检查。

### Linux

.deb 和 .rpm 软件包在安装时就会把 `oleafly` 放到你的 PATH 中。单独运行 `oleafly`（后面不带任何内容）会打开应用。

AppImage 需要一份副本，因为 AppImage 退出后，它内部的文件就会消失。你用较新的 AppImage 替换旧的之后，这一行会提供**更新**。如果 `~/.local/bin` 不在你的 PATH 中，这一行会显示要添加的那一行。

### 检查它是否可用

`oleafly version` 会打印应用版本，以及该命令会使用的引擎。`oleafly doctor` 会检查引擎、应用、Git、终端命令和你的 MCP 客户端，并为缺少的任何东西打印修复方法。它在项目之外也能用。

## 构建项目

`oleafly .` 会在应用中打开当前文件夹。其他每个命令都作用于你所在的文件夹；`-C` 后面跟一个路径，可以让它作用于别处。

```sh
cd ~/papers/thesis
oleafly init --engine typst
oleafly build
oleafly log --diagnostics
oleafly -C ~/papers/review --json build
```

- `oleafly init` 会把当前文件夹变成项目。`--engine` 接受 `tectonic`、`latexmk`、`typst` 或 `markdown`。
- `oleafly new` 后面跟一个文件夹，再加上 `--template` 和模板 id，会从模板创建项目。`oleafly templates list --all` 会列出这些模板。
- `oleafly build` 使用项目的引擎和设置，做法与应用相同：使用 Oleafly 自带的 Tectonic、Typst 和 Pandoc，或你安装的 LaTeX。`--main` 构建项目中的另一份文档，`--compiler` 为 latexmk 项目选择 LaTeX 编译器，`-o` 把 PDF 复制到别处，`--timeout` 设置以秒为单位的时限。
- 在应用中就地打开的文件夹，会用你在那里选择的引擎和主文档构建，输出到应用自己的构建文件夹。
- 应用和命令绝不会同时构建同一个项目：后一个会等前一个完成。构建失败时会保留最近一次成功的 PDF。
- `oleafly watch` 在你每次保存时重新构建。`oleafly log --diagnostics` 会列出带文件和行号的错误与警告，`oleafly clean` 会删除构建输出。

关于 Typst 的具体内容，参见 [Typst 项目](/docs/typst/#build-from-the-command-line)。

## 从编程代理中使用

编程代理在这个命令提供的三样东西配合下效果最好：用 `oleafly context` 得到项目地图，用 `--json` 得到它们能读懂的结果，以及说明哪里出了问题的退出码。连接代理有三种方式。

### oleafly-cli 技能

Oleafly 自带一个名为 `oleafly-cli` 的技能。它教代理学会这些命令、JSON 输出和退出码，以及最有效的循环：读取上下文、编辑、构建、读取诊断信息、修复第一个错误。

在 Oleafly 的终端和它启动的 CLI 代理中，像选其他技能一样选择它。对于你自己运行的代理，请开启**设置 → AI 助手 → 技能 → 与此计算机上的其他代理共享技能**。之后 Oleafly 会把它的技能（包括 `oleafly-cli`）链接到其他编程代理读取的文件夹中，例如 `~/.claude/skills`、`~/.codex/skills` 和 `~/.agents/skills`。对于读取其他文件夹的代理，`oleafly skills path` 会打印技能所在的位置。

### 通过 MCP 连接代理

`oleafly mcp` 是一个通过标准输入和输出通信的 MCP 服务器。当应用已打开你的项目时，它会把调用转交给应用自己的 [MCP 服务器](/docs/mcp/)，所以代理能用到应用的每个工具，也会看到你的批准提示。否则它会独立工作，提供只读工具（项目状态、项目地图、文件、搜索、日志、doctor 报告、引用查询）和 `compile`。无需复制 URL 或令牌，也无需安装 Node.js。

最快的设置方式是 `oleafly mcp config --client` 后面跟 `claude-code`、`claude-desktop`、`codex`、`cursor` 或 `gemini`。它会打印该客户端的条目；加上 `--write` 就会替你添加，并备份客户端的文件。之后请重启或重新连接客户端。在项目内，它会写入项目的设置；在其他位置，则写入你的用户设置，并使用该命令的完整路径，因为从桌面启动的应用可能看不到你的 PATH。

#### Claude Code

```sh
claude mcp add --scope user oleafly -- oleafly mcp
```

在项目内，`oleafly mcp config --client claude-code --write` 会改为把服务器添加到项目的 `.mcp.json`。

#### Claude Desktop

Claude Desktop 启动服务器时没有项目文件夹，所以它的条目始终通过应用工作：请让 Oleafly 带着你的项目保持打开。请使用 `oleafly` 的完整路径。在 Windows 上，路径中的每个反斜杠都要写两次。

```json title="claude_desktop_config.json"
{
  "mcpServers": {
    "oleafly": {
      "command": "/usr/local/bin/oleafly",
      "args": ["mcp", "--bridge", "always"]
    }
  }
}
```

该文件在 macOS 上位于 `~/Library/Application Support/Claude`，在 Windows 上位于 `%APPDATA%\Claude`。

#### Codex

```toml title="~/.codex/config.toml"
[mcp_servers.oleafly]
command = "oleafly"
args = ["mcp"]
tool_timeout_sec = 300
```

#### Cursor

所有项目通用请使用 `~/.cursor/mcp.json`，只用于某一个项目则使用该项目内的 `.cursor/mcp.json`。

```json title="~/.cursor/mcp.json"
{
  "mcpServers": {
    "oleafly": {
      "command": "oleafly",
      "args": ["mcp"]
    }
  }
}
```

#### Gemini CLI

```json title="~/.gemini/settings.json"
{
  "mcpServers": {
    "oleafly": {
      "command": "oleafly",
      "args": ["mcp"],
      "timeout": 300000
    }
  }
}
```

### 把整个项目交给代理

`oleafly context` 会绘出项目的地图：它的文件、大纲、标签、引用、缺失的文件、未解析的引用，以及最近一次构建的问题。`--format md` 给出可以粘贴进提示词的文本；`--format json` 给出同一份地图，供程序使用。

## 提交前检查论文

`oleafly check` 会对项目运行[预检检查](/docs/preflight/)，结果与预检面板相同：交叉引用、引用、标签、缺失的文件、参考文献字段、图片，以及盲审用的匿名性。需要已编译 PDF 的检查会使用最近一次构建。

`oleafly lint` 会运行 LaTeX 和 BibTeX 检查，在包含它们的版本中还会运行拼写和语法检查。`--fix` 会应用可以放心应用的修复。

两者都接受 `--format human`、`json` 或 `sarif`，而 `--exit-code` 会让它们在发现问题时以 9 退出。SARIF 可以配合 GitHub 之类的代码扫描服务使用：用 `oleafly check --format sarif -o preflight.sarif` 写出报告，用 `upload-sarif` 操作上传，每条发现就会显示在拉取请求中它所在的行上。

## 与在线 LaTeX 服务同步

`oleafly remote` 会从你在线 LaTeX 服务的账号下载项目，并让一个文件夹与其中一个项目保持同步，合并方式与应用相同。

### 登录

登录信息保存在应用的加密存储中，所以在应用里登录后，命令行也能用，反过来也一样。

- `oleafly auth login online --with-token` 会保存来自该服务账号设置的 Git 令牌。关联和同步需要它。
- `oleafly auth login online --from-browser firefox` 会从这台电脑上的浏览器复制你的登录状态，用于列出和下载项目。Firefox 在所有系统上都可用；Chrome、Edge 和 Brave 在 macOS 上可用。`--cookie-stdin` 则改为读取会话 cookie。
- `oleafly auth login git --host https://gitlab.com` 会保存某个 Git 主机的令牌。
- `oleafly auth status` 会列出每个登录及其来源，不显示任何密钥。
- `oleafly auth logout` 会移除一个登录。

:::caution[别让令牌留在 shell 历史里]
令牌通过标准输入传入，例如 `oleafly auth login online --with-token < token.txt`，绝不要作为参数。在终端里，命令会向你索要令牌，输入时不会显示内容。`oleafly auth token` 会为脚本打印已保存的令牌，所以请像对待密码一样对待它的输出。
:::

### 导入和同步项目

```sh
oleafly remote list
oleafly remote import 64a1f0c2e5b7 --into ~/papers
cd ~/papers/thesis
oleafly remote link
oleafly remote sync
```

- `oleafly remote import` 会把项目下载到新的文件夹中。任何账号都可以使用。
- `oleafly remote link` 通过该服务的 Git 集成把文件夹连接到它的在线项目，这需要 Git 令牌。
- `oleafly remote sync` 会把在线更改合并到文件夹，并发送你的更改。`--dry-run` 显示会有哪些变化，`--no-push` 只合并而不发送。
- 当一个文件在两边都有更改时，同步不会写入任何内容，并以 8 退出。请再次运行，并加上 `--resolve`，对每个文件写出文件路径，后跟 `=local` 或 `=remote`。
- `oleafly remote diff` 会显示差异；加上 `--exit-code` 时，文件有差异就以 9 退出，有冲突则以 8 退出。`--latexdiff --pdf` 会构建一份标出你所作更改的 PDF，使用你的 TeX 发行版中的 latexdiff。
- `oleafly remote status`、`oleafly remote unlink` 和 `oleafly remote open` 分别会显示关联、移除关联，以及在浏览器中打开项目。

## 使用 Oleafly 服务器

`oleafly server sign-in` 后面跟服务器地址，会用一个你在浏览器中批准的代码让命令行登录。命令行在服务器上是一台独立于应用的设备。

- `oleafly server status` 和 `oleafly server projects` 会显示你的服务器和共享项目。
- `oleafly server share` 会显示项目的链接，并开启或关闭链接共享和评论。
- `oleafly server members` 会列出项目中的人员，并添加、移除或更改他们。只有所有者能更改共享和成员。
- `oleafly server comments` 会列出、添加、回复和解决评论。无法立即发送的评论会被保留，并在下次发送。

首次共享项目要在应用中进行。参见[实时协作](/docs/collaboration/)。

## 在终端运行 Oleafly 代理

`oleafly ask` 会回答关于项目的问题，不会更改任何内容。`oleafly agent run` 则执行一项任务。

```sh
oleafly ask "Which sections cite Smith 2021?"
oleafly agent run --allow write "Fix the overfull boxes in chapter 3"
```

- 代理始终可以读取项目。`--allow` 可以加上 `write`、`commands` 或 `network`，对你没有允许的内容它一律拒绝。它从不会停下来提问。
- 更改会先写入 `.oleafly/agent-runs/` 中的一个审阅文件夹。`oleafly agent apply` 后面跟那个文件夹，就会把更改写入项目；运行时加上 `--apply` 则立即写入。
- 提供商、模型和推理强度来自应用的设置，或来自 `--provider`、`--model` 和 `--effort`。密钥来自提供商自己的环境变量，例如 `ANTHROPIC_API_KEY`，或来自应用的加密存储。
- `--json` 会在运行结束时打印一个结果，`--events` 则在代理工作时为每个事件再加一行 JSON。

### 退出后让研究任务继续运行

把一个[研究任务](/docs/research-tasks/)标记为**Oleafly 关闭后继续运行**。你退出时，一个小型后台辅助进程会接管这些任务，它们的实验运行会继续进行。需要你批准的步骤会让任务暂停，并发送一条通知。你再次打开 Oleafly 时，它会收回这些任务，并显示发生了什么。你可以在**设置 → 研究 → 后台任务**下关闭这项功能，或让辅助进程在你登录时启动。`oleafly daemon status` 会显示辅助进程在做什么。

## 命令参考

每个命令都可以用 `--help` 查看它的选项。完整参考在仓库里：[docs/cli.md](https://github.com/Oleafly/Oleafly/blob/main/docs/cli.md)。

### 项目与构建

| 命令 | 作用 |
|---|---|
| `oleafly open` | 在应用中打开文件夹（当前文件夹用 `oleafly .`） |
| `oleafly init` | 把当前文件夹变成项目 |
| `oleafly new` | 创建项目；如果你指定了模板，就从模板创建 |
| `oleafly templates` | 列出模板并显示其中一个 |
| `oleafly build` | 构建项目 |
| `oleafly watch` | 每次保存时重新构建 |
| `oleafly clean` | 删除构建输出 |
| `oleafly log` | 显示最近一次构建的日志或问题 |
| `oleafly doctor` | 检查引擎、应用和你的设置 |
| `oleafly version` | 显示版本和正在使用的引擎 |
| `oleafly project info` | 显示项目的设置 |
| `oleafly projects list` | 列出应用中的项目 |
| `oleafly config` | 获取和设置项目与应用的设置 |

### 写作与参考文献

| 命令 | 作用 |
|---|---|
| `oleafly cite` | 为 DOI、arXiv id、ISBN 或 PubMed id 打印 BibTeX；`--add` 会把它添加到参考文献中 |
| `oleafly literature` | 搜索 OpenAlex、Semantic Scholar、Crossref、arXiv 和 PubMed |
| `oleafly bib check` | 找出与任何真实记录都不匹配的条目 |
| `oleafly bib clean` | 修复引用键并删除重复项；`--apply` 会写入更改 |
| `oleafly stats` | 统计字数，以及标题、图片和公式的数量 |
| `oleafly synctex` | 把源码行映射到 PDF，也可以反向映射 |
| `oleafly export` | 把文档导出为 Word、HTML、Markdown、EPUB 等格式 |
| `oleafly convert` | 把一个文件转换成另一种格式 |
| `oleafly typst` | 列出、安装和移除 Typst 版本 |
| `oleafly checkpoint` | 列出、比较和复制应用的检查点 |

### 代理与自动化

| 命令 | 作用 |
|---|---|
| `oleafly context` | 为人或代理绘出项目的地图 |
| `oleafly mcp` | 运行 MCP 服务器；`mcp config` 用来设置客户端 |
| `oleafly skills` | 列出技能并打印它们所在的位置 |
| `oleafly ask` | 回答关于项目的问题 |
| `oleafly agent` | 让 Oleafly 代理执行一项任务 |
| `oleafly daemon` | 运行并控制让任务持续运行的辅助进程 |

### 检查

| 命令 | 作用 |
|---|---|
| `oleafly check` | 运行预检检查 |
| `oleafly lint` | 运行 LaTeX、BibTeX、拼写和语法检查 |

### 账号与同步

| 命令 | 作用 |
|---|---|
| `oleafly auth` | 登录在线 LaTeX 服务、Oleafly 服务器和 Git 主机 |
| `oleafly remote` | 导入、关联和同步在线项目 |
| `oleafly server` | 使用 Oleafly 服务器：项目、共享、成员、评论 |

### Shell 与帮助

| 命令 | 作用 |
|---|---|
| `oleafly completions` | 打印 bash、zsh、fish、PowerShell 或 elvish 的 shell 补全 |
| `oleafly man` | 打印手册页 |
| `oleafly help exit-codes` | 说明退出码 |

### 适用于每个命令的选项

| 选项 | 作用 |
|---|---|
| `-C` 后跟一个路径 | 对另一个项目文件夹运行命令 |
| `--json` | 打印一个 JSON 结果 |
| `--events` | 在结果之前，以 JSON 行的形式打印进度 |
| `--quiet` | 只打印结果 |
| `--log` | 显示 `none`、`tail` 或 `full` 编译器日志 |
| `--no-input` | 绝不提问 |
| `--color` | 使用 `auto`、`always` 或 `never` 颜色 |

## 供脚本使用的输出

### JSON 输出

使用 `--json` 时，每个命令都会打印一个 JSON 对象：`schema_version`、`ok`、`command`、该命令自己的字段和 `warnings`。命令失败时，`error` 包含 `kind`、稳定的 `code` 和 `message`。在有帮助时，它还会有 `hint`、`details`，以及在重试可能成功时的 `"retryable": true`。依赖某个字段之前，请先检查 `schema_version`。

```json
{
  "schema_version": 1,
  "type": "result",
  "ok": false,
  "command": "remote sync",
  "error": {
    "kind": "conflict",
    "code": "remote.conflicts",
    "message": "2 files changed both here and online.",
    "hint": "Pick a side with --resolve PATH=local or --resolve PATH=remote, then sync again.",
    "details": { "conflicts": ["main.tex", "refs.bib"] }
  },
  "warnings": []
}
```

`--events` 会在结果之前，为每个进度事件加一行 JSON。

### 退出码

`oleafly help exit-codes` 会打印同一张表。

| 代码 | 含义 |
|---|---|
| 0 | 成功 |
| 1 | Oleafly 内部出了问题 |
| 2 | 命令用法有误，或需要 `--yes` 才能继续 |
| 3 | 项目缺失或无效，或路径指向项目之外 |
| 4 | 它需要的某个工具或 Oleafly 应用没有安装 |
| 5 | 构建失败 |
| 6 | 你需要登录 |
| 7 | 网络出了问题 |
| 8 | 别的东西占用着项目，或同步有冲突 |
| 9 | 检查发现了问题 |
| 130 | 你按了 Ctrl+C |

### 提问、颜色和日志

没有终端时，命令从不提问。`--no-input` 同样会关闭提问，设置了 `CI` 变量时也一样；需要你回答“是”的命令这时会以退出码 2 失败，并要求加上 `--yes`。`NO_COLOR` 或 `--color never` 会关闭颜色。会离开项目的路径会被拒绝。

### 环境变量

| 变量 | 用途 |
|---|---|
| `OLEAFLY_DATA_DIR` | Oleafly 的数据文件夹，当它不是 `~/.oleafly` 时 |
| `OLEAFLY_TECTONIC`, `OLEAFLY_LATEXMK`, `OLEAFLY_TYPST`, `OLEAFLY_PANDOC` | 用来代替 Oleafly 自己找到的编译器的编译器 |
| `OLEAFLY_APP` | `oleafly open` 启动的 Oleafly 应用 |
| `OLEAFLY_ONLINE_GIT_TOKEN` | 在线 LaTeX 服务的 Git 令牌，用来代替已保存的那个 |
| `OLEAFLY_CLI` | 由 Oleafly 为它启动的程序设置：该命令的完整路径 |
| `CI` | 设置后，命令绝不提问 |
| `NO_COLOR` | 设置后，输出没有颜色 |

## 故障排查

| 你看到的现象 | 可以尝试 |
|---|---|
| 找不到 `oleafly` | 打开新的终端。然后在 Windows 上用 `Get-Command oleafly`、在 macOS 和 Linux 上用 `command -v oleafly` 检查，并把设置所显示的那一行添加到你的 shell 配置文件 |
| `oleafly doctor` 报告缺少引擎 | 用 doctor 打印的命令安装它，或在应用中打开该项目一次 |
| MCP 客户端无法启动服务器 | 在终端运行已配置的命令，使用 `oleafly mcp config` 给出的完整路径，并运行 `oleafly doctor` |
| 退出码 6 | 运行 `oleafly auth status`，然后重新登录 |
| 同步期间出现退出码 8 | 对它列出的每个文件加上 `--resolve`，再次运行同步 |
| 在 macOS 上，设置中显示“请先将 Oleafly 移到‘应用程序’文件夹” | 移动应用，从“应用程序”中打开它，然后选择**安装** |

## 相关页面

- [Typst 项目](/docs/typst/#build-from-the-command-line)
- [通过 MCP 连接](/docs/mcp/)
- [CLI 代理](/docs/cli-agents/)
- [预检检查](/docs/preflight/)
- [研究任务](/docs/research-tasks/)
