内容
# garrascript
**将提示词作为脚本。** garrascript 文件(简称 `grsc`)是一个 [docopt](http://docopt.org/) 接口和一个 LLM 提示词在同一个文件中:docopt 解析命令行参数,将解析结果插入到提示词中,然后将结果发送到 [OpenRouter](https://openrouter.ai) 上的模型 — 如果存在 `.mcp.json` 文件,则会附加 MCP 工具。
```bash
#!/usr/bin/env grsc
"""
poem: 按需写短诗。
用法:
poem [--tone=<tone>] <topic>...
poem --version
poem (-h | --help)
选项:
--tone=<tone> 诗歌的情绪 [默认值:playful].
"""
---
你是一位诗人。以 {{tone}} 的语气写作。保持在 8 行以内。
---
用 {{topic}} 写一首短诗。
```
```console
$ chmod +x poem.grsc
$ ./poem.grsc --tone=solemn the sea at night
...
$ ./poem.grsc --help # docopt 免费处理此功能
```
## 安装
```console
$ go install github.com/aldrinleal/garrascript/cmd/grsc@latest
```
## 配置
| 变量 | 目的 |
|-----------------------|--------------------------------------------------|
| `OPENROUTER_API_KEY` | 必需。您的 OpenRouter API 密钥。 |
| `OPENROUTER_MODEL` | 要使用的模型。默认为 `z-ai/glm-5.2`。 |
| `OPENROUTER_BASE_URL` | 可选的替代 OpenAI 兼容端点。 |
模型优先级:脚本自己的 `metadata.garrascript.model`(技能格式)优先,然后是 `OPENROUTER_MODEL`,然后是默认值。
### dotenv 文件
`--env-file=<path>` 在脚本运行前加载 `KEY=VALUE` 对,以便它们对 `{{env.VAR}}`、`$.mcp.json` 中的 `${VAR}` 和上述 `OPENROUTER_*` 设置可见。该标志可重复使用,必须在 `<script>` 之前;环境中已存在的变量永远不会被覆盖,并且在文件中,第一个定义键的文件优先。
脚本可以在 shebang 中携带自己的环境:
```bash
#!/usr/bin/env -S grsc --env-file .env
```
路径相对于工作目录,而不是脚本目录。请注意,Linux 会截断 shebang 行,最大长度为 255 个字符,因此请保持它们较短。
## 文件格式
`grsc` 接受两种布局,根据文件内容检测(`#!/usr/bin/env grsc` shebang 在两种布局中都是可选的)。
### 经典(`.grsc`)
1. 一个 `"""triple-quoted"""` docopt 文档字符串 — 这是您的脚本的 CLI。
2. 仅包含一行 `---`,然后是 **系统消息**。
3. 另一个 `---` 行,然后是 **用户消息**(运行到文件末尾;后面的 `---` 行保持不变)。
仅使用一个 `---` 分隔符时,没有系统消息,只有用户消息。
### 技能格式(`SKILL.md`)
[openclaw/clawhub 技能格式](https://docs.openclaw.ai/clawhub/skill-format) 的文件也可以运行:YAML 前置信息后跟 markdown 正文。
```markdown
---
name: haiku
description: 写一首关于某个主题的俳句。
version: 1.0.0
usage: |
用法:
haiku <topic>...
metadata:
openclaw:
requires:
env: [OPENROUTER_API_KEY]
bins: []
garrascript:
model: z-ai/glm-5.2 # 可选的每脚本模型覆盖
---
markdown 正文是系统消息。
---
正文中的独立 `---` 之后的所有内容都是用户消息。
```
映射规则:
- `description` + `usage`(顶级或 `metadata.garrascript.usage`)成为 docopt 文档。没有 `usage`,它默认为 `Usage: <name> [<input>...]`。
- 正文是系统消息;可选的独立 `---` 行分割出用户消息。或者,通过 `metadata.garrascript.user` 设置用户消息模板。
- `metadata.openclaw.requires.env` / `requires.bins`(以及 `clawdbot` / `clawdis` 别名)在运行前检查;缺少要求会中止。
- `version` 提供 docopt 的 `--version`。
## 插值
系统和用户消息中的 `{{placeholder}}` 令牌被替换为 docopt 结果:
- `{{topic}}`、`{{tone}}` — `<topic>` / `--tone` 的清理名称
- `{{<topic>}}`、`{{--tone}}` — 原始 docopt 键也起作用
- 重复参数 (`<topic>...`) 用空格连接
- 布尔值渲染为 `true` / `false`,未设置的选项为空字符串
- `{{env.HOME}}` — 环境变量
- 未知的占位符保持不变
## 内置工具
每个脚本都运行带有两个内置工具,模型可以调用:
- **`exit`** — 立即结束运行;`grsc` 进程使用给定的状态码(默认为 0)退出。这让脚本充当 shell 谓词:
```bash
Reply with nothing. Call exit with code 0 if the input is valid JSON,
code 1 otherwise: {{input}}
```
```console
$ ./is-json.grsc '{"a":1}' && echo valid
```
- **`write`** — 将 `text` 原样写入 `stdout` 或 `stderr`(`stream`,默认为 `stdout`)。对于发出精确的机器可读输出或将诊断信息写入 stderr,非常有用。
内置名称为纯名称(`exit`、`write`);MCP 工具始终具有命名空间(`server__tool`),因此它们永远不会冲突。
## MCP 工具
如果工作目录中有 `.mcp.json`(Claude Code 风格),`grsc` 连接到每个服务器,列出其工具,并将它们暴露给模型为 `<server>__<tool>`。工具调用在循环中透明地解析,直到模型生成其最终答案(工具活动记录到 stderr)。
```json
{
"mcpServers": {
"fs": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "."]
},
"remote": {
"type": "http",
"url": "https://example.com/mcp",
"headers": { "Authorization": "Bearer ${MY_TOKEN}" }
}
}
}
```
支持 `stdio`(默认)、`http`(可流式传输的 HTTP)和 `sse` 服务器;命令、参数、环境、URL 和标头中的 `${VAR}` 从环境中扩展。
## 示例
- [`examples/demo.grsc`](examples/demo.grsc) — 最小化问候
- [`examples/poem.grsc`](examples/poem.grsc) — 选项 + 位置参数
- [`examples/skills/haiku/SKILL.md`](examples/skills/haiku/SKILL.md) — 技能格式
- [`examples/tools/`](examples/tools/) — MCP 文件系统工具
## 开发
```console
$ go build ./...
$ go test ./...
```
## 许可证
[MIT](LICENSE)