关于 justfile
justfile 是一项为项目生成惯用 justfile 的技能,帮助开发者将 Makefile 和零散 Shell 脚本整理为可发现的命令入口。它以统一的 build 验证门和配套文档更新为默认方案。
主要功能
- 01按项目生态生成 justfile
- 02将现有命令迁移为 recipes
- 03提供 build 与 ci 验证门
- 04更新 Agent 指引与 CI 配置
- 05支持多生态模块组合
适用场景
- 01为新项目建立统一验证命令
- 02将 Makefile 和脚本迁移到 just
- 03为多语言仓库汇总各生态检查
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ paulnsorensen/ git-gouda --skill justfile安装后在 Claude Code 中输入/justfile确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
evals/evals.jsonreferences/agent-build.mdcomposition.mdgo.mdmanual.mdpython.mdruby.mdrust.mdtypescript.md详细介绍
justfile
为任何项目生成符合惯例的 justfile。用简洁、易于发现的命令运行器替代 Makefile 和临时编写的 shell 脚本。
为什么选择 just,而不是 Make
- 无需
.PHONY变通方法——所有配方都是命令,而不是文件目标 - 没有制表符缩进问题——任何空白字符都可以
- 一流支持参数、dotenv 加载、操作系统检测和模块
just --list配合文档注释即可立即发现可用命令- Shebang 配方让你可以直接内联编写 Python/Ruby/Node 代码
如需了解官方的功能选择理由——最常用的功能、让 justfile 真正物有所值的特殊用例,以及带深层链接的章节索引——请参阅
references/manual.md,其内容基于
Just 程序员手册。
默认做法:一个规范命令
此技能生成的每个 justfile 都会提供一个 Agent 在每次更改后运行的唯一命令——just build——以及对应的、不执行自动修复的 CI 命令 just ci。build 是默认配方。两者都会运行完整的检查流程(格式化/ lint → 类型检查 → 测试 →
覆盖率),并精简输出:每个通过的步骤显示 ✓ <step>,只有失败时才显示完整工具输出和文件:行号。
这是每个生成的 justfile 的默认设置,并非可选项——除非用户明确要求采用其他布局。相关理由(Agent 使用统一命令、确定的通过/失败结果以及精简的错误专用输出后,能够更快达成一致;附有引用)和完整配方模板、_gate 辅助配方,以及必须进行的 AGENTS.md / CI 更新,都位于
references/agent-build.md 中。编写任何 justfile 前都要阅读该文件。
build = 检查流程(启用自动修复)。ci = 检查流程(禁用自动修复)。用于编译或打包构件的配方命名为 dist(或 release)——绝不能命名为 build,因为该名称专用于检查流程。
协议
1. 检测项目
扫描项目根目录,查找生态标记:
| 文件 | 生态系统 | 参考文档 |
|---|---|---|
Cargo.toml | Rust | references/rust.md |
pyproject.toml、setup.py、uv.lock | Python | references/python.md |
package.json | TypeScript/JS | references/typescript.md |
go.mod | Go | references/go.md |
Gemfile | Ruby | references/ruby.md |
阅读对应的参考文件,了解特定语言的配方。
如果存在多个标记(例如,Rust 后端 + TypeScript 前端),请组合相应模式。对于真正的单体仓库,请使用模块(mod frontend、mod backend)——根目录的 build 检查流程会汇总各模块的检查流程,因此 just build 仍表示“验证所有内容”。关于模块/导入组合模式的完整说明(以及何时选择 import 而非 mod),请参阅
references/composition.md。
多生态系统命名: 当项目使用多种语言时(例如,使用 Rust + TypeScript 的 Tauri),请使用生态系统后缀,区分名称重叠的事项:
test-rust、test-ts(不要使用含义不明的通用名称test)fmt-rust、fmt-ts(分别对应各生态系统的格式化工具)lint-rust(clippy)、lint-ts(eslint/biome)- 汇总配方组合这些配方:
test: test-rust test-ts、fmt: fmt-rust fmt-ts - 跨两个生态系统的共享配方使用不带后缀的名称:
dev、build、clean
2. 检查现有构建文件
查找 Makefile、Taskfile.yml、Rakefile、package.json 脚本,或 scripts/、bin/ 中的 shell 脚本。如果找到:
- 迁移:将现有目标转换为 just 配方(参见下方的迁移表)
- 保留:保留 just 无法替代的复杂逻辑(例如,Make 对实际构建构件进行的文件目标依赖跟踪)
- 移除:只有在向用户确认后,才能删除旧文件
同时检查是否已有 justfile。如果存在,请向用户展示拟议更改的差异,并等待用户明确授权后再覆盖。
3. 编写 justfile
将 justfile 放在项目根目录中。遵循以下约定:
结构顺序:
- 设置项(
set dotenv-load、set shell) - 变量(版本、二进制文件名等)
- 默认配方 —
default: build(标准门禁)。仅当用户明确不需要默认门禁时,才使用@just --list - 门禁:
build(自动修复)+ci(不自动修复)+_gate辅助配方 — 参见references/agent-build.md - 门禁组合使用的细分配方:test、lint、fmt、typecheck、coverage
- 按用途划分的其他配方:run/dev、dist/release、docs
- 实用配方(clean 等)
- 私有辅助配方(使用
_前缀或[private])
配方命名:
- 使用 kebab-case:
test-coverage、build-release - 使用动词:
build、test、lint、deploy(不要用builder、tests) - 对于较大的文件,使用前缀分组:
db-migrate、db-seed、db-reset - 默认配方应是最常用的操作或
--list
文档注释:
每个公共配方上方一行都要添加注释——just --list 会显示此注释:
# Run the full test suite
test *args:
cargo test {{args}}
参数:
- 为可选参数设置默认值:
test filter="" - 对透传参数使用可变参数:
run *args - 谨慎使用
+args(至少需要 1 个参数) - 对于符合直觉的 CLI 标志(
just dist --target x86_64),使用[arg()]属性(v1.46+ — 参见下文“配方参数标志”)
**别名:**为开发者每天会输入多次的配方添加一个单字母别名。在配方下方一行定义别名,这样 just --list 会优先显示规范名称:
# Run tests
test *args:
cargo test {{args}}
alias t := test
不要为每个配方都创建别名——只为常用路径创建。
始终包含的设置项:
set dotenv-load
set shell := ["bash", "-euo", "pipefail", "-c"]
-euo pipefail 会让 shell 配方在出现任何错误、未设置变量或管道中断时立即失败——这与编写良好的 bash 脚本采用相同的严格策略。如果某个配方需要更宽松的行为,请在单条命令前使用 - 前缀来忽略错误,而不要使用较弱的 shell 标志。对于 Windows 目标或不依赖 bash 的项目,请省略 set shell 行——默认的 /bin/sh 足以应对大多数配方。
常用功能不再需要 set unstable:模块(自 just 1.31 起稳定)、[script] 属性(1.44)和 [arg()] 标志(1.46)在当前版本的 just 中都可以使用。只有在需要支持早于相关功能稳定版本的 just 时,才添加 set unstable。
**dotenv 加固:**缺少 .env 时,set dotenv-load 会静默无操作。如果项目确实需要其 .env(数据库 URL、API 密钥),则应让此类失败明确可见——快速失败,而不是使用空变量继续运行:
set dotenv-load
set dotenv-required # error if no dotenv file is found
# Pick ONE of the following (omit both to load ./.env):
set dotenv-path := ".env.local" # explicit path (relative to justfile), OR…
# set dotenv-filename := ".env.dev" # …a filename to search for up the tree
dotenv-required 会将缺少环境文件转为硬错误,而不是静默无操作——这符合“快速且明确地失败”的策略。使用 dotenv-path 指定确切的文件,或使用 dotenv-filename 更改 just 在目录树中查找的文件名。参见
Settings § dotenv。
工具依赖 — require()
如果某个配方依赖的工具不是标准系统命令,请在 justfile 顶部声明它,这样缺少该工具时,just --evaluate 会快速失败:
# https://github.com/jqlang/jq
jq := require("jq")
# https://github.com/casey/just (yes, just itself)
just := require("just")
使用 {{ jq }} 通过解析出的路径调用,也可以直接调用 jq——require() 已在求值时确认该工具存在,因此两种写法都可行。URL 注释还可作为安装提示。对于 git、curl 或语言工具链等普遍可用的工具,请跳过 require()——只声明新机器上可能缺少的工具。
4. 经令牌优化的输出(默认启用,无需选择)
build 和 ci 通过 references/agent-build.md 中的 _gate 辅助程序运行,该程序已进行精简:每个通过的步骤显示 ✓ <step>,只有失败时才显示完整工具输出(含文件:行号)。覆盖率检查在 gate 内运行——成功时会隐藏其表格,未达到阈值时则完整显示。(这取代了旧的“跳过覆盖率以节省令牌”建议:将覆盖率检查保留在 gate 中;由精简处理令牌成本,而不是省略检查。)
对于 gate 组合的细粒度配方,使用 @ 前缀以静默配方回显,并向 npm 传递 --silent --no-audit --no-fund,以去除横幅、审计和赞助信息。
5. 更新项目文档(必需)
生成配方只完成了一半——如果没有内容告知 Agent 使用唯一的规范命令,那么这个命令的价值就无从体现。创建 justfile 后,务必完成以下两项更新。完整代码片段见 references/agent-build.md。
Agent 上下文文件(AGENTS.md、CLAUDE.md、GEMINI.md、.cursor/rules,或运行环境使用的其他文件;如果不存在,则创建 AGENTS.md)——添加或替换构建部分,告知 Agent 始终运行这一个命令,并在失败时立即停止:
## Build & verification
This project has ONE canonical verification command. ALWAYS run it after
changing code, and treat a non-zero exit as a hard stop.
- `just build` — autofix, then lint, typecheck, test, and coverage. Run after
every change.
- `just ci` — the same gate with no autofixes; exactly what CI runs.
Output is compacted: `✓ <step>` on success, full output (file:line) only on
failure. Don't invent ad-hoc test/lint commands — run `just build`.
CI 工作流——将现有的验证步骤指向 just ci,让本地和 CI 运行相同的 gate。此技能不负责设计流水线;它只会重定向验证步骤(例如,将单独的 lint/test/coverage 步骤替换为单个 run: just ci)。请参阅 references/agent-build.md 中的 Actions 代码片段。
README.md——添加“开发”或“快速入门”部分:
## Development
### Prerequisites
- [just](https://github.com/casey/just) — `brew install just` / `cargo install just`
### Quick Start
```bash
just install # Install dependencies
just test # Run tests
just # See all available commands
Don't duplicate the full recipe list — `just --list` is self-documenting.
## Makefile Migration Table
| Makefile | justfile |
|----------|----------|
| `.PHONY: target` | (not needed) |
| `$(VAR)` | `{{var}}` |
| `$(shell cmd)` | `` `cmd` `` |
| `-include .env` | `set dotenv-load` |
| `ifeq ($(OS),Darwin)` | `if os() == "macos" { ... }` |
| `ifndef VAR` / `$(or ...)` | `env_var_or_default("VAR", "default")` |
| `make -C subdir` | `mod subdir` |
| `$(MAKE) target` | `just target` |
| `.DEFAULT_GOAL := help` | First recipe is default |
| `@cmd` (suppress echo) | `@cmd` (same) |
| Tab indentation | Any whitespace |
| `%:` pattern rules | Not applicable — just has no file targets |
## Key Syntax Reference
**Variables:**
```just
VERSION := "1.0.0"
GIT_HASH := `git rev-parse --short HEAD`
DB_URL := env_var_or_default("DATABASE_URL", "postgres://localhost/dev")
OPEN := if os() == "macos" { "open" } else { "xdg-open" }
配方属性:
[confirm("Deploy to production?")]
deploy: build test
[macos]
open-docs:
open target/doc/index.html
[linux]
open-docs:
xdg-open target/doc/index.html
[private]
_setup:
mkdir -p tmp/
# Group recipes in `just --list` output
[group("checks")]
lint:
cargo clippy
[group("checks")]
fmt:
cargo fmt
# Multiple attributes — same line (comma-separated) or stacked
[group("dev"), no-cd]
status:
git status
配方参数标志(v1.46+): 使用 [arg()] 将参数作为 CLI 选项公开,而不是作为位置参数。最适合用户在提示符下运行的配方:
[arg("target", long, help="Build target architecture")]
[arg("release", long, value="true", help="Build in release mode")]
dist target release="false":
cargo build --target {{target}} {{ if release == "true" { "--release" } else { "" } }}
用法:just dist --target x86_64 --release。运行 just --usage dist 查看生成的帮助信息。
脚本块([script]): 比 shebang 配方更简洁;如果脚本主体包含不希望逐行重新求值的 shell 控制流,则更适合使用它(自 just 1.44 起已稳定,无需 set unstable):
[script("bash")]
deploy env:
set -e
case {{env}} in
prod) URL="https://prod.example.com" ;;
stage) URL="https://stage.example.com" ;;
*) echo "unknown env: {{env}}"; exit 1 ;;
esac
curl -X POST "$URL/deploy"
[script("python3")]
analyze:
import json
print(json.load(open("results.json"))["total"])
跨平台移植性更好,而且能让整个主体作为一个代码块运行,因此优先使用 [script()],而不是 #!/usr/bin/env shebang。
内置颜色常量: 无需定义即可全局使用——RED、GREEN、YELLOW、BLUE、CYAN、MAGENTA,以及用于重置的 BOLD、UNDERLINE 和 NORMAL。适用于多步骤配方中的状态输出:
@check:
cargo check
echo -e '{{ GREEN }}✓ check passed{{ NORMAL }}'
@fail-loudly:
echo -e '{{ BOLD + RED }}deploy aborted{{ NORMAL }}'
不要在每个配方中随意添加颜色——仅在用于概述汇总步骤的状态行中使用颜色。
监视/开发循环: just 没有内置的监视标志——手册中的做法是让 watchexec 在监视的文件发生变化时重新运行配方:watchexec just <recipe>。这是与 gate 相对应的快速迭代循环。可将常见用例封装在 dev 配方中,并声明依赖项:
# https://github.com/watchexec/watchexec
watchexec := require("watchexec")
# Re-run the fast checks on every save (Ctrl-C to stop).
dev:
watchexec just test
watchexec just test 是日常使用的快速迭代循环;规范的 build gate 则继续用于每次更改后的验证。请参阅文件变更时重新运行配方。
模块(单体仓库): 完整模式请参阅 references/composition.md——将各模块的 gate 汇总到一个根级 build 中,以及 mod 与 import 的区别。
mod api # looks for api/justfile or api.just
mod web
mod? local # optional — no error if missing
# Usage: just api::test, just web::build
Shebang 配方(多行脚本,无需 set unstable):
analyze:
#!/usr/bin/env python3
import json
data = json.load(open("results.json"))
print(f"Total: {len(data)}")
对于 just ≥ 1.44,优先使用 [script("python3")] 而不是 shebang(已稳定,无需 set unstable)——它会将主体作为一个代码块运行,并避免 shebang 的跨平台兼容性问题。
反模式
- 不要重建 Make 的文件目标系统——just 只是命令运行器,不是构建系统
- 除非有充分理由,否则不要使用
set positional-arguments——{{arg}}更清晰 - 不要把密钥放进 justfiles——使用 dotenv 或环境变量
- 不要编写 200 行的 justfiles——使用模块(
mod)按职责拆分 - 不要逐条照搬 CI 流水线步骤——将其整合到
build/ci门禁中 - 不要将产物/编译配方命名为
build——该名称用于门禁;请使用dist或release
不要做的事
- 不要从头设计 CI 流水线或 GitHub Actions 工作流——但要
将现有 CI 验证步骤重定向到
just ci(参见第 5 步) - 不要创建 Dockerfiles 或容器配置
- 不要替换实际的构建系统(cargo、webpack、go build)——just 只是对它们进行封装
- 未经用户确认,不要移除现有 Makefiles
注意事项
just二进制文件可能不在 PATH 中——生成配方前先用which just检查- Shebang 配方需要明确指定
#!/usr/bin/env,以便在不同系统间保持可移植性 dotenv-load会向所有配方公开所有环境变量——对于包含大量密钥的项目,请避免使用- 模块路径相对于 justfile 所在位置,而非工作目录
set positional-arguments会改变配方中$1的工作方式——使用时请加以说明require("tool")会在求值时进行验证——使用{{ jq }}通过解析出的路径调用,或直接调用jq;在require确认该工具存在后,两种方式都可用[script()]从 just 1.44 起已稳定,模块从 1.31 起已稳定,[arg()]从 1.46 起已稳定——在当前版本的 just 中都无需设置set unstable。仅在使用较旧版本的 just 时添加set unstable`;如果依赖这些功能,请在 README 中注明相应的最低版本